套餐设置套餐管理完善
This commit is contained in:
@@ -1,115 +0,0 @@
|
|||||||
-- 诊断:门诊划价检索不出诊疗项目的问题
|
|
||||||
-- 问题描述:在门诊划价页面,检索不出诊疗项目
|
|
||||||
|
|
||||||
-- 1. 检查是否有诊疗项目定义数据
|
|
||||||
SELECT
|
|
||||||
COUNT(*) as total_count,
|
|
||||||
COUNT(CASE WHEN delete_flag = '0' THEN 1 END) as active_count,
|
|
||||||
COUNT(CASE WHEN delete_flag != '0' THEN 1 END) as deleted_count
|
|
||||||
FROM wor_activity_definition;
|
|
||||||
|
|
||||||
-- 2. 检查是否有收费项目(诊疗项目类型)
|
|
||||||
SELECT
|
|
||||||
T1.id,
|
|
||||||
T1.encounter_id,
|
|
||||||
T1.context_enum,
|
|
||||||
T1.product_id,
|
|
||||||
T1.status_enum,
|
|
||||||
T1.delete_flag,
|
|
||||||
T2.id as activity_def_id,
|
|
||||||
T2.name as activity_name,
|
|
||||||
T2.delete_flag as activity_delete_flag
|
|
||||||
FROM adm_charge_item AS T1
|
|
||||||
LEFT JOIN wor_activity_definition AS T2
|
|
||||||
ON T1.context_enum = 'ACTIVITY' -- 诊疗项目类型
|
|
||||||
AND T1.product_id = T2.id
|
|
||||||
AND T2.delete_flag = '0'
|
|
||||||
WHERE T1.context_enum = 'ACTIVITY'
|
|
||||||
AND T1.delete_flag = '0'
|
|
||||||
LIMIT 20;
|
|
||||||
|
|
||||||
-- 3. 检查是否有诊疗项目定义,但收费项目中的product_id无法匹配
|
|
||||||
SELECT
|
|
||||||
'诊疗项目定义存在,但收费项目无法匹配' as issue_type,
|
|
||||||
COUNT(*) as count
|
|
||||||
FROM wor_activity_definition wad
|
|
||||||
WHERE wad.delete_flag = '0'
|
|
||||||
AND NOT EXISTS (
|
|
||||||
SELECT 1
|
|
||||||
FROM adm_charge_item aci
|
|
||||||
WHERE aci.context_enum = 'ACTIVITY'
|
|
||||||
AND aci.product_id = wad.id
|
|
||||||
AND aci.delete_flag = '0'
|
|
||||||
);
|
|
||||||
|
|
||||||
-- 4. 检查收费项目中的诊疗项目,但定义表中没有对应数据
|
|
||||||
SELECT
|
|
||||||
'收费项目存在,但诊疗项目定义缺失' as issue_type,
|
|
||||||
COUNT(*) as count
|
|
||||||
FROM adm_charge_item aci
|
|
||||||
WHERE aci.context_enum = 'ACTIVITY'
|
|
||||||
AND aci.delete_flag = '0'
|
|
||||||
AND NOT EXISTS (
|
|
||||||
SELECT 1
|
|
||||||
FROM wor_activity_definition wad
|
|
||||||
WHERE wad.id = aci.product_id
|
|
||||||
AND wad.delete_flag = '0'
|
|
||||||
);
|
|
||||||
|
|
||||||
-- 5. 检查某个具体就诊的诊疗项目(替换encounterId为实际值)
|
|
||||||
-- SELECT
|
|
||||||
-- T1.encounter_id,
|
|
||||||
-- T1.id as charge_item_id,
|
|
||||||
-- T1.context_enum,
|
|
||||||
-- T1.product_id,
|
|
||||||
-- T1.status_enum,
|
|
||||||
-- T2.id as activity_def_id,
|
|
||||||
-- T2.name as activity_name,
|
|
||||||
-- T2.delete_flag as activity_delete_flag,
|
|
||||||
-- CASE
|
|
||||||
-- WHEN T2.id IS NULL THEN '诊疗项目定义不存在或已删除'
|
|
||||||
-- WHEN T2.delete_flag != '0' THEN '诊疗项目定义已删除'
|
|
||||||
-- ELSE '正常'
|
|
||||||
-- END as status
|
|
||||||
-- FROM adm_charge_item AS T1
|
|
||||||
-- LEFT JOIN wor_activity_definition AS T2
|
|
||||||
-- ON T1.context_enum = 'ACTIVITY'
|
|
||||||
-- AND T1.product_id = T2.id
|
|
||||||
-- WHERE T1.encounter_id = :encounterId -- 替换为实际的encounterId
|
|
||||||
-- AND T1.context_enum = 'ACTIVITY'
|
|
||||||
-- AND T1.delete_flag = '0'
|
|
||||||
-- AND T1.status_enum IN (1, 2, 3, 4, 5, 6); -- PLANNED, BILLABLE, BILLED, REFUNDING, REFUNDED, PART_REFUND
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -135,10 +135,15 @@ export function updateAuthRole(data) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 查询部门下拉树结构
|
// 查询部门下拉树结构
|
||||||
export function deptTreeSelect() {
|
// 默认只显示科室类型(typeEnum=2),如果需要其他类型,可以传入 params 覆盖
|
||||||
|
export function deptTreeSelect(params = {}) {
|
||||||
return request({
|
return request({
|
||||||
url: '/base-data-manage/organization/organization',
|
url: '/base-data-manage/organization/organization',
|
||||||
method: 'get'
|
method: 'get',
|
||||||
|
params: {
|
||||||
|
typeEnum: 2, // 默认只显示科室
|
||||||
|
...params // 允许外部传入参数覆盖默认值
|
||||||
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -469,7 +469,8 @@ async function getDiseaseTreatmentList() {
|
|||||||
// 诊疗目录分类查询下拉树结d构
|
// 诊疗目录分类查询下拉树结d构
|
||||||
async function getImplDepartList() {
|
async function getImplDepartList() {
|
||||||
try {
|
try {
|
||||||
const res = await getImplementDepartmentList();
|
// 只查询科室类型(typeEnum=2),不包含专业等其他类型
|
||||||
|
const res = await getImplementDepartmentList({ typeEnum: 2 });
|
||||||
if (res.code === 200) {
|
if (res.code === 200) {
|
||||||
if (res.data.records.length > 0) {
|
if (res.data.records.length > 0) {
|
||||||
organization.value = res.data.records.map((res) => {
|
organization.value = res.data.records.map((res) => {
|
||||||
|
|||||||
@@ -41,7 +41,7 @@
|
|||||||
</thead>
|
</thead>
|
||||||
<tbody>
|
<tbody>
|
||||||
<tr
|
<tr
|
||||||
v-for="(row, index) in tableData"
|
v-for="(row, index) in pagedTypeRows"
|
||||||
:key="row.id"
|
:key="row.id"
|
||||||
:class="{ 'editing': editingRowId === row.id }"
|
:class="{ 'editing': editingRowId === row.id }"
|
||||||
>
|
>
|
||||||
@@ -148,12 +148,16 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- 页码区域 -->
|
<!-- 页码区域 -->
|
||||||
<div class="pagination">
|
<div class="pagination" v-if="typeTotalPages > 1">
|
||||||
<div class="page-btn">上一页</div>
|
<div class="page-btn" :class="{ disabled: typeCurrentPage === 1 }" @click="typePrevPage">上一页</div>
|
||||||
<div class="page-btn active">1</div>
|
<div
|
||||||
<div class="page-btn">2</div>
|
v-for="p in typePageButtons"
|
||||||
<div class="page-btn">3</div>
|
:key="p"
|
||||||
<div class="page-btn">下一页</div>
|
class="page-btn"
|
||||||
|
:class="{ active: p === typeCurrentPage }"
|
||||||
|
@click="typeGoPage(p)"
|
||||||
|
>{{ p }}</div>
|
||||||
|
<div class="page-btn" :class="{ disabled: typeCurrentPage >= typeTotalPages }" @click="typeNextPage">下一页</div>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
@@ -239,7 +243,7 @@
|
|||||||
</thead>
|
</thead>
|
||||||
<tbody>
|
<tbody>
|
||||||
<tr
|
<tr
|
||||||
v-for="(item, index) in filteredInspectionItems"
|
v-for="(item, index) in pagedInspectionItems"
|
||||||
:key="item.id"
|
:key="item.id"
|
||||||
:class="{ 'editing': editingRowId === item.id }"
|
:class="{ 'editing': editingRowId === item.id }"
|
||||||
>
|
>
|
||||||
@@ -372,12 +376,16 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- 页码区域 -->
|
<!-- 页码区域 -->
|
||||||
<div class="pagination">
|
<div class="pagination" v-if="inspectionTotalPages > 1">
|
||||||
<div class="page-btn">上一页</div>
|
<div class="page-btn" :class="{ disabled: inspectionCurrentPage === 1 }" @click="inspectionPrevPage">上一页</div>
|
||||||
<div class="page-btn active">1</div>
|
<div
|
||||||
<div class="page-btn">2</div>
|
v-for="p in inspectionPageButtons"
|
||||||
<div class="page-btn">3</div>
|
:key="p"
|
||||||
<div class="page-btn">下一页</div>
|
class="page-btn"
|
||||||
|
:class="{ active: p === inspectionCurrentPage }"
|
||||||
|
@click="inspectionGoPage(p)"
|
||||||
|
>{{ p }}</div>
|
||||||
|
<div class="page-btn" :class="{ disabled: inspectionCurrentPage >= inspectionTotalPages }" @click="inspectionNextPage">下一页</div>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
@@ -687,9 +695,9 @@
|
|||||||
|
|
||||||
<script setup>
|
<script setup>
|
||||||
import useUserStore from '@/store/modules/user';
|
import useUserStore from '@/store/modules/user';
|
||||||
import {computed, onMounted, ref, watch} from 'vue';
|
import {computed, nextTick, onActivated, onMounted, ref, watch} from 'vue';
|
||||||
import {ElLoading, ElMessage, ElMessageBox} from 'element-plus';
|
import {ElLoading, ElMessage, ElMessageBox} from 'element-plus';
|
||||||
import {useRoute, useRouter} from 'vue-router';
|
import {onBeforeRouteUpdate, useRoute, useRouter} from 'vue-router';
|
||||||
import {
|
import {
|
||||||
addInspectionType,
|
addInspectionType,
|
||||||
delInspectionType,
|
delInspectionType,
|
||||||
@@ -785,6 +793,97 @@ const activeNav = ref(0);
|
|||||||
// 检验类型数据
|
// 检验类型数据
|
||||||
const tableData = ref([]);
|
const tableData = ref([]);
|
||||||
|
|
||||||
|
// ==============================
|
||||||
|
// 分页(检验类型 tab)
|
||||||
|
// ==============================
|
||||||
|
const typeCurrentPage = ref(1);
|
||||||
|
// 每页条数:按需求固定为10
|
||||||
|
const typePageSize = ref(10);
|
||||||
|
const typeTotalPages = computed(() => {
|
||||||
|
const total = tableData.value.length;
|
||||||
|
return Math.max(1, Math.ceil(total / typePageSize.value));
|
||||||
|
});
|
||||||
|
const typePageButtons = computed(() => {
|
||||||
|
const total = typeTotalPages.value;
|
||||||
|
return Array.from({ length: total }, (_, i) => i + 1);
|
||||||
|
});
|
||||||
|
// 按“大类编码(code)”排序后再分页展示(不要按序号 sortOrder 排)
|
||||||
|
function parseCodeParts(code) {
|
||||||
|
const s = (code ?? '').toString().trim();
|
||||||
|
// 支持 1、01、3-001、3_001 等:用 -/_ 分隔
|
||||||
|
const parts = s.split(/[-_]/g);
|
||||||
|
const mainRaw = parts[0] ?? '';
|
||||||
|
const subRaw = parts[1] ?? '';
|
||||||
|
const mainNum = Number.parseInt(mainRaw, 10);
|
||||||
|
const subNum = Number.parseInt(subRaw, 10);
|
||||||
|
return {
|
||||||
|
raw: s,
|
||||||
|
mainRaw,
|
||||||
|
subRaw,
|
||||||
|
mainIsNum: !Number.isNaN(mainNum),
|
||||||
|
subIsNum: !Number.isNaN(subNum),
|
||||||
|
mainNum,
|
||||||
|
subNum
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
const sortedTypeRows = computed(() => {
|
||||||
|
return [...tableData.value].sort((a, b) => {
|
||||||
|
const pa = parseCodeParts(a?.code);
|
||||||
|
const pb = parseCodeParts(b?.code);
|
||||||
|
|
||||||
|
// 先按主编码:数字优先按数值,否则按字符串
|
||||||
|
if (pa.mainIsNum && pb.mainIsNum) {
|
||||||
|
if (pa.mainNum !== pb.mainNum) return pa.mainNum - pb.mainNum;
|
||||||
|
} else {
|
||||||
|
const c = pa.mainRaw.localeCompare(pb.mainRaw, 'zh-Hans-CN', { numeric: true, sensitivity: 'base' });
|
||||||
|
if (c !== 0) return c;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 同主编码时:无子编码的排在前(大类在子类之前)
|
||||||
|
const aHasSub = !!pa.subRaw;
|
||||||
|
const bHasSub = !!pb.subRaw;
|
||||||
|
if (aHasSub !== bHasSub) return aHasSub ? 1 : -1;
|
||||||
|
|
||||||
|
// 再按子编码
|
||||||
|
if (pa.subIsNum && pb.subIsNum) {
|
||||||
|
if (pa.subNum !== pb.subNum) return pa.subNum - pb.subNum;
|
||||||
|
} else {
|
||||||
|
const c = pa.subRaw.localeCompare(pb.subRaw, 'zh-Hans-CN', { numeric: true, sensitivity: 'base' });
|
||||||
|
if (c !== 0) return c;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 最后兜底:按原字符串
|
||||||
|
return pa.raw.localeCompare(pb.raw, 'zh-Hans-CN', { numeric: true, sensitivity: 'base' });
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
const pagedTypeRows = computed(() => {
|
||||||
|
const start = (typeCurrentPage.value - 1) * typePageSize.value;
|
||||||
|
return sortedTypeRows.value.slice(start, start + typePageSize.value);
|
||||||
|
});
|
||||||
|
function typeGoPage(p) {
|
||||||
|
if (p < 1 || p > typeTotalPages.value) return;
|
||||||
|
typeCurrentPage.value = p;
|
||||||
|
}
|
||||||
|
function typePrevPage() {
|
||||||
|
if (typeCurrentPage.value <= 1) return;
|
||||||
|
typeCurrentPage.value -= 1;
|
||||||
|
}
|
||||||
|
function typeNextPage() {
|
||||||
|
if (typeCurrentPage.value >= typeTotalPages.value) return;
|
||||||
|
typeCurrentPage.value += 1;
|
||||||
|
}
|
||||||
|
watch(
|
||||||
|
() => tableData.value.length,
|
||||||
|
() => {
|
||||||
|
// 数据变化后,确保当前页有效
|
||||||
|
if (typeCurrentPage.value > typeTotalPages.value) {
|
||||||
|
typeCurrentPage.value = 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
// 获取检验类型列表 - 从后端API获取
|
// 获取检验类型列表 - 从后端API获取
|
||||||
const getInspectionTypeList = () => {
|
const getInspectionTypeList = () => {
|
||||||
listInspectionType().then(data => {
|
listInspectionType().then(data => {
|
||||||
@@ -989,6 +1088,44 @@ const filteredInspectionItems = computed(() => {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// ==============================
|
||||||
|
// 分页(检验项目 tab)
|
||||||
|
// ==============================
|
||||||
|
const inspectionCurrentPage = ref(1);
|
||||||
|
// 每页条数:按需求固定为10
|
||||||
|
const inspectionPageSize = ref(10);
|
||||||
|
const inspectionTotalPages = computed(() => {
|
||||||
|
const total = filteredInspectionItems.value.length;
|
||||||
|
return Math.max(1, Math.ceil(total / inspectionPageSize.value));
|
||||||
|
});
|
||||||
|
const inspectionPageButtons = computed(() => {
|
||||||
|
const total = inspectionTotalPages.value;
|
||||||
|
return Array.from({ length: total }, (_, i) => i + 1);
|
||||||
|
});
|
||||||
|
const pagedInspectionItems = computed(() => {
|
||||||
|
const start = (inspectionCurrentPage.value - 1) * inspectionPageSize.value;
|
||||||
|
return filteredInspectionItems.value.slice(start, start + inspectionPageSize.value);
|
||||||
|
});
|
||||||
|
function inspectionGoPage(p) {
|
||||||
|
if (p < 1 || p > inspectionTotalPages.value) return;
|
||||||
|
inspectionCurrentPage.value = p;
|
||||||
|
}
|
||||||
|
function inspectionPrevPage() {
|
||||||
|
if (inspectionCurrentPage.value <= 1) return;
|
||||||
|
inspectionCurrentPage.value -= 1;
|
||||||
|
}
|
||||||
|
function inspectionNextPage() {
|
||||||
|
if (inspectionCurrentPage.value >= inspectionTotalPages.value) return;
|
||||||
|
inspectionCurrentPage.value += 1;
|
||||||
|
}
|
||||||
|
watch(
|
||||||
|
() => filteredInspectionItems.value.length,
|
||||||
|
() => {
|
||||||
|
// 过滤条件变化后,回到第一页,避免出现“当前页没数据但页码还在后面”的体验
|
||||||
|
inspectionCurrentPage.value = 1;
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
// 执行过滤
|
// 执行过滤
|
||||||
const filterItems = () => {
|
const filterItems = () => {
|
||||||
// 过滤逻辑已经在computed属性中实现,这里可以添加额外的逻辑
|
// 过滤逻辑已经在computed属性中实现,这里可以添加额外的逻辑
|
||||||
@@ -1371,7 +1508,9 @@ const addNewRow = () => {
|
|||||||
ElMessage.warning('请先保存或取消当前正在编辑的行');
|
ElMessage.warning('请先保存或取消当前正在编辑的行');
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const newRow = { id: Date.now(), code: '', name: '', department: departments.value[0], sortOrder: tableData.value.length + 1, remark: '' };
|
// department 在表格里是字符串(科室名称);这里不要直接塞对象,否则后续 trim/校验会异常
|
||||||
|
const defaultDeptName = departments.value?.[0]?.name || '';
|
||||||
|
const newRow = { id: Date.now(), code: '', name: '', department: defaultDeptName, sortOrder: tableData.value.length + 1, remark: '' };
|
||||||
tableData.value.push(newRow);
|
tableData.value.push(newRow);
|
||||||
editingRowId.value = newRow.id;
|
editingRowId.value = newRow.id;
|
||||||
};
|
};
|
||||||
@@ -1392,40 +1531,27 @@ const handleConfirm = (row) => {
|
|||||||
sortOrder: row.sortOrder ? Number(row.sortOrder) : 0
|
sortOrder: row.sortOrder ? Number(row.sortOrder) : 0
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// 兼容 department 可能是对象的情况(例如 el-tree-select 返回节点对象)
|
||||||
|
if (submitData.department && typeof submitData.department === 'object') {
|
||||||
|
submitData.department = submitData.department.name || submitData.department.label || '';
|
||||||
|
}
|
||||||
|
|
||||||
console.log('原始row数据:', row);
|
console.log('原始row数据:', row);
|
||||||
console.log('提交前的submitData:', submitData);
|
console.log('提交前的submitData:', submitData);
|
||||||
|
|
||||||
// 验证必填字段,如果为空则删除该行
|
// 验证必填字段:为空则提示并保留该行(不要直接删行,否则用户“点确定就没了”体验很差)
|
||||||
if (!submitData.code || submitData.code.trim() === '') {
|
if (!submitData.code || submitData.code.trim() === '') {
|
||||||
// 删除空的编辑行
|
ElMessage.warning('请输入大类编码');
|
||||||
const index = tableData.value.findIndex(r => r.id === row.id);
|
|
||||||
if (index !== -1) {
|
|
||||||
tableData.value.splice(index, 1);
|
|
||||||
editingRowId.value = null;
|
|
||||||
ElMessage.info('已删除空行');
|
|
||||||
}
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!submitData.name || submitData.name.trim() === '') {
|
if (!submitData.name || submitData.name.trim() === '') {
|
||||||
// 删除空的编辑行
|
ElMessage.warning('请输入大类项目名称');
|
||||||
const index = tableData.value.findIndex(r => r.id === row.id);
|
|
||||||
if (index !== -1) {
|
|
||||||
tableData.value.splice(index, 1);
|
|
||||||
editingRowId.value = null;
|
|
||||||
ElMessage.info('已删除空行');
|
|
||||||
}
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!submitData.department || submitData.department.trim() === '') {
|
if (!submitData.department || String(submitData.department).trim() === '') {
|
||||||
// 删除空的编辑行
|
ElMessage.warning('请选择执行科室');
|
||||||
const index = tableData.value.findIndex(r => r.id === row.id);
|
|
||||||
if (index !== -1) {
|
|
||||||
tableData.value.splice(index, 1);
|
|
||||||
editingRowId.value = null;
|
|
||||||
ElMessage.info('已删除空行');
|
|
||||||
}
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1486,7 +1612,40 @@ const handleAdd = (row, index) => {
|
|||||||
ElMessage.warning('请先保存或取消当前正在编辑的行');
|
ElMessage.warning('请先保存或取消当前正在编辑的行');
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const newRow = { id: Date.now(), code: '', name: '', department: row.department, sortOrder: row.sortOrder + 1, remark: '' };
|
|
||||||
|
// 行内“+”:在当前大类下新增子类,编码按“父类编码-001”递增生成
|
||||||
|
const parentCode = (row?.code ?? '').toString().trim();
|
||||||
|
if (!parentCode) {
|
||||||
|
ElMessage.warning('请先填写并保存当前大类编码,再新增子类');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 找到该父类下已有的子类编码,取最大序号 + 1
|
||||||
|
// 支持如:1-001、01-002 等
|
||||||
|
const prefix = `${parentCode}-`;
|
||||||
|
let maxSeq = 0;
|
||||||
|
for (const r of tableData.value) {
|
||||||
|
const code = (r?.code ?? '').toString();
|
||||||
|
if (code.startsWith(prefix)) {
|
||||||
|
const suffix = code.slice(prefix.length);
|
||||||
|
const n = Number.parseInt(suffix, 10);
|
||||||
|
if (!Number.isNaN(n)) {
|
||||||
|
maxSeq = Math.max(maxSeq, n);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
const nextSeq = maxSeq + 1;
|
||||||
|
const childCode = `${parentCode}-${String(nextSeq).padStart(3, '0')}`;
|
||||||
|
|
||||||
|
const newRow = {
|
||||||
|
id: Date.now(),
|
||||||
|
code: childCode,
|
||||||
|
name: '',
|
||||||
|
department: row.department,
|
||||||
|
// 序号字段保持原逻辑:插入到父类下一行,默认沿用父类序号
|
||||||
|
sortOrder: row.sortOrder,
|
||||||
|
remark: ''
|
||||||
|
};
|
||||||
tableData.value.splice(index + 1, 0, newRow);
|
tableData.value.splice(index + 1, 0, newRow);
|
||||||
editingRowId.value = newRow.id;
|
editingRowId.value = newRow.id;
|
||||||
};
|
};
|
||||||
@@ -2069,22 +2228,52 @@ onMounted(() => {
|
|||||||
loadObservationItems();
|
loadObservationItems();
|
||||||
// 加载检验套餐明细项目
|
// 加载检验套餐明细项目
|
||||||
loadPackageItemsFromAPI();
|
loadPackageItemsFromAPI();
|
||||||
// 检查URL参数,如果有tab参数则切换到对应导航项
|
|
||||||
const query = router.currentRoute.value.query;
|
|
||||||
if (query.tab === '0' || query.tab === '1' || query.tab === '2') {
|
|
||||||
activeNav.value = parseInt(query.tab);
|
|
||||||
}
|
|
||||||
// 检查URL参数中是否有packageId,如果有则加载套餐数据(用于编辑或查看)
|
|
||||||
if (query.packageId) {
|
|
||||||
// 切换到套餐设置标签页
|
|
||||||
activeNav.value = 2;
|
|
||||||
// 加载套餐数据
|
|
||||||
loadInspectionPackage(query.packageId);
|
|
||||||
}
|
|
||||||
// 初始化计算套餐金额和服务费
|
// 初始化计算套餐金额和服务费
|
||||||
calculateAmounts();
|
calculateAmounts();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 关键修复:
|
||||||
|
* 从“套餐管理”跳转到这里时,通常只是改变 query(packageId/mode/tab),组件不会重新挂载,
|
||||||
|
* 所以仅靠 onMounted 读取一次 query 会导致“查看/修改”出现空白,刷新才正常。
|
||||||
|
* 这里监听 query 变化,自动切换 tab 并加载套餐数据。
|
||||||
|
*/
|
||||||
|
watch(
|
||||||
|
() => route.query.tab,
|
||||||
|
(tab) => {
|
||||||
|
if (tab === '0' || tab === '1' || tab === '2') {
|
||||||
|
activeNav.value = parseInt(String(tab));
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{ immediate: true }
|
||||||
|
);
|
||||||
|
|
||||||
|
const applyRouteForPackage = async (query) => {
|
||||||
|
const packageId = query?.packageId;
|
||||||
|
if (!packageId) return;
|
||||||
|
activeNav.value = 2;
|
||||||
|
await nextTick();
|
||||||
|
loadInspectionPackage(String(packageId));
|
||||||
|
};
|
||||||
|
|
||||||
|
watch(
|
||||||
|
() => route.query.packageId,
|
||||||
|
async () => {
|
||||||
|
await applyRouteForPackage(route.query);
|
||||||
|
},
|
||||||
|
{ immediate: true, flush: 'post' }
|
||||||
|
);
|
||||||
|
|
||||||
|
// 兜底:如果该页面被 keep-alive 缓存,从别的页面返回时不会触发 onMounted
|
||||||
|
onActivated(() => {
|
||||||
|
applyRouteForPackage(route.query);
|
||||||
|
});
|
||||||
|
|
||||||
|
// 兜底:同一路由复用/仅 query 变化时,确保能触发加载
|
||||||
|
onBeforeRouteUpdate((to) => {
|
||||||
|
applyRouteForPackage(to.query);
|
||||||
|
});
|
||||||
|
|
||||||
// 监听生成服务费选项变更
|
// 监听生成服务费选项变更
|
||||||
watch(generateServiceFee, (newVal) => {
|
watch(generateServiceFee, (newVal) => {
|
||||||
calculateAmounts();
|
calculateAmounts();
|
||||||
@@ -2422,6 +2611,12 @@ watch(packageItems, (newVal) => {
|
|||||||
border-color: #1890ff;
|
border-color: #1890ff;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.page-btn.disabled {
|
||||||
|
opacity: 0.5;
|
||||||
|
cursor: not-allowed;
|
||||||
|
pointer-events: none;
|
||||||
|
}
|
||||||
|
|
||||||
/* 套餐设置样式 */
|
/* 套餐设置样式 */
|
||||||
.top-bar {
|
.top-bar {
|
||||||
height: 48px;
|
height: 48px;
|
||||||
|
|||||||
Reference in New Issue
Block a user