refactor(inhospitalnursestation): 优化入院护士站应用的数据库查询性能

- 将CTE查询重构为子查询以提高执行效率
- 为位置和医生查询添加LIMIT 1约束以减少数据量
- 移除不必要的GROUP BY子句以简化查询逻辑
- 在前端组件中实现异步数据加载和错误处理机制
- 使用可选链操作符处理空值情况避免报错
- 添加防抖机制解决单击双击冲突问题
- 优化患者列表和床位列表的并行加载逻辑
- 清理调试用的console.log语句并替换为有意义的信息
This commit is contained in:
2026-01-19 22:36:04 +08:00
parent aa3beb848b
commit 803e4d0bb5
14 changed files with 234 additions and 171 deletions

View File

@@ -1,10 +0,0 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>测试合并11111</title>
</head>
<body>
</body>
</html>

View File

@@ -224,27 +224,6 @@
</select>
<select id="selectAdmissionPatientInfo"
resultType="com.openhis.web.inhospitalnursestation.dto.AdmissionPatientInfoDto">
WITH locations AS (SELECT ael.encounter_id,
ael.start_time,
al.form_enum,
al.id AS location_id,
al."name" AS location_name
FROM adm_encounter_location ael
LEFT JOIN adm_location al
ON ael.location_id = al.id
AND al.delete_flag = '0'
WHERE ael.status_enum = #{active}
AND ael.delete_flag = '0'),
practitioners AS (SELECT aep.encounter_id,
aep.type_code,
pra.id AS practitioner_id,
pra."name" AS practitioner_name
FROM adm_encounter_participant aep
LEFT JOIN adm_practitioner pra
ON aep.practitioner_id = pra.id
AND pra.delete_flag = '0'
WHERE aep.status_enum = #{active}
AND aep.delete_flag = '0')
SELECT ae.id AS encounter_id,
ae.bus_no,
ae.priority_enum,
@@ -273,27 +252,84 @@
fc.contract_name,
diagnosis.condition_names
FROM adm_encounter ae
LEFT JOIN locations AS bed
ON bed.encounter_id = ae.id
AND bed.form_enum = #{bed}
LEFT JOIN locations AS house
ON house.encounter_id = ae.id
AND house.form_enum = #{house}
LEFT JOIN locations AS ward
ON ward.encounter_id = ae.id
AND ward.form_enum = #{ward}
LEFT JOIN practitioners AS primaryNurse
ON primaryNurse.encounter_id = ae.id
AND primaryNurse.type_code = #{primaryNurse}
LEFT JOIN practitioners AS attendingDoctor
ON attendingDoctor.encounter_id = ae.id
AND attendingDoctor.type_code = #{attendingDoctor}
LEFT JOIN practitioners AS admittingDoctor
ON admittingDoctor.encounter_id = ae.id
AND admittingDoctor.type_code = #{admittingDoctor}
LEFT JOIN practitioners AS chiefDoctor
ON chiefDoctor.encounter_id = ae.id
AND chiefDoctor.type_code = #{chiefDoctor}
LEFT JOIN (
SELECT ael.encounter_id,
ael.start_time,
al.id AS location_id,
al."name" AS location_name
FROM adm_encounter_location ael
LEFT JOIN adm_location al ON ael.location_id = al.id AND al.delete_flag = '0'
WHERE ael.status_enum = #{active}
AND ael.delete_flag = '0'
AND ael.form_enum = #{bed}
LIMIT 1
) AS bed ON bed.encounter_id = ae.id
LEFT JOIN (
SELECT ael.encounter_id,
al.id AS location_id,
al."name" AS location_name
FROM adm_encounter_location ael
LEFT JOIN adm_location al ON ael.location_id = al.id AND al.delete_flag = '0'
WHERE ael.status_enum = #{active}
AND ael.delete_flag = '0'
AND ael.form_enum = #{house}
LIMIT 1
) AS house ON house.encounter_id = ae.id
LEFT JOIN (
SELECT ael.encounter_id,
al.id AS location_id,
al."name" AS location_name
FROM adm_encounter_location ael
LEFT JOIN adm_location al ON ael.location_id = al.id AND al.delete_flag = '0'
WHERE ael.status_enum = #{active}
AND ael.delete_flag = '0'
AND ael.form_enum = #{ward}
LIMIT 1
) AS ward ON ward.encounter_id = ae.id
LEFT JOIN (
SELECT aep.encounter_id,
pra.id AS practitioner_id,
pra."name" AS practitioner_name
FROM adm_encounter_participant aep
LEFT JOIN adm_practitioner pra ON aep.practitioner_id = pra.id AND pra.delete_flag = '0'
WHERE aep.status_enum = #{active}
AND aep.delete_flag = '0'
AND aep.type_code = #{primaryNurse}
LIMIT 1
) AS primaryNurse ON primaryNurse.encounter_id = ae.id
LEFT JOIN (
SELECT aep.encounter_id,
pra.id AS practitioner_id,
pra."name" AS practitioner_name
FROM adm_encounter_participant aep
LEFT JOIN adm_practitioner pra ON aep.practitioner_id = pra.id AND pra.delete_flag = '0'
WHERE aep.status_enum = #{active}
AND aep.delete_flag = '0'
AND aep.type_code = #{attendingDoctor}
LIMIT 1
) AS attendingDoctor ON attendingDoctor.encounter_id = ae.id
LEFT JOIN (
SELECT aep.encounter_id,
pra.id AS practitioner_id,
pra."name" AS practitioner_name
FROM adm_encounter_participant aep
LEFT JOIN adm_practitioner pra ON aep.practitioner_id = pra.id AND pra.delete_flag = '0'
WHERE aep.status_enum = #{active}
AND aep.delete_flag = '0'
AND aep.type_code = #{admittingDoctor}
LIMIT 1
) AS admittingDoctor ON admittingDoctor.encounter_id = ae.id
LEFT JOIN (
SELECT aep.encounter_id,
pra.id AS practitioner_id,
pra."name" AS practitioner_name
FROM adm_encounter_participant aep
LEFT JOIN adm_practitioner pra ON aep.practitioner_id = pra.id AND pra.delete_flag = '0'
WHERE aep.status_enum = #{active}
AND aep.delete_flag = '0'
AND aep.type_code = #{chiefDoctor}
LIMIT 1
) AS chiefDoctor ON chiefDoctor.encounter_id = ae.id
LEFT JOIN adm_organization ao
ON ao.id = ae.organization_id
AND ao.delete_flag = '0'
@@ -307,47 +343,17 @@
LEFT JOIN fin_contract fc
ON aa.contract_no = fc.bus_no
AND fc.delete_flag = '0'
LEFT JOIN (SELECT aed.encounter_id,
STRING_AGG(ccd.name, ', ') AS condition_names
FROM adm_encounter_diagnosis aed
INNER JOIN cli_condition cc
ON cc.id = aed.condition_id
AND cc.delete_flag = '0'
INNER JOIN cli_condition_definition ccd
ON ccd.id = cc.definition_id
AND ccd.delete_flag = '0'
WHERE aed.delete_flag = '0'
GROUP BY aed.encounter_id) AS diagnosis
ON ae.id = diagnosis.encounter_id
LEFT JOIN (
SELECT aed.encounter_id,
STRING_AGG(ccd.name, ', ') AS condition_names
FROM adm_encounter_diagnosis aed
INNER JOIN cli_condition cc ON cc.id = aed.condition_id AND cc.delete_flag = '0'
INNER JOIN cli_condition_definition ccd ON ccd.id = cc.definition_id AND ccd.delete_flag = '0'
WHERE aed.delete_flag = '0'
GROUP BY aed.encounter_id
) AS diagnosis ON ae.id = diagnosis.encounter_id
WHERE ae.id = #{encounterId}
AND ae.delete_flag = '0'
GROUP BY ae.id,
ae.bus_no,
ae.priority_enum,
ae.organization_id,
ae.start_time,
bed.start_time,
bed.location_id,
bed.location_name,
house.location_id,
house.location_name,
ward.location_id,
ward.location_name,
primaryNurse.practitioner_id,
primaryNurse.practitioner_name,
attendingDoctor.practitioner_id,
attendingDoctor.practitioner_name,
admittingDoctor.practitioner_id,
admittingDoctor.practitioner_name,
chiefDoctor.practitioner_id,
chiefDoctor.practitioner_name,
ao."name",
ap."name",
ap.gender_enum,
ap.birth_date,
ap.phone,
fc.contract_name,
diagnosis.condition_names
</select>
<select id="getAmount" resultType="com.openhis.web.inhospitalnursestation.dto.EncounterAccountDto">
SELECT aa.id,

View File

@@ -347,7 +347,7 @@ const printForm = () => {
};
function handleClick() {
console.log('112313413');
console.log('住院记录表单点击事件触发');
}
const resetFun = (data) => {

View File

@@ -582,7 +582,7 @@ function submitForm() {
console.log('params11========>', JSON.stringify(params));
orgRef.value.validate((valid) => {
if (valid) {
console.log('99999999');
console.log('表单验证通过,准备提交数据');
if (form.busNoParent) {
if (form.formEnum == 4) {

View File

@@ -59,12 +59,12 @@ const doRegistering = (row: any) => {
// })
/* 取消 */
const cancelAct = () => {
console.log('121231');
console.log('取消患者列表对话框操作');
}
/* 保存,登记 */
const handleSubmit = () => {
console.log('121231');
console.log('提交患者列表对话框操作');
}
defineExpose({})

View File

@@ -544,7 +544,7 @@ function handleDatePickerChange() {
// 清空
const onClear = () => {
console.log('1111111111');
console.log('费用明细查询条件已清空');
const today = new Date();
dateRangeValue.value = [formatDateStr(today, 'YYYY-MM-DD'), formatDateStr(today, 'YYYY-MM-DD')];

View File

@@ -44,8 +44,8 @@
>
<div class="bed-card__body">
<div>
<div class="bed-card__title" :title="item.houseName + '-' + item.bedName">
{{ item.houseName + '-' + item.bedName }}
<div class="bed-card__title" :title="(item.houseName || '-') + '-' + (item.bedName || '-')">
{{ (item.houseName || '-') + '-' + (item.bedName || '-') }}
</div>
<div class="bed-tag" :class="getBedTagClass(item)">
{{ item.bedStatus_enumText }}
@@ -130,6 +130,8 @@ const initInfoOptions = ref<InitInfoOptions>({
priorityOptions: [],
wardListOptions: [],
});
// 用于处理单击/双击冲突
let clickTimer = null;
let loadingInstance: any = undefined;
// 入院病区loading
const selectHosLoding = ref(true);
@@ -223,29 +225,38 @@ const queryParams = ref<{
bedStatus: '', // 这个字段现在只用于床位查询,不再用于患者列表查询
});
const ininData = () => {
Promise.all([
getInit().then((res) => {
initInfoOptions.value = res.data;
priorityOptions.value = res.data.priorityOptions || [];
return res;
}),
getPractitionerWard().then((res) => {
selectHosLoding.value = false;
queryParams.value.wardId = res[0].id;
initInfoOptions.value.wardListOptions = res;
return changeWardLocationId(res[0].id, true); // 传入 true 表示初始化阶段,不调用 getList
}),
]).then(() => {
const ininData = async () => {
try {
// 先获取初始化数据
const initRes = await getInit();
initInfoOptions.value = initRes.data;
priorityOptions.value = initRes.data.priorityOptions || [];
// 然后获取科室数据
const wardRes = await getPractitionerWard();
selectHosLoding.value = false;
queryParams.value.wardId = wardRes[0]?.id || '';
initInfoOptions.value.wardListOptions = wardRes;
// 获取病房数据
if (wardRes[0]?.id) {
await changeWardLocationId(wardRes[0].id, true); // 传入 true 表示初始化阶段,不调用 getList
}
// 最后获取列表数据
getList();
});
} catch (error) {
console.error('初始化数据失败:', error);
// 即使某个请求失败,也要尝试加载列表
getList();
}
};
onMounted(() => {
ininData();
});
const refreshTap = () => {
ininData();
const refreshTap = async () => {
await ininData();
};
defineExpose({ state, refreshTap });
@@ -257,23 +268,32 @@ const filteredBadList = computed(() => {
return badList.value.filter((item) => item.bedStatus == bedStatusFilter.value);
});
const getList = () => {
const getList = async () => {
loadingInstance = ElLoading.service({ fullscreen: true });
getPatientList();
// 床位查询不使用encounterStatus参数只使用基本的查询参数
const bedQueryParams = {
...queryParams.value,
encounterStatus: undefined, // 移除encounterStatus确保不影响床位列表查询
};
getBedInfo(bedQueryParams).then((res) => {
loadingInstance.close();
badList.value = res.data.records;
});
try {
// 并行获取患者列表和床位列表
const [patientData, bedRes] = await Promise.all([
getPatientList(),
getBedInfo({
...queryParams.value,
encounterStatus: undefined, // 移除encounterStatus确保不影响床位列表查询
})
]);
// 更新床位列表
badList.value = bedRes.data.records;
} catch (error) {
console.error('获取列表数据失败:', error);
} finally {
if (loadingInstance) {
loadingInstance.close();
}
}
};
// 重置查询条件
function resetQuery() {
async function resetQuery() {
// 不重置入院病区
const resetParams = {
...queryParams.value,
@@ -288,7 +308,7 @@ function resetQuery() {
bedStatus: '',
};
bedStatusFilter.value = '';
getList();
await getList();
}
// 入院病区下拉选
function changeWardLocationId(id: string | number, isInit = false) {
@@ -302,41 +322,72 @@ function changeWardLocationId(id: string | number, isInit = false) {
selectHoouseLoding.value = false;
wardLocationList.value = res;
if (!isInit) {
getList();
// 在非初始化情况下,需要同时更新患者列表和床位列表
getPatientList();
// 床位查询不使用encounterStatus参数只使用基本的查询参数
const bedQueryParams = {
...queryParams.value,
encounterStatus: undefined, // 移除encounterStatus确保不影响床位列表查询
};
getBedInfo(bedQueryParams).then((bedRes) => {
badList.value = bedRes.data.records;
});
}
return res;
});
}
// 入院病房下拉选
const onHosHouse = () => {
getList();
const onHosHouse = async () => {
await getList();
};
// 住院状态下拉选
const onHosStatus = () => {
getList();
const onHosStatus = async () => {
await getList();
};
// 获新入院患者列表
function getPatientList() {
async function getPatientList() {
// 为患者列表查询创建一个新的参数对象不包含bedStatus
const patientQueryParams = {
...queryParams.value,
bedStatus: undefined, // 移除bedStatus确保不影响患者列表查询
};
getPendingInfo(patientQueryParams).then((res) => {
try {
const res = await getPendingInfo(patientQueryParams);
loading.value = false;
patientList.value = res.data.records;
total.value = res.data.total;
});
return res;
} catch (error) {
console.error('获取患者列表失败:', error);
throw error;
}
}
const handleTransferInOk = () => {
const handleTransferInOk = async () => {
transferInDialogVisible.value = false;
getList();
await getList();
};
function handleCardClick(item: any, index: number) {}
// 单击患者卡片事件 - 直接触发入科选床界面
function handleCardClick(item: any, index: number) {
if (item.encounterStatus == 2) {
ElMessage({
message: '请分配病床!',
type: 'warning',
grouping: true,
showClose: true,
});
} else {
pendingInfo.value = {
...item,
entranceType: 1,
};
// 双击患者卡片事件
transferInDialogVisible.value = true;
}
}
// 双击患者卡片事件 - 保持原有逻辑
function handleCardDblClick(item: any) {
if (item.encounterStatus == 2) {
ElMessage({
@@ -367,8 +418,8 @@ function handleDragStart(event: DragEvent, item: any) {
}
}
function handleQuery() {
getList();
async function handleQuery() {
await getList();
}
// 拖拽结束事件

View File

@@ -17,7 +17,7 @@
<div class="patient-info">
<div style="display: flex; align-items: center; margin-bottom: 16px">
<div style="margin-right: 36px; font-size: 18px; font-weight: 700">
{{ props.pendingInfo.houseName + '-' + props.pendingInfo.bedName }}
{{ (props.pendingInfo.houseName || '-') + '-' + (props.pendingInfo.bedName || '-') }}
</div>
<div style="border-radius: 50px; border: 2px solid slategray; padding: 4px 12px">
{{ props.pendingInfo.contractName }}

View File

@@ -746,25 +746,42 @@ function handleGetDRMedication() {
});
}
const initData = () => {
getInit().then((res) => {
initInfoOptions.value = res.data;
const initData = async () => {
try {
// 并行获取初始化数据和科室数据
const [initRes, wardRes] = await Promise.all([
getInit(),
getPractitionerWard()
]);
// 处理初始化数据
initInfoOptions.value = initRes.data;
// 处理科室数据
queryParams.value.wardId = wardRes[0]?.id || '';
initInfoOptions.value.wardListOptions = wardRes;
// 获取病房数据
if (wardRes[0]?.id) {
changeWardLocationId(wardRes[0].id);
}
// 最后获取患者列表
getPatientList();
});
getPractitionerWard().then((res) => {
queryParams.value.wardId = res[0].id;
initInfoOptions.value.wardListOptions = res;
changeWardLocationId(res[0].id);
});
} catch (error) {
console.error('初始化数据失败:', error);
// 即使初始化失败,也要尝试加载患者列表
getPatientList();
}
};
// 初始化加载患者列表
onMounted(() => {
initData();
onMounted(async () => {
await initData();
});
const refreshTap = () => {
console.log('22222223');
initData();
const refreshTap = async () => {
console.log('刷新转科/出院页面数据');
await initData();
};
defineExpose({ refreshTap });
</script>

View File

@@ -44,16 +44,15 @@ const thirdRef = ref();
onBeforeMount(() => {});
onMounted(() => {});
defineExpose({ state });
const test = () => {
nextTick(() => {
if (activeTabName.value == 'first') {
firstRef?.value?.refreshTap();
} else if (activeTabName.value == 'second') {
secondRef?.value?.refreshTap();
} else if (activeTabName.value == 'third') {
thirdRef?.value?.refreshTap();
}
});
const test = async () => {
await nextTick();
if (activeTabName.value == 'first') {
await firstRef?.value?.refreshTap();
} else if (activeTabName.value == 'second') {
await secondRef?.value?.refreshTap();
} else if (activeTabName.value == 'third') {
await thirdRef?.value?.refreshTap();
}
};
const activeTabName = ref('first');

View File

@@ -496,7 +496,7 @@ const dateChange = () => {
};
// 计算时间
rulesFrom.value.recordTime = computed(() => {
console.log('11111111111111');
console.log('操作记录时间计算', rulesFrom.value.date + ' ' + rulesFrom.value.time);
return rulesFrom.value.date + ' ' + rulesFrom.value.time;
});

View File

@@ -274,7 +274,7 @@ function init1(data) {
* 点击患者列表行 获取患者体温单数据
*/
function viewPatient(row) {
console.log('1232312123221231');
console.log('查看患者体温单数据', row.patientName);
patientInfo.value = row;
console.log('点击患者列表行 获取患者体温单数据', row);

View File

@@ -557,7 +557,7 @@ watch(
queryParams.value.dispenseTimeETime = newQuery.occurrenceTimeETime + ' 23:59:59';
}
queryParams.value.flag = 1;
console.log('11111111111111');
console.log('药品明细查询参数已设置完成');
// 执行查询
getList();

View File

@@ -218,7 +218,7 @@ watch(
if (currentMonth < birthMonth || (currentMonth === birthMonth && currentDay < birthDay)) {
age--;
}
console.log('22222222');
console.log('计算患者年龄完成:', age);
form.value.age = age;
}