diff --git a/src/components/common/CommonTab.vue b/src/components/common/CommonTab.vue
index 590f169..20ec487 100644
--- a/src/components/common/CommonTab.vue
+++ b/src/components/common/CommonTab.vue
@@ -10,6 +10,7 @@
icon="el-icon-arrow-left"
:disabled="isLeftDisabled"
>
+
@@ -69,27 +70,43 @@ export default {
mounted() {
this.scrollWrapper = this.$refs.scrollWrapper;
this.$nextTick(() => {
- this.updateButtonStates();
+ // 使用防抖版本以避免重复调用
+ this.debouncedUpdateButtonStates();
});
this.scrollWrapper.addEventListener("scroll", this.handleScroll);
- window.addEventListener("resize", this.updateButtonStates);
+ // 记录引用,便于移除
+ this._resizeHandler = this.debouncedUpdateButtonStates;
+ window.addEventListener("resize", this._resizeHandler);
},
beforeDestroy() {
// 移除事件监听器
if (this.scrollWrapper) {
this.scrollWrapper.removeEventListener("scroll", this.handleScroll);
}
- window.removeEventListener("resize", this.updateButtonStates);
+ if (this._resizeHandler) {
+ window.removeEventListener("resize", this._resizeHandler);
+ }
},
methods: {
+ // 简单防抖实现
+ debounce(func, wait = 100) {
+ let timeout = null;
+ const self = this;
+ return function () {
+ const args = arguments;
+ if (timeout) clearTimeout(timeout);
+ timeout = setTimeout(() => {
+ timeout = null;
+ func.apply(self, args);
+ }, wait);
+ };
+ },
...mapMutations({
close: "closeTab",
}),
handleScroll() {
- // 使用 setTimeout 确保获取到最新的滚动位置
- setTimeout(() => {
- this.updateButtonStates();
- }, 50);
+ // 使用防抖版本避免高频触发
+ this.debouncedUpdateButtonStates();
},
// 标签向左切换
arrowBack() {
@@ -100,9 +117,21 @@ export default {
this.$refs.scrollWrapper.scrollBy({ left: 300, behavior: "smooth" });
},
updateButtonStates() {
- const { scrollLeft, scrollWidth, clientWidth } = this.scrollWrapper;
+ // 如果没有滚动容器或没有标签,直接禁用左右箭头
+ if (!this.scrollWrapper || !this.tags || this.tags.length === 0) {
+ this.isLeftDisabled = true;
+ this.isRightDisabled = true;
+ return;
+ }
+
+ // 防御性读取尺寸,部分浏览器/布局下可能为 0 或 undefined,使用 Number() 保证数值计算
+ const scrollLeft = Number(this.scrollWrapper.scrollLeft || 0);
+ const scrollWidth = Number(this.scrollWrapper.scrollWidth || 0);
+ const clientWidth = Number(this.scrollWrapper.clientWidth || 0);
+
this.isLeftDisabled = scrollLeft <= 0;
- this.isRightDisabled = scrollLeft + clientWidth >= scrollWidth - 1;
+ // 当内容宽度小于等于可视宽度时,右箭头应禁用
+ this.isRightDisabled = scrollWidth <= clientWidth || scrollLeft + clientWidth >= scrollWidth - 1;
},
scrollToActiveTag() {
this.$nextTick(() => {
@@ -134,9 +163,9 @@ export default {
behavior: 'smooth'
});
- // 滚动后更新按钮状态
+ // 滚动后更新按钮状态(防抖)
setTimeout(() => {
- this.updateButtonStates();
+ this.debouncedUpdateButtonStates();
}, 150);
}
});
@@ -149,37 +178,61 @@ export default {
this.handleScroll();
return;
}
+
// 关闭的标签是最右边的话,往左边跳转一个
if (index === length) {
if (this.tags[index - 1]) {
- this.$router.push({ path: this.tags[index - 1].routeUrl });
+ try {
+ this.$router.push(this.tags[index - 1].routeUrl);
+ } catch (e) {
+ this.$router.push({ path: this.tags[index - 1].routeUrl });
+ }
} else {
this.$router.push({ path: "/home" });
}
} else {
// 否则往右边跳转
- this.$router.push({ path: this.tags[index].routeUrl });
+ try {
+ this.$router.push(this.tags[index].routeUrl);
+ } catch (e) {
+ this.$router.push({ path: this.tags[index].routeUrl });
+ }
}
this.handleScroll();
},
changeMenu(item) {
if (item.displayName !== this.$route.name) {
- this.$router.push({ path: item.routeUrl });
- } else {
- // this.$message({
- // message: '请不要重复选择',
- // type: 'error'
- // });
+ // 点击标签页时,该标签页一定存在于tabsList中
+ // 使用 tabsList 中保存的完整 routeUrl(可能包含时间戳),以保持与创建时的 key 一致,避免刷新
+ try {
+ this.$router.push(item.routeUrl);
+ } catch (e) {
+ this.$router.push({ path: item.routeUrl });
+ }
}
this.$nextTick(() => {
this.scrollToActiveTag();
});
},
- async clearControlLabel() {
- await this.$store.commit("clearMenuTab");
- this.$router.push({ path: "/home" });
+ clearControlLabel() {
+ this.$store.commit("clearMenuTab");
+ // 等待 DOM 更新后重置滚动位置并刷新按钮状态
+ this.$nextTick(() => {
+ if (this.$refs.scrollWrapper) {
+ this.$refs.scrollWrapper.scrollLeft = 0;
+ }
+ // // 保证左右箭头状态正确
+ // this.debouncedUpdateButtonStates();
+ this.$router.push({ path: "/home" });
+ });
},
},
+ created() {
+ // 在实例生命周期早期创建防抖函数引用
+ this.debouncedUpdateButtonStates = this.debounce(function () {
+ this.updateButtonStates();
+ }, 100);
+ },
};
@@ -204,7 +257,7 @@ export default {
pointer-events: all;
cursor: pointer;
position: relative;
- margin: 0 64px;
+ margin: 0 64px 0 138px;
}
.scrollWrapper {
display: flex;
@@ -216,7 +269,7 @@ export default {
height: 0;
}
.el-tag {
- margin: 0 5px;
+ margin: 0 60px;
cursor: pointer;
padding: 0 0px 0 10px;
}
@@ -240,4 +293,4 @@ export default {
padding: 0px 5px;
height: 28px;
}
-
+
\ No newline at end of file
diff --git a/src/views/Home.vue b/src/views/Home.vue
index 456e49c..ea80d16 100644
--- a/src/views/Home.vue
+++ b/src/views/Home.vue
@@ -147,7 +147,7 @@
-
+
@@ -217,13 +217,16 @@ export default {
lsysConfig: {
apiurl: "http://10.1.12.140:9529",
softName: "创业体检管理系统"
- }
+ },
};
},
computed: {
...mapState(["window", "dialogWin", "sysConfig"]),
},
created() {
+ // 初始化openedTabs为响应式对象
+ this.$set(this, 'openedTabs', {});
+
let expires_in = parseInt(window.sessionStorage.getItem("expires_in"));
//console.log("dqtime / expires_in",dqtime,expires_in)
if (!expires_in) {
@@ -278,8 +281,41 @@ export default {
// console.log(key, keyPath);
// tree: any, childNodeName: any, idName: any, idVal: any
let node = getTreeNode(this.menuPriv, "treeChildren", "id", key);
- if (node && this.$route.path !== '/' + node.routeUrl){
- this.$store.commit('selectMenu', node)
+ if (!node) return;
+
+ // normalize current path (route.path may start with '/')
+ const currentPath = this.$route.path || '';
+ const targetPath = node.routeUrl && node.routeUrl.startsWith('/') ? node.routeUrl : '/' + node.routeUrl;
+ if (currentPath === targetPath) return;
+
+ if (this.LocalConfig.normal.displayTab) {
+ const exists = this.$store.state.tabsList.some(tab => tab.displayName === node.displayName);
+ if (exists) {
+ // 已在标签页中:使用 tabsList 中保存的 routeUrl(可能包含时间戳),避免刷新
+ const tab = this.$store.state.tabsList.find(t => t.displayName === node.displayName) || {};
+ const routeTo = tab.routeUrl || node.routeUrl || targetPath;
+ // router.push 可以接受字符串(包含查询)或对象
+ try {
+ this.$router.push(routeTo);
+ } catch (e) {
+ this.$router.push({ path: routeTo });
+ }
+ } else {
+ // 不在标签页中:添加时间戳强制刷新,并把带时间戳的完整 routeUrl 存入 tabsList
+ const ts = Date.now();
+ const base = node.routeUrl || targetPath;
+ const sep = base.indexOf('?') > -1 ? '&' : '?';
+ const full = base + sep + 't=' + ts;
+ const tabToAdd = Object.assign({}, node, { routeUrl: full });
+ this.$store.commit('selectMenu', tabToAdd);
+ try {
+ this.$router.push(full);
+ } catch (e) {
+ this.$router.push({ path: full });
+ }
+ }
+ } else {
+ this.$store.commit('selectMenu', node);
this.$router.push({ path: node.routeUrl });
}
},