|
|
@@ -262,9 +262,12 @@ export const useKeepAliveStore = defineStore({
|
|
|
!isReplace && tabStore.addTabs(tabsParams);
|
|
|
!isReplace && to.meta.isKeepAlive && this.addKeepAliveName(to);
|
|
|
},
|
|
|
- computedKeepAliveNamePro(to, from) {
|
|
|
+ async computedKeepAliveNamePro(to, from) {
|
|
|
const tabStore = useTabsStore();
|
|
|
+ const tabsMenuList = [...tabStore.tabsMenuList];
|
|
|
+ let isReplace = false;
|
|
|
|
|
|
+ // --- 生成 tab 参数 ---
|
|
|
const tabsParams = {
|
|
|
icon: to.meta.icon as string,
|
|
|
title: to.meta.title as string,
|
|
|
@@ -275,252 +278,136 @@ export const useKeepAliveStore = defineStore({
|
|
|
query: to.query
|
|
|
};
|
|
|
|
|
|
- // 如果需要锁定单据,添加锁定相关参数
|
|
|
- if (to.meta.needLock && Number(to.query.id)) {
|
|
|
+ if (to.meta.needLock && Number(to.query?.id)) {
|
|
|
tabsParams["needLock"] = to.meta.needLock;
|
|
|
tabsParams["keyword"] = String(to.meta.billtype);
|
|
|
tabsParams["billid"] = Number(to.query.id);
|
|
|
tabsParams["billcode"] = String(to.query.code);
|
|
|
}
|
|
|
|
|
|
- let isReplace = false;
|
|
|
- const tabsMenuList = [...tabStore.tabsMenuList];
|
|
|
-
|
|
|
- // 判断是否为同一单据的单据编码和单据类型
|
|
|
- const getBillCode = route => {
|
|
|
- return route?.query?.code || "";
|
|
|
- };
|
|
|
+ // --- 工具函数 ---
|
|
|
+ const getBillCode = route => route?.query?.code || "";
|
|
|
const getBillType = route => {
|
|
|
const pathMatch = route?.fullPath?.match(/\/([a-zA-Z]+)\/(detail|edit|copy|index)/);
|
|
|
return pathMatch ? pathMatch[1] : "";
|
|
|
- };
|
|
|
+ }; // 改为 meta 管理类型更可靠
|
|
|
+ const isSameBill = (code1, type1, code2, type2) =>
|
|
|
+ !!code1 && !!code2 && code1 === code2 && !!type1 && !!type2 && type1 === type2;
|
|
|
|
|
|
const toBillCode = getBillCode(to);
|
|
|
const fromBillCode = getBillCode(from);
|
|
|
const toBillType = getBillType(to);
|
|
|
const fromBillType = getBillType(from);
|
|
|
|
|
|
- // 判断是否为相同类型的单据(同时比较单据编码和单据类型)
|
|
|
- const isSameBill = (code1, type1, code2, type2) => {
|
|
|
- return code1 && code2 && code1 === code2 && type1 && type2 && type1 === type2;
|
|
|
- };
|
|
|
-
|
|
|
- console.log("computedKeepAliveNamePro 路由分析:", {
|
|
|
- to: to.fullPath,
|
|
|
- from: from?.fullPath,
|
|
|
- toBillCode,
|
|
|
- toBillType,
|
|
|
- fromBillCode,
|
|
|
- fromBillType,
|
|
|
- isSameBillType: isSameBill(toBillCode, toBillType, fromBillCode, fromBillType)
|
|
|
- });
|
|
|
-
|
|
|
- // 情况1: 列表页跳转到详情页 (/list -> /detail)
|
|
|
- const isListToDetail =
|
|
|
- (!from || from.fullPath.includes("/index")) && (to.fullPath.includes("/detail?") || to.fullPath.includes("/detail/"));
|
|
|
-
|
|
|
- if (isListToDetail && toBillCode) {
|
|
|
- // 查找是否有相同单据类型和单据编码的编辑页
|
|
|
- const editTabIndex = tabsMenuList.findIndex(item => {
|
|
|
+ // --- 查找 tab 工具函数 ---
|
|
|
+ const findTabIndex = (tabType: "edit" | "detail" | "copy") => {
|
|
|
+ return tabsMenuList.findIndex(item => {
|
|
|
const itemBillCode = getBillCode(item);
|
|
|
const itemBillType = getBillType(item);
|
|
|
- return (
|
|
|
- isSameBill(itemBillCode, itemBillType, toBillCode, toBillType) &&
|
|
|
- (item.path.includes("/edit?") || item.path.includes("/edit/"))
|
|
|
- );
|
|
|
+ const isTypeMatch =
|
|
|
+ (tabType === "edit" && item.path.includes("/edit")) ||
|
|
|
+ (tabType === "detail" && item.path.includes("/detail")) ||
|
|
|
+ (tabType === "copy" && item.path.includes("/copy"));
|
|
|
+ return isSameBill(itemBillCode, itemBillType, toBillCode, toBillType) && isTypeMatch;
|
|
|
});
|
|
|
+ };
|
|
|
|
|
|
- if (editTabIndex > -1) {
|
|
|
- // 保存被替换的编辑页信息
|
|
|
- const oldEditTab = tabsMenuList[editTabIndex];
|
|
|
-
|
|
|
- // 替换编辑页为详情页
|
|
|
- console.log("列表页->详情页: 替换编辑页", oldEditTab.path, "=>", to.fullPath);
|
|
|
- tabsMenuList[editTabIndex] = tabsParams;
|
|
|
- tabStore.setTabs(tabsMenuList);
|
|
|
-
|
|
|
- // 移除编辑页的 keepAlive 缓存(removeKeepAliveName 已包含解锁逻辑)
|
|
|
- console.log("情况1解锁检查:", {
|
|
|
- oldEditTab: {
|
|
|
- path: oldEditTab.path,
|
|
|
- needLock: oldEditTab.needLock,
|
|
|
- billid: oldEditTab.billid,
|
|
|
- keyword: oldEditTab.keyword,
|
|
|
- billcode: oldEditTab.billcode
|
|
|
- }
|
|
|
- });
|
|
|
- this.removeKeepAliveName(oldEditTab);
|
|
|
+ // --- 替换 tab 并管理 keep-alive ---
|
|
|
+ const replaceTab = (index: number) => {
|
|
|
+ const oldTab = tabsMenuList[index];
|
|
|
+ tabsMenuList[index] = tabsParams;
|
|
|
+ tabStore.setTabs(tabsMenuList);
|
|
|
|
|
|
- isReplace = true;
|
|
|
- to.meta.isKeepAlive && this.addKeepAliveName(to);
|
|
|
- to.meta.isKeepAlive && this.updateKeepAliveName(to);
|
|
|
+ if (oldTab?.name) {
|
|
|
+ this.removeKeepAliveName(oldTab); // 移除旧缓存
|
|
|
}
|
|
|
- }
|
|
|
-
|
|
|
- // 情况2: 详情页跳转到编辑页 (/detail -> /edit)
|
|
|
- const isDetailToEdit =
|
|
|
- from &&
|
|
|
- (from.fullPath.includes("/detail?") || from.fullPath.includes("/detail/")) &&
|
|
|
- (to.fullPath.includes("/edit?") || to.fullPath.includes("/edit/")) &&
|
|
|
- isSameBill(toBillCode, toBillType, fromBillCode, fromBillType);
|
|
|
|
|
|
- if (isDetailToEdit) {
|
|
|
- // 查找是否有相同单据类型和单据编码的详情页
|
|
|
- const detailTabIndex = tabsMenuList.findIndex(item => {
|
|
|
- const itemBillCode = getBillCode(item);
|
|
|
- const itemBillType = getBillType(item);
|
|
|
- const isDetailTab = item.path.includes("/detail?") || item.path.includes("/detail/");
|
|
|
- console.log("检查tab:", {
|
|
|
- itemPath: item.path,
|
|
|
- itemBillCode,
|
|
|
- itemBillType,
|
|
|
- toBillCode,
|
|
|
- toBillType,
|
|
|
- isDetailTab,
|
|
|
- match: isSameBill(itemBillCode, itemBillType, toBillCode, toBillType) && isDetailTab
|
|
|
- });
|
|
|
- return isSameBill(itemBillCode, itemBillType, toBillCode, toBillType) && isDetailTab;
|
|
|
- });
|
|
|
-
|
|
|
- console.log("找到的详情页索引:", detailTabIndex);
|
|
|
- if (detailTabIndex > -1) {
|
|
|
- // 替换详情页为编辑页
|
|
|
- console.log("详情页->编辑页: 替换详情页", tabsMenuList[detailTabIndex].path, "=>", to.fullPath);
|
|
|
- tabsMenuList[detailTabIndex] = tabsParams;
|
|
|
- tabStore.setTabs(tabsMenuList);
|
|
|
- isReplace = true;
|
|
|
- to.meta.isKeepAlive && this.addKeepAliveName(to);
|
|
|
- to.meta.isKeepAlive && this.updateKeepAliveName(to);
|
|
|
+ if (to.meta.isKeepAlive) {
|
|
|
+ this.addKeepAliveName(to);
|
|
|
+ this.updateKeepAliveName(to);
|
|
|
}
|
|
|
- }
|
|
|
|
|
|
- // 情况3: 编辑页跳转到详情页 (/edit -> /detail),需要解锁单据
|
|
|
- const isEditToDetailPro =
|
|
|
- from &&
|
|
|
- (from.fullPath.includes("/edit?") || from.fullPath.includes("/edit/")) &&
|
|
|
- (to.fullPath.includes("/detail?") || to.fullPath.includes("/detail/")) &&
|
|
|
- isSameBill(toBillCode, toBillType, fromBillCode, fromBillType);
|
|
|
-
|
|
|
- if (isEditToDetailPro) {
|
|
|
- console.log("编辑页->详情页: 解锁单据", fromBillType, fromBillCode);
|
|
|
- // 查找是否有相同单据类型和单据编码的编辑页
|
|
|
- const editTabIndex = tabsMenuList.findIndex(item => {
|
|
|
- const itemBillCode = getBillCode(item);
|
|
|
- const itemBillType = getBillType(item);
|
|
|
- const isEditTab = item.path.includes("/edit?") || item.path.includes("/edit/");
|
|
|
- console.log("检查tab:", {
|
|
|
- itemPath: item.path,
|
|
|
- itemBillCode,
|
|
|
- itemBillType,
|
|
|
- fromBillCode,
|
|
|
- fromBillType,
|
|
|
- isEditTab,
|
|
|
- match: isSameBill(itemBillCode, itemBillType, fromBillCode, fromBillType) && isEditTab
|
|
|
- });
|
|
|
- return isSameBill(itemBillCode, itemBillType, fromBillCode, fromBillType) && isEditTab;
|
|
|
- });
|
|
|
+ isReplace = true;
|
|
|
+ };
|
|
|
|
|
|
- console.log("找到的编辑页索引:", editTabIndex);
|
|
|
- if (editTabIndex > -1) {
|
|
|
- // 替换编辑页为详情页
|
|
|
- console.log("编辑页->详情页: 替换编辑页", tabsMenuList[editTabIndex].path, "=>", to.fullPath);
|
|
|
- tabsMenuList[editTabIndex] = tabsParams;
|
|
|
- tabStore.setTabs(tabsMenuList);
|
|
|
-
|
|
|
- // 移除编辑页的 keepAlive 缓存
|
|
|
- this.removeKeepAliveName(from);
|
|
|
-
|
|
|
- // 手动解锁单据(因为 from 路由对象可能缺少锁定属性,需要单独处理)
|
|
|
- if (from.meta?.needLock && from.query?.id) {
|
|
|
- UnLockBill({
|
|
|
- keyword: String(from.meta.billtype),
|
|
|
- billid: Number(from.query.id),
|
|
|
- billcode: String(from.query.code)
|
|
|
- }).catch(err => {
|
|
|
- console.warn("edit->detail 解锁失败:", err);
|
|
|
+ // --- 解锁单据 ---
|
|
|
+ const unlockBill = async route => {
|
|
|
+ if (route?.meta?.needLock && route?.query?.id) {
|
|
|
+ try {
|
|
|
+ await UnLockBill({
|
|
|
+ keyword: String(route.meta.billtype),
|
|
|
+ billid: Number(route.query.id),
|
|
|
+ billcode: String(route.query.code)
|
|
|
});
|
|
|
+ } catch (err) {
|
|
|
+ console.warn("解锁单据失败:", err);
|
|
|
}
|
|
|
+ }
|
|
|
+ };
|
|
|
+
|
|
|
+ // --- 逻辑判断 ---
|
|
|
+ const fromName = from?.name || "";
|
|
|
|
|
|
- isReplace = true;
|
|
|
- to.meta.isKeepAlive && this.addKeepAliveName(to);
|
|
|
- to.meta.isKeepAlive && this.updateKeepAliveName(to);
|
|
|
+ // 情况1: 列表 -> 详情
|
|
|
+ if ((!from || fromNameIncludes(from, "/index")) && toNameIncludes(to, "/detail") && toBillCode) {
|
|
|
+ const editTabIndex = findTabIndex("edit");
|
|
|
+ if (editTabIndex > -1) {
|
|
|
+ await unlockBill(tabsMenuList[editTabIndex]);
|
|
|
+ replaceTab(editTabIndex);
|
|
|
}
|
|
|
}
|
|
|
|
|
|
- // 情况4: 列表页跳转到编辑页 (/list -> /edit),需要替换相同单据的详情页
|
|
|
- const isListToEdit =
|
|
|
- (!from || from.fullPath.includes("/index")) && (to.fullPath.includes("/edit?") || to.fullPath.includes("/edit/"));
|
|
|
- if (isListToEdit && toBillCode) {
|
|
|
- // 查找是否有相同单据类型和单据编码的详情页
|
|
|
- const detailTabIndex = tabsMenuList.findIndex(item => {
|
|
|
- const itemBillCode = getBillCode(item);
|
|
|
- const itemBillType = getBillType(item);
|
|
|
- const isDetailTab = item.path.includes("/detail?") || item.path.includes("/detail/");
|
|
|
- console.log("检查tab:", {
|
|
|
- itemPath: item.path,
|
|
|
- itemBillCode,
|
|
|
- itemBillType,
|
|
|
- toBillCode,
|
|
|
- toBillType,
|
|
|
- isDetailTab,
|
|
|
- match: isSameBill(itemBillCode, itemBillType, toBillCode, toBillType) && isDetailTab
|
|
|
- });
|
|
|
- return isSameBill(itemBillCode, itemBillType, toBillCode, toBillType) && isDetailTab;
|
|
|
- });
|
|
|
+ // 情况2: 详情 -> 编辑
|
|
|
+ if (
|
|
|
+ fromName &&
|
|
|
+ toNameIncludes(to, "/edit") &&
|
|
|
+ fromNameIncludes(from, "/detail") &&
|
|
|
+ isSameBill(toBillCode, toBillType, fromBillCode, fromBillType)
|
|
|
+ ) {
|
|
|
+ const detailTabIndex = findTabIndex("detail");
|
|
|
+ if (detailTabIndex > -1) replaceTab(detailTabIndex);
|
|
|
+ }
|
|
|
|
|
|
- console.log("找到的详情页索引:", detailTabIndex);
|
|
|
- if (detailTabIndex > -1) {
|
|
|
- // 替换详情页为编辑页
|
|
|
- console.log("列表页->编辑页: 替换详情页", tabsMenuList[detailTabIndex].path, "=>", to.fullPath);
|
|
|
- tabsMenuList[detailTabIndex] = tabsParams;
|
|
|
- tabStore.setTabs(tabsMenuList);
|
|
|
- isReplace = true;
|
|
|
- to.meta.isKeepAlive && this.addKeepAliveName(to);
|
|
|
- to.meta.isKeepAlive && this.updateKeepAliveName(to);
|
|
|
+ // 情况3: 编辑 -> 详情
|
|
|
+ if (
|
|
|
+ fromName &&
|
|
|
+ fromNameIncludes(from, "/edit") &&
|
|
|
+ toNameIncludes(to, "/detail") &&
|
|
|
+ isSameBill(toBillCode, toBillType, fromBillCode, fromBillType)
|
|
|
+ ) {
|
|
|
+ const editTabIndex = findTabIndex("edit");
|
|
|
+ if (editTabIndex > -1) {
|
|
|
+ await unlockBill(from); // 保证顺序
|
|
|
+ replaceTab(editTabIndex);
|
|
|
}
|
|
|
}
|
|
|
|
|
|
- // 情况5: 复制页跳转到详情页 (/copy -> /detail),复制保存后生成新单据
|
|
|
- // 需要将复制tab替换为新单据的详情tab
|
|
|
- const isCopyToDetail =
|
|
|
- from &&
|
|
|
- (from.fullPath.includes("/copy?") || from.fullPath.includes("/copy/")) &&
|
|
|
- (to.fullPath.includes("/detail?") || to.fullPath.includes("/detail/"));
|
|
|
-
|
|
|
- if (isCopyToDetail) {
|
|
|
- console.log("复制页->详情页: 替换复制tab为新单据详情tab", {
|
|
|
- from: from?.fullPath,
|
|
|
- to: to.fullPath,
|
|
|
- fromBillCode,
|
|
|
- toBillCode,
|
|
|
- note: "虽然单据编码不同,但需要替换当前复制页tab"
|
|
|
- });
|
|
|
-
|
|
|
- // 查找复制页tab的索引
|
|
|
- const copyTabIndex = tabsMenuList.findIndex(item => {
|
|
|
- const isCopyTab = item.path.includes("/copy?") || item.path.includes("/copy/");
|
|
|
- // 通过from.fullPath匹配当前正在跳转的复制页
|
|
|
- return isCopyTab && item.path === from.fullPath;
|
|
|
- });
|
|
|
+ // 情况4: 列表 -> 编辑
|
|
|
+ if ((!from || fromNameIncludes(from, "/index")) && toNameIncludes(to, "/edit") && toBillCode) {
|
|
|
+ const detailTabIndex = findTabIndex("detail");
|
|
|
+ if (detailTabIndex > -1) replaceTab(detailTabIndex);
|
|
|
+ }
|
|
|
|
|
|
- console.log("找到的复制页索引:", copyTabIndex);
|
|
|
- if (copyTabIndex > -1) {
|
|
|
- // 替换复制页为新单据详情页
|
|
|
- console.log("复制页->详情页: 替换复制页", tabsMenuList[copyTabIndex].path, "=>", to.fullPath);
|
|
|
- tabsMenuList[copyTabIndex] = tabsParams;
|
|
|
- tabStore.setTabs(tabsMenuList);
|
|
|
- isReplace = true;
|
|
|
- to.meta.isKeepAlive && this.addKeepAliveName(to);
|
|
|
- to.meta.isKeepAlive && this.updateKeepAliveName(to);
|
|
|
- } else {
|
|
|
- console.log("未找到复制页tab,将添加新tab");
|
|
|
- }
|
|
|
+ // 情况5: 复制 -> 详情
|
|
|
+ if (fromNameIncludes(from, "/copy") && toNameIncludes(to, "/detail") && to.query?.fromCopySave) {
|
|
|
+ const copyTabIndex = tabsMenuList.findIndex(item => item.path === from.fullPath);
|
|
|
+ if (copyTabIndex > -1) replaceTab(copyTabIndex);
|
|
|
}
|
|
|
|
|
|
- // 如果没有发生替换,则正常添加tab
|
|
|
+ // 默认添加 tab
|
|
|
if (!isReplace) {
|
|
|
tabStore.addTabs(tabsParams);
|
|
|
- to.meta.isKeepAlive && this.addKeepAliveName(to);
|
|
|
+ if (to.meta.isKeepAlive) {
|
|
|
+ this.addKeepAliveName(to);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ // --- 辅助函数: 判断 route.name 类型 ---
|
|
|
+ function toNameIncludes(route, type: string) {
|
|
|
+ return route?.fullPath?.toString().toLowerCase().includes(type);
|
|
|
+ }
|
|
|
+ function fromNameIncludes(route, type: string) {
|
|
|
+ return route?.fullPath?.toString().toLowerCase().includes(type);
|
|
|
}
|
|
|
}
|
|
|
}
|