From b37e141c00a123cf362fae00c1e63175d41c4bbe Mon Sep 17 00:00:00 2001
From: Junjie <fallin.jie@qq.com>
Date: 星期二, 10 三月 2026 17:01:06 +0800
Subject: [PATCH] #
---
src/main/webapp/views/index.html | 724 +++++++++++++++++++++++++++++++++++++++++++++---------
1 files changed, 596 insertions(+), 128 deletions(-)
diff --git a/src/main/webapp/views/index.html b/src/main/webapp/views/index.html
index b9bf30f..e6fd9eb 100644
--- a/src/main/webapp/views/index.html
+++ b/src/main/webapp/views/index.html
@@ -37,12 +37,23 @@
}
.layout-aside {
+ position: relative;
+ flex-shrink: 0;
display: flex;
flex-direction: column;
overflow: hidden;
border-radius: 16px;
background: linear-gradient(180deg, #16324d 0%, #0d2237 100%);
box-shadow: 0 14px 32px rgba(22, 50, 77, 0.18);
+ transform: translateZ(0);
+ backface-visibility: hidden;
+ will-change: width;
+ transition: width 0.22s cubic-bezier(0.22, 1, 0.36, 1),
+ box-shadow 0.22s ease;
+ }
+
+ .layout-aside.is-animating {
+ pointer-events: none;
}
.layout-panel {
@@ -55,6 +66,8 @@
background: #f5f7fa;
box-shadow: 0 14px 32px rgba(83, 104, 129, 0.12);
border: 1px solid #e4eaf2;
+ transform: translateZ(0);
+ backface-visibility: hidden;
}
.aside-logo {
@@ -66,6 +79,8 @@
box-sizing: border-box;
color: #fff;
border-bottom: 1px solid rgba(255, 255, 255, 0.08);
+ transition: min-height 0.22s cubic-bezier(0.22, 1, 0.36, 1),
+ padding 0.22s cubic-bezier(0.22, 1, 0.36, 1);
}
.aside-logo-image {
@@ -74,6 +89,8 @@
max-width: 178px;
height: auto;
object-fit: contain;
+ transform: translateZ(0);
+ transition: max-width 0.22s cubic-bezier(0.22, 1, 0.36, 1);
}
.aside-logo.is-collapse {
@@ -88,6 +105,17 @@
.aside-search {
padding: 12px 12px 8px;
box-sizing: border-box;
+ }
+
+ .aside-fade-enter-active,
+ .aside-fade-leave-active {
+ transition: opacity 0.14s ease, transform 0.18s ease;
+ }
+
+ .aside-fade-enter,
+ .aside-fade-leave-to {
+ opacity: 0;
+ transform: translate3d(-10px, 0, 0);
}
.aside-search .el-input__inner {
@@ -109,6 +137,7 @@
.aside-scroll {
flex: 1;
min-height: 0;
+ transform: translateZ(0);
}
.aside-scroll .el-scrollbar__wrap {
@@ -118,6 +147,7 @@
.side-menu {
border-right: none;
background: transparent;
+ transform: translateZ(0);
}
.side-menu .el-submenu__title,
@@ -127,6 +157,7 @@
margin: 0 10px 6px;
border-radius: 10px;
box-sizing: border-box;
+ backface-visibility: hidden;
}
.side-menu .el-submenu__title:hover,
@@ -228,6 +259,44 @@
color: rgba(255, 255, 255, 0.58);
}
+ .aside-loading {
+ padding: 4px 12px 12px;
+ box-sizing: border-box;
+ }
+
+ .aside-skeleton-item {
+ position: relative;
+ height: 46px;
+ margin: 0 10px 6px;
+ overflow: hidden;
+ border-radius: 10px;
+ background: rgba(255, 255, 255, 0.08);
+ }
+
+ .aside-skeleton-item::after {
+ content: "";
+ position: absolute;
+ inset: 0;
+ transform: translateX(-100%);
+ background: linear-gradient(90deg,
+ rgba(255, 255, 255, 0) 0%,
+ rgba(255, 255, 255, 0.16) 48%,
+ rgba(255, 255, 255, 0) 100%);
+ animation: asideSkeletonShimmer 1.25s ease-in-out infinite;
+ }
+
+ .aside-skeleton-item:nth-child(3n) {
+ width: calc(100% - 28px);
+ }
+
+ .aside-skeleton-item:nth-child(4n + 2) {
+ width: calc(100% - 44px);
+ }
+
+ .aside-skeleton-item:nth-child(5n) {
+ width: calc(100% - 36px);
+ }
+
.aside-footer {
padding: 14px 16px 16px;
border-top: 1px solid rgba(255, 255, 255, 0.08);
@@ -300,6 +369,10 @@
justify-content: flex-end;
gap: 8px;
flex-shrink: 0;
+ }
+
+ .lang-select {
+ width: 160px;
}
.header-right .el-tag {
@@ -450,6 +523,12 @@
}
}
+ @keyframes asideSkeletonShimmer {
+ 100% {
+ transform: translateX(100%);
+ }
+ }
+
.ai-drawer-layer {
box-shadow: -8px 0 24px rgba(0, 0, 0, 0.15) !important;
border-radius: 8px 0 0 8px !important;
@@ -485,72 +564,89 @@
<body>
<div id="app" v-cloak>
<el-container class="shell-container">
- <el-aside class="layout-aside" :width="asideWidth">
- <div class="aside-logo" :class="{ 'is-collapse': isCollapse }">
+ <el-aside
+ class="layout-aside"
+ :class="{ 'is-animating': collapseAnimating }"
+ :width="asideWidth">
+ <div class="aside-logo" :class="{ 'is-collapse': asideCompact }">
<img class="aside-logo-image" src="../static/images/zy-logo.png" alt="娴欐睙涓壃">
</div>
- <div class="aside-search" v-show="!isCollapse">
- <el-input
- v-model.trim="menuKeyword"
- size="small"
- clearable
- prefix-icon="el-icon-search"
- placeholder="鎼滅储鑿滃崟">
- </el-input>
- </div>
-
- <el-scrollbar class="aside-scroll" v-loading="menuLoading">
- <el-menu
- ref="sideMenu"
- class="side-menu"
- :default-active="activeMenuKey"
- :collapse="isCollapse"
- :collapse-transition="false"
- :default-openeds="defaultOpeneds"
- unique-opened
- background-color="transparent"
- text-color="#c6d1df"
- active-text-color="#ffffff">
- <el-submenu
- v-for="group in filteredMenus"
- :key="'group-' + group.menuId"
- :index="'group-' + group.menuId">
- <template slot="title">
- <i :class="resolveMenuIcon(group.menuCode)"></i>
- <span>{{ group.menu }}</span>
- </template>
- <el-menu-item
- v-for="item in group.subMenu"
- :key="item.tabKey"
- :index="item.tabKey"
- @click="handleMenuSelect(group, item)">
- {{ item.name }}
- </el-menu-item>
- </el-submenu>
- </el-menu>
-
- <div class="aside-empty" v-if="!menuLoading && filteredMenus.length === 0">
- <el-empty
- :image-size="80"
- :description="menuKeyword ? '娌℃湁鍖归厤鑿滃崟' : '褰撳墠璐﹀彿娌℃湁鍙敤鑿滃崟'">
- </el-empty>
+ <transition name="aside-fade">
+ <div class="aside-search" v-show="showAsideExtras">
+ <el-input
+ v-model.trim="menuKeyword"
+ size="small"
+ clearable
+ prefix-icon="el-icon-search"
+ :placeholder="t('index.searchMenu')">
+ </el-input>
</div>
+ </transition>
+
+ <el-scrollbar class="aside-scroll">
+ <div v-if="menuLoading" class="aside-loading" aria-hidden="true">
+ <div
+ v-for="n in 8"
+ :key="'menu-skeleton-' + n"
+ class="aside-skeleton-item">
+ </div>
+ </div>
+
+ <template v-else>
+ <el-menu
+ ref="sideMenu"
+ class="side-menu"
+ :default-active="activeMenuKey"
+ :collapse="menuCollapse"
+ :collapse-transition="false"
+ :default-openeds="defaultOpeneds"
+ unique-opened
+ background-color="transparent"
+ text-color="#c6d1df"
+ active-text-color="#ffffff">
+ <el-submenu
+ v-for="group in filteredMenus"
+ :key="'group-' + group.menuId"
+ :index="'group-' + group.menuId">
+ <template slot="title">
+ <i :class="resolveMenuIcon(group.menuCode)"></i>
+ <span>{{ group.menu }}</span>
+ </template>
+ <el-menu-item
+ v-for="item in group.subMenu"
+ :key="item.tabKey"
+ :index="item.tabKey"
+ @click="handleMenuSelect(group, item)">
+ {{ item.name }}
+ </el-menu-item>
+ </el-submenu>
+ </el-menu>
+
+ <div class="aside-empty" v-if="filteredMenus.length === 0">
+ <el-empty
+ :image-size="80"
+ :description="menuKeyword ? t('index.noMatchedMenu') : t('index.noAvailableMenu')">
+ </el-empty>
+ </div>
+ </template>
</el-scrollbar>
- <div class="aside-footer" v-show="!isCollapse">
- <div class="aside-footer-copy">漏 2026 娴欐睙涓壃绔嬪簱鎶�鏈湁闄愬叕鍙�</div>
- <div class="aside-footer-version">
- <span class="aside-footer-version-text">{{ versionText }}</span>
- <el-tag
- v-if="versionType"
- size="mini"
- :type="versionTagType"
- effect="dark">
- {{ versionTypeTag }}
- </el-tag>
+ <transition name="aside-fade">
+ <div class="aside-footer" v-show="showAsideExtras">
+ <div class="aside-footer-copy">漏 2026 {{ t('app.company') }}</div>
+ <div class="aside-footer-version">
+ <span class="aside-footer-version-text">{{ versionText }}</span>
+ <el-tag
+ v-if="versionType"
+ size="mini"
+ :type="versionTagType"
+ effect="dark">
+ {{ versionTypeTag }}
+ </el-tag>
+ </div>
</div>
- </div>
+ </transition>
</el-aside>
<el-container class="layout-panel">
@@ -573,7 +669,7 @@
size="mini"
:type="licenseTagType"
effect="dark">
- 涓存椂璁稿彲璇佹湁鏁堟湡锛歿{ licenseDays }}澶�
+ {{ t('index.licenseDays', [licenseDays]) }}
</el-tag>
<el-tag
v-if="fakeVisible"
@@ -582,8 +678,20 @@
:type="fakeRunning ? 'danger' : 'info'"
effect="dark"
@click.native="toggleFakeSystem">
- {{ fakeRunning ? '浠跨湡杩愯涓�' : '浠跨湡鏈繍琛�' }}
+ {{ fakeRunning ? t('index.fakeRunning') : t('index.fakeStopped') }}
</el-tag>
+ <el-select
+ v-model="currentLocale"
+ size="mini"
+ class="lang-select"
+ @change="handleLocaleChange">
+ <el-option
+ v-for="item in localeOptions"
+ :key="item.tag"
+ :label="item.label"
+ :value="item.tag">
+ </el-option>
+ </el-select>
<el-button circle size="mini" icon="el-icon-refresh" @click="refreshActiveTab"></el-button>
<el-button circle size="mini" icon="el-icon-full-screen" @click="toggleFullScreen"></el-button>
@@ -594,8 +702,8 @@
<i class="el-icon-arrow-down"></i>
</span>
<el-dropdown-menu slot="dropdown">
- <el-dropdown-item command="profile">鍩烘湰璧勬枡</el-dropdown-item>
- <el-dropdown-item command="logout" divided>閫�鍑虹櫥褰�</el-dropdown-item>
+ <el-dropdown-item command="profile">{{ t('common.profile') }}</el-dropdown-item>
+ <el-dropdown-item command="logout" divided>{{ t('common.logout') }}</el-dropdown-item>
</el-dropdown-menu>
</el-dropdown>
</div>
@@ -606,7 +714,6 @@
class="page-tabs"
v-model="activeTab"
type="card"
- @tab-click="handleTabClick"
@tab-remove="removeTab">
<el-tab-pane
v-for="tab in tabs"
@@ -618,10 +725,10 @@
</el-tabs>
<div class="tabs-tools">
- <el-tooltip content="鍏抽棴鍏朵粬椤电" placement="top">
+ <el-tooltip :content="t('common.closeOtherTabs')" placement="top">
<el-button size="mini" icon="el-icon-close" @click="closeOtherTabs"></el-button>
</el-tooltip>
- <el-tooltip content="杩斿洖鎺у埗涓績" placement="top">
+ <el-tooltip :content="t('common.backHome')" placement="top">
<el-button size="mini" type="primary" icon="el-icon-house" @click="openHomeTab"></el-button>
</el-tooltip>
</div>
@@ -638,6 +745,7 @@
v-for="tab in tabs"
:key="'frame-' + tab.name"
class="page-frame"
+ :data-tab-name="tab.name"
v-show="activeTab === tab.name"
:src="tab.currentSrc"
@load="handleFrameLoad(tab.name)">
@@ -648,13 +756,13 @@
</el-container>
<el-dialog
- title="璁稿彲璇佸嵆灏嗚繃鏈�"
+ :title="t('index.licenseExpiring')"
:visible.sync="licenseDialogVisible"
width="420px"
:close-on-click-modal="false">
<div class="license-dialog-text">{{ licenseDialogText }}</div>
<span slot="footer">
- <el-button type="primary" @click="licenseDialogVisible = false">鐭ラ亾浜�</el-button>
+ <el-button type="primary" @click="licenseDialogVisible = false">{{ t('common.ok') }}</el-button>
</span>
</el-dialog>
@@ -669,7 +777,7 @@
<script type="text/javascript" src="../static/js/jquery/jquery-3.3.1.min.js"></script>
<script type="text/javascript" src="../static/js/layer/layer.js"></script>
-<script type="text/javascript" src="../static/js/common.js"></script>
+<script type="text/javascript" src="../static/js/common.js?v=20260309_i18n_fix1"></script>
<script type="text/javascript" src="../static/vue/js/vue.min.js"></script>
<script type="text/javascript" src="../static/vue/element/element.js"></script>
<script>
@@ -687,17 +795,59 @@
group: "璐︽埛涓績",
menuKey: ""
};
+ var SIDEBAR_TRANSITION_MS = 220;
+ var SIDEBAR_EXPAND_CONTENT_DELAY = 180;
var TAB_STORAGE_KEY = "wcs-element-home-tabs";
var USER_STORAGE_KEY = "username";
+ var INDEX_I18N_FALLBACKS = {
+ "app.title": "娴欐睙涓壃 - 鑷姩鍖栫珛浣撲粨搴� - WCS",
+ "app.company": "娴欐睙涓壃绔嬪簱鎶�鏈湁闄愬叕鍙�",
+ "common.loadingPage": "姝e湪鍔犺浇椤甸潰...",
+ "common.loadingTab": "姝e湪鍔犺浇 鈥渰0}鈥� ...",
+ "common.refreshingTab": "姝e湪鍒锋柊 鈥渰0}鈥� ...",
+ "common.ok": "鐭ラ亾浜�",
+ "common.prompt": "鎻愮ず",
+ "common.profile": "鍩烘湰璧勬枡",
+ "common.logout": "閫�鍑虹櫥褰�",
+ "common.closeOtherTabs": "鍏抽棴鍏朵粬椤电",
+ "common.backHome": "杩斿洖鎺у埗涓績",
+ "common.aiAssistant": "AI鍔╂墜",
+ "common.workPage": "宸ヤ綔椤甸潰",
+ "common.businessPage": "涓氬姟椤甸潰",
+ "index.searchMenu": "鎼滅储鑿滃崟",
+ "index.noMatchedMenu": "娌℃湁鍖归厤鑿滃崟",
+ "index.noAvailableMenu": "褰撳墠璐﹀彿娌℃湁鍙敤鑿滃崟",
+ "index.licenseDays": "涓存椂璁稿彲璇佹湁鏁堟湡锛歿0}澶�",
+ "index.fakeRunning": "浠跨湡杩愯涓�",
+ "index.fakeStopped": "浠跨湡鏈繍琛�",
+ "index.licenseExpiring": "璁稿彲璇佸嵆灏嗚繃鏈�",
+ "index.homeTab": "鎺у埗涓績",
+ "index.homeGroup": "瀹炴椂鐩戞帶",
+ "index.profileGroup": "璐︽埛涓績",
+ "index.versionLoading": "Version loading...",
+ "index.licenseExpireAt": "璁稿彲璇佸皢浜� {0} 杩囨湡锛屽墿浣欐湁鏁堟湡锛歿1} 澶┿��",
+ "index.confirmStopFake": "纭畾瑕佸仠姝豢鐪熸ā鎷熷悧锛�",
+ "index.confirmStartFake": "纭畾瑕佸惎鍔ㄤ豢鐪熸ā鎷熷悧锛�",
+ "index.fakeStoppedSuccess": "浠跨湡妯℃嫙宸插仠姝�",
+ "index.fakeStartedSuccess": "浠跨湡妯℃嫙宸插惎鍔�",
+ "index.operationFailed": "鎿嶄綔澶辫触",
+ "index.menuLoadFailed": "鑿滃崟鍔犺浇澶辫触",
+ "index.menuLoadFailedDetail": "鑿滃崟鍔犺浇澶辫触锛岃妫�鏌ユ帴鍙g姸鎬�"
+ };
new Vue({
el: "#app",
data: function () {
return {
isCollapse: false,
- menuLoading: false,
+ asideCompact: false,
+ menuCollapse: false,
+ showAsideExtras: true,
+ collapseAnimating: false,
+ collapseTimer: null,
+ menuLoading: true,
pageLoading: true,
- loadingText: "姝e湪鍔犺浇椤甸潰...",
+ loadingText: window.WCS_I18N ? window.WCS_I18N.tl("姝e湪鍔犺浇椤甸潰...") : "姝e湪鍔犺浇椤甸潰...",
menuKeyword: "",
menus: [],
defaultOpeneds: [],
@@ -709,17 +859,21 @@
licenseDays: null,
licenseDialogVisible: false,
licenseDialogText: "",
+ currentLocale: window.WCS_I18N ? window.WCS_I18N.getLocale() : "zh-CN",
+ localeOptions: [],
fakeVisible: false,
fakeRunning: false,
fakeStatusInterval: null,
- userName: localStorage.getItem(USER_STORAGE_KEY) || "绠$悊鍛�",
+ menuSyncVersion: 0,
+ menuSyncTimer: null,
+ userName: localStorage.getItem(USER_STORAGE_KEY) || (window.WCS_I18N ? window.WCS_I18N.tl("绠$悊鍛�") : "绠$悊鍛�"),
aiLayerIndex: null,
aiTipIndex: null
};
},
computed: {
asideWidth: function () {
- return this.isCollapse ? "72px" : "248px";
+ return this.asideCompact ? "72px" : "248px";
},
filteredMenus: function () {
var keyword = (this.menuKeyword || "").toLowerCase();
@@ -764,7 +918,7 @@
return result;
},
activeTabMeta: function () {
- return this.getTabByName(this.activeTab) || this.createTab(HOME_TAB_CONFIG);
+ return this.getTabByName(this.activeTab) || this.createTab(this.resolveHomeConfig());
},
activeTabTitle: function () {
return this.activeTabMeta.title;
@@ -774,7 +928,7 @@
},
versionText: function () {
if (!this.version) {
- return "Version loading...";
+ return this.t("index.versionLoading");
}
return "Version " + this.version;
},
@@ -806,18 +960,18 @@
return "info";
},
userShortName: function () {
- return (this.userName || "绠$悊鍛�").substring(0, 1);
+ return (this.userName || this.tl("绠$悊鍛�")).substring(0, 1);
}
},
watch: {
activeTab: function () {
var tab = this.getTabByName(this.activeTab);
- this.activeMenuKey = tab ? (tab.menuKey || this.findMenuKeyByUrl(tab.url)) : "";
+ this.syncMenuStateByUrl(tab ? tab.url : this.resolveHomeConfig().url);
this.pageLoading = !!(tab && !tab.loaded);
if (this.pageLoading) {
- this.loadingText = "姝e湪鍔犺浇 鈥�" + tab.title + "鈥� ...";
+ this.loadingText = this.t("common.loadingTab", [tab.title]);
}
- document.title = (tab ? tab.title : HOME_TAB_CONFIG.title) + " - 娴欐睙涓壃 - 鑷姩鍖栫珛浣撲粨搴� - WCS";
+ this.updateDocumentTitle(tab ? tab.title : this.resolveHomeConfig().title);
this.persistTabs();
}
},
@@ -828,6 +982,7 @@
}
this.restoreTabs();
+ this.bindI18n();
this.installCompatBridge();
this.loadSystemVersion();
this.loadMenu();
@@ -837,7 +992,7 @@
},
mounted: function () {
$("#ai-assistant-btn").html(getAiIconHtml(60, 60));
- document.title = this.activeTabTitle + " - 娴欐睙涓壃 - 鑷姩鍖栫珛浣撲粨搴� - WCS";
+ this.updateDocumentTitle(this.activeTabTitle);
},
beforeDestroy: function () {
if (this.fakeStatusInterval) {
@@ -848,12 +1003,112 @@
clearInterval(this.userSyncTimer);
this.userSyncTimer = null;
}
+ if (this.menuSyncTimer) {
+ clearTimeout(this.menuSyncTimer);
+ this.menuSyncTimer = null;
+ }
+ if (this.collapseTimer) {
+ clearTimeout(this.collapseTimer);
+ this.collapseTimer = null;
+ }
if (this.aiTipIndex) {
layer.close(this.aiTipIndex);
this.aiTipIndex = null;
}
},
methods: {
+ t: function (key, params) {
+ var value = window.WCS_I18N ? window.WCS_I18N.t(key, params) : key;
+ if (value !== key) {
+ return value;
+ }
+ value = INDEX_I18N_FALLBACKS[key] || key;
+ if (!params) {
+ return value;
+ }
+ if (Object.prototype.toString.call(params) === "[object Array]") {
+ for (var i = 0; i < params.length; i++) {
+ value = value.replace(new RegExp("\\{" + i + "\\}", "g"), params[i]);
+ }
+ return value;
+ }
+ return value;
+ },
+ tl: function (text) {
+ return window.WCS_I18N ? window.WCS_I18N.tl(text) : text;
+ },
+ bindI18n: function () {
+ var that = this;
+ if (!window.WCS_I18N) {
+ return;
+ }
+ window.WCS_I18N.onReady(function (i18n) {
+ that.currentLocale = i18n.getLocale();
+ that.localeOptions = i18n.getLocaleOptions();
+ that.refreshI18nState();
+ });
+ },
+ refreshI18nState: function () {
+ var that = this;
+ var homeConfig = this.resolveHomeConfig();
+ var profileConfig = this.resolveProfileConfig();
+ var i;
+ HOME_TAB_CONFIG.title = homeConfig.title;
+ HOME_TAB_CONFIG.group = homeConfig.group;
+ PROFILE_TAB_CONFIG.title = profileConfig.title;
+ PROFILE_TAB_CONFIG.group = profileConfig.group;
+ for (i = 0; i < this.tabs.length; i++) {
+ if (this.isHomeTabUrl(this.tabs[i].url)) {
+ this.tabs[i].title = homeConfig.title;
+ this.tabs[i].group = homeConfig.group;
+ this.tabs[i].home = true;
+ } else if (this.resolveViewSrc(this.tabs[i].url) === this.resolveViewSrc(profileConfig.url)) {
+ this.tabs[i].title = profileConfig.title;
+ this.tabs[i].group = profileConfig.group;
+ } else {
+ this.tabs[i].title = this.translateTabTitle(this.tabs[i].title);
+ this.tabs[i].group = this.tl(this.tabs[i].group);
+ }
+ }
+ this.updateDocumentTitle(this.activeTabTitle);
+ this.persistTabs();
+ this.updateLicenseDialogText();
+ this.$nextTick(function () {
+ if (window.WCS_I18N) {
+ window.WCS_I18N.apply(document.body);
+ }
+ that.syncAllFramesI18n();
+ });
+ },
+ handleLocaleChange: function (locale) {
+ if (window.WCS_I18N) {
+ window.WCS_I18N.setLocale(locale);
+ }
+ },
+ resolveHomeConfig: function () {
+ return {
+ title: this.t("index.homeTab"),
+ url: HOME_TAB_CONFIG.url,
+ home: true,
+ group: this.t("index.homeGroup"),
+ menuKey: HOME_TAB_CONFIG.menuKey || ""
+ };
+ },
+ resolveProfileConfig: function () {
+ return {
+ title: this.t("common.profile"),
+ url: PROFILE_TAB_CONFIG.url,
+ home: false,
+ group: this.t("index.profileGroup"),
+ menuKey: PROFILE_TAB_CONFIG.menuKey || ""
+ };
+ },
+ translateTabTitle: function (title) {
+ return this.tl(title);
+ },
+ updateDocumentTitle: function (title) {
+ document.title = title + " - " + this.t("app.title");
+ },
resolveMenuIcon: function (code) {
var iconMap = {
index: "el-icon-s-home",
@@ -876,7 +1131,7 @@
title: config.title,
name: config.url,
url: config.url,
- currentSrc: config.url,
+ currentSrc: this.addNonce(config.url),
home: !!config.home,
group: config.group || "",
menuKey: config.menuKey || "",
@@ -885,17 +1140,17 @@
},
normalizeStoredTab: function (tab) {
var created = this.createTab({
- title: tab.title,
+ title: this.translateTabTitle(tab.title),
url: this.resolveViewSrc(tab.url),
home: !!tab.home,
- group: tab.group || "",
+ group: this.tl(tab.group || ""),
menuKey: tab.menuKey || ""
});
created.loaded = false;
return created;
},
restoreTabs: function () {
- var homeTab = this.createTab(HOME_TAB_CONFIG);
+ var homeTab = this.createTab(this.resolveHomeConfig());
var raw = localStorage.getItem(TAB_STORAGE_KEY);
var parsed;
var tabs = [];
@@ -937,9 +1192,9 @@
this.tabs = tabs;
this.activeTab = this.hasTab(active) ? active : homeTab.name;
- this.loadingText = "姝e湪鍔犺浇 鈥�" + this.activeTabTitle + "鈥� ...";
+ this.loadingText = this.t("common.loadingTab", [this.activeTabTitle]);
this.pageLoading = true;
- document.title = this.activeTabTitle + " - 娴欐睙涓壃 - 鑷姩鍖栫珛浣撲粨搴� - WCS";
+ this.updateDocumentTitle(this.activeTabTitle);
},
persistTabs: function () {
var tabs = [];
@@ -960,6 +1215,10 @@
},
hasTab: function (name) {
return !!this.getTabByName(name);
+ },
+ isHomeTabUrl: function (url) {
+ var homeUrl = this.resolveHomeConfig().url;
+ return this.resolveViewSrc(url || homeUrl) === this.resolveViewSrc(homeUrl);
},
getTabByName: function (name) {
var i;
@@ -992,28 +1251,29 @@
}
}
- this.loadingText = "姝e湪鍔犺浇 鈥�" + tab.title + "鈥� ...";
+ this.loadingText = this.t("common.loadingTab", [tab.title]);
this.pageLoading = !tab.loaded;
this.activeTab = tab.name;
- this.activeMenuKey = tab.menuKey || this.findMenuKeyByUrl(tab.url);
+ this.syncMenuStateByUrl(tab.url);
},
openHomeTab: function () {
- this.addOrActivateTab(HOME_TAB_CONFIG);
+ this.addOrActivateTab(this.resolveHomeConfig());
},
openProfileTab: function () {
- this.addOrActivateTab(PROFILE_TAB_CONFIG);
+ this.addOrActivateTab(this.resolveProfileConfig());
},
closeAllTabs: function () {
- this.tabs = [this.createTab(HOME_TAB_CONFIG)];
- this.activeTab = HOME_TAB_CONFIG.url;
- this.activeMenuKey = "";
+ var homeConfig = this.resolveHomeConfig();
+ this.tabs = [this.createTab(homeConfig)];
+ this.activeTab = homeConfig.url;
+ this.syncMenuStateByUrl(homeConfig.url);
this.pageLoading = true;
- this.loadingText = "姝e湪鍔犺浇 鈥滄帶鍒朵腑蹇冣�� ...";
+ this.loadingText = this.t("common.loadingTab", [homeConfig.title]);
this.persistTabs();
},
closeOtherTabs: function () {
var active = this.getTabByName(this.activeTab);
- var homeTab = this.createTab(HOME_TAB_CONFIG);
+ var homeTab = this.createTab(this.resolveHomeConfig());
var result = [homeTab];
if (active && active.name !== homeTab.name) {
@@ -1025,7 +1285,7 @@
},
removeTab: function (name) {
var i;
- var nextTabName = HOME_TAB_CONFIG.url;
+ var nextTabName = this.resolveHomeConfig().url;
for (i = 0; i < this.tabs.length; i++) {
if (this.tabs[i].name === name) {
@@ -1042,21 +1302,19 @@
}
if (this.tabs.length === 0) {
- this.tabs.push(this.createTab(HOME_TAB_CONFIG));
- nextTabName = HOME_TAB_CONFIG.url;
+ this.tabs.push(this.createTab(this.resolveHomeConfig()));
+ nextTabName = this.resolveHomeConfig().url;
}
this.activeTab = nextTabName;
this.persistTabs();
- },
- handleTabClick: function () {
- this.activeMenuKey = this.findMenuKeyByUrl(this.activeTabUrl);
},
handleFrameLoad: function (name) {
var tab = this.getTabByName(name);
if (tab) {
tab.loaded = true;
}
+ this.syncFrameI18n(name);
if (this.activeTab === name) {
this.pageLoading = false;
}
@@ -1068,14 +1326,144 @@
}
tab.loaded = false;
tab.currentSrc = this.addNonce(tab.url);
- this.loadingText = "姝e湪鍒锋柊 鈥�" + tab.title + "鈥� ...";
+ this.loadingText = this.t("common.refreshingTab", [tab.title]);
this.pageLoading = true;
},
addNonce: function (url) {
return url + (url.indexOf("?") === -1 ? "?" : "&") + "_t=" + new Date().getTime();
},
+ findFrameElement: function (name) {
+ var frames;
+ var i;
+ if (!this.$el) {
+ return null;
+ }
+ frames = this.$el.querySelectorAll("iframe[data-tab-name]");
+ for (i = 0; i < frames.length; i++) {
+ if (frames[i].getAttribute("data-tab-name") === name) {
+ return frames[i];
+ }
+ }
+ return null;
+ },
+ syncFrameI18n: function (name) {
+ var that = this;
+ var frame = this.findFrameElement(name);
+ var frameWindow;
+ var frameDocument;
+ var script;
+
+ function applyFrameI18n() {
+ try {
+ if (!frameWindow.WCS_I18N || typeof frameWindow.WCS_I18N.onReady !== "function") {
+ return;
+ }
+ frameWindow.WCS_I18N.setLocale(that.currentLocale || "zh-CN", false);
+ frameWindow.WCS_I18N.onReady(function (i18n) {
+ i18n.apply(frameDocument.body || frameDocument.documentElement);
+ if (frameDocument.title) {
+ frameDocument.title = i18n.tl(frameDocument.title);
+ }
+ });
+ } catch (e) {
+ }
+ }
+
+ if (!frame) {
+ return;
+ }
+ try {
+ frameWindow = frame.contentWindow;
+ frameDocument = frameWindow.document;
+ } catch (e) {
+ return;
+ }
+ try {
+ frameWindow.localStorage.setItem("wcs_lang", this.currentLocale || "zh-CN");
+ } catch (e) {
+ }
+ if (frameDocument && frameDocument.documentElement) {
+ frameDocument.documentElement.lang = this.currentLocale || "zh-CN";
+ }
+ if (frameWindow.WCS_I18N && typeof frameWindow.WCS_I18N.onReady === "function") {
+ applyFrameI18n();
+ return;
+ }
+ if (!frameDocument || !frameDocument.head || frameDocument.getElementById("wcs-i18n-bridge-script")) {
+ return;
+ }
+ script = frameDocument.createElement("script");
+ script.id = "wcs-i18n-bridge-script";
+ script.type = "text/javascript";
+ script.src = baseUrl + "/static/js/common.js?v=20260309_i18n_fix1";
+ script.onload = applyFrameI18n;
+ frameDocument.head.appendChild(script);
+ },
+ syncAllFramesI18n: function () {
+ var i;
+ for (i = 0; i < this.tabs.length; i++) {
+ this.syncFrameI18n(this.tabs[i].name);
+ }
+ },
+ clearCollapseTimer: function () {
+ if (this.collapseTimer) {
+ clearTimeout(this.collapseTimer);
+ this.collapseTimer = null;
+ }
+ },
+ nextFrame: function (callback) {
+ if (window.requestAnimationFrame) {
+ window.requestAnimationFrame(function () {
+ callback();
+ });
+ return;
+ }
+ setTimeout(callback, 16);
+ },
+ finishCollapseStage: function (callback, delay) {
+ var that = this;
+ this.clearCollapseTimer();
+ this.collapseTimer = setTimeout(function () {
+ that.collapseTimer = null;
+ callback();
+ }, delay);
+ },
toggleCollapse: function () {
- this.isCollapse = !this.isCollapse;
+ var that = this;
+
+ if (this.collapseAnimating) {
+ return;
+ }
+
+ this.collapseAnimating = true;
+
+ if (this.isCollapse) {
+ this.isCollapse = false;
+ this.asideCompact = false;
+ this.nextFrame(function () {
+ that.finishCollapseStage(function () {
+ that.menuCollapse = false;
+ that.showAsideExtras = true;
+ that.collapseAnimating = false;
+ that.$nextTick(function () {
+ that.syncMenuStateByUrl(that.activeTabUrl);
+ });
+ }, SIDEBAR_EXPAND_CONTENT_DELAY);
+ });
+ return;
+ }
+
+ this.isCollapse = true;
+ this.showAsideExtras = false;
+ this.menuCollapse = true;
+ this.$nextTick(function () {
+ that.nextFrame(function () {
+ that.asideCompact = true;
+ that.finishCollapseStage(function () {
+ that.collapseAnimating = false;
+ }, SIDEBAR_TRANSITION_MS);
+ });
+ });
},
handleMenuSelect: function (group, item) {
this.addOrActivateTab({
@@ -1104,6 +1492,24 @@
}
return "";
},
+ findMenuGroupIndexByUrl: function (url) {
+ var normalized = this.resolveViewSrc(url);
+ var i;
+ var j;
+ var group;
+ var item;
+
+ for (i = 0; i < this.menus.length; i++) {
+ group = this.menus[i];
+ for (j = 0; j < group.subMenu.length; j++) {
+ item = group.subMenu[j];
+ if (item.url === normalized) {
+ return "group-" + group.menuId;
+ }
+ }
+ }
+ return "";
+ },
normalizeMenuData: function (data) {
var result = [];
var i;
@@ -1120,7 +1526,7 @@
item = group.subMenu[j];
subMenu.push({
id: item.id,
- name: item.name || item.code || "鏈懡鍚嶉〉闈�",
+ name: item.name || item.code || this.tl("鏈懡鍚嶉〉闈�"),
code: item.code || "",
url: this.buildMenuSrc(item.code, item.id),
tabKey: this.buildMenuSrc(item.code, item.id)
@@ -1129,7 +1535,7 @@
result.push({
menuId: group.menuId,
- menu: group.menu || "鏈懡鍚嶅垎缁�",
+ menu: group.menu || this.tl("鏈懡鍚嶅垎缁�"),
menuCode: group.menuCode || "",
subMenu: subMenu
});
@@ -1156,7 +1562,7 @@
},
resolveViewSrc: function (path) {
if (!path) {
- return HOME_TAB_CONFIG.url;
+ return this.resolveHomeConfig().url;
}
if (/^https?:\/\//.test(path) || path.indexOf(baseUrl) === 0) {
return path;
@@ -1188,6 +1594,65 @@
menu.close(openedMenus[i]);
}
},
+ syncMenuStateByUrl: function (url) {
+ var targetUrl = this.resolveViewSrc(url || this.resolveHomeConfig().url);
+ var activeMenuKey = "";
+ var groupIndex = "";
+ var that = this;
+ var syncVersion;
+ var applyMenuState;
+
+ if (!this.isHomeTabUrl(targetUrl)) {
+ activeMenuKey = this.findMenuKeyByUrl(targetUrl);
+ if (activeMenuKey) {
+ groupIndex = this.findMenuGroupIndexByUrl(targetUrl);
+ }
+ }
+
+ this.activeMenuKey = activeMenuKey;
+ this.defaultOpeneds = groupIndex ? [groupIndex] : [];
+ this.menuSyncVersion += 1;
+ syncVersion = this.menuSyncVersion;
+ applyMenuState = function () {
+ var menu = that.$refs.sideMenu;
+ var openedMenus;
+ if (syncVersion !== that.menuSyncVersion) {
+ return;
+ }
+ if (!menu) {
+ return;
+ }
+ if (that.menuCollapse) {
+ return;
+ }
+ openedMenus = menu.openedMenus ? menu.openedMenus.slice() : [];
+ if (!groupIndex) {
+ if (openedMenus.length) {
+ that.collapseAllMenus();
+ }
+ return;
+ }
+ if (openedMenus.indexOf(groupIndex) > -1) {
+ return;
+ }
+ if (openedMenus.length) {
+ that.collapseAllMenus();
+ }
+ menu.open(groupIndex);
+ };
+
+ this.$nextTick(function () {
+ applyMenuState();
+ if (that.menuSyncTimer) {
+ clearTimeout(that.menuSyncTimer);
+ that.menuSyncTimer = null;
+ }
+ that.menuSyncTimer = setTimeout(function () {
+ applyMenuState();
+ that.menuSyncTimer = null;
+ }, 160);
+ });
+ },
loadMenu: function () {
var that = this;
this.menuLoading = true;
@@ -1199,20 +1664,16 @@
that.menuLoading = false;
if (res.code === 200) {
that.menus = that.normalizeMenuData(res.data || []);
- that.defaultOpeneds = [];
- that.activeMenuKey = that.findMenuKeyByUrl(that.activeTabUrl);
- that.$nextTick(function () {
- that.collapseAllMenus();
- });
+ that.syncMenuStateByUrl(that.activeTabUrl);
} else if (res.code === 403) {
top.location.href = baseUrl + "/login";
} else {
- that.$message.error(res.msg || "鑿滃崟鍔犺浇澶辫触");
+ that.$message.error(res.msg || that.t("index.menuLoadFailed"));
}
},
error: function () {
that.menuLoading = false;
- that.$message.error("鑿滃崟鍔犺浇澶辫触锛岃妫�鏌ユ帴鍙g姸鎬�");
+ that.$message.error(that.t("index.menuLoadFailedDetail"));
}
});
},
@@ -1259,6 +1720,7 @@
showPopup: function (days) {
var currentDate;
var expiryDate;
+ var formattedDate;
if (days === "" || days === null || typeof days === "undefined") {
this.hidePopup();
@@ -1268,9 +1730,15 @@
currentDate = new Date();
expiryDate = new Date();
expiryDate.setDate(currentDate.getDate() + Number(days) + 1);
- this.licenseDialogText = "璁稿彲璇佸皢浜� " + new Intl.DateTimeFormat("zh-CN").format(expiryDate) +
- " 杩囨湡锛屽墿浣欐湁鏁堟湡锛�" + days + " 澶┿��";
+ formattedDate = new Intl.DateTimeFormat(this.currentLocale || "zh-CN").format(expiryDate);
+ this.licenseDialogText = this.t("index.licenseExpireAt", [formattedDate, days]);
this.licenseDialogVisible = true;
+ },
+ updateLicenseDialogText: function () {
+ if (this.licenseDays === "" || this.licenseDays === null || typeof this.licenseDays === "undefined" || this.licenseDays > 15) {
+ return;
+ }
+ this.showPopup(this.licenseDays);
},
hidePopup: function () {
this.licenseDialogVisible = false;
@@ -1318,17 +1786,17 @@
if (this.fakeRunning) {
url = baseUrl + "/openapi/stopFakeSystem";
- text = "纭畾瑕佸仠姝豢鐪熸ā鎷熷悧锛�";
- successMsg = "浠跨湡妯℃嫙宸插仠姝�";
+ text = this.t("index.confirmStopFake");
+ successMsg = this.t("index.fakeStoppedSuccess");
running = false;
} else {
url = baseUrl + "/openapi/startFakeSystem";
- text = "纭畾瑕佸惎鍔ㄤ豢鐪熸ā鎷熷悧锛�";
- successMsg = "浠跨湡妯℃嫙宸插惎鍔�";
+ text = this.t("index.confirmStartFake");
+ successMsg = this.t("index.fakeStartedSuccess");
running = true;
}
- this.$confirm(text, "鎻愮ず", {
+ this.$confirm(text, this.t("common.prompt"), {
type: "warning"
}).then(function () {
$.ajax({
@@ -1340,7 +1808,7 @@
that.fakeRunning = running;
that.$message.success(successMsg);
} else {
- that.$message.error(res.msg || "鎿嶄綔澶辫触");
+ that.$message.error(res.msg || that.t("index.operationFailed"));
}
}
});
@@ -1355,7 +1823,7 @@
},
showAiTip: function () {
this.hideAiTip();
- this.aiTipIndex = layer.tips("AI鍔╂墜", "#ai-assistant-btn", {
+ this.aiTipIndex = layer.tips(this.t("common.aiAssistant"), "#ai-assistant-btn", {
tips: [1, "#333"],
time: -1
});
@@ -1436,7 +1904,7 @@
startUserSync: function () {
var that = this;
this.userSyncTimer = setInterval(function () {
- that.userName = localStorage.getItem(USER_STORAGE_KEY) || "绠$悊鍛�";
+ that.userName = localStorage.getItem(USER_STORAGE_KEY) || that.tl("绠$悊鍛�");
}, 1000);
},
installCompatBridge: function () {
@@ -1448,7 +1916,7 @@
};
window.admin.changeTheme = window.admin.changeTheme || function () {};
window.admin.activeNav = function (url) {
- that.activeMenuKey = that.findMenuKeyByUrl(that.resolveViewSrc(url));
+ that.syncMenuStateByUrl(that.resolveViewSrc(url));
};
window.index = window.index || {};
@@ -1459,10 +1927,10 @@
}
url = that.resolveViewSrc(param.menuPath);
that.addOrActivateTab({
- title: that.stripTags(param.menuName) || "宸ヤ綔椤甸潰",
+ title: that.stripTags(param.menuName) || that.t("common.workPage"),
url: url,
home: false,
- group: "涓氬姟椤甸潰",
+ group: that.t("common.businessPage"),
menuKey: that.findMenuKeyByUrl(url)
});
};
@@ -1474,10 +1942,10 @@
}
url = that.resolveViewSrc(param.menuPath);
that.addOrActivateTab({
- title: that.stripTags(param.menuName) || HOME_TAB_CONFIG.title,
+ title: that.stripTags(param.menuName) || that.resolveHomeConfig().title,
url: url,
home: true,
- group: HOME_TAB_CONFIG.group,
+ group: that.resolveHomeConfig().group,
menuKey: that.findMenuKeyByUrl(url)
});
};
--
Gitblit v1.9.1