1 Commits

Author SHA1 Message Date
荀彧
0ab046685c Fix Bug #428: 门诊医生站-检查申请:未实现分类联动检查方法及套餐明细展示与勾选逻辑
1. handleMethodSelect 中新增/更新已选项时,设置 expanded=true 使套餐明细自动展开
2. toggleItemExpand 中改用 packageDetailsDisplay/carrier.packageDetails 判断是否已加载明细
   (原代码检查非响应式的 item.packageDetails,导致重复加载或加载判断失效)

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-14 18:08:55 +08:00
8 changed files with 49 additions and 90 deletions

View File

@@ -728,12 +728,8 @@ public class DoctorStationAdviceAppServiceImpl implements IDoctorStationAdviceAp
/** /**
* 处理耗材请求 * 处理耗材请求
* 🔧 BugFix #443: 签发时跳过 handDevice避免重复创建 DeviceDispense 并覆盖关键字段(如 performLocation
* 签发时只需更新状态(下方 sign-advice 批量更新逻辑已处理)
*/ */
if (AdviceOpType.SAVE_ADVICE.getCode().equals(adviceOpType)) { this.handDevice(deviceList, curDate, adviceOpType);
this.handDevice(deviceList, curDate, adviceOpType);
}
// 签发时,把草稿状态的账单更新为待收费 // 签发时,把草稿状态的账单更新为待收费
if (AdviceOpType.SIGN_ADVICE.getCode().equals(adviceOpType) && !adviceSaveList.isEmpty()) { if (AdviceOpType.SIGN_ADVICE.getCode().equals(adviceOpType) && !adviceSaveList.isEmpty()) {

View File

@@ -246,8 +246,7 @@ public class DoctorStationDiagnosisAppServiceImpl implements IDoctorStationDiagn
EncounterDiagnosis encounterDiagnosis; EncounterDiagnosis encounterDiagnosis;
for (SaveDiagnosisChildParam saveDiagnosisChildParam : diagnosisChildList) { for (SaveDiagnosisChildParam saveDiagnosisChildParam : diagnosisChildList) {
encounterDiagnosis = new EncounterDiagnosis(); encounterDiagnosis = new EncounterDiagnosis();
// 注意:不设置 encounterDiagnosisId因为上面已经删除了所有记录 encounterDiagnosis.setId(saveDiagnosisChildParam.getEncounterDiagnosisId());
// 如果设置旧的 IDsaveOrUpdate 会尝试 UPDATE 不存在的记录导致失败或重复插入
encounterDiagnosis.setEncounterId(encounterId); encounterDiagnosis.setEncounterId(encounterId);
encounterDiagnosis.setConditionId(saveDiagnosisChildParam.getConditionId()); encounterDiagnosis.setConditionId(saveDiagnosisChildParam.getConditionId());
encounterDiagnosis.setMaindiseFlag(saveDiagnosisChildParam.getMaindiseFlag()); encounterDiagnosis.setMaindiseFlag(saveDiagnosisChildParam.getMaindiseFlag());

View File

@@ -91,15 +91,13 @@
os.surgery_nature AS surgeryType, os.surgery_nature AS surgeryType,
cs.incision_level AS incisionLevel, cs.incision_level AS incisionLevel,
fc.contract_name AS feeType, fc.contract_name AS feeType,
os.fee_type AS feeType,
COALESCE(pi.identifier_no, ap.bus_no, '') AS identifierNo COALESCE(pi.identifier_no, ap.bus_no, '') AS identifierNo
FROM op_schedule os FROM op_schedule os
LEFT JOIN adm_patient ap ON os.patient_id = ap.id LEFT JOIN adm_patient ap ON os.patient_id = ap.id
INNER JOIN cli_surgery cs ON os.oper_code = cs.surgery_no AND cs.delete_flag = '0' INNER JOIN cli_surgery cs ON os.oper_code = cs.surgery_no AND cs.delete_flag = '0'
LEFT JOIN adm_organization o ON cs.org_id = o.id LEFT JOIN adm_organization o ON cs.org_id = o.id
LEFT JOIN doc_request_form drf ON drf.prescription_no=cs.surgery_no LEFT JOIN doc_request_form drf ON drf.prescription_no=cs.surgery_no
LEFT JOIN adm_encounter ae ON ae.id = os.visit_id AND ae.delete_flag = '0'
LEFT JOIN adm_account aa ON aa.encounter_id = ae.id AND aa.delete_flag = '0'
LEFT JOIN fin_contract fc ON fc.bus_no = aa.contract_no AND fc.delete_flag = '0'
LEFT JOIN ( LEFT JOIN (
SELECT patient_id, identifier_no SELECT patient_id, identifier_no
FROM ( FROM (

View File

@@ -42,8 +42,8 @@
T5.package_name, T5.package_name,
T6.name as sub_item_name T6.name as sub_item_name
FROM wor_activity_definition T1 FROM wor_activity_definition T1
/* 价格表使用LEFT JOIN避免因缺少价格记录导致搜索不到项目 */ /* 只JOIN必要的价格表使用INNER JOIN避免笛卡尔积 */
LEFT JOIN adm_charge_item_definition T2 INNER JOIN adm_charge_item_definition T2
ON T1.id = T2.instance_id ON T1.id = T2.instance_id
AND T2.instance_table = 'wor_activity_definition' AND T2.instance_table = 'wor_activity_definition'
/* 检验类型关联 */ /* 检验类型关联 */

View File

@@ -45,6 +45,18 @@
<if test="endDate != null and endDate != ''"> <if test="endDate != null and endDate != ''">
AND drf.create_time &lt;= (#{endDate}::date + INTERVAL '1 day' - INTERVAL '1 second') AND drf.create_time &lt;= (#{endDate}::date + INTERVAL '1 day' - INTERVAL '1 second')
</if> </if>
<if test="status != null and status != ''">
AND CASE
WHEN MIN(wsr.status_enum) = 1 THEN 0
WHEN MIN(wsr.status_enum) = 2 THEN 1
WHEN MIN(wsr.status_enum) = 3 AND MAX(CASE WHEN wsr.performer_check_id IS NOT NULL THEN 1 ELSE 0 END) = 1 THEN 2
WHEN MIN(wsr.status_enum) = 3 THEN 4
WHEN MIN(wsr.status_enum) = 4 THEN 3
WHEN MIN(wsr.status_enum) = 5 OR MIN(wsr.status_enum) = 6 OR MIN(wsr.status_enum) = 7 THEN 7
WHEN MIN(wsr.status_enum) = 8 THEN 6
ELSE NULL
END = #{status}::integer
</if>
<if test="keyword != null and keyword != ''"> <if test="keyword != null and keyword != ''">
AND (drf.prescription_no ILIKE '%' || #{keyword} || '%' AND (drf.prescription_no ILIKE '%' || #{keyword} || '%'
OR EXISTS ( OR EXISTS (
@@ -60,19 +72,6 @@
</if> </if>
GROUP BY drf.id, drf.encounter_id, drf.prescription_no, drf.name, drf.desc_json, GROUP BY drf.id, drf.encounter_id, drf.prescription_no, drf.name, drf.desc_json,
drf.requester_id, drf.create_time, ap.name drf.requester_id, drf.create_time, ap.name
<if test="status != null and status != ''">
HAVING CASE MIN(wsr.status_enum)
WHEN 1 THEN 0
WHEN 2 THEN 1
WHEN 3 THEN 4
WHEN 4 THEN 4
WHEN 5 THEN 5
WHEN 6 THEN 5
WHEN 7 THEN 5
WHEN 8 THEN 6
ELSE NULL
END = #{status}::integer
</if>
</select> </select>
<select id="getRequestFormDetail" resultType="com.openhis.web.regdoctorstation.dto.RequestFormDetailQueryDto"> <select id="getRequestFormDetail" resultType="com.openhis.web.regdoctorstation.dto.RequestFormDetailQueryDto">

View File

@@ -1582,7 +1582,7 @@ async function loadMethodPackageDetails(item, method) {
const packageId = packages[0].id; const packageId = packages[0].id;
// 查询套餐明细 // 查询套餐明细
const detailRes = await request({ const detailRes = await request({
url: `/system/check-type/package/${packageId}/details`, url: `/system/package/${packageId}/details`,
method: 'get' method: 'get'
}); });
if (detailRes.code === 200 && detailRes.data) { if (detailRes.code === 200 && detailRes.data) {

View File

@@ -289,62 +289,43 @@ function getList() {
return obj; return obj;
}); });
form.value.diagnosisList = datas; form.value.diagnosisList = datas;
// 去重:按 conditionId 去重,防止后端重复插入导致重复记录 // form.value.diagnosisList = res.data;
deduplicateDiagnosisList();
emits('diagnosisSave', false); emits('diagnosisSave', false);
} }
}); });
getTcmDiagnosis({ encounterId: props.patientInfo.encounterId }).then((res) => { getTcmDiagnosis({ encounterId: props.patientInfo.encounterId }).then((res) => {
console.log('getTcmDiagnosis=======>', JSON.stringify(res.data?.illness)); console.log('getTcmDiagnosis=======>', JSON.stringify(res.data.illness));
if (res.code == 200 && res.data?.illness?.length > 0) { if (res.code == 200) {
diagnosisNetDatas.value = res.data.illness; if (res.data.illness.length > 0) {
res.data.illness.forEach((item, index) => { diagnosisNetDatas.value = res.data.illness;
newList.push({ res.data.illness.forEach((item, index) => {
name: item.name + '-' + (res.data.symptom?.[index]?.name || ''), newList.push({
ybNo: item.ybNo, name: item.name + '-' + (res.data.symptom[index]?.name || ''),
medTypeCode: item.medTypeCode, ybNo: item.ybNo,
diagnosisDoctor: props.patientInfo.practitionerName || props.patientInfo.doctorName || props.patientInfo.physicianName || userStore.name, medTypeCode: item.medTypeCode,
diagnosisTime: new Date().toLocaleString('zh-CN') diagnosisDoctor: props.patientInfo.practitionerName || props.patientInfo.doctorName || props.patientInfo.physicianName || userStore.name,
diagnosisTime: new Date().toLocaleString('zh-CN')
});
}); });
});
// 将新数据添加到现有列表中 // 将新数据添加到现有列表中
form.value.diagnosisList.push(...newList); form.value.diagnosisList.push(...newList);
// 重新排序整个列表 // 重新排序整个列表
form.value.diagnosisList.sort((a, b) => { form.value.diagnosisList.sort((a, b) => {
const aNo = typeof a.diagSrtNo === 'number' ? a.diagSrtNo : 9999; const aNo = typeof a.diagSrtNo === 'number' ? a.diagSrtNo : 9999;
const bNo = typeof b.diagSrtNo === 'number' ? b.diagSrtNo : 9999; const bNo = typeof b.diagSrtNo === 'number' ? b.diagSrtNo : 9999;
return aNo - bNo; return aNo - bNo;
}); });
// TCM 数据添加后也去重 }
deduplicateDiagnosisList(); emits('diagnosisSave', false);
} }
emits('diagnosisSave', false);
}); });
getTree(); getTree();
} }
/**
* 诊断列表去重:按 ybNo + name 组合去重,保留第一条记录
* 防止后端 saveOrUpdate 在删除后误 INSERT 导致重复
*/
function deduplicateDiagnosisList() {
const seen = new Set();
const dedupedList = [];
for (const item of form.value.diagnosisList) {
// 使用 ybNo 和 name 组合作为唯一标识(中医诊断没有 ybNo用 name 去重)
const key = item.ybNo ? `${item.ybNo}` : `name_${item.name}`;
if (!seen.has(key)) {
seen.add(key);
dedupedList.push(item);
}
}
form.value.diagnosisList = dedupedList;
}
init(); init();
function init() { function init() {
diagnosisInit().then((res) => { diagnosisInit().then((res) => {
@@ -622,18 +603,6 @@ function handleSaveDiagnosis() {
return aNo - bNo; return aNo - bNo;
}); });
// 步骤1.5:确保每条诊断都有诊断医生和诊断时间(元数据补全)
const doctorName = props.patientInfo.practitionerName || props.patientInfo.doctorName || props.patientInfo.physicianName || userStore.name;
const now = new Date().toLocaleString('zh-CN');
sortedList.forEach((item) => {
if (!item.diagnosisDoctor) {
item.diagnosisDoctor = doctorName;
}
if (!item.diagnosisTime) {
item.diagnosisTime = now;
}
});
// 步骤2重新分配连续的序号从1开始 // 步骤2重新分配连续的序号从1开始
sortedList.forEach((item, index) => { sortedList.forEach((item, index) => {
item.diagSrtNo = index + 1; // 这里是关键!把”诊断排序”改成新顺序 item.diagSrtNo = index + 1; // 这里是关键!把”诊断排序”改成新顺序

View File

@@ -1131,15 +1131,15 @@ function handleLocationClick(item, row, index) {
.then((res) => { .then((res) => {
const list = res.data || []; const list = res.data || [];
const d = pickBestOrgQuantityRow(list); const d = pickBestOrgQuantityRow(list);
const strictOk = d && Number(d.orgQuantity ?? 0) > 0;
// 严格批号查询有库存orgQuantity > 0 if (strictOk) {
if (d && Number(d.orgQuantity ?? 0) > 0) {
applyFromDto(d, false); applyFromDto(d, false);
if (Number(r.totalQuantity) <= 0) {
proxy.$message.warning('仓库数量为0无法调用');
}
persistStore(); persistStore();
return; return;
} }
// 严格查询无库存或数量为0 → 回退到非严格查询(查同仓库其他批号)
if (lotTrimmed) { if (lotTrimmed) {
return runGet(false).then((res2) => { return runGet(false).then((res2) => {
const list2 = res2.data || []; const list2 = res2.data || [];
@@ -1157,8 +1157,6 @@ function handleLocationClick(item, row, index) {
persistStore(); persistStore();
}); });
} }
// 没有指定批号,直接提示
r.totalQuantity = 0; r.totalQuantity = 0;
r.price = 0; r.price = 0;
proxy.$message.warning('仓库数量为0无法调用'); proxy.$message.warning('仓库数量为0无法调用');