检验项目设置-》套餐管理:点击【新增】跳转至套餐设置界面系统未进行初始化新增模式界面数据
212
检验项目设置-》套餐管理:点击行【编辑】跳转至套餐设置编辑模式该行的套餐数据未正确引入
213
检验项目设置-》套餐管理:点击行【查看】跳转至套餐设置界面套餐内容显示错误并且未进入只读模式
This commit is contained in:
2026-03-27 16:39:41 +08:00
parent e2e5999276
commit 6d23d36a9c
2 changed files with 99 additions and 85 deletions

View File

@@ -813,7 +813,8 @@ import {
updateInspectionPackage,
getInspectionPackage,
listInspectionPackageDetails,
saveInspectionPackageDetails
saveInspectionPackageDetails,
batchSaveInspectionPackageDetails
} from '@/api/system/inspectionPackage';
import { getTenantPage } from '@/api/system/tenant';
import {deptTreeSelect} from '@/api/system/user';
@@ -1470,6 +1471,8 @@ const packageItems = ref([]);
const packageMode = ref('add');
// 当前编辑的套餐ID用于编辑和查看模式
const currentPackageId = ref(null);
// 正在从后端加载套餐数据的标志,加载期间跳过 calculateAmounts 防止覆盖后端金额
const isLoadingPackage = ref(false);
// 是否为查看模式(只读)
const isViewMode = computed(() => packageMode.value === 'view');
@@ -2364,6 +2367,10 @@ const savePackageData = async (basicInfo, detailData) => {
if (isEditMode) {
// 编辑模式调用更新API
basicResponse = await updateInspectionPackage(basicInfo);
if (basicResponse.code !== 200) {
loading.close();
throw new Error(basicResponse.msg || '更新基本信息失败');
}
packageId = currentPackageId.value;
} else {
// 新增模式调用新增API
@@ -2390,29 +2397,41 @@ const savePackageData = async (basicInfo, detailData) => {
// 验证套餐ID是否存在
if (!packageId) {
loading.close();
console.error('无法从响应中获取套餐ID完整响应:', basicResponse);
throw new Error('保存成功但未返回套餐ID。请检查后端接口是否正确返回了packageId或id字段');
}
}
// 2. 分别保存每个明细数据到明细表,并将后端返回的 id 回填到 packageItems
for (let i = 0; i < detailData.length; i++) {
const detailItem = {
...detailData[i],
packageId: packageId
// 2. 保存明细数据:编辑模式用批量接口(先删旧后插新),新增模式逐条新增
if (isEditMode) {
// 编辑模式:调用批量保存接口,后端会先删除旧明细再插入新明细
const batchPayload = {
basicInformationId: packageId,
details: detailData.map(item => ({ ...item, packageId: packageId }))
};
const detailResponse = await saveInspectionPackageDetails(detailItem);
if (detailResponse.code !== 200) {
const batchResponse = await batchSaveInspectionPackageDetails(batchPayload);
if (batchResponse.code !== 200) {
loading.close();
throw new Error(`保存第 ${i + 1} 个明细项失败: ${detailResponse.msg || '未知错误'}`);
throw new Error(batchResponse.msg || '保存明细数据失败');
}
} else {
// 新增模式:逐条保存并回填后端生成的明细 id
for (let i = 0; i < detailData.length; i++) {
const detailItem = {
...detailData[i],
packageId: packageId
};
// 回填后端生成的明细 id防止取消编辑时被误判为新增行
// 后端返回字段名是 detailId见 InspectionPackageDetail.java
if (detailResponse.data && (detailResponse.data.detailId || detailResponse.data.id)) {
packageItems.value[i].id = detailResponse.data.detailId || detailResponse.data.id;
const detailResponse = await saveInspectionPackageDetails(detailItem);
if (detailResponse.code !== 200) {
loading.close();
throw new Error(`保存第 ${i + 1} 个明细项失败: ${detailResponse.msg || '未知错误'}`);
}
// 回填后端生成的明细 id防止取消编辑时被误判为新增行
if (detailResponse.data && (detailResponse.data.detailId || detailResponse.data.id)) {
packageItems.value[i].id = detailResponse.data.detailId || detailResponse.data.id;
}
}
}
@@ -2421,8 +2440,14 @@ const savePackageData = async (basicInfo, detailData) => {
ElMessage.success('保存成功');
// 保存成功后重置表单
doResetForm();
if (isEditMode) {
// 编辑模式:重新加载最新数据,保持在编辑页面
loadInspectionPackage(String(packageId));
} else {
// 新增模式:保存成功后重置表单
doResetForm();
}
} catch (error) {
// 确保在错误时也关闭loading
@@ -2495,7 +2520,7 @@ const doResetForm = () => {
// 清空明细数据
packageItems.value = [];
// 重置模式为新增
// 重置为新增模式(仅在外部未指定 mode 时,由调用方负责设置 packageMode
packageMode.value = 'add';
currentPackageId.value = null;
@@ -2527,6 +2552,9 @@ const loadInspectionPackage = async (packageId) => {
const basicData = basicResponse.data;
const detailData = detailResponse.data || [];
// 【关键】暂停 packageItems 的 watch防止赋值时触发 calculateAmounts 覆盖后端返回的金额
isLoadingPackage.value = true;
// 填充基本信息
packageLevel.value = basicData.packageLevel;
packageName.value = basicData.packageName;
@@ -2536,8 +2564,8 @@ const loadInspectionPackage = async (packageId) => {
showPackageName.value = basicData.showPackageName !== false;
generateServiceFee.value = basicData.generateServiceFee !== false;
enablePackagePrice.value = basicData.enablePackagePrice !== false;
packageAmount.value = basicData.packageAmount || 0.00;
serviceFee.value = basicData.serviceFee || 0.00;
packageAmount.value = parseFloat(basicData.packageAmount || 0);
serviceFee.value = parseFloat(basicData.serviceFee || 0);
selectedLisGroup.value = basicData.lisGroup || '';
bloodVolume.value = basicData.bloodVolume || '';
remarks.value = basicData.remarks || '';
@@ -2559,11 +2587,15 @@ const loadInspectionPackage = async (packageId) => {
origin: item.origin || ''
}));
// 恢复监听
isLoadingPackage.value = false;
loading.close();
ElMessage.success('套餐数据加载成功');
} catch (error) {
console.error('加载套餐数据失败:', error);
isLoadingPackage.value = false;
ElMessage.error(error.message || '加载套餐数据失败');
}
};
@@ -2597,47 +2629,43 @@ watch(activity_category_code, (newVal) => {
}, { immediate: true });
/**
* 关键修复:
* 从“套餐管理”跳转到这里时,通常只是改变 querypackageId/mode/tab组件不会重新挂载
* 所以仅靠 onMounted 读取一次 query 会导致“查看/修改”出现空白,刷新才正常。
* 这里监听 query 变化,自动切换 tab 并加载套餐数据。
* 统一监听 query 变化,处理 tab 切换和套餐数据加载。
* 使用 watch(route) 深度监听,确保在 keep-alive 场景下同路由 query 变化也能响应。
*/
watch(
() => route.query.tab,
(tab) => {
if (tab === '0' || tab === '1' || tab === '2') {
activeNav.value = parseInt(String(tab));
}
},
{ immediate: true }
);
const applyRouteForPackage = async (query) => {
const tab = query?.tab;
const packageId = query?.packageId;
const mode = query?.mode || 'add';
// 设置当前模式和套餐ID
packageMode.value = mode;
currentPackageId.value = packageId ? String(packageId) : null;
// 如果是新增模式,重置表单
// 先切换 tab
if (tab === '0' || tab === '1' || tab === '2') {
activeNav.value = parseInt(tab);
};
// 只有 tab=2套餐设置才处理套餐数据
if (activeNav.value !== 2) return;
// 新增模式:重置表单,然后明确设置 mode
if (mode === 'add' || !packageId) {
activeNav.value = 2;
doResetForm();
doResetForm(); // 内部会设 packageMode='add',符合预期
return;
}
activeNav.value = 2;
// 编辑/查看模式:先设置 mode 和 ID再加载数据
packageMode.value = mode;
currentPackageId.value = String(packageId);
await nextTick();
loadInspectionPackage(String(packageId));
};
// 监听整个 route.query确保任何 query 变化tab/packageId/mode都能触发
watch(
() => route.query.packageId,
async () => {
await applyRouteForPackage(route.query);
() => route.query,
(newQuery) => {
applyRouteForPackage(newQuery);
},
{ immediate: true, flush: 'post' }
{ immediate: true, deep: true }
);
// 兜底:如果该页面被 keep-alive 缓存,从别的页面返回时不会触发 onMounted
@@ -2652,11 +2680,14 @@ onBeforeRouteUpdate((to) => {
// 监听生成服务费选项变更
watch(generateServiceFee, (newVal) => {
if (isLoadingPackage.value) return;
calculateAmounts();
});
// 监听套餐项目变化
watch(packageItems, (newVal) => {
// 加载期间跳过计算,防止覆盖后端返回的金额
if (isLoadingPackage.value) return;
calculateAmounts();
}, { deep: true });
// 样本类型数据