Compare commits
21 Commits
63a3f63380
...
陈琳
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
2cedcefacb | ||
|
|
4feac503a0 | ||
|
|
d747b0b380 | ||
|
|
af0a0957d0 | ||
|
|
6964f4f0a0 | ||
|
|
b8d663d5fa | ||
|
|
e32ef40f48 | ||
|
|
04903dc0b9 | ||
|
|
cd9dddb948 | ||
|
|
14ebcea2e6 | ||
|
|
7694122409 | ||
|
|
dd0cdf0af3 | ||
|
|
c6a29aa7f4 | ||
|
|
19b3bf5f3a | ||
|
|
51a75a6787 | ||
|
|
79a91f0a77 | ||
|
|
f1e30bb3a7 | ||
|
|
49a2313d7a | ||
|
|
677106afc2 | ||
|
|
925f3dde41 | ||
|
|
ae805eb89c |
@@ -2,13 +2,9 @@ package com.openhis.web.clinicalmanage.controller;
|
|||||||
|
|
||||||
import com.baomidou.mybatisplus.core.metadata.IPage;
|
import com.baomidou.mybatisplus.core.metadata.IPage;
|
||||||
import com.core.common.core.domain.R;
|
import com.core.common.core.domain.R;
|
||||||
import com.openhis.common.enums.ActivityDefCategory;
|
|
||||||
import com.openhis.web.clinicalmanage.appservice.ISurgicalScheduleAppService;
|
import com.openhis.web.clinicalmanage.appservice.ISurgicalScheduleAppService;
|
||||||
import com.openhis.web.clinicalmanage.dto.OpCreateScheduleDto;
|
import com.openhis.web.clinicalmanage.dto.OpCreateScheduleDto;
|
||||||
import com.openhis.web.clinicalmanage.dto.OpScheduleDto;
|
import com.openhis.web.clinicalmanage.dto.OpScheduleDto;
|
||||||
import com.openhis.web.regdoctorstation.appservice.IRequestFormManageAppService;
|
|
||||||
import com.openhis.web.regdoctorstation.dto.RequestFormDto;
|
|
||||||
import com.openhis.web.regdoctorstation.dto.RequestFormPageDto;
|
|
||||||
import lombok.AllArgsConstructor;
|
import lombok.AllArgsConstructor;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import org.springframework.web.bind.annotation.*;
|
import org.springframework.web.bind.annotation.*;
|
||||||
@@ -30,7 +26,6 @@ import java.util.Map;
|
|||||||
public class SurgicalScheduleController {
|
public class SurgicalScheduleController {
|
||||||
|
|
||||||
private final ISurgicalScheduleAppService surgicalScheduleAppService;
|
private final ISurgicalScheduleAppService surgicalScheduleAppService;
|
||||||
private final IRequestFormManageAppService requestFormManageAppService;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 分页查询手术安排列表
|
* 分页查询手术安排列表
|
||||||
@@ -92,27 +87,6 @@ public class SurgicalScheduleController {
|
|||||||
return surgicalScheduleAppService.deleteSurgerySchedule(scheduleId);
|
return surgicalScheduleAppService.deleteSurgerySchedule(scheduleId);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* 分页查询待排期手术申请列表
|
|
||||||
*
|
|
||||||
* @param requestFormDto 查询条件
|
|
||||||
* @return 手术申请列表
|
|
||||||
*/
|
|
||||||
@PostMapping(value = "/apply-list")
|
|
||||||
public R<IPage<RequestFormPageDto>> getSurgeryApplyList(@RequestBody RequestFormDto requestFormDto) {
|
|
||||||
if (requestFormDto.getPageNo() == null) {
|
|
||||||
requestFormDto.setPageNo(1);
|
|
||||||
}
|
|
||||||
if (requestFormDto.getPageSize() == null) {
|
|
||||||
requestFormDto.setPageSize(10);
|
|
||||||
}
|
|
||||||
//虽然很想这么写,但是库里的手术申请单的type_code都是直接写的SURGERY
|
|
||||||
// requestFormDto.setTypeCode(ActivityDefCategory.PROCEDURE.getCode());
|
|
||||||
//只查询手术申请单
|
|
||||||
requestFormDto.setTypeCode("SURGERY");
|
|
||||||
return R.ok(requestFormManageAppService.getRequestFormPage(requestFormDto));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 导出手术安排列表
|
* 导出手术安排列表
|
||||||
*
|
*
|
||||||
|
|||||||
@@ -59,16 +59,6 @@ public interface IDoctorStationAdviceAppService {
|
|||||||
*/
|
*/
|
||||||
R<?> getRequestBaseInfo(Long encounterId);
|
R<?> getRequestBaseInfo(Long encounterId);
|
||||||
|
|
||||||
/**
|
|
||||||
* 查询医嘱请求数据(支持按生成来源和来源单据号过滤)
|
|
||||||
*
|
|
||||||
* @param encounterId 就诊id
|
|
||||||
* @param generateSourceEnum 生成来源(可选,如手术计费=6)
|
|
||||||
* @param sourceBillNo 来源业务单据号(可选)
|
|
||||||
* @return 医嘱请求数据
|
|
||||||
*/
|
|
||||||
R<?> getRequestBaseInfo(Long encounterId, Integer generateSourceEnum, String sourceBillNo);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 门诊签退医嘱
|
* 门诊签退医嘱
|
||||||
*
|
*
|
||||||
|
|||||||
@@ -957,16 +957,11 @@ public class DoctorStationAdviceAppServiceImpl implements IDoctorStationAdviceAp
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
for (AdviceSaveDto adviceSaveDto : deleteList) {
|
for (AdviceSaveDto adviceSaveDto : deleteList) {
|
||||||
Long requestId = adviceSaveDto.getRequestId();
|
iMedicationRequestService.removeById(adviceSaveDto.getRequestId());
|
||||||
// 🔧 Bug #442: 跳过 requestId 为 null 的记录,避免删除不存在的药品请求
|
|
||||||
if (requestId == null) {
|
|
||||||
log.warn("BugFix#442: handMedication - 跳过 requestId 为 null 的删除请求");
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
iMedicationRequestService.removeById(requestId);
|
|
||||||
// 删除已经产生的药品发放信息
|
// 删除已经产生的药品发放信息
|
||||||
iMedicationDispenseService.deleteMedicationDispense(adviceSaveDto.getRequestId());
|
iMedicationDispenseService.deleteMedicationDispense(adviceSaveDto.getRequestId());
|
||||||
// 🔧 Bug Fix #219: 删除费用项
|
// 🔧 Bug Fix #219: 删除费用项
|
||||||
|
Long requestId = adviceSaveDto.getRequestId();
|
||||||
String serviceTable = CommonConstants.TableName.MED_MEDICATION_REQUEST;
|
String serviceTable = CommonConstants.TableName.MED_MEDICATION_REQUEST;
|
||||||
// 直接删除费用项
|
// 直接删除费用项
|
||||||
iChargeItemService.deleteByServiceTableAndId(serviceTable, requestId);
|
iChargeItemService.deleteByServiceTableAndId(serviceTable, requestId);
|
||||||
@@ -1422,11 +1417,6 @@ public class DoctorStationAdviceAppServiceImpl implements IDoctorStationAdviceAp
|
|||||||
log.info("BugFix#219: handDevice - 开始删除循环, deleteList.size={}", deleteList.size());
|
log.info("BugFix#219: handDevice - 开始删除循环, deleteList.size={}", deleteList.size());
|
||||||
for (AdviceSaveDto adviceSaveDto : deleteList) {
|
for (AdviceSaveDto adviceSaveDto : deleteList) {
|
||||||
Long requestId = adviceSaveDto.getRequestId();
|
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);
|
log.info("BugFix#219: handDevice - 删除开始: requestId={}", requestId);
|
||||||
|
|
||||||
// 1. 删除耗材请求
|
// 1. 删除耗材请求
|
||||||
@@ -1731,17 +1721,12 @@ public class DoctorStationAdviceAppServiceImpl implements IDoctorStationAdviceAp
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
for (AdviceSaveDto adviceSaveDto : deleteList) {
|
for (AdviceSaveDto adviceSaveDto : deleteList) {
|
||||||
Long requestId = adviceSaveDto.getRequestId();
|
iServiceRequestService.removeById(adviceSaveDto.getRequestId());// 删除诊疗
|
||||||
// 🔧 Bug #442: 跳过 requestId 为 null 的记录,避免删除不存在的诊疗请求
|
|
||||||
if (requestId == null) {
|
|
||||||
log.warn("BugFix#442: handService - 跳过 requestId 为 null 的删除请求");
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
iServiceRequestService.removeById(requestId);// 删除诊疗
|
|
||||||
iServiceRequestService.remove(
|
iServiceRequestService.remove(
|
||||||
new LambdaQueryWrapper<ServiceRequest>().eq(ServiceRequest::getParentId,
|
new LambdaQueryWrapper<ServiceRequest>().eq(ServiceRequest::getParentId,
|
||||||
requestId));// 删除诊疗套餐对应的子项
|
adviceSaveDto.getRequestId()));// 删除诊疗套餐对应的子项
|
||||||
// 🔧 Bug Fix #219: 删除费用项
|
// 🔧 Bug Fix #219: 删除费用项
|
||||||
|
Long requestId = adviceSaveDto.getRequestId();
|
||||||
String serviceTable = CommonConstants.TableName.WOR_SERVICE_REQUEST;
|
String serviceTable = CommonConstants.TableName.WOR_SERVICE_REQUEST;
|
||||||
// 直接删除费用项
|
// 直接删除费用项
|
||||||
iChargeItemService.deleteByServiceTableAndId(serviceTable, requestId);
|
iChargeItemService.deleteByServiceTableAndId(serviceTable, requestId);
|
||||||
@@ -1798,9 +1783,8 @@ public class DoctorStationAdviceAppServiceImpl implements IDoctorStationAdviceAp
|
|||||||
log.info("handService - 自动补全founderOrgId: founderOrgId={}", adviceSaveDto.getFounderOrgId());
|
log.info("handService - 自动补全founderOrgId: founderOrgId={}", adviceSaveDto.getFounderOrgId());
|
||||||
}
|
}
|
||||||
|
|
||||||
// 🔧 Bug Fix #238/#454: 诊疗项目执行科室非空校验(删除操作跳过校验)
|
// 🔧 Bug Fix #238: 诊疗项目执行科室非空校验
|
||||||
if (adviceSaveDto.getAdviceType() != null && adviceSaveDto.getAdviceType() == 3
|
if (adviceSaveDto.getAdviceType() != null && adviceSaveDto.getAdviceType() == 3) {
|
||||||
&& !DbOpType.DELETE.getCode().equals(adviceSaveDto.getDbOpType())) {
|
|
||||||
Long effectiveOrgId = adviceSaveDto.getEffectiveOrgId();
|
Long effectiveOrgId = adviceSaveDto.getEffectiveOrgId();
|
||||||
if (effectiveOrgId == null) {
|
if (effectiveOrgId == null) {
|
||||||
throw new ServiceException("诊疗项目必须选择执行科室");
|
throw new ServiceException("诊疗项目必须选择执行科室");
|
||||||
@@ -2003,25 +1987,13 @@ public class DoctorStationAdviceAppServiceImpl implements IDoctorStationAdviceAp
|
|||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public R<?> getRequestBaseInfo(Long encounterId) {
|
public R<?> getRequestBaseInfo(Long encounterId) {
|
||||||
return this.getRequestBaseInfo(encounterId, null, null);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public R<?> getRequestBaseInfo(Long encounterId, Integer generateSourceEnum, String sourceBillNo) {
|
|
||||||
// 当前账号的参与者id
|
// 当前账号的参与者id
|
||||||
Long practitionerId = SecurityUtils.getLoginUser().getPractitionerId();
|
Long practitionerId = SecurityUtils.getLoginUser().getPractitionerId();
|
||||||
// 未指定generateSourceEnum时,默认只查询医生开立的医嘱
|
|
||||||
int sourceEnum = (generateSourceEnum != null) ? generateSourceEnum : GenerateSource.DOCTOR_PRESCRIPTION.getValue();
|
|
||||||
// 医嘱请求数据
|
// 医嘱请求数据
|
||||||
List<RequestBaseDto> requestBaseInfo = doctorStationAdviceAppMapper.getRequestBaseInfo(encounterId, null,
|
List<RequestBaseDto> requestBaseInfo = doctorStationAdviceAppMapper.getRequestBaseInfo(encounterId, null,
|
||||||
CommonConstants.TableName.MED_MEDICATION_REQUEST, CommonConstants.TableName.WOR_DEVICE_REQUEST,
|
CommonConstants.TableName.MED_MEDICATION_REQUEST, CommonConstants.TableName.WOR_DEVICE_REQUEST,
|
||||||
CommonConstants.TableName.WOR_SERVICE_REQUEST, practitionerId, Whether.NO.getCode(),
|
CommonConstants.TableName.WOR_SERVICE_REQUEST, practitionerId, Whether.NO.getCode(),
|
||||||
sourceEnum, sourceBillNo);
|
GenerateSource.DOCTOR_PRESCRIPTION.getValue());
|
||||||
// 手术计费场景:sourceBillNo 不为空时,只保留诊疗请求(3/6),过滤掉药品(1)和耗材(2)
|
|
||||||
if (sourceBillNo != null && !sourceBillNo.isEmpty()) {
|
|
||||||
requestBaseInfo.removeIf(dto -> dto.getAdviceType() != null
|
|
||||||
&& (dto.getAdviceType() == 1 || dto.getAdviceType() == 2));
|
|
||||||
}
|
|
||||||
for (RequestBaseDto requestBaseDto : requestBaseInfo) {
|
for (RequestBaseDto requestBaseDto : requestBaseInfo) {
|
||||||
// 请求状态
|
// 请求状态
|
||||||
requestBaseDto
|
requestBaseDto
|
||||||
@@ -2142,7 +2114,7 @@ public class DoctorStationAdviceAppServiceImpl implements IDoctorStationAdviceAp
|
|||||||
List<RequestBaseDto> requestBaseInfo = doctorStationAdviceAppMapper.getRequestBaseInfo(encounterId, patientId,
|
List<RequestBaseDto> requestBaseInfo = doctorStationAdviceAppMapper.getRequestBaseInfo(encounterId, patientId,
|
||||||
CommonConstants.TableName.MED_MEDICATION_REQUEST, CommonConstants.TableName.WOR_DEVICE_REQUEST,
|
CommonConstants.TableName.MED_MEDICATION_REQUEST, CommonConstants.TableName.WOR_DEVICE_REQUEST,
|
||||||
CommonConstants.TableName.WOR_SERVICE_REQUEST, practitionerId, Whether.YES.getCode(),
|
CommonConstants.TableName.WOR_SERVICE_REQUEST, practitionerId, Whether.YES.getCode(),
|
||||||
GenerateSource.DOCTOR_PRESCRIPTION.getValue(), null);
|
GenerateSource.DOCTOR_PRESCRIPTION.getValue());
|
||||||
for (RequestBaseDto requestBaseDto : requestBaseInfo) {
|
for (RequestBaseDto requestBaseDto : requestBaseInfo) {
|
||||||
// 请求状态
|
// 请求状态
|
||||||
requestBaseDto
|
requestBaseDto
|
||||||
|
|||||||
@@ -307,15 +307,13 @@ public class DoctorStationMainAppServiceImpl implements IDoctorStationMainAppSer
|
|||||||
if (queueItem != null && queueItem.getPoolId() != null && queueItem.getSlotId() != null) {
|
if (queueItem != null && queueItem.getPoolId() != null && queueItem.getSlotId() != null) {
|
||||||
divPoolId = queueItem.getPoolId();
|
divPoolId = queueItem.getPoolId();
|
||||||
divSlotId = queueItem.getSlotId();
|
divSlotId = queueItem.getSlotId();
|
||||||
}
|
} else if (encounter.getOrderId() != null) {
|
||||||
// 队列项 poolId/slotId 缺失时,通过 encounter.orderId → order_main.slot_id → adm_schedule_slot.pool_id 回退获取
|
|
||||||
if ((divPoolId == null || divSlotId == null) && encounter.getOrderId() != null) {
|
|
||||||
try {
|
try {
|
||||||
Order order = iOrderService.getById(encounter.getOrderId());
|
Order order = iOrderService.getById(encounter.getOrderId());
|
||||||
if (order != null && order.getSlotId() != null) {
|
if (order != null && order.getSlotId() != null) {
|
||||||
ScheduleSlot slot = scheduleSlotMapper.selectById(order.getSlotId());
|
divSlotId = order.getSlotId();
|
||||||
|
ScheduleSlot slot = scheduleSlotMapper.selectById(divSlotId);
|
||||||
if (slot != null) {
|
if (slot != null) {
|
||||||
divSlotId = slot.getId();
|
|
||||||
divPoolId = slot.getPoolId();
|
divPoolId = slot.getPoolId();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -112,16 +112,11 @@ public class DoctorStationAdviceController {
|
|||||||
* 查询医嘱请求数据
|
* 查询医嘱请求数据
|
||||||
*
|
*
|
||||||
* @param encounterId 就诊id
|
* @param encounterId 就诊id
|
||||||
* @param generateSourceEnum 生成来源(可选,用于按来源过滤,如手术计费=6)
|
|
||||||
* @param sourceBillNo 来源业务单据号(可选,用于按来源单据过滤)
|
|
||||||
* @return 医嘱请求数据
|
* @return 医嘱请求数据
|
||||||
*/
|
*/
|
||||||
@GetMapping(value = "/request-base-info")
|
@GetMapping(value = "/request-base-info")
|
||||||
public R<?> getRequestBaseInfo(
|
public R<?> getRequestBaseInfo(@RequestParam(required = false) Long encounterId) {
|
||||||
@RequestParam(required = false) Long encounterId,
|
return iDoctorStationAdviceAppService.getRequestBaseInfo(encounterId);
|
||||||
@RequestParam(required = false) Integer generateSourceEnum,
|
|
||||||
@RequestParam(required = false) String sourceBillNo) {
|
|
||||||
return iDoctorStationAdviceAppService.getRequestBaseInfo(encounterId, generateSourceEnum, sourceBillNo);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -122,8 +122,7 @@ public interface DoctorStationAdviceAppMapper {
|
|||||||
@Param("MED_MEDICATION_REQUEST") String MED_MEDICATION_REQUEST,
|
@Param("MED_MEDICATION_REQUEST") String MED_MEDICATION_REQUEST,
|
||||||
@Param("WOR_DEVICE_REQUEST") String WOR_DEVICE_REQUEST,
|
@Param("WOR_DEVICE_REQUEST") String WOR_DEVICE_REQUEST,
|
||||||
@Param("WOR_SERVICE_REQUEST") String WOR_SERVICE_REQUEST, @Param("practitionerId") Long practitionerId,
|
@Param("WOR_SERVICE_REQUEST") String WOR_SERVICE_REQUEST, @Param("practitionerId") Long practitionerId,
|
||||||
@Param("historyFlag") String historyFlag, @Param("generateSourceEnum") Integer generateSourceEnum,
|
@Param("historyFlag") String historyFlag, @Param("generateSourceEnum") Integer generateSourceEnum);
|
||||||
@Param("sourceBillNo") String sourceBillNo);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 查询就诊费用性质
|
* 查询就诊费用性质
|
||||||
|
|||||||
@@ -16,7 +16,6 @@ import lombok.AllArgsConstructor;
|
|||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import org.springframework.web.bind.annotation.*;
|
import org.springframework.web.bind.annotation.*;
|
||||||
|
|
||||||
import java.time.LocalDate;
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -143,32 +142,6 @@ public class RequestFormManageController {
|
|||||||
return R.ok(iRequestFormManageAppService.getRequestForm(encounterId, ActivityDefCategory.PROCEDURE.getCode()));
|
return R.ok(iRequestFormManageAppService.getRequestForm(encounterId, ActivityDefCategory.PROCEDURE.getCode()));
|
||||||
}
|
}
|
||||||
/**
|
/**
|
||||||
* 分页查询手术申请单(全局,不需要encounterId,用于门诊手术安排查找弹窗)
|
|
||||||
*
|
|
||||||
* @param surgeryNo 手术单号(模糊查询,可选)
|
|
||||||
* @param applyTimeStart 申请时间起始(可选)
|
|
||||||
* @param applyTimeEnd 申请时间截止(可选)
|
|
||||||
* @param mainDoctorId 主刀医生ID(可选)
|
|
||||||
* @param applyDeptId 申请科室ID(可选)
|
|
||||||
* @param pageNo 页码,默认1
|
|
||||||
* @param pageSize 每页数量,默认10
|
|
||||||
* @return 分页手术申请单列表
|
|
||||||
*/
|
|
||||||
@GetMapping(value = "/get-surgery-page")
|
|
||||||
public R<IPage<RequestFormPageDto>> getSurgeryRequestFormPage(
|
|
||||||
@RequestParam(required = false) String surgeryNo,
|
|
||||||
@RequestParam(required = false) LocalDate applyTimeStart,
|
|
||||||
@RequestParam(required = false) LocalDate applyTimeEnd,
|
|
||||||
@RequestParam(required = false) Long mainDoctorId,
|
|
||||||
@RequestParam(required = false) Long applyDeptId,
|
|
||||||
@RequestParam(defaultValue = "1") Integer pageNo,
|
|
||||||
@RequestParam(defaultValue = "10") Integer pageSize) {
|
|
||||||
RequestFormDto dto = new RequestFormDto(surgeryNo, null, applyTimeStart, applyTimeEnd,
|
|
||||||
mainDoctorId, applyDeptId, pageNo, pageSize);
|
|
||||||
return R.ok(iRequestFormManageAppService.getRequestFormPage(dto));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 分页查询申请单
|
* 分页查询申请单
|
||||||
* @return 申请单
|
* @return 申请单
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -14,10 +14,6 @@ public class RequestFormDto {
|
|||||||
* 手术单号
|
* 手术单号
|
||||||
*/
|
*/
|
||||||
private String surgeryNo;
|
private String surgeryNo;
|
||||||
/**
|
|
||||||
* 申请单类型编码
|
|
||||||
*/
|
|
||||||
private String typeCode;
|
|
||||||
/**
|
/**
|
||||||
* 申请时间开始
|
* 申请时间开始
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -527,9 +527,6 @@
|
|||||||
LEFT JOIN cli_condition AS cc ON cc.id = T1.condition_id AND cc.delete_flag = '0'
|
LEFT JOIN cli_condition AS cc ON cc.id = T1.condition_id AND cc.delete_flag = '0'
|
||||||
LEFT JOIN cli_condition_definition AS ccd ON ccd.id = cc.definition_id
|
LEFT JOIN cli_condition_definition AS ccd ON ccd.id = cc.definition_id
|
||||||
WHERE T1.delete_flag = '0' AND T1.tcm_flag = 0
|
WHERE T1.delete_flag = '0' AND T1.tcm_flag = 0
|
||||||
<if test="generateSourceEnum != null">
|
|
||||||
AND T1.generate_source_enum = #{generateSourceEnum}
|
|
||||||
</if>
|
|
||||||
<if test="historyFlag == '0'.toString()">
|
<if test="historyFlag == '0'.toString()">
|
||||||
AND T1.encounter_id = #{encounterId}
|
AND T1.encounter_id = #{encounterId}
|
||||||
</if>
|
</if>
|
||||||
@@ -698,9 +695,6 @@
|
|||||||
-- based_on_table='med_medication_request' → 输液/皮试执行记录,应排除
|
-- based_on_table='med_medication_request' → 输液/皮试执行记录,应排除
|
||||||
-- based_on_table='exam_apply'/'lab_apply' → 申请单原始医嘱,应保留
|
-- based_on_table='exam_apply'/'lab_apply' → 申请单原始医嘱,应保留
|
||||||
AND (T1.based_on_id IS NULL OR T1.based_on_table IS NULL OR T1.based_on_table NOT IN ('med_medication_request', 'med_medication_dispense'))
|
AND (T1.based_on_id IS NULL OR T1.based_on_table IS NULL OR T1.based_on_table NOT IN ('med_medication_request', 'med_medication_dispense'))
|
||||||
<if test="sourceBillNo != null and sourceBillNo != ''">
|
|
||||||
AND T1.prescription_no = #{sourceBillNo}
|
|
||||||
</if>
|
|
||||||
<if test="historyFlag == '0'.toString()">
|
<if test="historyFlag == '0'.toString()">
|
||||||
AND T1.encounter_id = #{encounterId}
|
AND T1.encounter_id = #{encounterId}
|
||||||
</if>
|
</if>
|
||||||
|
|||||||
@@ -161,9 +161,6 @@
|
|||||||
<if test="requestFormDto.surgeryNo != null and requestFormDto.surgeryNo != ''">
|
<if test="requestFormDto.surgeryNo != null and requestFormDto.surgeryNo != ''">
|
||||||
AND drf.prescription_no LIKE CONCAT('%', #{requestFormDto.surgeryNo}, '%')
|
AND drf.prescription_no LIKE CONCAT('%', #{requestFormDto.surgeryNo}, '%')
|
||||||
</if>
|
</if>
|
||||||
<if test="requestFormDto.typeCode != null and requestFormDto.typeCode != ''">
|
|
||||||
AND drf.type_code = #{requestFormDto.typeCode}
|
|
||||||
</if>
|
|
||||||
<if test="requestFormDto.applyTimeStart != null">
|
<if test="requestFormDto.applyTimeStart != null">
|
||||||
AND drf.create_time >= #{requestFormDto.applyTimeStart}
|
AND drf.create_time >= #{requestFormDto.applyTimeStart}
|
||||||
</if>
|
</if>
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ CREATE TABLE IF NOT EXISTS triage_queue_item (
|
|||||||
patient_name VARCHAR(255),
|
patient_name VARCHAR(255),
|
||||||
healthcare_name VARCHAR(255),
|
healthcare_name VARCHAR(255),
|
||||||
practitioner_name VARCHAR(255),
|
practitioner_name VARCHAR(255),
|
||||||
status INTEGER NOT NULL DEFAULT 0, -- 分诊队列状态: 0=WAITING(等待), 10=CALLING(叫号中), 20=IN_CLINIC(诊中), 30=COMPLETED(已完成), 40=SKIPPED(已跳过)
|
status VARCHAR(50) NOT NULL, -- WAITING/CALLING/SKIPPED/COMPLETED
|
||||||
queue_order INTEGER NOT NULL,
|
queue_order INTEGER NOT NULL,
|
||||||
create_time TIMESTAMP,
|
create_time TIMESTAMP,
|
||||||
update_time TIMESTAMP,
|
update_time TIMESTAMP,
|
||||||
|
|||||||
@@ -1,30 +0,0 @@
|
|||||||
-- Bug #400 修复:triage_queue_item.status 字段类型修正
|
|
||||||
-- 原 DDL 将 status 定义为 VARCHAR(50),但 Java 实体 TriageQueueItem.status 为 Integer 类型,
|
|
||||||
-- 应用层使用 TriageQueueStatus 枚举值(0/10/20/30/40)写入,类型不匹配导致 MyBatis-Plus
|
|
||||||
-- 无法正确映射 status 字段,完诊时 status 更新为 30 失败。
|
|
||||||
--
|
|
||||||
-- 注意:必须在后端实际连接的 schema 中执行(dev=hisdev, test=histest, prd=hisprd)
|
|
||||||
-- 执行前请先确认:SET search_path TO hisdev; (或对应的 schema)
|
|
||||||
|
|
||||||
-- 1. 先将已有的字符串值转换为对应的整数值
|
|
||||||
-- 如果之前写入的是枚举 code(如 'waiting'、'completed'),需要先转换
|
|
||||||
UPDATE triage_queue_item
|
|
||||||
SET status = CASE
|
|
||||||
WHEN status IN ('0', 'waiting', 'WAITING') THEN 0
|
|
||||||
WHEN status IN ('10', 'calling', 'CALLING') THEN 10
|
|
||||||
WHEN status IN ('20', 'in-clinic', 'IN_CLINIC', 'in-clinic') THEN 20
|
|
||||||
WHEN status IN ('30', 'completed', 'COMPLETED') THEN 30
|
|
||||||
WHEN status IN ('40', 'skipped', 'SKIPPED') THEN 40
|
|
||||||
WHEN status IN ('50', 'refunded', 'REFUNDED') THEN 50
|
|
||||||
WHEN status IN ('60', 'follow', 'FOLLOW') THEN 60
|
|
||||||
ELSE 0
|
|
||||||
END
|
|
||||||
WHERE status IS NOT NULL AND status !~ '^[0-9]+$';
|
|
||||||
|
|
||||||
-- 2. 修改字段类型为 INTEGER
|
|
||||||
ALTER TABLE triage_queue_item
|
|
||||||
ALTER COLUMN status TYPE INTEGER USING status::INTEGER;
|
|
||||||
|
|
||||||
-- 3. 设置默认值
|
|
||||||
ALTER TABLE triage_queue_item
|
|
||||||
ALTER COLUMN status SET DEFAULT 0;
|
|
||||||
@@ -163,7 +163,7 @@ export function updateCheckPart(data) {
|
|||||||
// 查询检查套餐列表
|
// 查询检查套餐列表
|
||||||
export function listCheckPackage(query) {
|
export function listCheckPackage(query) {
|
||||||
return request({
|
return request({
|
||||||
url: '/system/package/list',
|
url: '/system/check-package/list',
|
||||||
method: 'get',
|
method: 'get',
|
||||||
params: query
|
params: query
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -58,17 +58,10 @@ export function singOut(data) {
|
|||||||
/**
|
/**
|
||||||
* 获取患者本次就诊处方
|
* 获取患者本次就诊处方
|
||||||
*/
|
*/
|
||||||
export function getPrescriptionList(encounterId, generateSourceEnum, sourceBillNo) {
|
export function getPrescriptionList(encounterId) {
|
||||||
let url = '/doctor-station/advice/request-base-info?encounterId=' + encounterId
|
// Add timestamp to bypass browser caching and ensure fresh data is loaded
|
||||||
if (generateSourceEnum != null) {
|
|
||||||
url += '&generateSourceEnum=' + generateSourceEnum
|
|
||||||
}
|
|
||||||
if (sourceBillNo != null) {
|
|
||||||
url += '&sourceBillNo=' + encodeURIComponent(sourceBillNo)
|
|
||||||
}
|
|
||||||
url += '&t=' + Date.now()
|
|
||||||
return request({
|
return request({
|
||||||
url: url,
|
url: '/doctor-station/advice/request-base-info?encounterId=' + encounterId + '&t=' + Date.now(),
|
||||||
method: 'get',
|
method: 'get',
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -381,14 +381,6 @@ const props = defineProps({
|
|||||||
activeTab: {
|
activeTab: {
|
||||||
type: String,
|
type: String,
|
||||||
},
|
},
|
||||||
generateSourceEnum: {
|
|
||||||
type: Number,
|
|
||||||
default: null,
|
|
||||||
},
|
|
||||||
sourceBillNo: {
|
|
||||||
type: String,
|
|
||||||
default: null,
|
|
||||||
},
|
|
||||||
});
|
});
|
||||||
const isAdding = ref(false);
|
const isAdding = ref(false);
|
||||||
const isSaving = ref(false); // #437 防重复提交锁
|
const isSaving = ref(false); // #437 防重复提交锁
|
||||||
@@ -476,11 +468,7 @@ watch(
|
|||||||
|
|
||||||
function getListInfo(addNewRow) {
|
function getListInfo(addNewRow) {
|
||||||
isAdding.value = false;
|
isAdding.value = false;
|
||||||
getPrescriptionList(
|
getPrescriptionList(props.patientInfo.encounterId).then((res) => {
|
||||||
props.patientInfo.encounterId,
|
|
||||||
props.generateSourceEnum ?? undefined,
|
|
||||||
props.sourceBillNo ?? undefined,
|
|
||||||
).then((res) => {
|
|
||||||
// 为每行数据添加 adviceTypeValue 字段,用于类型下拉框显示
|
// 为每行数据添加 adviceTypeValue 字段,用于类型下拉框显示
|
||||||
prescriptionList.value = (res.data || []).map(item => {
|
prescriptionList.value = (res.data || []).map(item => {
|
||||||
// 根据 adviceType 和 categoryCode 找到对应的 adviceTypeValue
|
// 根据 adviceType 和 categoryCode 找到对应的 adviceTypeValue
|
||||||
@@ -880,23 +868,19 @@ function handleDelete() {
|
|||||||
proxy.$modal.msgWarning('请选择要删除的项目');
|
proxy.$modal.msgWarning('请选择要删除的项目');
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
let deleteList = groupIndexList.value.map((index) => {
|
let deleteList = groupIndexList.value.map((index) => {
|
||||||
const item = prescriptionList.value[index];
|
const item = prescriptionList.value[index];
|
||||||
// 只删除待签发且未收费的项目
|
// 只删除待签发且未收费的项目
|
||||||
if (item.statusEnum != 1 || item.chargeStatus == 5) {
|
if (item.statusEnum != 1 || item.chargeStatus == 5) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
// 🔧 Bug #442: 已保存的行必须有有效的 requestId,否则跳过(避免后端删除不存在的记录)
|
|
||||||
if (item.requestId == null || item.requestId === undefined || item.requestId === '') {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
return {
|
return {
|
||||||
requestId: item.requestId,
|
requestId: item.requestId,
|
||||||
dbOpType: '3',
|
dbOpType: '3',
|
||||||
adviceType: item.adviceType,
|
adviceType: item.adviceType,
|
||||||
};
|
};
|
||||||
}).filter(item => item !== null); // 过滤掉已签发、已收费或无 requestId 的项目
|
}).filter(item => item !== null); // 过滤掉已签发或已收费的项目
|
||||||
|
|
||||||
if (deleteList.length == 0) {
|
if (deleteList.length == 0) {
|
||||||
proxy.$modal.msgWarning('只能删除待签发且未收费的项目');
|
proxy.$modal.msgWarning('只能删除待签发且未收费的项目');
|
||||||
|
|||||||
@@ -1243,14 +1243,11 @@ async function show(diagnosisData) {
|
|||||||
const res = await getNextCardNo(orgCode);
|
const res = await getNextCardNo(orgCode);
|
||||||
if (res.code === 200 && res.data && res.data.length >= 12) {
|
if (res.code === 200 && res.data && res.data.length >= 12) {
|
||||||
cardNo = res.data;
|
cardNo = res.data;
|
||||||
} else {
|
|
||||||
// API返回失败或不合规时,生成临时卡号避免保存时 cardNo 为空导致后端校验失败
|
|
||||||
cardNo = 'TEMP_' + Date.now();
|
|
||||||
}
|
}
|
||||||
|
// API失败或返回不合规时保持为空字符串,由用户手动填写或后端自动生成
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
console.error('获取卡片编号失败:', err);
|
console.error('获取卡片编号失败:', err);
|
||||||
// API调用异常时,生成临时卡号
|
// 保持为空,不使用不合规的临时值
|
||||||
cardNo = 'TEMP_' + Date.now();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
form.value = {
|
form.value = {
|
||||||
@@ -1433,8 +1430,8 @@ async function buildSubmitData() {
|
|||||||
function validateFormManually() {
|
function validateFormManually() {
|
||||||
const errors = [];
|
const errors = [];
|
||||||
|
|
||||||
// 卡片编号验证(至少12位,后端自动生成16位编号;临时卡号 TEMP_ 开头允许通过)
|
// 卡片编号验证(至少12位,后端自动生成16位编号)
|
||||||
if (form.value.cardNo && !form.value.cardNo.startsWith('TEMP_') && form.value.cardNo.length < 12) {
|
if (form.value.cardNo && form.value.cardNo.length < 12) {
|
||||||
errors.push('卡片编号至少12位');
|
errors.push('卡片编号至少12位');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -402,21 +402,6 @@
|
|||||||
<span class="method-price">¥{{ method.packagePrice || item.price }}</span>
|
<span class="method-price">¥{{ method.packagePrice || item.price }}</span>
|
||||||
</el-checkbox>
|
</el-checkbox>
|
||||||
</div>
|
</div>
|
||||||
<!-- 选中方法后,显示对应的套餐明细 -->
|
|
||||||
<div v-if="item.selectedMethod && item.methodPackageDetails && item.methodPackageDetails.length > 0" class="method-package-details">
|
|
||||||
<div class="method-package-header">
|
|
||||||
<span class="method-package-title">套餐明细 - {{ item.selectedMethod.name }}</span>
|
|
||||||
</div>
|
|
||||||
<div v-for="detail in item.methodPackageDetails" :key="detail.id" class="method-option">
|
|
||||||
<el-checkbox v-model="detail.checked">
|
|
||||||
<span class="method-name">{{ detail.name }}</span>
|
|
||||||
<span class="method-price">数量: {{ detail.quantity }} ¥{{ detail.price }}</span>
|
|
||||||
</el-checkbox>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div v-if="item.selectedMethod && item.methodPackageLoading" class="method-package-loading">
|
|
||||||
加载套餐明细中...
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -434,7 +419,7 @@ import { ElMessage, ElMessageBox } from 'element-plus';
|
|||||||
import { Printer, Delete, ArrowDown, ArrowUp, Close } from '@element-plus/icons-vue';
|
import { Printer, Delete, ArrowDown, ArrowUp, Close } from '@element-plus/icons-vue';
|
||||||
import useUserStore from '@/store/modules/user';
|
import useUserStore from '@/store/modules/user';
|
||||||
import request from '@/utils/request';
|
import request from '@/utils/request';
|
||||||
import { listCheckMethod, searchCheckMethod, listCheckPackage } from '@/api/system/checkType';
|
import { listCheckMethod, searchCheckMethod } from '@/api/system/checkType';
|
||||||
import { getEncounterDiagnosis } from '../api.js';
|
import { getEncounterDiagnosis } from '../api.js';
|
||||||
|
|
||||||
const props = defineProps({
|
const props = defineProps({
|
||||||
@@ -460,7 +445,7 @@ async function loadPackageDetails(row, treeNode, resolve) {
|
|||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
const res = await request({
|
const res = await request({
|
||||||
url: `/system/package/${row.packageId}/details`,
|
url: `/exam/package/${row.packageId}/details`,
|
||||||
method: 'get'
|
method: 'get'
|
||||||
});
|
});
|
||||||
if (res.code === 200 && res.data) {
|
if (res.code === 200 && res.data) {
|
||||||
@@ -482,28 +467,14 @@ async function loadPackageDetails(row, treeNode, resolve) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// #428修复: 为已选择项目加载套餐明细(通过packageId或packageName查询)
|
// #428: 为已选择项目加载套餐明细
|
||||||
async function loadPackageDetailsForItem(item) {
|
async function loadPackageDetailsForItem(item) {
|
||||||
if (!item.isPackage || (!item.packageId && !item.packageName)) {
|
if (!item.isPackage || !item.packageId) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
try {
|
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({
|
const res = await request({
|
||||||
url: `/system/package/${packageId}/details`,
|
url: `/exam/package/${item.packageId}/details`,
|
||||||
method: 'get'
|
method: 'get'
|
||||||
});
|
});
|
||||||
if (res.code === 200 && res.data) {
|
if (res.code === 200 && res.data) {
|
||||||
@@ -511,7 +482,7 @@ async function loadPackageDetailsForItem(item) {
|
|||||||
...detail,
|
...detail,
|
||||||
name: detail.name || detail.itemName,
|
name: detail.name || detail.itemName,
|
||||||
unit: detail.unit || '次',
|
unit: detail.unit || '次',
|
||||||
price: detail.price || detail.unitPrice || 0,
|
price: detail.price || detail.itemPrice || 0,
|
||||||
quantity: detail.quantity || 1
|
quantity: detail.quantity || 1
|
||||||
}));
|
}));
|
||||||
} else {
|
} else {
|
||||||
@@ -730,9 +701,7 @@ function handleCollapseChange(activeName) {
|
|||||||
setTimeout(() => { isAnimating.value = false; }, 300); // 与 CSS 过渡时长一致
|
setTimeout(() => { isAnimating.value = false; }, 300); // 与 CSS 过渡时长一致
|
||||||
|
|
||||||
if (activeName) {
|
if (activeName) {
|
||||||
// Bug #428修复: 直接从 categoryList(原始响应式数组)查找分类,
|
const cat = filteredCategoryList.value.find(c => c.typeId == activeName);
|
||||||
// 确保后续 handleCategoryExpand 对 cat.methods 的赋值能正确触发 Vue 响应式更新
|
|
||||||
const cat = categoryList.value.find(c => c.typeId == activeName);
|
|
||||||
if (cat && (!cat.methods || cat.methods.length === 0)) {
|
if (cat && (!cat.methods || cat.methods.length === 0)) {
|
||||||
handleCategoryExpand(cat); // 异步加载,不 await
|
handleCategoryExpand(cat); // 异步加载,不 await
|
||||||
}
|
}
|
||||||
@@ -1024,20 +993,12 @@ function handleRowClick(row) {
|
|||||||
selectedItems.value = [];
|
selectedItems.value = [];
|
||||||
activeDetailTab.value = 'applyForm';
|
activeDetailTab.value = 'applyForm';
|
||||||
request({ url: `/exam/apply/${row.applyNo}`, method: 'get' }).then(async res => {
|
request({ url: `/exam/apply/${row.applyNo}`, method: 'get' }).then(async res => {
|
||||||
const resp = res.data || res;
|
const d = res.data || res;
|
||||||
// Bug #408修复: items 在 AjaxResult 顶层(res.items / resp.items),不在 ExamApply 对象内
|
if (d.data) Object.assign(form, d.data);
|
||||||
// 防御性提取:优先取顶层 items,兼容嵌套在 resp.data.items 的情况
|
if (d.items && Array.isArray(d.items)) {
|
||||||
let rawItems = res.items || resp.items;
|
|
||||||
if (!rawItems && resp.data && typeof resp.data === 'object') {
|
|
||||||
rawItems = resp.data.items;
|
|
||||||
}
|
|
||||||
rawItems = rawItems || [];
|
|
||||||
const d = resp.data || resp;
|
|
||||||
if (d) Object.assign(form, d);
|
|
||||||
if (Array.isArray(rawItems) && rawItems.length > 0) {
|
|
||||||
try {
|
try {
|
||||||
// 为每个项目加载检查方法
|
// 为每个项目加载检查方法
|
||||||
const itemsWithMethods = await Promise.all(rawItems.map(async m => {
|
const itemsWithMethods = await Promise.all(d.items.map(async m => {
|
||||||
const item = {
|
const item = {
|
||||||
id: m.itemCode, name: m.itemName,
|
id: m.itemCode, name: m.itemName,
|
||||||
price: m.itemFee || 0, quantity: 1,
|
price: m.itemFee || 0, quantity: 1,
|
||||||
@@ -1151,8 +1112,7 @@ async function handleMethodSelect(checked, method, cat) {
|
|||||||
// 如果该项目不存在,创建一个并关联方法
|
// 如果该项目不存在,创建一个并关联方法
|
||||||
if (selectedItems.value.length > 0) {
|
if (selectedItems.value.length > 0) {
|
||||||
const currentCategory = selectedItems.value[0].checkType;
|
const currentCategory = selectedItems.value[0].checkType;
|
||||||
// Bug #428修复: 使用 cat.typeName 进行比较(与 newItem.checkType 保持一致)
|
const newCategory = cat.typeCode || '';
|
||||||
const newCategory = cat.typeName || '';
|
|
||||||
if (currentCategory !== newCategory) {
|
if (currentCategory !== newCategory) {
|
||||||
ElMessage.warning('一个检查单不能同时选择多个项目类型的检查项目');
|
ElMessage.warning('一个检查单不能同时选择多个项目类型的检查项目');
|
||||||
return;
|
return;
|
||||||
@@ -1237,8 +1197,7 @@ async function handleItemSelect(checked, item, cat) {
|
|||||||
|
|
||||||
if (selectedItems.value.length > 0) {
|
if (selectedItems.value.length > 0) {
|
||||||
const currentCategory = selectedItems.value[0].checkType;
|
const currentCategory = selectedItems.value[0].checkType;
|
||||||
// Bug #428修复: 使用 cat.typeName 进行比较(与 effectiveCheckType 保持一致)
|
const newCategory = cat.typeCode || '';
|
||||||
const newCategory = cat.typeName || '';
|
|
||||||
if (currentCategory !== newCategory) {
|
if (currentCategory !== newCategory) {
|
||||||
ElMessage.warning('一个检查单不能同时选择多个项目类型的检查项目');
|
ElMessage.warning('一个检查单不能同时选择多个项目类型的检查项目');
|
||||||
item.checked = false;
|
item.checked = false;
|
||||||
@@ -1259,7 +1218,6 @@ async function handleItemSelect(checked, item, cat) {
|
|||||||
selectedMethod: null,
|
selectedMethod: null,
|
||||||
expanded: false, // Bug #384修复: 新增展开状态,默认不展开
|
expanded: false, // Bug #384修复: 新增展开状态,默认不展开
|
||||||
isPackage: !!item.packageName, // Bug #428修复: 标记是否为套餐
|
isPackage: !!item.packageName, // Bug #428修复: 标记是否为套餐
|
||||||
packageName: item.packageName || null, // Bug #426修复: 套餐名称,用于查找packageId
|
|
||||||
packageId: item.packageId || null // Bug #428修复: 套餐ID
|
packageId: item.packageId || null // Bug #428修复: 套餐ID
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -1292,68 +1250,21 @@ async function toggleItemExpand(item) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Bug #384修复: 勾选框选择检查方法(单选逻辑)
|
// Bug #384修复: 勾选框选择检查方法(单选逻辑)
|
||||||
async function selectMethodCheckbox(checked, item, method) {
|
function selectMethodCheckbox(checked, item, method) {
|
||||||
if (checked) {
|
if (checked) {
|
||||||
item.selectedMethod = method;
|
item.selectedMethod = method;
|
||||||
// 动态加载该方法对应的套餐明细
|
|
||||||
await loadMethodPackageDetails(item, method);
|
|
||||||
} else {
|
} else {
|
||||||
item.selectedMethod = null;
|
item.selectedMethod = null;
|
||||||
item.methodPackageDetails = [];
|
|
||||||
}
|
}
|
||||||
// 联动更新表单检查方法显示字段
|
// 联动更新表单检查方法显示字段
|
||||||
updateMethodDisplay();
|
updateMethodDisplay();
|
||||||
|
|
||||||
// #430: 套餐金额实时同步到申请单
|
// #430: 套餐金额实时同步到申请单
|
||||||
nextTick(() => {
|
nextTick(() => {
|
||||||
form.totalAmount = totalAmountCalc.value;
|
form.totalAmount = totalAmountCalc.value;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
// 根据检查方法的packageName加载对应的套餐明细
|
|
||||||
async function loadMethodPackageDetails(item, method) {
|
|
||||||
item.methodPackageLoading = true;
|
|
||||||
item.methodPackageDetails = [];
|
|
||||||
try {
|
|
||||||
if (!method.packageName) {
|
|
||||||
item.methodPackageLoading = false;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
// 通过packageName查询套餐获取packageId
|
|
||||||
const pkgRes = await listCheckPackage({ packageName: method.packageName });
|
|
||||||
let packages = pkgRes?.data || [];
|
|
||||||
if (!Array.isArray(packages)) {
|
|
||||||
packages = packages.records || packages.data || [];
|
|
||||||
}
|
|
||||||
if (packages.length === 0) {
|
|
||||||
item.methodPackageLoading = false;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
const packageId = packages[0].id;
|
|
||||||
// 查询套餐明细
|
|
||||||
const detailRes = await request({
|
|
||||||
url: `/system/package/${packageId}/details`,
|
|
||||||
method: 'get'
|
|
||||||
});
|
|
||||||
if (detailRes.code === 200 && detailRes.data) {
|
|
||||||
item.methodPackageDetails = detailRes.data.map(d => ({
|
|
||||||
id: d.id,
|
|
||||||
name: d.itemName || d.name,
|
|
||||||
quantity: d.quantity || 1,
|
|
||||||
unit: d.unit || '次',
|
|
||||||
price: d.unitPrice || d.price || 0,
|
|
||||||
amount: d.amount || d.total || 0,
|
|
||||||
checked: true // 默认勾选
|
|
||||||
}));
|
|
||||||
}
|
|
||||||
} catch (err) {
|
|
||||||
console.error('加载方法套餐明细失败:', err);
|
|
||||||
item.methodPackageDetails = [];
|
|
||||||
} finally {
|
|
||||||
item.methodPackageLoading = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Bug #384修复: 更新检查方法显示字段(联动)
|
// Bug #384修复: 更新检查方法显示字段(联动)
|
||||||
function updateMethodDisplay() {
|
function updateMethodDisplay() {
|
||||||
// 找到第一个有选中检查方法的项目
|
// 找到第一个有选中检查方法的项目
|
||||||
@@ -1759,29 +1670,6 @@ defineExpose({ getList });
|
|||||||
margin-left: 8px;
|
margin-left: 8px;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* 选中方法后显示的套餐明细 */
|
|
||||||
.method-package-details {
|
|
||||||
margin-top: 4px;
|
|
||||||
padding: 4px 0;
|
|
||||||
border-top: 1px dashed #dcdfe6;
|
|
||||||
}
|
|
||||||
|
|
||||||
.method-package-header {
|
|
||||||
padding: 2px 0 4px 24px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.method-package-title {
|
|
||||||
font-size: 10px;
|
|
||||||
color: #909399;
|
|
||||||
font-weight: 500;
|
|
||||||
}
|
|
||||||
|
|
||||||
.method-package-loading {
|
|
||||||
padding: 4px 0 4px 24px;
|
|
||||||
font-size: 10px;
|
|
||||||
color: #c0c4cc;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* 折叠组件细节 */
|
/* 折叠组件细节 */
|
||||||
:deep(.el-collapse) {
|
:deep(.el-collapse) {
|
||||||
border: none;
|
border: none;
|
||||||
|
|||||||
@@ -44,17 +44,6 @@ export function getSurgery(queryParams) {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* 分页查询手术申请单(全局,不需要encounterId,用于门诊手术安排查找弹窗)
|
|
||||||
*/
|
|
||||||
export function getSurgeryPage(queryParams) {
|
|
||||||
return request({
|
|
||||||
url: '/reg-doctorstation/request-form/get-surgery-page',
|
|
||||||
method: 'get',
|
|
||||||
params: queryParams,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 查询护理医嘱信息
|
* 查询护理医嘱信息
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -1210,7 +1210,7 @@ function handleSave() {
|
|||||||
isSaving.value = false;
|
isSaving.value = false;
|
||||||
getListInfo(false);
|
getListInfo(false);
|
||||||
bindMethod.value = {};
|
bindMethod.value = {};
|
||||||
nextId.value = 1;
|
nextId.value == 1;
|
||||||
} else {
|
} else {
|
||||||
proxy.$modal.msgError(res.message);
|
proxy.$modal.msgError(res.message);
|
||||||
isSaving.value = false;
|
isSaving.value = false;
|
||||||
@@ -1376,21 +1376,13 @@ function handleSaveSign(row, index) {
|
|||||||
savePrescription({ regAdviceSaveList: [row] }).then((res) => {
|
savePrescription({ regAdviceSaveList: [row] }).then((res) => {
|
||||||
if (res.code === 200) {
|
if (res.code === 200) {
|
||||||
proxy.$modal.msgSuccess('保存成功');
|
proxy.$modal.msgSuccess('保存成功');
|
||||||
nextId.value = 1;
|
nextId.value == 1;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
// 新增行:调用保存接口将数据持久化到后端
|
if (prescriptionList.value[0].adviceName) {
|
||||||
row.dbOpType = '1';
|
handleAddPrescription();
|
||||||
savePrescription({ regAdviceSaveList: [row] }).then((res) => {
|
}
|
||||||
if (res.code === 200) {
|
|
||||||
proxy.$modal.msgSuccess('保存成功');
|
|
||||||
nextId.value = 1;
|
|
||||||
// 保存成功后刷新列表,确保后端返回的数据带 requestId
|
|
||||||
getListInfo(false);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
// 不需要再添加空行,保存成功后由 getListInfo 处理
|
|
||||||
}
|
}
|
||||||
adviceQueryParams.value.adviceType = undefined;
|
adviceQueryParams.value.adviceType = undefined;
|
||||||
}
|
}
|
||||||
@@ -1437,13 +1429,12 @@ function handleSaveBatch() {
|
|||||||
if (row) row.isEdit = false;
|
if (row) row.isEdit = false;
|
||||||
});
|
});
|
||||||
getListInfo(false);
|
getListInfo(false);
|
||||||
nextId.value = 1;
|
nextId.value == 1;
|
||||||
isSaving.value = false;
|
isSaving.value = false;
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.catch((error) => {
|
.catch((error) => {
|
||||||
isSaving.value = false;
|
isSaving.value = false;
|
||||||
proxy.$modal.msgError(error?.msg || '保存失败,请重试');
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1571,21 +1562,17 @@ function handleSaveGroup(orderGroupList) {
|
|||||||
// 🔥 新版组件已经预处理了数据,优先使用 mergedDetail
|
// 🔥 新版组件已经预处理了数据,优先使用 mergedDetail
|
||||||
const mergedDetail = item.mergedDetail || {
|
const mergedDetail = item.mergedDetail || {
|
||||||
...(item.orderDetailInfos || {}),
|
...(item.orderDetailInfos || {}),
|
||||||
adviceName: item.orderDefinitionName || item.orderDetailInfos?.adviceName || '未知项目',
|
adviceName: item.orderDetailInfos?.adviceName || item.orderDefinitionName || '未知项目',
|
||||||
adviceType: item.orderDetailInfos?.adviceType,
|
adviceType: item.orderDetailInfos?.adviceType,
|
||||||
adviceDefinitionId: item.orderDefinitionId || item.orderDetailInfos?.adviceDefinitionId,
|
adviceDefinitionId: item.orderDefinitionId || item.orderDetailInfos?.adviceDefinitionId,
|
||||||
quantity: item.quantity,
|
quantity: item.quantity,
|
||||||
unitCode: item.unitCode || item.orderDetailInfos?.unitCode,
|
unitCode: item.unitCode || item.orderDetailInfos?.unitCode,
|
||||||
unitCodeName: item.unitCodeName,
|
unitCodeName: item.unitCodeName,
|
||||||
// 🔧 Bug #403 修复:dose/doseQuantity/dispensePerDuration 需用 null 检查,
|
dose: item.dose || item.orderDetailInfos?.dose,
|
||||||
// 避免组套中值为 null 时回退到医嘱库的 orderDetailInfos
|
|
||||||
dose: item.dose !== undefined && item.dose !== null ? item.dose : item.orderDetailInfos?.dose,
|
|
||||||
rateCode: item.rateCode || item.orderDetailInfos?.rateCode,
|
rateCode: item.rateCode || item.orderDetailInfos?.rateCode,
|
||||||
methodCode: item.methodCode || item.orderDetailInfos?.methodCode,
|
methodCode: item.methodCode || item.orderDetailInfos?.methodCode,
|
||||||
dispensePerDuration: item.dispensePerDuration !== undefined && item.dispensePerDuration !== null
|
dispensePerDuration: item.dispensePerDuration || item.orderDetailInfos?.dispensePerDuration,
|
||||||
? item.dispensePerDuration : item.orderDetailInfos?.dispensePerDuration,
|
doseQuantity: item.doseQuantity,
|
||||||
doseQuantity: item.doseQuantity !== undefined && item.doseQuantity !== null
|
|
||||||
? item.doseQuantity : item.orderDetailInfos?.doseQuantity,
|
|
||||||
inventoryList: item.orderDetailInfos?.inventoryList || [],
|
inventoryList: item.orderDetailInfos?.inventoryList || [],
|
||||||
priceList: item.orderDetailInfos?.priceList || [],
|
priceList: item.orderDetailInfos?.priceList || [],
|
||||||
partPercent: item.orderDetailInfos?.partPercent || 1,
|
partPercent: item.orderDetailInfos?.partPercent || 1,
|
||||||
@@ -1604,21 +1591,20 @@ function handleSaveGroup(orderGroupList) {
|
|||||||
setValue(mergedDetail);
|
setValue(mergedDetail);
|
||||||
|
|
||||||
// 创建新的处方项目
|
// 创建新的处方项目
|
||||||
// 🔧 Bug #403 修复:关键字段使用 null-safe 回退到 mergedDetail(已由 setValue 填充完整数据)
|
|
||||||
const newRow = {
|
const newRow = {
|
||||||
...prescriptionList.value[rowIndex.value],
|
...prescriptionList.value[rowIndex.value],
|
||||||
patientId: patientInfo.value.patientId,
|
patientId: patientInfo.value.patientId,
|
||||||
encounterId: patientInfo.value.encounterId,
|
encounterId: patientInfo.value.encounterId,
|
||||||
accountId: accountId.value,
|
accountId: accountId.value,
|
||||||
quantity: item.quantity ?? mergedDetail.quantity,
|
quantity: item.quantity,
|
||||||
methodCode: item.methodCode ?? mergedDetail.methodCode,
|
methodCode: item.methodCode,
|
||||||
rateCode: item.rateCode ?? mergedDetail.rateCode,
|
rateCode: item.rateCode,
|
||||||
dispensePerDuration: item.dispensePerDuration ?? mergedDetail.dispensePerDuration,
|
dispensePerDuration: item.dispensePerDuration,
|
||||||
dose: item.dose ?? mergedDetail.dose,
|
dose: item.dose,
|
||||||
doseQuantity: item.doseQuantity ?? mergedDetail.doseQuantity,
|
doseQuantity: item.doseQuantity,
|
||||||
executeNum: 1,
|
executeNum: 1,
|
||||||
unitCode: item.unitCode ?? mergedDetail.unitCode,
|
unitCode: item.unitCode,
|
||||||
unitCode_dictText: item.unitCodeName || mergedDetail.unitCodeName || '',
|
unitCode_dictText: item.unitCodeName || '',
|
||||||
statusEnum: 1,
|
statusEnum: 1,
|
||||||
orgId: resolveOrgId(item.orderDetailInfos?.orgId || mergedDetail.orgId || patientInfo.value?.inHospitalOrgId) || '',
|
orgId: resolveOrgId(item.orderDetailInfos?.orgId || mergedDetail.orgId || patientInfo.value?.inHospitalOrgId) || '',
|
||||||
// 🔧 修复:同时保存 orgName,确保树匹配不到时仍有中文名称可显示
|
// 🔧 修复:同时保存 orgName,确保树匹配不到时仍有中文名称可显示
|
||||||
|
|||||||
@@ -453,10 +453,6 @@ const loadPatientInfo = () => {
|
|||||||
interventionForm.value.startTime = dayjs(res.data.startTime).format(
|
interventionForm.value.startTime = dayjs(res.data.startTime).format(
|
||||||
'YYYY-MM-DD HH:mm:ss'
|
'YYYY-MM-DD HH:mm:ss'
|
||||||
);
|
);
|
||||||
} else if (res.data.inHosTime) {
|
|
||||||
interventionForm.value.startTime = dayjs(res.data.inHosTime).format(
|
|
||||||
'YYYY-MM-DD HH:mm:ss'
|
|
||||||
);
|
|
||||||
} else {
|
} else {
|
||||||
interventionForm.value.startTime = dayjs(new Date()).format('YYYY-MM-DD HH:mm:ss');
|
interventionForm.value.startTime = dayjs(new Date()).format('YYYY-MM-DD HH:mm:ss');
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -829,9 +829,7 @@
|
|||||||
</el-descriptions>
|
</el-descriptions>
|
||||||
</div>
|
</div>
|
||||||
<div style="padding: 10px">
|
<div style="padding: 10px">
|
||||||
<prescriptionlist v-if="showChargeDialog" :patientInfo="chargePatientInfo" ref="prescriptionRef"
|
<prescriptionlist v-if="showChargeDialog" :patientInfo="chargePatientInfo" ref="prescriptionRef" />
|
||||||
:generateSourceEnum="1"
|
|
||||||
:sourceBillNo="chargePatientInfo.sourceBillNo" />
|
|
||||||
<div class="overlay" v-if="disabled"></div>
|
<div class="overlay" v-if="disabled"></div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -874,32 +872,16 @@ import { Loading } from '@element-plus/icons-vue' // 🔧 新增:导入 Loadin
|
|||||||
import { getPrescriptionList } from '@/views/clinicmanagement/bargain/component/api'
|
import { getPrescriptionList } from '@/views/clinicmanagement/bargain/component/api'
|
||||||
|
|
||||||
// API 导入
|
// API 导入
|
||||||
import {
|
import { getSurgerySchedulePage, addSurgerySchedule, updateSurgerySchedule, deleteSurgerySchedule, getSurgeryScheduleDetail } from '@/api/surgicalschedule'
|
||||||
getSurgerySchedulePage,
|
|
||||||
addSurgerySchedule,
|
|
||||||
updateSurgerySchedule,
|
|
||||||
deleteSurgerySchedule,
|
|
||||||
getSurgeryScheduleDetail
|
|
||||||
} from '@/api/surgicalschedule'
|
|
||||||
import { listUser } from '@/api/system/user'
|
import { listUser } from '@/api/system/user'
|
||||||
import { deptTreeSelect } from '@/api/system/user'
|
import { deptTreeSelect } from '@/api/system/user'
|
||||||
import { listOperatingRoom } from '@/api/operatingroom'
|
import { listOperatingRoom } from '@/api/operatingroom'
|
||||||
import { getSurgeryPage} from '@/views/inpatientDoctor/home/components/applicationShow/api.js'
|
import { getSurgery} from '@/views/inpatientDoctor/home/components/applicationShow/api.js'
|
||||||
|
import { getTenantPage } from '@/api/system/tenant'
|
||||||
import { getContract } from '@/views/inpatientDoctor/home/components/api.js'
|
import { getContract } from '@/views/inpatientDoctor/home/components/api.js'
|
||||||
import request from '@/utils/request'
|
|
||||||
import SurgeryCharge from '../charge/surgerycharge/index.vue'
|
import SurgeryCharge from '../charge/surgerycharge/index.vue'
|
||||||
import TemporaryMedical from './temporaryMedical.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 { proxy } = getCurrentInstance()
|
||||||
const userStore = useUserStore()
|
const userStore = useUserStore()
|
||||||
const loading = ref(true)
|
const loading = ref(true)
|
||||||
@@ -1128,7 +1110,7 @@ onMounted(() => {
|
|||||||
|
|
||||||
// 加载卫生机构列表
|
// 加载卫生机构列表
|
||||||
function loadOrgList() {
|
function loadOrgList() {
|
||||||
getTenantPageSilent({ pageNo: 1, pageSize: 1000 })
|
getTenantPage({ pageNo: 1, pageSize: 1000 })
|
||||||
.then(res => {
|
.then(res => {
|
||||||
if (res.code === 200) {
|
if (res.code === 200) {
|
||||||
const records = res.data?.records || res.data || []
|
const records = res.data?.records || res.data || []
|
||||||
@@ -1406,8 +1388,8 @@ async function handleChargeCharge(row) {
|
|||||||
orgId: userStore.organizationId || userStore.orgId || userStore.tenantId || 1,
|
orgId: userStore.organizationId || userStore.orgId || userStore.tenantId || 1,
|
||||||
// 添加账户ID
|
// 添加账户ID
|
||||||
accountId: accountId,
|
accountId: accountId,
|
||||||
// 添加手术单号用于关联对应的手术医嘱
|
// 添加手术申请单号用于追溯
|
||||||
sourceBillNo: row.operCode,
|
sourceBillNo: row.applyId,
|
||||||
//添加计费标志手术计费
|
//添加计费标志手术计费
|
||||||
generateSourceEnum: 6
|
generateSourceEnum: 6
|
||||||
}
|
}
|
||||||
@@ -1468,8 +1450,7 @@ function handleMedicalAdvice(row) {
|
|||||||
role: userStore.roles[0],
|
role: userStore.roles[0],
|
||||||
effectiveOrgId : row.effectiveOrgId,
|
effectiveOrgId : row.effectiveOrgId,
|
||||||
orgId: userStore.orgId,
|
orgId: userStore.orgId,
|
||||||
positionId: userStore.orgId,
|
positionId: userStore.orgId
|
||||||
applyId: row.applyId // 手术申请单ID,用于过滤关联医嘱
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// 🔧 关键修复:如果已有提交的医嘱数据,并且是同一个患者的就诊,则使用保存的数据
|
// 🔧 关键修复:如果已有提交的医嘱数据,并且是同一个患者的就诊,则使用保存的数据
|
||||||
@@ -1767,7 +1748,7 @@ function handleQuoteBilling() {
|
|||||||
// 重新拉取计费药品数据
|
// 重新拉取计费药品数据
|
||||||
if (temporaryPatientInfo.value.visitId) {
|
if (temporaryPatientInfo.value.visitId) {
|
||||||
temporaryMedicalLoading.value = true // 🔧 新增:开始加载
|
temporaryMedicalLoading.value = true // 🔧 新增:开始加载
|
||||||
getPrescriptionList(temporaryPatientInfo.value.visitId, 6, temporaryPatientInfo.value.operCode).then((res) => {
|
getPrescriptionList(temporaryPatientInfo.value.visitId).then((res) => {
|
||||||
if (res.code === 200 && res.data) {
|
if (res.code === 200 && res.data) {
|
||||||
// 🔧 修复:先清空旧数据,避免数据累积
|
// 🔧 修复:先清空旧数据,避免数据累积
|
||||||
temporaryBillingMedicines.value = []
|
temporaryBillingMedicines.value = []
|
||||||
@@ -2042,7 +2023,7 @@ function handleFindApply() {
|
|||||||
getSurgicalScheduleList()
|
getSurgicalScheduleList()
|
||||||
}
|
}
|
||||||
|
|
||||||
// 获取手术申请列表(用于”查找”弹窗)
|
// 获取手术申请列表(用于“查找”弹窗)
|
||||||
function getSurgicalScheduleList() {
|
function getSurgicalScheduleList() {
|
||||||
applyLoading.value = true
|
applyLoading.value = true
|
||||||
const params = { ...applyQueryParams }
|
const params = { ...applyQueryParams }
|
||||||
@@ -2051,7 +2032,8 @@ function getSurgicalScheduleList() {
|
|||||||
params.applyTimeEnd = params.applyTimeRange[1]
|
params.applyTimeEnd = params.applyTimeRange[1]
|
||||||
delete params.applyTimeRange
|
delete params.applyTimeRange
|
||||||
}
|
}
|
||||||
getSurgeryPage(params).then((res) => {
|
getSurgery(params).then((res) => {
|
||||||
|
// Check if data is nested under data.data or directly under data
|
||||||
const responseData = res.data.data || res.data
|
const responseData = res.data.data || res.data
|
||||||
applyList.value = responseData.records || []
|
applyList.value = responseData.records || []
|
||||||
applyTotal.value = responseData.total || 0
|
applyTotal.value = responseData.total || 0
|
||||||
@@ -2300,4 +2282,4 @@ function getRowClassName({ row, rowIndex }) {
|
|||||||
border-bottom: 1px solid #d9ecff !important;
|
border-bottom: 1px solid #d9ecff !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
</style>
|
</style>
|
||||||
@@ -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