@ -711,7 +711,7 @@
</template>
<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 { ElMessage, ElMessageBox, ElLoading } from 'element-plus';
import type { FormInstance, FormRules } from 'element-plus';
@ -1392,35 +1392,40 @@ const handleEdit = (row: MaterialBaseVO) => {
dialog.visible = true;
nextTick(() => {
const data = JSON.parse(JSON.stringify(row) );
Object.assign(form.value, data);
console.log(" 🔍 nextTick 开始执行 ... " );
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) {
const parts = data.category.split('/');
if (parts.length > 0) {
tempCategorySuffix.value = parts.pop() || '';
tempCategoryPrefix.value = parts;
if (data.category) {
const parts = data.category.split('/');
if (parts.length > 0) {
tempCategorySuffix.value = parts.pop() || '';
tempCategoryPrefix.value = parts;
} else {
tempCategoryPrefix.value = [];
tempCategorySuffix.value = data.category;
}
} else {
tempCategoryPrefix.value = [];
tempCategorySuffix.value = data.category ;
tempCategorySuffix.value = '' ;
}
} else {
tempCategoryPrefix.value = [];
tempCategorySuffix.value = '' ;
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) }));
} 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.searchField = 'all';
getList();
// 清理 URL 参数,防止刷新后重复触发搜索
router . replace ( { path : route . path , query : { } } ) ;
// 清理 URL 参数,防止刷新后重复触发搜索(仅当 URL 确实带参时才清理,避免触发组件 key 变化)
if (Object.keys(route.query).length > 0) {
router.replace({ path: route.path, query: {} });
}
}
},
{ immediate: true }
@ -2010,6 +2017,10 @@ onMounted(() => {
});
}
});
onUnmounted(() => {
console.warn(" 💀 警告 : 当前 list . vue 组件被销毁了 ! 如果你看到这条日志 , 说明 router . replace 把页面重置了 ! " ) ;
} ) ;
< / script >
< style scoped >