Compare commits
61 Commits
bug475-fix
...
c012974fd0
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
c012974fd0 | ||
|
|
5a83ff2aca | ||
|
|
92ce2d10a1 | ||
|
|
420a5a977a | ||
|
|
6e0e78cd8d | ||
|
|
763c822574 | ||
|
|
9bec956b4f | ||
|
|
65a772c7b2 | ||
| 994fd9bacc | |||
|
|
cec8a44bd9 | ||
|
|
8157063749 | ||
|
|
41562c5bbd | ||
|
|
51fba4488e | ||
|
|
00ff4158a1 | ||
|
|
a09020a4fd | ||
|
|
f7a3f658fb | ||
|
|
dd36dc49ea | ||
|
|
1c9bb92663 | ||
|
|
6ddd9bb2dc | ||
|
|
c8ed4e5856 | ||
|
|
253ceaffc6 | ||
|
|
ed7c388d11 | ||
|
|
f581f72693 | ||
|
|
55b517c8c6 | ||
|
|
0c36230158 | ||
|
|
351a2fba2e | ||
|
|
09e5825dab | ||
|
|
1f94efa1d2 | ||
|
|
d4d9ede5d7 | ||
|
|
876e46bfea | ||
|
|
7388e01b5d | ||
|
|
4af2fc5f54 | ||
|
|
c04432e39a | ||
|
|
21e68da15e | ||
|
|
6fdf96edab | ||
|
|
2ef1ce9f35 | ||
|
|
11fd9b839c | ||
|
|
5357ddb220 | ||
|
|
79bd7c0281 | ||
|
|
4c4f01abd1 | ||
|
|
b4d452995f | ||
|
|
23c75b147e | ||
|
|
1e431d096d | ||
|
|
e1de467b68 | ||
| 53a3460092 | |||
|
|
084d04d518 | ||
|
|
d7f8a20d76 | ||
| 331fc532fc | |||
|
|
dafa5961c4 | ||
|
|
f223192ec5 | ||
|
|
c7956a116b | ||
|
|
845354e863 | ||
|
|
56ea4b6af1 | ||
|
|
703e9ead43 | ||
|
|
a43f98cc5a | ||
|
|
9215c288d3 | ||
|
|
777ba71c7d | ||
|
|
c3dfd3eb21 | ||
|
|
8093f8acda | ||
|
|
8fae6fe3d5 | ||
|
|
5af86494dd |
@@ -228,10 +228,8 @@ public class DoctorStationAdviceAppServiceImpl implements IDoctorStationAdviceAp
|
||||
// 医嘱定义ID集合
|
||||
List<Long> adviceDefinitionIdList = adviceBaseDtoList.stream().map(AdviceBaseDto::getAdviceDefinitionId)
|
||||
.collect(Collectors.toList());
|
||||
// 费用定价主表ID集合(过滤null值,手术项目无定价定义)
|
||||
List<Long> chargeItemDefinitionIdList = adviceBaseDtoList.stream()
|
||||
.map(AdviceBaseDto::getChargeItemDefinitionId)
|
||||
.filter(Objects::nonNull)
|
||||
// 费用定价主表ID集合
|
||||
List<Long> chargeItemDefinitionIdList = adviceBaseDtoList.stream().map(AdviceBaseDto::getChargeItemDefinitionId)
|
||||
.collect(Collectors.toList());
|
||||
|
||||
// 判断是否包含药品或耗材类型(只有这些类型才需要库存相关查询)
|
||||
@@ -277,9 +275,9 @@ public class DoctorStationAdviceAppServiceImpl implements IDoctorStationAdviceAp
|
||||
medLocationConfig = Collections.emptyList();
|
||||
allowedLocByCategory = Collections.emptyMap();
|
||||
}
|
||||
// 费用定价子表信息 - 仅药品/耗材需要批次定价查询,手术/诊疗无库存概念不需要
|
||||
// 费用定价子表信息 - 使用分批处理避免大量参数问题
|
||||
List<AdvicePriceDto> childCharge = new ArrayList<>();
|
||||
if (hasMedOrDevice && chargeItemDefinitionIdList != null && !chargeItemDefinitionIdList.isEmpty()) {
|
||||
if (chargeItemDefinitionIdList != null && !chargeItemDefinitionIdList.isEmpty()) {
|
||||
// 分批处理,每批最多1000个ID,增加批次大小以减少查询次数
|
||||
int batchSize = 1000;
|
||||
for (int i = 0; i < chargeItemDefinitionIdList.size(); i += batchSize) {
|
||||
@@ -959,16 +957,11 @@ public class DoctorStationAdviceAppServiceImpl implements IDoctorStationAdviceAp
|
||||
}
|
||||
}
|
||||
for (AdviceSaveDto adviceSaveDto : deleteList) {
|
||||
Long requestId = adviceSaveDto.getRequestId();
|
||||
// 🔧 Bug #442: 跳过 requestId 为 null 的记录,避免删除不存在的药品请求
|
||||
if (requestId == null) {
|
||||
log.warn("BugFix#442: handMedication - 跳过 requestId 为 null 的删除请求");
|
||||
continue;
|
||||
}
|
||||
iMedicationRequestService.removeById(requestId);
|
||||
iMedicationRequestService.removeById(adviceSaveDto.getRequestId());
|
||||
// 删除已经产生的药品发放信息
|
||||
iMedicationDispenseService.deleteMedicationDispense(adviceSaveDto.getRequestId());
|
||||
// 🔧 Bug Fix #219: 删除费用项
|
||||
Long requestId = adviceSaveDto.getRequestId();
|
||||
String serviceTable = CommonConstants.TableName.MED_MEDICATION_REQUEST;
|
||||
// 直接删除费用项
|
||||
iChargeItemService.deleteByServiceTableAndId(serviceTable, requestId);
|
||||
@@ -1424,11 +1417,6 @@ public class DoctorStationAdviceAppServiceImpl implements IDoctorStationAdviceAp
|
||||
log.info("BugFix#219: handDevice - 开始删除循环, deleteList.size={}", deleteList.size());
|
||||
for (AdviceSaveDto adviceSaveDto : deleteList) {
|
||||
Long requestId = adviceSaveDto.getRequestId();
|
||||
// 🔧 Bug #442: 跳过 requestId 为 null 的记录,避免删除不存在的耗材请求
|
||||
if (requestId == null) {
|
||||
log.warn("BugFix#442: handDevice - 跳过 requestId 为 null 的删除请求");
|
||||
continue;
|
||||
}
|
||||
log.info("BugFix#219: handDevice - 删除开始: requestId={}", requestId);
|
||||
|
||||
// 1. 删除耗材请求
|
||||
@@ -1733,17 +1721,12 @@ public class DoctorStationAdviceAppServiceImpl implements IDoctorStationAdviceAp
|
||||
}
|
||||
}
|
||||
for (AdviceSaveDto adviceSaveDto : deleteList) {
|
||||
Long requestId = adviceSaveDto.getRequestId();
|
||||
// 🔧 Bug #442: 跳过 requestId 为 null 的记录,避免删除不存在的诊疗请求
|
||||
if (requestId == null) {
|
||||
log.warn("BugFix#442: handService - 跳过 requestId 为 null 的删除请求");
|
||||
continue;
|
||||
}
|
||||
iServiceRequestService.removeById(requestId);// 删除诊疗
|
||||
iServiceRequestService.removeById(adviceSaveDto.getRequestId());// 删除诊疗
|
||||
iServiceRequestService.remove(
|
||||
new LambdaQueryWrapper<ServiceRequest>().eq(ServiceRequest::getParentId,
|
||||
requestId));// 删除诊疗套餐对应的子项
|
||||
adviceSaveDto.getRequestId()));// 删除诊疗套餐对应的子项
|
||||
// 🔧 Bug Fix #219: 删除费用项
|
||||
Long requestId = adviceSaveDto.getRequestId();
|
||||
String serviceTable = CommonConstants.TableName.WOR_SERVICE_REQUEST;
|
||||
// 直接删除费用项
|
||||
iChargeItemService.deleteByServiceTableAndId(serviceTable, requestId);
|
||||
@@ -1800,9 +1783,8 @@ public class DoctorStationAdviceAppServiceImpl implements IDoctorStationAdviceAp
|
||||
log.info("handService - 自动补全founderOrgId: founderOrgId={}", adviceSaveDto.getFounderOrgId());
|
||||
}
|
||||
|
||||
// 🔧 Bug Fix #238/#454: 诊疗项目执行科室非空校验(删除操作跳过校验)
|
||||
if (adviceSaveDto.getAdviceType() != null && adviceSaveDto.getAdviceType() == 3
|
||||
&& !DbOpType.DELETE.getCode().equals(adviceSaveDto.getDbOpType())) {
|
||||
// 🔧 Bug Fix #238: 诊疗项目执行科室非空校验
|
||||
if (adviceSaveDto.getAdviceType() != null && adviceSaveDto.getAdviceType() == 3) {
|
||||
Long effectiveOrgId = adviceSaveDto.getEffectiveOrgId();
|
||||
if (effectiveOrgId == null) {
|
||||
throw new ServiceException("诊疗项目必须选择执行科室");
|
||||
|
||||
@@ -63,4 +63,20 @@ public interface IRequestFormManageAppService {
|
||||
* @return 申请单
|
||||
*/
|
||||
IPage<RequestFormPageDto> getRequestFormPage(RequestFormDto requestFormDto);
|
||||
|
||||
/**
|
||||
* 删除申请单(仅待签发状态可删除)
|
||||
*
|
||||
* @param requestFormId 申请单ID
|
||||
* @return 结果
|
||||
*/
|
||||
R<?> deleteRequestForm(Long requestFormId);
|
||||
|
||||
/**
|
||||
* 撤回申请单(已签发状态撤回至待签发)
|
||||
*
|
||||
* @param requestFormId 申请单ID
|
||||
* @return 结果
|
||||
*/
|
||||
R<?> withdrawRequestForm(Long requestFormId);
|
||||
}
|
||||
|
||||
@@ -76,13 +76,6 @@ public class RequestFormManageAppServiceImpl implements IRequestFormManageAppSer
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public R<?> saveRequestForm(RequestFormSaveDto requestFormSaveDto, String typeCode) {
|
||||
// 诊疗执行科室配置校验(必须在任何数据库操作之前)
|
||||
List<ActivityOrganizationConfigDto> activityOrganizationConfig =
|
||||
requestFormManageAppMapper.getActivityOrganizationConfig(typeCode);
|
||||
if (activityOrganizationConfig.isEmpty()) {
|
||||
throw new ServiceException("请先配置当前时间段的执行科室");
|
||||
}
|
||||
|
||||
// 诊疗处方号
|
||||
String prescriptionNo;
|
||||
// 申请单ID
|
||||
@@ -149,6 +142,12 @@ public class RequestFormManageAppServiceImpl implements IRequestFormManageAppSer
|
||||
// 诊疗集合
|
||||
List<ActivitySaveDto> activityList = requestFormSaveDto.getActivityList();
|
||||
log.info("保存申请单,typeCode={}, activityListSize={}, encounterId={}", typeCode, activityList != null ? activityList.size() : 0, encounterId);
|
||||
// 诊疗执行科室配置
|
||||
List<ActivityOrganizationConfigDto> activityOrganizationConfig =
|
||||
requestFormManageAppMapper.getActivityOrganizationConfig(typeCode);
|
||||
if (activityOrganizationConfig.isEmpty()) {
|
||||
throw new ServiceException("请先配置当前时间段的执行科室");
|
||||
}
|
||||
|
||||
for (ActivitySaveDto activitySaveDto : activityList) {
|
||||
serviceRequest = new ServiceRequest();
|
||||
@@ -475,4 +474,68 @@ public class RequestFormManageAppServiceImpl implements IRequestFormManageAppSer
|
||||
return requestFormManageAppMapper.getRequestFormPage(requestFormDto, page);
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除申请单(仅待签发状态可删除)
|
||||
*/
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public R<?> deleteRequestForm(Long requestFormId) {
|
||||
if (requestFormId == null) {
|
||||
return R.fail("申请单ID不能为空");
|
||||
}
|
||||
RequestForm requestForm = iRequestFormService.getById(requestFormId);
|
||||
if (requestForm == null) {
|
||||
return R.fail("申请单不存在");
|
||||
}
|
||||
if (!Integer.valueOf(0).equals(requestForm.getStatus())) {
|
||||
return R.fail("仅待签发状态的申请单可删除");
|
||||
}
|
||||
// 删除申请单
|
||||
iRequestFormService.removeById(requestFormId);
|
||||
// 删除关联的诊疗项目及账单
|
||||
String prescriptionNo = requestForm.getPrescriptionNo();
|
||||
List<Long> serviceRequestIds = iServiceRequestService
|
||||
.list(new LambdaQueryWrapper<ServiceRequest>().eq(ServiceRequest::getPrescriptionNo, prescriptionNo))
|
||||
.stream().map(ServiceRequest::getId).collect(Collectors.toList());
|
||||
for (Long serviceRequestId : serviceRequestIds) {
|
||||
iServiceRequestService.removeById(serviceRequestId);
|
||||
iChargeItemService.deleteByServiceTableAndId(CommonConstants.TableName.WOR_SERVICE_REQUEST, serviceRequestId);
|
||||
}
|
||||
return R.ok(null, "删除成功");
|
||||
}
|
||||
|
||||
/**
|
||||
* 撤回申请单(已签发状态撤回至待签发)
|
||||
*/
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public R<?> withdrawRequestForm(Long requestFormId) {
|
||||
if (requestFormId == null) {
|
||||
return R.fail("申请单ID不能为空");
|
||||
}
|
||||
RequestForm requestForm = iRequestFormService.getById(requestFormId);
|
||||
if (requestForm == null) {
|
||||
return R.fail("申请单不存在");
|
||||
}
|
||||
if (!Integer.valueOf(1).equals(requestForm.getStatus())) {
|
||||
return R.fail("仅已签发状态的申请单可撤回");
|
||||
}
|
||||
// 将申请单状态回滚至待签发
|
||||
RequestForm updateForm = new RequestForm();
|
||||
updateForm.setId(requestFormId);
|
||||
updateForm.setStatus(0);
|
||||
iRequestFormService.updateById(updateForm);
|
||||
// 将关联的诊疗项目状态回滚至DRAFT
|
||||
String prescriptionNo = requestForm.getPrescriptionNo();
|
||||
List<ServiceRequest> serviceRequests = iServiceRequestService
|
||||
.list(new LambdaQueryWrapper<ServiceRequest>().eq(ServiceRequest::getPrescriptionNo, prescriptionNo));
|
||||
for (ServiceRequest serviceRequest : serviceRequests) {
|
||||
ServiceRequest updateService = new ServiceRequest();
|
||||
updateService.setId(serviceRequest.getId());
|
||||
updateService.setStatusEnum(RequestStatus.DRAFT.getValue());
|
||||
iServiceRequestService.updateById(updateService);
|
||||
}
|
||||
return R.ok(null, "撤回成功");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -99,7 +99,7 @@ public class RequestFormManageController {
|
||||
* @param startDate 开始日期(可选,格式:yyyy-MM-dd)
|
||||
* @param endDate 结束日期(可选,格式:yyyy-MM-dd)
|
||||
* @param status 单据状态(可选)
|
||||
* @param keyword 关键字(可选,申请单号/检验项目模糊匹配)
|
||||
* @param keyword 关键字(可选,申请单号/检验项目名称模糊匹配)
|
||||
* @return 检验申请单
|
||||
*/
|
||||
@GetMapping(value = "/get-inspection")
|
||||
@@ -163,7 +163,7 @@ public class RequestFormManageController {
|
||||
@RequestParam(required = false) Long applyDeptId,
|
||||
@RequestParam(defaultValue = "1") Integer pageNo,
|
||||
@RequestParam(defaultValue = "10") Integer pageSize) {
|
||||
RequestFormDto dto = new RequestFormDto(surgeryNo, ActivityDefCategory.PROCEDURE.getCode(), applyTimeStart, applyTimeEnd,
|
||||
RequestFormDto dto = new RequestFormDto(surgeryNo, null, applyTimeStart, applyTimeEnd,
|
||||
mainDoctorId, applyDeptId, pageNo, pageSize);
|
||||
return R.ok(iRequestFormManageAppService.getRequestFormPage(dto));
|
||||
}
|
||||
|
||||
@@ -280,9 +280,17 @@
|
||||
aa.balance_amount
|
||||
) AS personal_account
|
||||
ON personal_account.encounter_id = ae.id
|
||||
LEFT JOIN med_medication_dispense mmd
|
||||
LEFT JOIN (
|
||||
SELECT med_req_id, status_enum
|
||||
FROM (
|
||||
SELECT med_req_id, status_enum,
|
||||
ROW_NUMBER() OVER (PARTITION BY med_req_id ORDER BY id DESC) AS rn
|
||||
FROM med_medication_dispense
|
||||
WHERE delete_flag = '0'
|
||||
) t
|
||||
WHERE rn = 1
|
||||
) mmd
|
||||
ON mmd.med_req_id = T1.id
|
||||
AND mmd.delete_flag = '0'
|
||||
WHERE T1.delete_flag = '0'
|
||||
AND T1.refund_medicine_id IS NULL
|
||||
AND T1.generate_source_enum = #{doctorPrescription}
|
||||
|
||||
@@ -288,7 +288,7 @@
|
||||
AND T1.refund_device_id IS NULL
|
||||
ORDER BY T1.status_enum)
|
||||
UNION ALL
|
||||
(SELECT CASE WHEN T1.category_enum = 4 THEN 6 ELSE 3 END AS advice_type,
|
||||
(SELECT CASE WHEN T1.category_enum = 4 THEN 6 ELSE COALESCE(T1.category_enum, 3) END AS advice_type,
|
||||
T1.id AS request_id,
|
||||
T1.id || '-3' AS unique_key,
|
||||
T1.requester_id AS requester_id,
|
||||
@@ -373,4 +373,4 @@
|
||||
</if>
|
||||
</select>
|
||||
|
||||
</mapper>
|
||||
</mapper>
|
||||
@@ -59,4 +59,9 @@ public class RequestForm extends HisBaseEntity {
|
||||
*/
|
||||
private String typeCode;
|
||||
|
||||
/**
|
||||
* 单据状态 0=待签发 1=已签发 2=已校对 3=待接收 4=已接收 5=已检查 6=已出报告 7=已作废
|
||||
*/
|
||||
private Integer status;
|
||||
|
||||
}
|
||||
@@ -15,7 +15,7 @@
|
||||
DELETE
|
||||
FROM adm_encounter_diagnosis
|
||||
WHERE encounter_id = #{encounterId}
|
||||
AND tcm_flag = 0
|
||||
AND tcm_flag = 1
|
||||
</delete>
|
||||
<select id="getEncounterDiagnosisByEncounterConDefId"
|
||||
resultType="com.openhis.administration.domain.EncounterDiagnosis">
|
||||
|
||||
@@ -372,6 +372,7 @@ import {
|
||||
} from './diagnosistreatment';
|
||||
import PopoverList from '@/components/OpenHis/popoverList/index.vue';
|
||||
import medicineList from './medicineList.vue';
|
||||
import MedicineList from '../components/medicineList.vue';
|
||||
import {getCurrentInstance, nextTick, watch} from 'vue';
|
||||
|
||||
const { proxy } = getCurrentInstance();
|
||||
@@ -466,9 +467,9 @@ function calculateTotalPrice() {
|
||||
try {
|
||||
let sum = 0;
|
||||
treatmentItems.value.forEach((item) => {
|
||||
if (item.adviceDefinitionId && item.adviceDefinitionId !== '') {
|
||||
const price = Number(item.retailPrice) || 0;
|
||||
const count = Number(item.childrenRequestNum) || 0;
|
||||
if (item.adviceDefinitionId && item.retailPrice && item.childrenRequestNum) {
|
||||
const price = parseFloat(item.retailPrice) || 0;
|
||||
const count = parseInt(item.childrenRequestNum) || 0;
|
||||
sum += price * count;
|
||||
}
|
||||
});
|
||||
@@ -478,10 +479,7 @@ function calculateTotalPrice() {
|
||||
(item) => item.adviceDefinitionId && item.adviceDefinitionId !== ''
|
||||
);
|
||||
if (hasValidItem) {
|
||||
// 使用 nextTick 确保总价更新后零售价才更新,避免 Vue 响应式时序问题
|
||||
nextTick(() => {
|
||||
form.value.retailPrice = parseFloat(totalPrice.value) || 0;
|
||||
});
|
||||
form.value.retailPrice = parseFloat(totalPrice.value);
|
||||
} else {
|
||||
form.value.retailPrice = undefined;
|
||||
}
|
||||
@@ -567,16 +565,15 @@ function edit() {
|
||||
form.value.pricingFlag = 1;
|
||||
}
|
||||
|
||||
// 处理子项数据,确保包含retailPrice和name字段
|
||||
// 处理子项数据,确保包含retailPrice字段
|
||||
if (props.item.childrenJson) {
|
||||
const parsedItems = JSON.parse(props.item.childrenJson);
|
||||
treatmentItems.value = parsedItems.map((item) => ({
|
||||
...item,
|
||||
name: item.name || '',
|
||||
retailPrice: item.retailPrice || 0,
|
||||
}));
|
||||
} else {
|
||||
treatmentItems.value = [{ adviceDefinitionId: '', childrenRequestNum: 1, name: '', retailPrice: 0 }];
|
||||
treatmentItems.value = [{ adviceDefinitionId: '', childrenRequestNum: 1, retailPrice: 0 }];
|
||||
}
|
||||
form.value.permittedUnitCode = form.value.permittedUnitCode
|
||||
? form.value.permittedUnitCode.toString()
|
||||
@@ -621,7 +618,7 @@ function reset() {
|
||||
chrgitmLv: undefined, //医保等级
|
||||
pricingFlag: 1, // 划价标记,默认允许划价
|
||||
};
|
||||
treatmentItems.value = [{ adviceDefinitionId: '', childrenRequestNum: 1, name: '', retailPrice: 0 }];
|
||||
treatmentItems.value = [{ adviceDefinitionId: '', childrenRequestNum: 1, retailPrice: 0 }];
|
||||
totalPrice.value = '0.00';
|
||||
proxy.resetForm('diagnosisTreatmentRef');
|
||||
}
|
||||
@@ -763,10 +760,7 @@ function selectRow(row, index) {
|
||||
treatmentItems.value[index].adviceDefinitionId = row.id;
|
||||
treatmentItems.value[index].retailPrice = row.retailPrice || 0;
|
||||
medicineSearchKey.value = '';
|
||||
// 使用 nextTick 确保 DOM 更新后再计算总价
|
||||
nextTick(() => {
|
||||
calculateTotalPrice();
|
||||
});
|
||||
calculateTotalPrice();
|
||||
}
|
||||
|
||||
// 清空诊疗子项
|
||||
|
||||
@@ -36,7 +36,6 @@ const emit = defineEmits(['selectRow']);
|
||||
const diagnosisTreatmentList = ref([]); // 原始数据列表
|
||||
const filteredList = ref([]); // 过滤后的数据列表
|
||||
const hasLoaded = ref(false); // 标记是否已加载数据
|
||||
const isLoading = ref(false); // 标记是否正在加载
|
||||
|
||||
// 获取诊疗项目列表
|
||||
function getList() {
|
||||
@@ -54,7 +53,7 @@ function getList() {
|
||||
getDiagnosisTreatmentList({ statusEnum: 2, pageSize: 1000, pageNo: 1 })
|
||||
.then((res) => {
|
||||
diagnosisTreatmentList.value =
|
||||
res.data?.records?.filter((item) => item.childrenJson == null || item.childrenJson === '') || [];
|
||||
res.data?.records?.filter((item) => item.childrenJson == null) || [];
|
||||
filterList(); // 初始化过滤
|
||||
hasLoaded.value = true; // 标记为已加载
|
||||
})
|
||||
@@ -63,47 +62,6 @@ function getList() {
|
||||
});
|
||||
}
|
||||
|
||||
// 服务端搜索(当用户输入搜索关键词时)
|
||||
function searchList(searchKey) {
|
||||
if (!searchKey || searchKey.trim() === '') return;
|
||||
isLoading.value = true;
|
||||
// 使用较大的pageSize确保搜索结果尽可能多
|
||||
getDiagnosisTreatmentList({ statusEnum: 2, searchKey: searchKey.trim(), pageSize: 5000, pageNo: 1 })
|
||||
.then((res) => {
|
||||
diagnosisTreatmentList.value =
|
||||
res.data?.records?.filter((item) => item.childrenJson == null || item.childrenJson === '') || [];
|
||||
filterList();
|
||||
})
|
||||
.catch((err) => {
|
||||
console.error('搜索诊疗项目数据失败:', err);
|
||||
})
|
||||
.finally(() => {
|
||||
isLoading.value = false;
|
||||
});
|
||||
}
|
||||
|
||||
// 获取预加载数据(不带搜索关键词时使用)
|
||||
function loadPreloadedData() {
|
||||
if (props.preloadedData && props.preloadedData.length > 0) {
|
||||
diagnosisTreatmentList.value = props.preloadedData;
|
||||
filterList();
|
||||
hasLoaded.value = true;
|
||||
return;
|
||||
}
|
||||
|
||||
if (hasLoaded.value) return;
|
||||
getDiagnosisTreatmentList({ statusEnum: 2, pageSize: 1000, pageNo: 1 })
|
||||
.then((res) => {
|
||||
diagnosisTreatmentList.value =
|
||||
res.data?.records?.filter((item) => item.childrenJson == null || item.childrenJson === '') || [];
|
||||
filterList();
|
||||
hasLoaded.value = true;
|
||||
})
|
||||
.catch((err) => {
|
||||
console.error('获取诊疗项目数据失败:', err);
|
||||
});
|
||||
}
|
||||
|
||||
// 监听shouldLoadData属性变化,仅在首次为true时加载数据
|
||||
watch(
|
||||
() => props.shouldLoadData,
|
||||
@@ -128,17 +86,11 @@ watch(
|
||||
{ immediate: true }
|
||||
);
|
||||
|
||||
// 监听搜索关键词变化,有搜索词时走服务端搜索,否则走本地过滤
|
||||
// 监听搜索关键词变化,实时过滤数据
|
||||
watch(
|
||||
() => props.searchKey,
|
||||
(newVal) => {
|
||||
if (newVal && newVal.trim() !== '') {
|
||||
// 有搜索关键词,走服务端搜索
|
||||
searchList(newVal);
|
||||
} else {
|
||||
// 搜索词为空,使用预加载数据
|
||||
loadPreloadedData();
|
||||
}
|
||||
() => {
|
||||
filterList();
|
||||
}
|
||||
);
|
||||
|
||||
|
||||
@@ -880,23 +880,19 @@ function handleDelete() {
|
||||
proxy.$modal.msgWarning('请选择要删除的项目');
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
let deleteList = groupIndexList.value.map((index) => {
|
||||
const item = prescriptionList.value[index];
|
||||
// 只删除待签发且未收费的项目
|
||||
if (item.statusEnum != 1 || item.chargeStatus == 5) {
|
||||
return null;
|
||||
}
|
||||
// 🔧 Bug #442: 已保存的行必须有有效的 requestId,否则跳过(避免后端删除不存在的记录)
|
||||
if (item.requestId == null || item.requestId === undefined || item.requestId === '') {
|
||||
return null;
|
||||
}
|
||||
return {
|
||||
requestId: item.requestId,
|
||||
dbOpType: '3',
|
||||
adviceType: item.adviceType,
|
||||
};
|
||||
}).filter(item => item !== null); // 过滤掉已签发、已收费或无 requestId 的项目
|
||||
}).filter(item => item !== null); // 过滤掉已签发或已收费的项目
|
||||
|
||||
if (deleteList.length == 0) {
|
||||
proxy.$modal.msgWarning('只能删除待签发且未收费的项目');
|
||||
|
||||
@@ -1243,14 +1243,11 @@ async function show(diagnosisData) {
|
||||
const res = await getNextCardNo(orgCode);
|
||||
if (res.code === 200 && res.data && res.data.length >= 12) {
|
||||
cardNo = res.data;
|
||||
} else {
|
||||
// API返回失败或不合规时,生成临时卡号避免保存时 cardNo 为空导致后端校验失败
|
||||
cardNo = 'TEMP_' + Date.now();
|
||||
}
|
||||
// API失败或返回不合规时保持为空字符串,由用户手动填写或后端自动生成
|
||||
} catch (err) {
|
||||
console.error('获取卡片编号失败:', err);
|
||||
// API调用异常时,生成临时卡号
|
||||
cardNo = 'TEMP_' + Date.now();
|
||||
// 保持为空,不使用不合规的临时值
|
||||
}
|
||||
|
||||
form.value = {
|
||||
@@ -1433,8 +1430,8 @@ async function buildSubmitData() {
|
||||
function validateFormManually() {
|
||||
const errors = [];
|
||||
|
||||
// 卡片编号验证(至少12位,后端自动生成16位编号;临时卡号 TEMP_ 开头允许通过)
|
||||
if (form.value.cardNo && !form.value.cardNo.startsWith('TEMP_') && form.value.cardNo.length < 12) {
|
||||
// 卡片编号验证(至少12位,后端自动生成16位编号)
|
||||
if (form.value.cardNo && form.value.cardNo.length < 12) {
|
||||
errors.push('卡片编号至少12位');
|
||||
}
|
||||
|
||||
|
||||
@@ -482,28 +482,14 @@ async function loadPackageDetails(row, treeNode, resolve) {
|
||||
}
|
||||
}
|
||||
|
||||
// #428修复: 为已选择项目加载套餐明细(通过packageId或packageName查询)
|
||||
// #428: 为已选择项目加载套餐明细
|
||||
async function loadPackageDetailsForItem(item) {
|
||||
if (!item.isPackage || (!item.packageId && !item.packageName)) {
|
||||
if (!item.isPackage || !item.packageId) {
|
||||
return;
|
||||
}
|
||||
try {
|
||||
let packageId = item.packageId;
|
||||
if (!packageId && item.packageName) {
|
||||
// CheckPart 没有 packageId 字段,需要通过 packageName 查询获取
|
||||
const pkgRes = await listCheckPackage({ packageName: item.packageName });
|
||||
let packages = pkgRes?.data || [];
|
||||
if (!Array.isArray(packages)) {
|
||||
packages = packages.records || packages.data || [];
|
||||
}
|
||||
if (packages.length === 0) {
|
||||
item.packageDetails = [];
|
||||
return;
|
||||
}
|
||||
packageId = packages[0].id;
|
||||
}
|
||||
const res = await request({
|
||||
url: `/system/package/${packageId}/details`,
|
||||
url: `/system/package/${item.packageId}/details`,
|
||||
method: 'get'
|
||||
});
|
||||
if (res.code === 200 && res.data) {
|
||||
@@ -511,7 +497,7 @@ async function loadPackageDetailsForItem(item) {
|
||||
...detail,
|
||||
name: detail.name || detail.itemName,
|
||||
unit: detail.unit || '次',
|
||||
price: detail.price || detail.unitPrice || 0,
|
||||
price: detail.price || detail.itemPrice || 0,
|
||||
quantity: detail.quantity || 1
|
||||
}));
|
||||
} else {
|
||||
@@ -711,7 +697,6 @@ async function handleCategoryExpand(cat) {
|
||||
code: m.code,
|
||||
price: m.price || 0,
|
||||
packageName: m.packageName || '',
|
||||
packageId: m.packageId || null,
|
||||
packagePrice: m.packagePrice || null,
|
||||
serviceFee: m.serviceFee || null
|
||||
}));
|
||||
@@ -730,9 +715,7 @@ function handleCollapseChange(activeName) {
|
||||
setTimeout(() => { isAnimating.value = false; }, 300); // 与 CSS 过渡时长一致
|
||||
|
||||
if (activeName) {
|
||||
// Bug #428修复: 直接从 categoryList(原始响应式数组)查找分类,
|
||||
// 确保后续 handleCategoryExpand 对 cat.methods 的赋值能正确触发 Vue 响应式更新
|
||||
const cat = categoryList.value.find(c => c.typeId == activeName);
|
||||
const cat = filteredCategoryList.value.find(c => c.typeId == activeName);
|
||||
if (cat && (!cat.methods || cat.methods.length === 0)) {
|
||||
handleCategoryExpand(cat); // 异步加载,不 await
|
||||
}
|
||||
@@ -1025,16 +1008,11 @@ function handleRowClick(row) {
|
||||
activeDetailTab.value = 'applyForm';
|
||||
request({ url: `/exam/apply/${row.applyNo}`, method: 'get' }).then(async res => {
|
||||
const resp = res.data || res;
|
||||
// Bug #408修复: items 在 AjaxResult 顶层(res.items / resp.items),不在 ExamApply 对象内
|
||||
// 防御性提取:优先取顶层 items,兼容嵌套在 resp.data.items 的情况
|
||||
let rawItems = res.items || resp.items;
|
||||
if (!rawItems && resp.data && typeof resp.data === 'object') {
|
||||
rawItems = resp.data.items;
|
||||
}
|
||||
rawItems = rawItems || [];
|
||||
// 保存 items 在顶层响应中,避免后面 d.data 赋值后丢失
|
||||
const rawItems = resp.items;
|
||||
const d = resp.data || resp;
|
||||
if (d) Object.assign(form, d);
|
||||
if (Array.isArray(rawItems) && rawItems.length > 0) {
|
||||
if (rawItems && Array.isArray(rawItems)) {
|
||||
try {
|
||||
// 为每个项目加载检查方法
|
||||
const itemsWithMethods = await Promise.all(rawItems.map(async m => {
|
||||
@@ -1065,18 +1043,12 @@ function handleRowClick(row) {
|
||||
code: md.code,
|
||||
price: m.itemFee || 0, // fallback 到已保存的价格
|
||||
packageName: md.packageName || '',
|
||||
packageId: md.packageId || null,
|
||||
packagePrice: md.packagePrice || null, // Bug #384修复: 套餐价格
|
||||
serviceFee: md.serviceFee || null
|
||||
}));
|
||||
// 如果有已保存的检查方法信息,尝试匹配
|
||||
if (m.checkMethodId) {
|
||||
item.selectedMethod = item.methods.find(md => md.id === m.checkMethodId) || null;
|
||||
// 从已保存的方法中获取套餐信息
|
||||
if (item.selectedMethod?.packageId) {
|
||||
item.isPackage = true;
|
||||
item.packageId = item.selectedMethod.packageId;
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (err) {
|
||||
@@ -1137,13 +1109,6 @@ async function handleMethodSelect(checked, method, cat) {
|
||||
const existingItem = selectedItems.value.find(s => s.id === targetItem.id);
|
||||
if (existingItem) {
|
||||
existingItem.selectedMethod = method;
|
||||
// 从方法中获取套餐信息
|
||||
if (method.packageId) {
|
||||
existingItem.isPackage = true;
|
||||
existingItem.packageId = method.packageId;
|
||||
// 预加载套餐明细
|
||||
loadPackageDetailsForItem(existingItem);
|
||||
}
|
||||
updateMethodDisplay();
|
||||
return;
|
||||
}
|
||||
@@ -1151,15 +1116,14 @@ async function handleMethodSelect(checked, method, cat) {
|
||||
// 如果该项目不存在,创建一个并关联方法
|
||||
if (selectedItems.value.length > 0) {
|
||||
const currentCategory = selectedItems.value[0].checkType;
|
||||
// Bug #428修复: 使用 cat.typeName 进行比较(与 newItem.checkType 保持一致)
|
||||
const newCategory = cat.typeName || '';
|
||||
const newCategory = cat.typeCode || '';
|
||||
if (currentCategory !== newCategory) {
|
||||
ElMessage.warning('一个检查单不能同时选择多个项目类型的检查项目');
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
const newItem = {
|
||||
selectedItems.value.push({
|
||||
id: targetItem.id, name: targetItem.name,
|
||||
price: targetItem.price, quantity: 1,
|
||||
serviceFee: targetItem.serviceFee || 0,
|
||||
@@ -1171,16 +1135,9 @@ async function handleMethodSelect(checked, method, cat) {
|
||||
methods: [method],
|
||||
selectedMethod: method,
|
||||
expanded: false,
|
||||
// 从方法中获取套餐信息(优先级高于项目本身的 packageName)
|
||||
isPackage: !!method.packageId || !!targetItem.packageName,
|
||||
packageId: method.packageId || targetItem.packageId || null
|
||||
};
|
||||
selectedItems.value.push(newItem);
|
||||
|
||||
// 如果是套餐,预加载套餐明细
|
||||
if (newItem.isPackage && newItem.packageId) {
|
||||
loadPackageDetailsForItem(newItem);
|
||||
}
|
||||
isPackage: !!targetItem.packageName,
|
||||
packageId: targetItem.packageId || null
|
||||
});
|
||||
|
||||
// 自动回填执行科室
|
||||
if (selectedItems.value.length === 1 && cat?.performDeptName) {
|
||||
@@ -1225,7 +1182,6 @@ async function handleItemSelect(checked, item, cat) {
|
||||
code: m.code,
|
||||
price: m.price || item.price, // fallback 到项目价格
|
||||
packageName: m.packageName || '',
|
||||
packageId: m.packageId || null,
|
||||
packagePrice: m.packagePrice || null, // Bug #384修复: 套餐价格
|
||||
serviceFee: m.serviceFee || null // Bug #384修复: 服务费
|
||||
}));
|
||||
@@ -1237,8 +1193,7 @@ async function handleItemSelect(checked, item, cat) {
|
||||
|
||||
if (selectedItems.value.length > 0) {
|
||||
const currentCategory = selectedItems.value[0].checkType;
|
||||
// Bug #428修复: 使用 cat.typeName 进行比较(与 effectiveCheckType 保持一致)
|
||||
const newCategory = cat.typeName || '';
|
||||
const newCategory = cat.typeCode || '';
|
||||
if (currentCategory !== newCategory) {
|
||||
ElMessage.warning('一个检查单不能同时选择多个项目类型的检查项目');
|
||||
item.checked = false;
|
||||
@@ -1259,7 +1214,6 @@ async function handleItemSelect(checked, item, cat) {
|
||||
selectedMethod: null,
|
||||
expanded: false, // Bug #384修复: 新增展开状态,默认不展开
|
||||
isPackage: !!item.packageName, // Bug #428修复: 标记是否为套餐
|
||||
packageName: item.packageName || null, // Bug #426修复: 套餐名称,用于查找packageId
|
||||
packageId: item.packageId || null // Bug #428修复: 套餐ID
|
||||
});
|
||||
|
||||
|
||||
@@ -3326,13 +3326,9 @@ function syncGroupFields(row) {
|
||||
}
|
||||
|
||||
// 同步执行科室
|
||||
// 🔧 Bug #455: 诊疗类医嘱(adviceType=3)不使用项目配置的执行科室,
|
||||
// 避免配置ID不在机构树中导致显示原始ID,保持患者就诊科室即可
|
||||
if (row.orgId || row.positionId) {
|
||||
if (Number(row.adviceType) != 3) {
|
||||
// 🔧 修复:优先使用项目所属科室(orgId),其次positionId
|
||||
prescriptionList.value[rowIndex.value].orgId = row.orgId || row.positionId;
|
||||
}
|
||||
// 🔧 修复:优先使用项目所属科室(orgId),其次positionId
|
||||
prescriptionList.value[rowIndex.value].orgId = row.orgId || row.positionId;
|
||||
}
|
||||
|
||||
// 同步皮试标记
|
||||
@@ -3416,11 +3412,8 @@ async function setValue(row) {
|
||||
showPopover: false, // 确保查询框关闭
|
||||
};
|
||||
console.log('[BugFix] setValue - prescriptionList[rowIndex].adviceType_dictText:', prescriptionList.value[rowIndex.value].adviceType_dictText);
|
||||
// 🔧 Bug #455: 诊疗医嘱(adviceType=3)的执行科室默认使用患者就诊科室,
|
||||
// 不使用positionId(诊疗目录配置的执行科室),避免配置ID不在机构树中导致显示原始ID
|
||||
if (Number(row.adviceType) != 3) {
|
||||
prescriptionList.value[rowIndex.value].orgId = row.positionId || props.patientInfo?.orgId;
|
||||
}
|
||||
// 🔧 Bug #455: 执行科室默认逻辑:使用positionId(诊疗执行科室配置) → 患者就诊科室,不再使用row.orgId(项目所属科室)
|
||||
prescriptionList.value[rowIndex.value].orgId = row.positionId || props.patientInfo?.orgId;
|
||||
prescriptionList.value[rowIndex.value].dose = row.dose || row.doseQuantity;
|
||||
prescriptionList.value[rowIndex.value].quantity = row.quantity || 1;
|
||||
prescriptionList.value[rowIndex.value].unitCodeList = unitCodeList.value;
|
||||
|
||||
@@ -169,6 +169,7 @@
|
||||
<script setup>
|
||||
import {getCurrentInstance} from 'vue'; // 添加 nextTick 导入
|
||||
import useUserStore from '@/store/modules/user';
|
||||
import { formatDateStr } from '@/utils';
|
||||
import {
|
||||
delEncounterDiagnosis,
|
||||
deleteDiagnosisBind,
|
||||
@@ -286,10 +287,22 @@ function getList() {
|
||||
if (obj.diagSrtNo == null) {
|
||||
obj.diagSrtNo = '1';
|
||||
}
|
||||
// 补充缺失的元数据字段
|
||||
if (!obj.diagnosisDoctor) {
|
||||
obj.diagnosisDoctor = props.patientInfo.practitionerName || props.patientInfo.doctorName || props.patientInfo.physicianName || userStore.name;
|
||||
}
|
||||
if (!obj.diagnosisTime) {
|
||||
obj.diagnosisTime = item.diagnosisTime || getCurrentDate();
|
||||
}
|
||||
if (!obj.classification) {
|
||||
obj.classification = item.typeName === '中医诊断' ? '中医' : '西医';
|
||||
}
|
||||
if (obj.longTermFlag == null) {
|
||||
obj.longTermFlag = 0;
|
||||
}
|
||||
return obj;
|
||||
});
|
||||
form.value.diagnosisList = datas;
|
||||
// form.value.diagnosisList = res.data;
|
||||
emits('diagnosisSave', false);
|
||||
}
|
||||
});
|
||||
@@ -305,13 +318,16 @@ function getList() {
|
||||
ybNo: item.ybNo,
|
||||
medTypeCode: item.medTypeCode,
|
||||
diagnosisDoctor: props.patientInfo.practitionerName || props.patientInfo.doctorName || props.patientInfo.physicianName || userStore.name,
|
||||
diagnosisTime: new Date().toLocaleString('zh-CN')
|
||||
diagnosisTime: item.diagnosisTime || getCurrentDate(),
|
||||
diagSrtNo: item.diagSrtNo,
|
||||
classification: '中医',
|
||||
longTermFlag: item.longTermFlag || 0
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
// 将新数据添加到现有列表中
|
||||
form.value.diagnosisList.push(...newList);
|
||||
|
||||
|
||||
// 重新排序整个列表
|
||||
form.value.diagnosisList.sort((a, b) => {
|
||||
const aNo = typeof a.diagSrtNo === 'number' ? a.diagSrtNo : 9999;
|
||||
@@ -322,7 +338,7 @@ function getList() {
|
||||
emits('diagnosisSave', false);
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
getTree();
|
||||
}
|
||||
|
||||
@@ -339,11 +355,12 @@ function handleImport() {
|
||||
if (!props.patientInfo || !props.patientInfo.encounterId) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
if (props.patientInfo.contractName != '自费') {
|
||||
// 获取患者慢性病信息
|
||||
getChronicDisease({ encounterId: props.patientInfo.encounterId }).then((res) => {
|
||||
if (res.data && res.data.length > 0) {
|
||||
const currentDate = getCurrentDate();
|
||||
res.data.forEach((item, index) => {
|
||||
form.value.diagnosisList.push({
|
||||
...item,
|
||||
@@ -355,7 +372,10 @@ function handleImport() {
|
||||
iptDiseTypeCode: 2,
|
||||
diagnosisDesc: '',
|
||||
diagnosisDoctor: props.patientInfo.practitionerName || props.patientInfo.doctorName || props.patientInfo.physicianName || userStore.name,
|
||||
diagnosisTime: new Date().toLocaleString('zh-CN'),
|
||||
diagnosisTime: currentDate,
|
||||
onsetDate: currentDate,
|
||||
classification: '西医',
|
||||
longTermFlag: 0,
|
||||
//添加 patientId
|
||||
patientId: props.patientInfo.patientId
|
||||
},
|
||||
@@ -470,6 +490,7 @@ function handleAddDiagnosis() {
|
||||
* 添加诊断项
|
||||
*/
|
||||
function addDiagnosisItem() {
|
||||
const currentDate = getCurrentDate();
|
||||
form.value.diagnosisList.push({
|
||||
showPopover: false,
|
||||
name: undefined,
|
||||
@@ -479,9 +500,10 @@ function addDiagnosisItem() {
|
||||
iptDiseTypeCode: 2,
|
||||
diagnosisDesc: '',
|
||||
diagnosisDoctor: props.patientInfo.practitionerName || props.patientInfo.doctorName || props.patientInfo.physicianName || userStore.name,
|
||||
diagnosisTime: new Date().toLocaleString('zh-CN'),
|
||||
|
||||
// 新增这一行:为每个诊断项添加 patientId
|
||||
diagnosisTime: currentDate,
|
||||
classification: '西医',
|
||||
onsetDate: currentDate,
|
||||
longTermFlag: 0,
|
||||
patientId: props.patientInfo.patientId
|
||||
});
|
||||
|
||||
@@ -558,16 +580,7 @@ function handleMaindise(value, index) {
|
||||
/**
|
||||
* 保存诊断
|
||||
*/
|
||||
/**
|
||||
* 保存诊断
|
||||
*/
|
||||
/**
|
||||
* 保存诊断
|
||||
*/
|
||||
/**
|
||||
* 保存诊断
|
||||
*/
|
||||
function handleSaveDiagnosis() {
|
||||
async function handleSaveDiagnosis() {
|
||||
for (let index = 0; index < (form.value.diagnosisList || []).length; index++) {
|
||||
const item = form.value.diagnosisList[index];
|
||||
if (!item.diagSrtNo) {
|
||||
@@ -578,7 +591,7 @@ function handleSaveDiagnosis() {
|
||||
break;
|
||||
}
|
||||
}
|
||||
proxy.$refs.formRef.validate((valid) => {
|
||||
proxy.$refs.formRef.validate(async (valid) => {
|
||||
if (valid) {
|
||||
if (form.value.diagnosisList.length === 0) {
|
||||
proxy.$modal.msgWarning('诊断不能为空');
|
||||
@@ -591,43 +604,51 @@ function handleSaveDiagnosis() {
|
||||
// 设置保存标志,避免触发watch监听器
|
||||
isSaving.value = true;
|
||||
|
||||
// 步骤1:深拷贝并按 diagSrtNo 排序
|
||||
const sortedList = [...form.value.diagnosisList].sort((a, b) => {
|
||||
const aNo = typeof a.diagSrtNo === 'number' ? a.diagSrtNo : 9999;
|
||||
const bNo = typeof b.diagSrtNo === 'number' ? b.diagSrtNo : 9999;
|
||||
return aNo - bNo;
|
||||
});
|
||||
try {
|
||||
// 步骤1:深拷贝并按 diagSrtNo 排序
|
||||
const sortedList = [...form.value.diagnosisList].sort((a, b) => {
|
||||
const aNo = typeof a.diagSrtNo === 'number' ? a.diagSrtNo : 9999;
|
||||
const bNo = typeof b.diagSrtNo === 'number' ? b.diagSrtNo : 9999;
|
||||
return aNo - bNo;
|
||||
});
|
||||
|
||||
// 步骤2:重新分配连续的序号(从1开始)
|
||||
sortedList.forEach((item, index) => {
|
||||
item.diagSrtNo = index + 1; // 这里是关键!把“诊断排序”改成新顺序
|
||||
});
|
||||
// 步骤2:转换日期格式为后端期望的格式
|
||||
const diagnosisChildList = sortedList.map(item => ({
|
||||
...item,
|
||||
onsetDate: item.onsetDate ? formatDateStr(item.onsetDate, 'YYYY/M/D HH:mm:ss') : null,
|
||||
diagnosisTime: item.diagnosisTime ? formatDateStr(item.diagnosisTime, 'YYYY/M/D HH:mm:ss') : null
|
||||
}));
|
||||
|
||||
// 步骤3:提交排序后的数据
|
||||
const res = await saveDiagnosis({
|
||||
patientId: props.patientInfo.patientId,
|
||||
encounterId: props.patientInfo.encounterId,
|
||||
diagnosisChildList: diagnosisChildList,
|
||||
});
|
||||
|
||||
// 步骤3:提交排序后的数据
|
||||
saveDiagnosis({
|
||||
patientId: props.patientInfo.patientId,
|
||||
encounterId: props.patientInfo.encounterId,
|
||||
diagnosisChildList: sortedList,
|
||||
}).then((res) => {
|
||||
if (res.code === 200) {
|
||||
// 步骤4:更新本地数据,使用全新对象防止响应式问题
|
||||
form.value.diagnosisList = sortedList.map(item => ({ ...item }));
|
||||
|
||||
// 步骤4:从服务器刷新数据,确保获取最新的诊断信息(避免重复记录)
|
||||
await getList();
|
||||
getTree();
|
||||
emits('diagnosisSave', false);
|
||||
proxy.$modal.msgSuccess('诊断已保存');
|
||||
|
||||
// 食源性疾病逻辑
|
||||
isFoodDiseasesNew({ encounterId: props.patientInfo.encounterId }).then((res2) => {
|
||||
if (res2.code === 20 && res2.data) {
|
||||
if (res2.code === 200 && res2.data) {
|
||||
window.open(res2.data, '_blank');
|
||||
}
|
||||
});
|
||||
}
|
||||
}).finally(() => {
|
||||
} catch (error) {
|
||||
console.error('保存诊断失败:', error);
|
||||
const errorMsg = error?.response?.data?.msg || error?.message || '保存诊断失败,请稍后重试';
|
||||
proxy.$modal.msgError(errorMsg);
|
||||
} finally {
|
||||
setTimeout(() => {
|
||||
isSaving.value = false;
|
||||
}, 100);
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -687,6 +708,7 @@ function handleNodeClick(data) {
|
||||
proxy.$modal.msgWarning('该诊断项已存在');
|
||||
return;
|
||||
}
|
||||
const currentDate = getCurrentDate();
|
||||
form.value.diagnosisList.push({
|
||||
ybNo: data.ybNo,
|
||||
name: data.name,
|
||||
@@ -694,9 +716,12 @@ function handleNodeClick(data) {
|
||||
medTypeCode: undefined,
|
||||
diagSrtNo: form.value.diagnosisList.length + 1,
|
||||
definitionId: data.definitionId,
|
||||
classification: '西医',
|
||||
onsetDate: currentDate,
|
||||
diagnosisDoctor: props.patientInfo.practitionerName || props.patientInfo.doctorName || props.patientInfo.physicianName || userStore.name,
|
||||
diagnosisTime: new Date().toLocaleString('zh-CN'),
|
||||
// 添加 patientId
|
||||
diagnosisTime: currentDate,
|
||||
longTermFlag: 0,
|
||||
selectedDiseases: data.ybNo ? [data.ybNo] : [],
|
||||
patientId: props.patientInfo.patientId
|
||||
});
|
||||
if (form.value.diagnosisList.length == 1) {
|
||||
|
||||
@@ -72,45 +72,6 @@
|
||||
<el-input v-model="form.attention" autocomplete="off" type="textarea" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<!-- 申请类型 -->
|
||||
<el-col :span="12">
|
||||
<el-form-item label="申请类型" prop="applicationType" style="width: 100%">
|
||||
<el-radio-group v-model="form.applicationType">
|
||||
<el-radio :value="0">普通</el-radio>
|
||||
<el-radio :value="1">急诊</el-radio>
|
||||
</el-radio-group>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<!-- 标本类型 -->
|
||||
<el-col :span="12">
|
||||
<el-form-item label="标本类型" prop="specimenName" style="width: 100%">
|
||||
<el-select v-model="form.specimenName" placeholder="请选择标本类型" style="width: 100%">
|
||||
<el-option label="血液" value="血液" />
|
||||
<el-option label="尿液" value="尿液" />
|
||||
<el-option label="粪便" value="粪便" />
|
||||
<el-option label="痰液" value="痰液" />
|
||||
<el-option label="咽拭子" value="咽拭子" />
|
||||
<el-option label="脑脊液" value="脑脊液" />
|
||||
<el-option label="胸腹水" value="胸腹水" />
|
||||
<el-option label="关节液" value="关节液" />
|
||||
<el-option label="分泌物" value="分泌物" />
|
||||
<el-option label="其他" value="其他" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<!-- 执行时间 -->
|
||||
<el-col :span="12">
|
||||
<el-form-item label="执行时间" prop="executeTime" style="width: 100%">
|
||||
<el-date-picker
|
||||
v-model="form.executeTime"
|
||||
type="datetime"
|
||||
placeholder="选择执行时间"
|
||||
format="YYYY-MM-DD HH:mm:ss"
|
||||
value-format="YYYY-MM-DD HH:mm:ss"
|
||||
style="width: 100%"
|
||||
/>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</el-form>
|
||||
</div>
|
||||
@@ -191,9 +152,6 @@ const form = reactive({
|
||||
otherDiagnosis: '', // 其他诊断
|
||||
relatedResult: '', // 相关结果
|
||||
attention: '', // 注意事项
|
||||
applicationType: 0, // 申请类型 0-普通 1-急诊
|
||||
specimenName: '血液', // 标本类型
|
||||
executeTime: null, // 执行时间
|
||||
primaryDiagnosisList: [], //主诊断目录
|
||||
otherDiagnosisList: [], //其他断目录
|
||||
});
|
||||
@@ -206,7 +164,7 @@ onMounted(() => {
|
||||
* type(1:watch监听类型 2:点击保存类型)
|
||||
* selectProjectIds(选中项目的id数组)
|
||||
* */
|
||||
const projectWithDepartment = (selectProjectIds, type) => {
|
||||
const projectWithDepartment = (selectProjectIds) => {
|
||||
//1.获取选中的项目 2.判断项目的执行科室是否相同 3.判断执行科室是否配置 4.将项目的执行科室复值到执行科室下拉选位置
|
||||
let isRelease = true;
|
||||
// 选中项目的数组
|
||||
|
||||
@@ -483,7 +483,7 @@ const submit = () => {
|
||||
encounterId: patientInfo.value.encounterId,
|
||||
organizationId: patientInfo.value.inHospitalOrgId,
|
||||
requestFormId: '',
|
||||
name: applicationListAllFilter.map(item => item.adviceName).join('、'),
|
||||
name: '检查申请单',
|
||||
descJson: JSON.stringify(submitForm),
|
||||
categoryEnum: '2',
|
||||
}).then((res) => {
|
||||
|
||||
@@ -5,14 +5,16 @@
|
||||
-->
|
||||
<template>
|
||||
<div class="surgery-container">
|
||||
<div v-loading="loading" class="transfer-wrapper" style="min-height: 300px;">
|
||||
<el-transfer
|
||||
v-model="transferValue"
|
||||
:data="applicationList"
|
||||
filter-placeholder="项目代码/名称"
|
||||
filterable
|
||||
:titles="['未选择', '已选择']"
|
||||
/>
|
||||
<div class="transfer-wrapper">
|
||||
<div v-loading="loading" style="min-height: 300px;">
|
||||
<el-transfer
|
||||
v-model="transferValue"
|
||||
:data="applicationList"
|
||||
filter-placeholder="项目代码/名称"
|
||||
filterable
|
||||
:titles="['未选择', '已选择']"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div class="bloodTransfusion-form">
|
||||
<el-form :model="form" :rules="rules" ref="formRef" label-width="120px" class="demo-ruleForm">
|
||||
@@ -101,8 +103,8 @@ const findTreeItem = (list, id) => {
|
||||
const emits = defineEmits(['submitOk']);
|
||||
const props = defineProps({});
|
||||
const state = reactive({});
|
||||
const applicationListAll = ref();
|
||||
const applicationList = ref();
|
||||
const applicationListAll = ref([]);
|
||||
const applicationList = ref([]);
|
||||
const orgOptions = ref([]); // 科室选项
|
||||
const loading = ref(false); // 加载状态
|
||||
const getList = () => {
|
||||
|
||||
@@ -631,6 +631,12 @@ function getListInfo(addNewRow) {
|
||||
handleAddPrescription();
|
||||
}
|
||||
});
|
||||
}).catch((err) => {
|
||||
console.error('处方列表加载失败:', err);
|
||||
// 🔧 Bug #405 修复:列表加载失败时,确保所有行被锁定(isEdit=false)
|
||||
// 防止行永久处于可编辑状态
|
||||
prescriptionList.value.forEach(item => { item.isEdit = false; });
|
||||
loadingInstance.close();
|
||||
});
|
||||
getContract({ encounterId: patientInfo.value.encounterId }).then((res) => {
|
||||
contractList.value = res.data;
|
||||
@@ -1181,27 +1187,19 @@ function handleSave() {
|
||||
});
|
||||
// 此处签发处方和单行保存处方传参相同,后台已经将传参存为JSON字符串,此处直接转换为JSON即可
|
||||
loading.value = true;
|
||||
let list = [];
|
||||
try {
|
||||
list = saveList.map((item) => {
|
||||
const parsedContent = item.contentJson ? JSON.parse(item.contentJson) || {} : {};
|
||||
return {
|
||||
...parsedContent,
|
||||
adviceType: item.adviceType,
|
||||
requestId: item.requestId,
|
||||
dbOpType: '1',
|
||||
groupId: item.groupId,
|
||||
uniqueKey: undefined,
|
||||
// 确保 therapyEnum 被正确传递
|
||||
therapyEnum: parsedContent.therapyEnum || item.therapyEnum || '1',
|
||||
};
|
||||
});
|
||||
} catch (error) {
|
||||
loading.value = false;
|
||||
isSaving.value = false;
|
||||
proxy.$modal.msgError('医嘱内容解析失败,请检查待签发医嘱');
|
||||
return;
|
||||
}
|
||||
let list = saveList.map((item) => {
|
||||
const parsedContent = JSON.parse(item.contentJson);
|
||||
return {
|
||||
...parsedContent,
|
||||
adviceType: item.adviceType,
|
||||
requestId: item.requestId,
|
||||
dbOpType: '1',
|
||||
groupId: item.groupId,
|
||||
uniqueKey: undefined,
|
||||
// 确保 therapyEnum 被正确传递
|
||||
therapyEnum: parsedContent.therapyEnum || item.therapyEnum || '1',
|
||||
};
|
||||
});
|
||||
// 保存签发按钮
|
||||
isSaving.value = true;
|
||||
console.log('签发处方参数:', {
|
||||
@@ -1451,6 +1449,12 @@ function handleSaveBatch() {
|
||||
})
|
||||
.catch((error) => {
|
||||
isSaving.value = false;
|
||||
// 🔧 Bug #405 修复:保存失败时也锁定行,防止行永久处于可编辑状态
|
||||
filterPrescriptionList.value.forEach(item => {
|
||||
if (item.statusEnum == 1 && !item.requestId) {
|
||||
item.isEdit = false;
|
||||
}
|
||||
});
|
||||
proxy.$modal.msgError(error?.msg || '保存失败,请重试');
|
||||
});
|
||||
}
|
||||
|
||||
@@ -302,29 +302,6 @@ function getSelectRows() {
|
||||
});
|
||||
return list;
|
||||
}
|
||||
|
||||
function getTableRef(index) {
|
||||
return proxy.$refs['tableRef' + index]?.[0];
|
||||
}
|
||||
|
||||
function selectAllRows() {
|
||||
prescriptionList.value.forEach((item, index) => {
|
||||
const tableRef = getTableRef(index);
|
||||
if (!tableRef) {
|
||||
return;
|
||||
}
|
||||
item.forEach((row) => {
|
||||
tableRef.toggleRowSelection(row, true);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
function clearSelection() {
|
||||
prescriptionList.value.forEach((item, index) => {
|
||||
getTableRef(index)?.clearSelection();
|
||||
});
|
||||
}
|
||||
|
||||
function handleRateChange(value, item, row) {
|
||||
// 拼接当前选中时间
|
||||
if (value) {
|
||||
@@ -342,8 +319,6 @@ function handleRateChange(value, item, row) {
|
||||
defineExpose({
|
||||
handleGetPrescription,
|
||||
handleMedicineSummary,
|
||||
selectAllRows,
|
||||
clearSelection,
|
||||
});
|
||||
</script>
|
||||
|
||||
|
||||
@@ -69,11 +69,7 @@
|
||||
</div>
|
||||
<div>
|
||||
<span class="descriptions-item-label">全选:</span>
|
||||
<el-switch
|
||||
v-model="chooseAll"
|
||||
:disabled="isDetails != '1'"
|
||||
@change="handelSwicthChange"
|
||||
/>
|
||||
<el-switch v-model="chooseAll" @change="handelSwicthChange" />
|
||||
<el-button class="ml20 mr20" type="primary" @click="handleExecute"> 汇总领药 </el-button>
|
||||
</div>
|
||||
</div>
|
||||
@@ -164,31 +160,24 @@ function handleClick(tabName) {
|
||||
}
|
||||
|
||||
function handleGetPrescription() {
|
||||
chooseAll.value = false;
|
||||
prescriptionRefs.value?.handleGetPrescription();
|
||||
prescriptionRefs.value.handleGetPrescription();
|
||||
}
|
||||
|
||||
function handelSwicthChange(value) {
|
||||
if (!prescriptionRefs.value) {
|
||||
chooseAll.value = false;
|
||||
return;
|
||||
}
|
||||
if (value) {
|
||||
prescriptionRefs.value.selectAllRows();
|
||||
function handelSwicthChange() {
|
||||
if (chooseAll.value) {
|
||||
proxy.$refs['prescriptionRefs'].selectAllRows();
|
||||
} else {
|
||||
prescriptionRefs.value.clearSelection();
|
||||
proxy.$refs['prescriptionRefs'].clearSelection();
|
||||
}
|
||||
}
|
||||
|
||||
function handleRadioChange(value) {
|
||||
chooseAll.value = false;
|
||||
if (value == '1') {
|
||||
handleGetPrescription();
|
||||
}
|
||||
}
|
||||
|
||||
function handleTherapyChange() {
|
||||
chooseAll.value = false;
|
||||
handleGetPrescription();
|
||||
}
|
||||
|
||||
@@ -227,4 +216,4 @@ provide('handleGetPrescription', (value) => {
|
||||
:deep(.el-tabs__header) {
|
||||
margin: 0;
|
||||
}
|
||||
</style>
|
||||
</style>
|
||||
@@ -885,21 +885,11 @@ import { listUser } from '@/api/system/user'
|
||||
import { deptTreeSelect } from '@/api/system/user'
|
||||
import { listOperatingRoom } from '@/api/operatingroom'
|
||||
import { getSurgeryPage} from '@/views/inpatientDoctor/home/components/applicationShow/api.js'
|
||||
import { getTenantPage } from '@/api/system/tenant'
|
||||
import { getContract } from '@/views/inpatientDoctor/home/components/api.js'
|
||||
import request from '@/utils/request'
|
||||
import SurgeryCharge from '../charge/surgerycharge/index.vue'
|
||||
import TemporaryMedical from './temporaryMedical.vue'
|
||||
|
||||
// 静默获取卫生机构列表(跳过拦截器错误提示,手术室护士等角色可能无此权限)
|
||||
function getTenantPageSilent(query) {
|
||||
return request({
|
||||
url: '/system/tenant/page',
|
||||
method: 'get',
|
||||
params: query,
|
||||
skipErrorMsg: true
|
||||
})
|
||||
}
|
||||
|
||||
const { proxy } = getCurrentInstance()
|
||||
const userStore = useUserStore()
|
||||
const loading = ref(true)
|
||||
@@ -1128,7 +1118,7 @@ onMounted(() => {
|
||||
|
||||
// 加载卫生机构列表
|
||||
function loadOrgList() {
|
||||
getTenantPageSilent({ pageNo: 1, pageSize: 1000 })
|
||||
getTenantPage({ pageNo: 1, pageSize: 1000 })
|
||||
.then(res => {
|
||||
if (res.code === 200) {
|
||||
const records = res.data?.records || res.data || []
|
||||
|
||||
@@ -1,5 +0,0 @@
|
||||
-- Bug #434 修复:为 op_schedule 表添加 incision_level 字段
|
||||
-- 手术安排表需要存储切口类型,以便在编辑弹窗中正确回显和保存
|
||||
ALTER TABLE op_schedule ADD COLUMN IF NOT EXISTS incision_level INT2;
|
||||
|
||||
COMMENT ON COLUMN op_schedule.incision_level IS '手术切口等级 1-I级切口 2-II级切口 3-III级切口 4-IV级切口';
|
||||
Reference in New Issue
Block a user