Merge remote-tracking branch 'origin/develop' into develop
This commit is contained in:
@@ -146,7 +146,7 @@
|
|||||||
v-model="scope.row.doseQuantity"
|
v-model="scope.row.doseQuantity"
|
||||||
@input="
|
@input="
|
||||||
(value) => {
|
(value) => {
|
||||||
scope.row.dose = value / scope.row.unitConversionRatio;
|
scope.row.dose = value * scope.row.unitConversionRatio;
|
||||||
}
|
}
|
||||||
"
|
"
|
||||||
/>
|
/>
|
||||||
@@ -164,7 +164,7 @@
|
|||||||
v-model="scope.row.dose"
|
v-model="scope.row.dose"
|
||||||
@input="
|
@input="
|
||||||
(value) => {
|
(value) => {
|
||||||
scope.row.doseQuantity = value * scope.row.unitConversionRatio;
|
scope.row.doseQuantity = value / scope.row.unitConversionRatio;
|
||||||
}
|
}
|
||||||
"
|
"
|
||||||
/>
|
/>
|
||||||
|
|||||||
@@ -227,7 +227,7 @@
|
|||||||
v-model="scope.row.doseQuantity"
|
v-model="scope.row.doseQuantity"
|
||||||
@input="
|
@input="
|
||||||
(value) => {
|
(value) => {
|
||||||
scope.row.dose = value / scope.row.unitConversionRatio;
|
scope.row.dose = value * scope.row.unitConversionRatio;
|
||||||
}
|
}
|
||||||
"
|
"
|
||||||
/>
|
/>
|
||||||
@@ -238,7 +238,7 @@
|
|||||||
v-model="scope.row.dose"
|
v-model="scope.row.dose"
|
||||||
@input="
|
@input="
|
||||||
(value) => {
|
(value) => {
|
||||||
scope.row.doseQuantity = value * scope.row.unitConversionRatio;
|
scope.row.doseQuantity = value / scope.row.unitConversionRatio;
|
||||||
}
|
}
|
||||||
"
|
"
|
||||||
/>
|
/>
|
||||||
|
|||||||
@@ -268,14 +268,14 @@
|
|||||||
<template #default="{ row }">
|
<template #default="{ row }">
|
||||||
<template v-if="editingRowId === row.id">
|
<template v-if="editingRowId === row.id">
|
||||||
<el-select v-model="row.feePackageId" placeholder="选择费用套餐" size="small" style="width: 100%;" filterable clearable
|
<el-select v-model="row.feePackageId" placeholder="选择费用套餐" size="small" style="width: 100%;" filterable clearable
|
||||||
@change="(val) => { const pkg = feePackages.find(p => p.id === val); row.package = pkg ? pkg.packageName : ''; updateAmountFromPackage(row); }"
|
@change="(val) => { const pkg = feePackages.find(p => String(p.id) === String(val)); row.package = pkg ? pkg.packageName : ''; updateAmountFromPackage(row); }"
|
||||||
@visible-change="(visible) => { if (visible && feePackages.length === 0) getFeePackages() }">
|
@visible-change="(visible) => { if (visible && feePackages.length === 0) getFeePackages() }">
|
||||||
<el-option label="选择费用套餐" value="" />
|
<el-option label="选择费用套餐" value="" />
|
||||||
<el-option
|
<el-option
|
||||||
v-for="pkg in feePackages"
|
v-for="pkg in feePackages"
|
||||||
:key="pkg.id"
|
:key="pkg.id"
|
||||||
:label="pkg.packageName"
|
:label="pkg.packageName"
|
||||||
:value="pkg.id"
|
:value="String(pkg.id)"
|
||||||
/>
|
/>
|
||||||
</el-select>
|
</el-select>
|
||||||
</template>
|
</template>
|
||||||
@@ -353,7 +353,7 @@
|
|||||||
v-for="item in (row.subItemOptions || [])"
|
v-for="item in (row.subItemOptions || [])"
|
||||||
:key="item.id"
|
:key="item.id"
|
||||||
:label="item.name"
|
:label="item.name"
|
||||||
:value="item.id"
|
:value="Number(item.id)"
|
||||||
/>
|
/>
|
||||||
</el-select>
|
</el-select>
|
||||||
</template>
|
</template>
|
||||||
@@ -488,7 +488,24 @@
|
|||||||
</div>
|
</div>
|
||||||
<div class="form-item">
|
<div class="form-item">
|
||||||
<span class="form-label">卫生机构</span>
|
<span class="form-label">卫生机构</span>
|
||||||
<el-input :model-value="userStore.orgName || '测试机构'" readonly />
|
<el-select
|
||||||
|
v-model="selectedTenantId"
|
||||||
|
placeholder="请选择卫生机构"
|
||||||
|
style="width: 100%;"
|
||||||
|
@change="handleTenantChange"
|
||||||
|
clearable
|
||||||
|
filterable
|
||||||
|
:loading="loadingTenant"
|
||||||
|
no-data-text="暂无数据,请稍后重试"
|
||||||
|
@visible-change="handleTenantVisibleChange"
|
||||||
|
>
|
||||||
|
<el-option
|
||||||
|
v-for="item in tenantOptions"
|
||||||
|
:key="item.value"
|
||||||
|
:label="item.label"
|
||||||
|
:value="item.value"
|
||||||
|
/>
|
||||||
|
</el-select>
|
||||||
</div>
|
</div>
|
||||||
<div class="form-item">
|
<div class="form-item">
|
||||||
<span class="form-label">套餐金额</span>
|
<span class="form-label">套餐金额</span>
|
||||||
@@ -1006,7 +1023,83 @@ const handleFocus = () => {
|
|||||||
}
|
}
|
||||||
*/
|
*/
|
||||||
};
|
};
|
||||||
|
// 获取当前登录用户信息
|
||||||
|
// --- 新增:存储租户/机构列表和当前选中的值 ---
|
||||||
|
const tenantOptions = ref([]); // 存储从后端获取的租户列表
|
||||||
|
const selectedTenantId = ref(null); // 存储当前选中的租户ID
|
||||||
|
// --- 新增:控制租户列表加载状态 ---
|
||||||
|
const loadingTenant = ref(false); // 控制下拉框的加载状态
|
||||||
|
|
||||||
|
const fetchTenantList = async () => {
|
||||||
|
|
||||||
|
if (loadingTenant.value) return; // 防止重复请求
|
||||||
|
loadingTenant.value = true;
|
||||||
|
|
||||||
|
try {
|
||||||
|
|
||||||
|
const response = await request({
|
||||||
|
url: '/system/tenant/page',
|
||||||
|
method: 'get',
|
||||||
|
params: {
|
||||||
|
pageNum: 1,
|
||||||
|
pageSize: 100
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
if (response.code === 200) {
|
||||||
|
let tenantData = [];
|
||||||
|
|
||||||
|
// --- 关键修改:优先检查 records 字段 ---
|
||||||
|
if (response.data && response.data.records && Array.isArray(response.data.records)) {
|
||||||
|
tenantData = response.data.records;
|
||||||
|
|
||||||
|
} else if (response.data && response.data.rows && Array.isArray(response.data.rows)) {
|
||||||
|
// 兼容旧的 rows 格式
|
||||||
|
tenantData = response.data.rows;
|
||||||
|
|
||||||
|
} else if (response.data && Array.isArray(response.data)) {
|
||||||
|
// 兼容最简单的数组格式
|
||||||
|
tenantData = response.data;
|
||||||
|
|
||||||
|
} else {
|
||||||
|
|
||||||
|
tenantData = [];
|
||||||
|
}
|
||||||
|
|
||||||
|
// 格式化数据以适应 el-select
|
||||||
|
tenantOptions.value = tenantData.map(item => ({
|
||||||
|
value: item.id,
|
||||||
|
label: item.tenantName || item.name || item.orgName || String(item.id) || '未知机构'
|
||||||
|
}));
|
||||||
|
|
||||||
|
// 如果仍未设置默认值且列表不为空,选择第一个
|
||||||
|
if (!selectedTenantId.value && tenantOptions.value.length > 0) {
|
||||||
|
selectedTenantId.value = tenantOptions.value[0].value;
|
||||||
|
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
|
||||||
|
ElMessage.error(response.msg || '获取机构列表失败,请联系管理员');
|
||||||
|
tenantOptions.value = [];
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
|
||||||
|
ElMessage.error('网络异常或数据解析错误,请检查控制台日志');
|
||||||
|
tenantOptions.value = [];
|
||||||
|
} finally {
|
||||||
|
// 确保无论成功还是失败都停止加载状态
|
||||||
|
loadingTenant.value = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
// 展开时若列表为空则加载数据
|
||||||
|
const handleTenantVisibleChange = async (visible) => {
|
||||||
|
if (visible && tenantOptions.value.length === 0) { // 仅在展开且列表为空时加载
|
||||||
|
await fetchTenantList();
|
||||||
|
}
|
||||||
|
};
|
||||||
/**
|
/**
|
||||||
* 获取数据方法
|
* 获取数据方法
|
||||||
* 这里不再接收搜索关键词,而是直接拉取所有启用的套餐
|
* 这里不再接收搜索关键词,而是直接拉取所有启用的套餐
|
||||||
@@ -1061,10 +1154,6 @@ const handlePackageVisibleChange = (visible) => {
|
|||||||
|
|
||||||
// 可选:如果希望页面一打开就预加载一次,保留 onMounted
|
// 可选:如果希望页面一打开就预加载一次,保留 onMounted
|
||||||
// 如果希望完全由用户点击触发,可以注释掉 onMounted
|
// 如果希望完全由用户点击触发,可以注释掉 onMounted
|
||||||
onMounted(() => {
|
|
||||||
// getFeePackages();
|
|
||||||
});
|
|
||||||
|
|
||||||
|
|
||||||
// ==============================
|
// ==============================
|
||||||
// 【修复】级联下拉框逻辑 (包含直接请求代码)
|
// 【修复】级联下拉框逻辑 (包含直接请求代码)
|
||||||
@@ -1160,24 +1249,37 @@ const handleEditRow = (row) => {
|
|||||||
|
|
||||||
// 初始化行内属性
|
// 初始化行内属性
|
||||||
if (!row.subItemOptions) row.subItemOptions = [];
|
if (!row.subItemOptions) row.subItemOptions = [];
|
||||||
row.loadingSubItems = false;
|
|
||||||
|
|
||||||
// 回显名称
|
// 预加载费用套餐列表(确保下拉框能显示名称而不是ID)
|
||||||
|
if (feePackages.value.length === 0) {
|
||||||
|
getFeePackages();
|
||||||
|
}
|
||||||
|
|
||||||
|
// 如果已有子项ID但选项列表为空,且有大类ID,则主动加载子类列表
|
||||||
|
if (row.inspectionTypeId && row.subItemOptions.length === 0) {
|
||||||
|
row.loadingSubItems = true;
|
||||||
|
fetchInspectionTypesRequest({ parentId: row.inspectionTypeId }).then(res => {
|
||||||
|
let subData = [];
|
||||||
|
if (res.code === 200) {
|
||||||
|
if (res.data && Array.isArray(res.data)) subData = res.data;
|
||||||
|
else if (res.data && res.data.rows) subData = res.data.rows;
|
||||||
|
else if (res.data && res.data.data && Array.isArray(res.data.data)) subData = res.data.data;
|
||||||
|
}
|
||||||
|
row.subItemOptions = subData;
|
||||||
|
}).finally(() => {
|
||||||
|
row.loadingSubItems = false;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// 回显检验大类名称
|
||||||
if (row.inspectionTypeId && !row.inspectionTypeName) {
|
if (row.inspectionTypeId && !row.inspectionTypeName) {
|
||||||
const p = parentTypeOptions.value.find(i => i.id === row.inspectionTypeId);
|
const p = parentTypeOptions.value.find(i => i.id === row.inspectionTypeId);
|
||||||
if (p) row.inspectionTypeName = p.name;
|
if (p) row.inspectionTypeName = p.name;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (row.subItemId && row.subItemOptions.length > 0) {
|
|
||||||
const s = row.subItemOptions.find(i => i.id === row.subItemId);
|
|
||||||
if (s) row.subItemName = s.name;
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
// ... 其他初始化代码
|
loadParentTypes();
|
||||||
loadParentTypes(); // <--- 确保这一行存在
|
|
||||||
// ...
|
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
@@ -1292,15 +1394,15 @@ const loadObservationItems = async (resetPage = false) => {
|
|||||||
code: item.busNo || '',
|
code: item.busNo || '',
|
||||||
name: item.name || '',
|
name: item.name || '',
|
||||||
testType: item.inspectionTypeId_dictText || item.testType || '',
|
testType: item.inspectionTypeId_dictText || item.testType || '',
|
||||||
inspectionTypeId: item.inspectionTypeId || null,
|
inspectionTypeId: item.inspectionTypeId ? Number(item.inspectionTypeId) : null,
|
||||||
package: item.packageName || '',
|
package: item.packageName || '',
|
||||||
feePackageId: item.feePackageId || null,
|
feePackageId: item.feePackageId ? String(item.feePackageId) : null,
|
||||||
sampleType: item.specimenCode || '',
|
sampleType: item.specimenCode || '',
|
||||||
amount: parseFloat(item.retailPrice || 0),
|
amount: parseFloat(item.retailPrice || 0),
|
||||||
sortOrder: item.sortOrder || null,
|
sortOrder: item.sortOrder || null,
|
||||||
serviceRange: item.serviceRange || '全部',
|
serviceRange: item.serviceRange || '全部',
|
||||||
subItemName: item.subItemName || '',
|
subItemName: item.subItemName || '',
|
||||||
subItemId: item.subItemId || null,
|
subItemId: item.subItemId ? Number(item.subItemId) : null,
|
||||||
remark: item.descriptionText || '',
|
remark: item.descriptionText || '',
|
||||||
status: true
|
status: true
|
||||||
}));
|
}));
|
||||||
@@ -1319,8 +1421,8 @@ const packageFilter = ref('');
|
|||||||
// 过滤后的检验项目数据(仅保留费用套餐的前端过滤,其他过滤已由后端处理)
|
// 过滤后的检验项目数据(仅保留费用套餐的前端过滤,其他过滤已由后端处理)
|
||||||
const filteredInspectionItems = computed(() => {
|
const filteredInspectionItems = computed(() => {
|
||||||
return inspectionItems.value.filter(item => {
|
return inspectionItems.value.filter(item => {
|
||||||
// 按费用套餐过滤(费用套餐是前端自定义字段,需要前端过滤)
|
// 按费用套餐过滤(用 feePackageId 与选中的套餐 id 比对)
|
||||||
if (packageFilter.value && item.package !== packageFilter.value) {
|
if (packageFilter.value && String(item.feePackageId) !== String(packageFilter.value)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
@@ -1873,7 +1975,7 @@ const addNewItem = () => {
|
|||||||
amount: 0.00,
|
amount: 0.00,
|
||||||
sortOrder: inspectionItems.value.length + 1,
|
sortOrder: inspectionItems.value.length + 1,
|
||||||
serviceRange: '全部',
|
serviceRange: '全部',
|
||||||
sub医技Type: '',
|
subItemName: '',
|
||||||
remark: '',
|
remark: '',
|
||||||
status: true
|
status: true
|
||||||
};
|
};
|
||||||
@@ -1881,19 +1983,47 @@ const addNewItem = () => {
|
|||||||
editingRowId.value = newItem.id;
|
editingRowId.value = newItem.id;
|
||||||
};
|
};
|
||||||
|
|
||||||
const editItem = (item) => {
|
const editItem = async (item) => {
|
||||||
if (editingRowId.value === item.id) {
|
if (editingRowId.value === item.id) {
|
||||||
// 如果当前行已经在编辑模式,点击编辑按钮则保存
|
|
||||||
saveItem(item);
|
saveItem(item);
|
||||||
} else {
|
return;
|
||||||
// 否则进入编辑模式
|
|
||||||
editingRowId.value = item.id;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 初始化行内属性
|
||||||
|
if (!item.subItemOptions) item.subItemOptions = [];
|
||||||
|
|
||||||
|
// 并行预加载:费用套餐列表 + 当前行的子类列表
|
||||||
|
const tasks = [];
|
||||||
|
|
||||||
|
if (feePackages.value.length === 0) {
|
||||||
|
tasks.push(getFeePackages());
|
||||||
|
}
|
||||||
|
|
||||||
|
if (item.inspectionTypeId && item.subItemOptions.length === 0) {
|
||||||
|
item.loadingSubItems = true;
|
||||||
|
tasks.push(
|
||||||
|
fetchInspectionTypesRequest({ parentId: item.inspectionTypeId }).then(res => {
|
||||||
|
let subData = [];
|
||||||
|
if (res.code === 200) {
|
||||||
|
if (res.data && Array.isArray(res.data)) subData = res.data;
|
||||||
|
else if (res.data && res.data.rows) subData = res.data.rows;
|
||||||
|
else if (res.data && res.data.data && Array.isArray(res.data.data)) subData = res.data.data;
|
||||||
|
}
|
||||||
|
item.subItemOptions = subData;
|
||||||
|
}).finally(() => {
|
||||||
|
item.loadingSubItems = false;
|
||||||
|
})
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 等所有数据加载完再切换编辑态,确保 el-select 能回显正确文字
|
||||||
|
await Promise.all(tasks);
|
||||||
|
editingRowId.value = item.id;
|
||||||
};
|
};
|
||||||
|
|
||||||
const updateAmountFromPackage = (item) => {
|
const updateAmountFromPackage = (item) => {
|
||||||
if (item.feePackageId) {
|
if (item.feePackageId) {
|
||||||
const selectedPackage = feePackages.value.find(pkg => pkg.id === item.feePackageId);
|
const selectedPackage = feePackages.value.find(pkg => String(pkg.id) === String(item.feePackageId));
|
||||||
if (selectedPackage) {
|
if (selectedPackage) {
|
||||||
// 套餐总金额 = 套餐金额 + 服务费
|
// 套餐总金额 = 套餐金额 + 服务费
|
||||||
const packageAmount = parseFloat(selectedPackage.packageAmount || 0);
|
const packageAmount = parseFloat(selectedPackage.packageAmount || 0);
|
||||||
@@ -1943,6 +2073,15 @@ const saveItem = async (item) => {
|
|||||||
ElMessage.error('小类编码已存在');
|
ElMessage.error('小类编码已存在');
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
// 【新增】验证小类项目名称唯一性
|
||||||
|
// 逻辑:遍历列表,排除当前正在编辑的行(id不同),且名称(trim后)相同
|
||||||
|
const isDuplicateName = inspectionItems.value.some(i =>
|
||||||
|
i.id !== item.id && i.name.trim() === item.name.trim()
|
||||||
|
);
|
||||||
|
if (isDuplicateName) {
|
||||||
|
ElMessage.error('小类项目名称已存在');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// 从费用套餐获取金额
|
// 从费用套餐获取金额
|
||||||
updateAmountFromPackage(item);
|
updateAmountFromPackage(item);
|
||||||
@@ -2015,8 +2154,8 @@ const deleteItem = async (id) => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const cancelEdit = (item) => {
|
const cancelEdit = (item) => {
|
||||||
// 如果是新添加的行,则直接删除
|
// 如果是新添加的行,则直接删除(临时ID为数字类型)
|
||||||
if (item.id.toString().length > 10) { // 临时ID,使用Date.now()生成
|
if (typeof item.id === 'number') {
|
||||||
const index = inspectionItems.value.findIndex(i => i.id === item.id);
|
const index = inspectionItems.value.findIndex(i => i.id === item.id);
|
||||||
if (index !== -1) {
|
if (index !== -1) {
|
||||||
inspectionItems.value.splice(index, 1);
|
inspectionItems.value.splice(index, 1);
|
||||||
@@ -2370,19 +2509,21 @@ const handlePackageManagement = () => {
|
|||||||
const refreshPage = () => {
|
const refreshPage = () => {
|
||||||
getInspectionTypeList();
|
getInspectionTypeList();
|
||||||
// 刷新时也重新加载套餐项目
|
// 刷新时也重新加载套餐项目
|
||||||
loadPackageItemsFromAPI();
|
// loadPackageItemsFromAPI();
|
||||||
};
|
};
|
||||||
|
|
||||||
// 页面加载时获取数据
|
// 页面加载时获取数据
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
getInspectionTypeList();
|
getInspectionTypeList();
|
||||||
getLisGroupList();
|
getLisGroupList();
|
||||||
// 加载检验套餐明细项目
|
// // 加载检验套餐明细项目
|
||||||
loadPackageItemsFromAPI();
|
// loadPackageItemsFromAPI();
|
||||||
// 初始化计算套餐金额和服务费
|
// // 初始化计算套餐金额和服务费
|
||||||
calculateAmounts();
|
// calculateAmounts();
|
||||||
|
fetchTenantList(); // 页面加载时获取租户列表
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
// 监听检验分类代码,当字典数据加载完成后加载检验项目数据
|
// 监听检验分类代码,当字典数据加载完成后加载检验项目数据
|
||||||
watch(activity_category_code, (newVal) => {
|
watch(activity_category_code, (newVal) => {
|
||||||
if (newVal && newVal.length > 0 && inspectionItems.value.length === 0) {
|
if (newVal && newVal.length > 0 && inspectionItems.value.length === 0) {
|
||||||
|
|||||||
Reference in New Issue
Block a user