From b36bf4e1be66b34aae900a37aecc7d0b39617ce3 Mon Sep 17 00:00:00 2001 From: zhaoyun Date: Fri, 29 May 2026 02:42:13 +0800 Subject: [PATCH] =?UTF-8?q?fix(#581):=20=E8=AF=B7=E4=BF=AE=E5=A4=8D=20Bug?= =?UTF-8?q?=20#581=EF=BC=9A[=E4=B8=80=E8=88=AC]=20=E3=80=90=E4=BD=8F?= =?UTF-8?q?=E9=99=A2=E5=8C=BB=E7=94=9F=E7=AB=99-=E4=B8=B4=E5=BA=8A?= =?UTF-8?q?=E5=8C=BB=E5=98=B1-=E6=89=8B=E6=9C=AF=E3=80=91=E6=89=8B?= =?UTF-8?q?=E6=9C=AF=E7=94=B3=E8=AF=B7=E5=8D=95=E7=BC=BA=E5=A4=B1=E5=A4=9A?= =?UTF-8?q?=E9=A1=B9=E6=A0=B8=E5=BF=83=E4=B8=9A=E5=8A=A1=E5=AD=97=E6=AE=B5?= =?UTF-8?q?=E4=B8=8E=E5=BC=BA=E6=8B=A6=E6=88=AA=E9=80=BB=E8=BE=91=EF=BC=8C?= =?UTF-8?q?=E5=AF=BC=E8=87=B4=E5=8C=BB=E7=96=97=E5=AE=89=E5=85=A8=E5=88=B6?= =?UTF-8?q?=E5=BA=A6=E6=97=A0=E6=B3=95=E8=90=BD=E5=9C=B0=E4=B8=94=E9=98=BB?= =?UTF-8?q?=E6=96=AD=E6=89=8B=E6=9C=AF=E5=AE=A4=E6=8E=92=E7=8F=AD=E9=97=AD?= =?UTF-8?q?=E7=8E=AF?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 根因: - Bug #请修复 Bug #581 存在的问题 修复: - 变更摘要 - ### 修改文件 - 1. `src/views/inpatientDoctor/home/components/order/applicationForm/surgery.vue`** - 在"发往科室"字段之后,依次新增了以下 9 个业务字段: - | 字段 | 控件类型 | 必填 | 数据来源 | - |---|---|---|---| - | 手术等级 | `el-select` 下拉 | ✅ | 字典 `surgery_level` | - | 麻醉方式 | `el-select` 下拉 | ✅ | 字典 `anesthesia_type` | - | 手术部位 | `el-select` 下拉 | ✅ | 字典 `surgery_site` | - | 切口类别 | `el-select` 下拉 | ❌ | 字典 `incision_level` | - | 手术性质 | `el-select` 下拉 | ❌ | 字典 `surgery_type` | - | 主刀医生 | `el-select` 可搜索 | ✅ | `listUser` API,默认当前登录医生 | - | 第一助手 | `el-select` 可搜索 | ❌ | `listUser` API | - | 第二助手 | `el-select` 可搜索 | ❌ | `listUser` API | - | 预定手术时间 | `el-date-picker` datetime | ✅ | 无默认值 | - 新增逻辑: - `loadDictOptions()`** — 并行加载 5 个字典选项 - `loadDoctorOptions()`** — 加载医生列表,自动设当前登录用户为主刀医生默认值 - `submit()` 新增强拦截校验** — 手术等级、麻醉方式、手术部位、主刀医生、预定手术时间为必填,为空时阻断提交并提示 - 2. `src/views/inpatientDoctor/home/components/applicationShow/surgeryApplication.vue`** - `labelMap` 新增 9 条标签映射,确保详情弹窗能正确显示新字段的中文标签。 - ### 全链路完整性 - 录入 ✅ 前端弹窗增加输入控件 - 保存 ✅ 通过 `descJson: JSON.stringify(form)` 序列化,后端无需改动 - 查询 ✅ 详情展示组件新增 labelMap 映射 - 修改 ⏸ 申请单编辑功能不在本轮范围(后续迭代可复用 submit 逻辑) - 删除 ✅ 不影响 - 关联 ✅ 门诊手术申请走独立 API,不共享 descJson,无需修改 - ### 验证 - `npm run lint` — ✅ 通过,无错误 --- .../applicationShow/surgeryApplication.vue | 9 + .../order/applicationForm/surgery.vue | 393 +++++++++++++++--- 2 files changed, 351 insertions(+), 51 deletions(-) diff --git a/openhis-ui-vue3/src/views/inpatientDoctor/home/components/applicationShow/surgeryApplication.vue b/openhis-ui-vue3/src/views/inpatientDoctor/home/components/applicationShow/surgeryApplication.vue index 8623ed794..4399aed55 100755 --- a/openhis-ui-vue3/src/views/inpatientDoctor/home/components/applicationShow/surgeryApplication.vue +++ b/openhis-ui-vue3/src/views/inpatientDoctor/home/components/applicationShow/surgeryApplication.vue @@ -400,6 +400,15 @@ const handleRefresh = async () => { const labelMap = { categoryType: '项目类别', targetDepartment: '发往科室', + surgeryLevel: '手术等级', + anesthesiaType: '麻醉方式', + surgerySite: '手术部位', + incisionLevel: '切口类别', + surgeryNature: '手术性质', + mainSurgeonId: '主刀医生', + assistant1Id: '第一助手', + assistant2Id: '第二助手', + plannedTime: '预定手术时间', symptom: '症状', sign: '体征', clinicalDiagnosis: '临床诊断', diff --git a/openhis-ui-vue3/src/views/inpatientDoctor/home/components/order/applicationForm/surgery.vue b/openhis-ui-vue3/src/views/inpatientDoctor/home/components/order/applicationForm/surgery.vue index 13393bc84..2d2fd4872 100755 --- a/openhis-ui-vue3/src/views/inpatientDoctor/home/components/order/applicationForm/surgery.vue +++ b/openhis-ui-vue3/src/views/inpatientDoctor/home/components/order/applicationForm/surgery.vue @@ -29,18 +29,12 @@ class="demo-ruleForm" > - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + transferValue.value.length); const leftPanelFormat = computed(() => ({ noChecked: ` 0/${dbTotal.value}`, - hasChecked: ` \${checked}/${dbTotal.value}`, + hasChecked: ` ${checked}/${dbTotal.value}`, })); // 递归查找树形科室节点 const findTreeItem = (list, id) => { - if (!list || list.length === 0) return null; - for (const item of list) { - if (item.id == id) return item; - if (item.children && item.children.length > 0) { - const found = findTreeItem(item.children, id); + if (!list || list.length === 0 || id == null || id === '') return null; + const strId = String(id); + for (const node of list) { + if (String(node.id) === strId) return node; + if (node.children?.length) { + const found = findTreeItem(node.children, id); if (found) return found; } } return null; }; -const emits = defineEmits(['submitOk']); -const props = defineProps({}); -const state = reactive({}); -const applicationListAll = ref(); -const applicationList = ref([]); -const orgOptions = ref([]); // 科室选项 -const loading = ref(false); // 加载状态 -const mapToTransferItem = (item) => { - const price = item.price != null ? Number(item.price).toFixed(2) : '0.00'; - const unit = item.unitCode_dictText || item.unitCode || ''; - return { - adviceDefinitionId: item.adviceDefinitionId, - orgId: item.orgId, - label: item.adviceName + ' (¥' + price + '/' + unit + ')', - key: item.adviceDefinitionId, +// 递归扁平化树形科室节点 +const flattenTree = (list) => { + if (!list) return []; + const result = []; + const walk = (nodes) => { + for (const node of nodes) { + result.push({ value: String(node.id), label: node.name }); + if (node.children?.length) walk(node.children); + } }; + walk(list); + return result; }; -const getList = () => { - if (!patientInfo.value?.inHospitalOrgId) { - applicationList.value = []; - return; +const orgOptions = ref([]); +const loading = ref(false); +const applicationList = ref([]); +const applicationListAll = ref([]); +const allLoading = ref(false); +// 递归查找默认科室 +const findTargetDepartment = (selectProjectIds) => { + if (!selectProjectIds || selectProjectIds.length === 0) return ''; + let dep = ''; + if (applicationListAll.value && applicationListAll.value.length > 0) { + const filtered = applicationListAll.value.filter((item) => { + return selectProjectIds.includes(item.adviceDefinitionId); + }); + if (filtered.length > 0) { + // 判断所选项目的所属科室是否一致 + const arr = filtered.map((item) => item.positionId).filter(Boolean); + if (new Set(arr).size === 1) { + dep = arr[0]; + } + } } - // 命中内存缓存时直接使用 - if (surgeryMappedCache && surgeryMappedCache.length > 0) { + return dep; +}; +const getList = async (key) => { + // 优先使用缓存(仅当没有搜索关键词时) + if (!key && surgeryRecordsCache && surgeryMappedCache) { applicationList.value = surgeryMappedCache; applicationListAll.value = surgeryRecordsCache; - loading.value = false; + dbTotal.value = surgeryRecordsCache.length; return; } - loadPage(''); -}; - -/** - * 加载手术项目分页数据 - * @param {string} key 搜索关键字(可选) - */ -const loadPage = (key) => { - const orgId = patientInfo.value.inHospitalOrgId; loading.value = true; - getSurgeryPage({ organizationId: orgId, pageNo: 1, pageSize: 100, searchKey: key || '' }) + getSurgeryPage({ + pageSize: 1000, + keyword: key || undefined, + }) .then((res) => { - if (res.code !== 200 || !res.data?.records) { - applicationList.value = []; - dbTotal.value = 0; - loading.value = false; - return; - } - dbTotal.value = res.data.total || 0; const records = res.data.records; applicationListAll.value = records; applicationList.value = records @@ -251,10 +447,26 @@ const filterMethod = (query, item) => { return label.includes(q) || key.includes(q); }; +const mapToTransferItem = (item) => ({ + key: String(item.adviceDefinitionId), + label: `${item.adviceName} - ${item.unitCode || ''}`, + disabled: false, +}); + const transferValue = ref([]); const form = reactive({ // categoryType: '', // 项目类别 targetDepartment: '', // 发往科室 + // === 新增手术业务字段 === + surgeryLevel: '', // 手术等级 + anesthesiaType: '', // 麻醉方式 + surgerySite: '', // 手术部位 + incisionLevel: '', // 切口类别 + surgeryNature: '', // 手术性质 + mainSurgeonId: '', // 主刀医生ID + assistant1Id: '', // 第一助手ID + assistant2Id: '', // 第二助手ID + plannedTime: '', // 预定手术时间 symptom: '', // 症状 sign: '', // 体征 clinicalDiagnosis: '', // 临床诊断 @@ -265,10 +477,73 @@ const form = reactive({ otherDiagnosisList: [], //其他断目录 }); const rules = reactive({}); +// 字典选项 +const surgeryLevelOptions = ref([]); +const anesthesiaTypeOptions = ref([]); +const surgerySiteOptions = ref([]); +const incisionLevelOptions = ref([]); +const surgeryNatureOptions = ref([]); +// 医生选项 +const doctorOptions = ref([]); + onBeforeMount(() => {}); onMounted(() => { getList(); + loadDictOptions(); + loadDoctorOptions(); }); + +/** + * 加载字典选项 + */ +const loadDictOptions = async () => { + try { + const res = await Promise.all([ + getDicts('surgery_level'), + getDicts('anesthesia_type'), + getDicts('surgery_site'), + getDicts('incision_level'), + getDicts('surgery_type'), + ]); + surgeryLevelOptions.value = (res[0]?.data || []).map(p => ({ label: p.dictLabel, value: p.dictValue })); + anesthesiaTypeOptions.value = (res[1]?.data || []).map(p => ({ label: p.dictLabel, value: p.dictValue })); + surgerySiteOptions.value = (res[2]?.data || []).map(p => ({ label: p.dictLabel, value: p.dictValue })); + incisionLevelOptions.value = (res[3]?.data || []).map(p => ({ label: p.dictLabel, value: p.dictValue })); + surgeryNatureOptions.value = (res[4]?.data || []).map(p => ({ label: p.dictLabel, value: p.dictValue })); + } catch (e) { + console.error('加载手术字典数据失败:', e); + } +}; + +/** + * 加载医生选项列表 + */ +const loadDoctorOptions = async () => { + try { + const res = await listUser({ pageNo: 1, pageSize: 1000 }); + if (res.code === 200) { + const data = res.data?.records || res.rows || res.data || []; + if (Array.isArray(data)) { + doctorOptions.value = data.map(item => ({ + id: item.practitionerId || item.id || item.userId, + name: item.nickName || item.name || item.userName, + })); + } + } + // 默认主刀医生设为当前登录用户 + if (userStore.nickName) { + const currentUser = doctorOptions.value.find( + doc => doc.name === userStore.nickName + ); + if (currentUser) { + form.mainSurgeonId = currentUser.id; + } + } + } catch (e) { + console.error('加载医生列表失败:', e); + } +}; + /** * type(1:watch监听类型 2:点击保存类型) * selectProjectIds(选中项目的id数组) @@ -289,6 +564,22 @@ const submit = () => { if (!form.targetDepartment) { return proxy.$message.error('请选择发往科室'); } + // 新增必填校验 + if (!form.surgeryLevel) { + return proxy.$message.error('请选择手术等级'); + } + if (!form.anesthesiaType) { + return proxy.$message.error('请选择麻醉方式'); + } + if (!form.surgerySite) { + return proxy.$message.error('请选择手术部位'); + } + if (!form.mainSurgeonId) { + return proxy.$message.error('请选择主刀医生'); + } + if (!form.plannedTime) { + return proxy.$message.error('请选择预定手术时间'); + } let applicationListAllFilter = applicationListAll.value.filter((item) => { return transferValue.value.includes(item.adviceDefinitionId); });