fix: 修复搜索跳转弹窗无法打开的问题
- AppMain.vue: 将 router-view 的 key 从 route.fullPath 改为 route.path,避免 query 参数变化导致组件销毁重建 - list.vue: watch 中 router.replace 增加 query 非空判断,防止不必要的 URL 清理 - list.vue: handleEdit 的 nextTick 增加 try-catch 防御性保护 - list.vue: 添加 onUnmounted 调试探针
This commit is contained in:
@ -1,7 +1,7 @@
|
|||||||
<template>
|
<template>
|
||||||
<section class="app-main">
|
<section class="app-main">
|
||||||
<router-view v-slot="{ Component, route }">
|
<router-view v-slot="{ Component, route }">
|
||||||
<component :is="Component" :key="route.fullPath" />
|
<component :is="Component" :key="route.path" />
|
||||||
</router-view>
|
</router-view>
|
||||||
</section>
|
</section>
|
||||||
</template>
|
</template>
|
||||||
|
|||||||
@ -711,7 +711,7 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { ref, reactive, onMounted, nextTick, computed, watch } from 'vue';
|
import { ref, reactive, onMounted, onUnmounted, nextTick, computed, watch } from 'vue';
|
||||||
import { Plus, Document, DocumentCopy, Refresh, Setting, Rank, Camera, Download, Bell, CircleCheck, Files, ZoomIn, Delete, Picture, ShoppingCart, Upload } from '@element-plus/icons-vue';
|
import { Plus, Document, DocumentCopy, Refresh, Setting, Rank, Camera, Download, Bell, CircleCheck, Files, ZoomIn, Delete, Picture, ShoppingCart, Upload } from '@element-plus/icons-vue';
|
||||||
import { ElMessage, ElMessageBox, ElLoading } from 'element-plus';
|
import { ElMessage, ElMessageBox, ElLoading } from 'element-plus';
|
||||||
import type { FormInstance, FormRules } from 'element-plus';
|
import type { FormInstance, FormRules } from 'element-plus';
|
||||||
@ -1392,35 +1392,40 @@ const handleEdit = (row: MaterialBaseVO) => {
|
|||||||
dialog.visible = true;
|
dialog.visible = true;
|
||||||
|
|
||||||
nextTick(() => {
|
nextTick(() => {
|
||||||
const data = JSON.parse(JSON.stringify(row));
|
console.log("🔍 nextTick 开始执行...");
|
||||||
Object.assign(form.value, data);
|
try {
|
||||||
|
const data = JSON.parse(JSON.stringify(row));
|
||||||
|
Object.assign(form.value, data);
|
||||||
|
|
||||||
// 深拷贝保存原始数据用于脏检查
|
// 深拷贝保存原始数据用于脏检查
|
||||||
originalForm.value = JSON.parse(JSON.stringify(data));
|
originalForm.value = JSON.parse(JSON.stringify(data));
|
||||||
|
|
||||||
if (data.category) {
|
if (data.category) {
|
||||||
const parts = data.category.split('/');
|
const parts = data.category.split('/');
|
||||||
if (parts.length > 0) {
|
if (parts.length > 0) {
|
||||||
tempCategorySuffix.value = parts.pop() || '';
|
tempCategorySuffix.value = parts.pop() || '';
|
||||||
tempCategoryPrefix.value = parts;
|
tempCategoryPrefix.value = parts;
|
||||||
|
} else {
|
||||||
|
tempCategoryPrefix.value = [];
|
||||||
|
tempCategorySuffix.value = data.category;
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
tempCategoryPrefix.value = [];
|
tempCategoryPrefix.value = [];
|
||||||
tempCategorySuffix.value = data.category;
|
tempCategorySuffix.value = '';
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
tempCategoryPrefix.value = [];
|
const images = row.generalImage || [];
|
||||||
tempCategorySuffix.value = '';
|
const manuals = row.generalManual || [];
|
||||||
|
|
||||||
|
// 只显示真正的上传文件,备注字段已由 Object.assign 自动回显到 form.productImageRemark / form.manualLinkRemark
|
||||||
|
const imgFiles = images.filter(u => isInternalFile(u));
|
||||||
|
const manualFiles = manuals.filter(u => isInternalFile(u));
|
||||||
|
|
||||||
|
fileListImage.value = imgFiles.map(url => ({ name: url.split('/').pop(), url: getImageUrl(url) }));
|
||||||
|
fileListManual.value = manualFiles.map(url => ({ name: url.split('/').pop(), url: getImageUrl(url) }));
|
||||||
|
} catch (error) {
|
||||||
|
console.error("🚨 抓到凶手了!nextTick 内部执行崩溃:", error);
|
||||||
}
|
}
|
||||||
|
|
||||||
const images = row.generalImage || [];
|
|
||||||
const manuals = row.generalManual || [];
|
|
||||||
|
|
||||||
// 只显示真正的上传文件,备注字段已由 Object.assign 自动回显到 form.productImageRemark / form.manualLinkRemark
|
|
||||||
const imgFiles = images.filter(u => isInternalFile(u));
|
|
||||||
const manualFiles = manuals.filter(u => isInternalFile(u));
|
|
||||||
|
|
||||||
fileListImage.value = imgFiles.map(url => ({ name: url.split('/').pop(), url: getImageUrl(url) }));
|
|
||||||
fileListManual.value = manualFiles.map(url => ({ name: url.split('/').pop(), url: getImageUrl(url) }));
|
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -1963,8 +1968,10 @@ watch(
|
|||||||
queryParams.keyword = newKeyword as string;
|
queryParams.keyword = newKeyword as string;
|
||||||
queryParams.searchField = 'all';
|
queryParams.searchField = 'all';
|
||||||
getList();
|
getList();
|
||||||
// 清理 URL 参数,防止刷新后重复触发搜索
|
// 清理 URL 参数,防止刷新后重复触发搜索(仅当 URL 确实带参时才清理,避免触发组件 key 变化)
|
||||||
router.replace({ path: route.path, query: {} });
|
if (Object.keys(route.query).length > 0) {
|
||||||
|
router.replace({ path: route.path, query: {} });
|
||||||
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{ immediate: true }
|
{ immediate: true }
|
||||||
@ -2010,6 +2017,10 @@ onMounted(() => {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
onUnmounted(() => {
|
||||||
|
console.warn("💀 警告:当前 list.vue 组件被销毁了!如果你看到这条日志,说明 router.replace 把页面重置了!");
|
||||||
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style scoped>
|
<style scoped>
|
||||||
|
|||||||
Reference in New Issue
Block a user