Compare commits
1 Commits
赵云-bug486
...
赵云-fix-476
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
7480acaeb1 |
@@ -200,10 +200,9 @@ public interface ICommonService {
|
||||
* 批号匹配
|
||||
*
|
||||
* @param encounterIdList 就诊id列表
|
||||
* @param requestIdList 医嘱请求id列表(可选,用于限定仅校验与当前执行医嘱关联的耗材)
|
||||
* @return 处理结果
|
||||
*/
|
||||
R<?> lotNumberMatch(List<Long> encounterIdList, List<Long> requestIdList);
|
||||
R<?> lotNumberMatch(List<Long> encounterIdList);
|
||||
|
||||
/**
|
||||
* 根据机构ID获取机构名称
|
||||
|
||||
@@ -39,10 +39,8 @@ import com.openhis.web.common.dto.*;
|
||||
import com.openhis.web.common.mapper.CommonAppMapper;
|
||||
import com.openhis.web.pharmacymanage.dto.InventoryDetailDto;
|
||||
import com.openhis.workflow.domain.DeviceDispense;
|
||||
import com.openhis.workflow.domain.DeviceRequest;
|
||||
import com.openhis.workflow.domain.InventoryItem;
|
||||
import com.openhis.workflow.service.IDeviceDispenseService;
|
||||
import com.openhis.workflow.service.IDeviceRequestService;
|
||||
import com.openhis.workflow.service.IInventoryItemService;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
@@ -101,9 +99,6 @@ public class CommonServiceImpl implements ICommonService {
|
||||
@Resource
|
||||
private IDeviceDispenseService deviceDispenseService;
|
||||
|
||||
@Resource
|
||||
private IDeviceRequestService deviceRequestService;
|
||||
|
||||
/**
|
||||
* 获取药房列表
|
||||
*
|
||||
@@ -683,11 +678,10 @@ public class CommonServiceImpl implements ICommonService {
|
||||
* 批号匹配
|
||||
*
|
||||
* @param encounterIdList 就诊id列表
|
||||
* @param requestIdList 医嘱请求id列表(可选,用于限定仅校验与当前执行医嘱关联的耗材)
|
||||
* @return 处理结果
|
||||
*/
|
||||
@Override
|
||||
public R<?> lotNumberMatch(List<Long> encounterIdList, List<Long> requestIdList) {
|
||||
public R<?> lotNumberMatch(List<Long> encounterIdList) {
|
||||
// 查询患者待发放的药品信息
|
||||
List<MedicationDispense> medicationDispenseList = medicationDispenseService
|
||||
.list(new LambdaQueryWrapper<MedicationDispense>().in(MedicationDispense::getEncounterId, encounterIdList)
|
||||
@@ -804,27 +798,10 @@ public class CommonServiceImpl implements ICommonService {
|
||||
}
|
||||
}
|
||||
// 查询患者待发放的耗材信息
|
||||
LambdaQueryWrapper<DeviceDispense> deviceDispenseQuery = new LambdaQueryWrapper<DeviceDispense>()
|
||||
.in(DeviceDispense::getEncounterId, encounterIdList)
|
||||
.eq(DeviceDispense::getStatusEnum, DispenseStatus.PREPARATION.getValue())
|
||||
.eq(DeviceDispense::getDeleteFlag, DelFlag.NO.getCode());
|
||||
// 若传入requestIdList,则仅查询与指定医嘱请求关联的耗材,避免其他未执行医嘱的耗材记录干扰
|
||||
if (requestIdList != null && !requestIdList.isEmpty()) {
|
||||
List<Long> deviceReqIds = deviceRequestService
|
||||
.list(new LambdaQueryWrapper<DeviceRequest>()
|
||||
.in(DeviceRequest::getBasedOnId, requestIdList)
|
||||
.eq(DeviceRequest::getBasedOnTable, CommonConstants.TableName.WOR_SERVICE_REQUEST))
|
||||
.stream()
|
||||
.map(DeviceRequest::getId)
|
||||
.collect(java.util.stream.Collectors.toList());
|
||||
if (!deviceReqIds.isEmpty()) {
|
||||
deviceDispenseQuery.in(DeviceDispense::getDeviceReqId, deviceReqIds);
|
||||
} else {
|
||||
// 无关联的耗材请求,直接跳过耗材校验
|
||||
deviceDispenseQuery.eq(DeviceDispense::getId, -1L);
|
||||
}
|
||||
}
|
||||
List<DeviceDispense> deviceDispenseList = deviceDispenseService.list(deviceDispenseQuery);
|
||||
List<DeviceDispense> deviceDispenseList = deviceDispenseService
|
||||
.list(new LambdaQueryWrapper<DeviceDispense>().in(DeviceDispense::getEncounterId, encounterIdList)
|
||||
.eq(DeviceDispense::getStatusEnum, DispenseStatus.PREPARATION.getValue())
|
||||
.eq(DeviceDispense::getDeleteFlag, DelFlag.NO.getCode()));
|
||||
// 耗材批号匹配
|
||||
if (deviceDispenseList != null && !deviceDispenseList.isEmpty()) {
|
||||
// 获取待发放的耗材id
|
||||
|
||||
@@ -274,13 +274,10 @@ public class CommonAppController {
|
||||
* 批号匹配
|
||||
*
|
||||
* @param encounterIdList 就诊id列表
|
||||
* @param requestIdList 医嘱请求id列表(可选,用于限定仅校验与当前执行医嘱关联的耗材)
|
||||
* @return 处理结果
|
||||
*/
|
||||
@GetMapping("/lot-number-match")
|
||||
public R<?> lotNumberMatch(
|
||||
@RequestParam(value = "encounterIdList") List<Long> encounterIdList,
|
||||
@RequestParam(value = "requestIdList", required = false) List<Long> requestIdList) {
|
||||
return commonService.lotNumberMatch(encounterIdList, requestIdList);
|
||||
public R<?> lotNumberMatch(@RequestParam(value = "encounterIdList") List<Long> encounterIdList) {
|
||||
return commonService.lotNumberMatch(encounterIdList);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -81,35 +81,36 @@ public class RequestFormManageAppServiceImpl implements IRequestFormManageAppSer
|
||||
Long requestFormId = requestFormSaveDto.getRequestFormId();
|
||||
boolean isEdit = requestFormId != null && requestFormId != 0L;
|
||||
|
||||
// 校验所有activityList中的项目是否都配置了执行科室,并收集positionId供后续使用
|
||||
// 必须在任何数据库操作之前完成全部校验,避免部分保存后异常导致脏数据
|
||||
List<ActivitySaveDto> activityList = requestFormSaveDto.getActivityList();
|
||||
if (activityList == null || activityList.isEmpty()) {
|
||||
throw new ServiceException("请选择检查项目");
|
||||
}
|
||||
|
||||
// 🔧 Bug #475: 查询诊疗执行科室配置
|
||||
// 诊疗执行科室配置校验(必须在任何数据库操作之前)
|
||||
List<ActivityOrganizationConfigDto> activityOrganizationConfig =
|
||||
requestFormManageAppMapper.getActivityOrganizationConfig(typeCode);
|
||||
if (activityOrganizationConfig.isEmpty()) {
|
||||
throw new ServiceException("请先配置当前时间段的执行科室");
|
||||
}
|
||||
|
||||
// 缓存校验结果,先全部验证通过后再进行数据库操作
|
||||
// 优先使用前端传入的positionId(用户手动选择的发往科室),仅在未选择时使用配置的执行科室
|
||||
// 逐个校验activityList中的项目是否都配置了执行科室,并收集positionId供后续使用
|
||||
// 必须在任何数据库操作之前完成全部校验,避免部分保存后异常导致脏数据
|
||||
// 🔧 Bug #516: 优先使用前端传入的positionId(用户手动选择的发往科室),仅在未选择时使用配置的执行科室
|
||||
List<ActivitySaveDto> activityList = requestFormSaveDto.getActivityList();
|
||||
// 缓存校验结果,避免主循环中重复查询和可能出现的数据不一致
|
||||
java.util.Map<Long, Long> activityIdToPositionIdMap = new java.util.HashMap<>();
|
||||
for (ActivitySaveDto activitySaveDto : activityList) {
|
||||
// 优先使用前端传入的positionId(用户手动选择的科室)
|
||||
Long frontendPositionId = activitySaveDto.getPositionId();
|
||||
if (frontendPositionId != null) {
|
||||
activityIdToPositionIdMap.put(activitySaveDto.getAdviceDefinitionId(), frontendPositionId);
|
||||
continue;
|
||||
if (activityList != null && !activityList.isEmpty()) {
|
||||
for (ActivitySaveDto activitySaveDto : activityList) {
|
||||
// 优先使用前端传入的positionId(用户手动选择的科室)
|
||||
Long frontendPositionId = activitySaveDto.getPositionId();
|
||||
if (frontendPositionId != null) {
|
||||
activityIdToPositionIdMap.put(activitySaveDto.getAdviceDefinitionId(), frontendPositionId);
|
||||
continue;
|
||||
}
|
||||
// 前端未传入时,使用配置的执行科室
|
||||
Long configPositionId = activityOrganizationConfig.stream()
|
||||
.filter(dto -> activitySaveDto.getAdviceDefinitionId().equals(dto.getActivityDefinitionId()))
|
||||
.map(ActivityOrganizationConfigDto::getOrganizationId).findFirst().orElse(null);
|
||||
if (configPositionId == null) {
|
||||
throw new ServiceException(activitySaveDto.getAdviceDefinitionName() + "未配置当前时间段的执行科室");
|
||||
}
|
||||
activityIdToPositionIdMap.put(activitySaveDto.getAdviceDefinitionId(), configPositionId);
|
||||
}
|
||||
// 前端未传入时,使用配置的执行科室
|
||||
Long configPositionId = activityOrganizationConfig.stream()
|
||||
.filter(dto -> activitySaveDto.getAdviceDefinitionId().equals(dto.getActivityDefinitionId()))
|
||||
.map(ActivityOrganizationConfigDto::getOrganizationId).findFirst().orElse(null);
|
||||
if (configPositionId == null) {
|
||||
throw new ServiceException(activitySaveDto.getAdviceDefinitionName() + "未配置当前时间段的执行科室");
|
||||
}
|
||||
activityIdToPositionIdMap.put(activitySaveDto.getAdviceDefinitionId(), configPositionId);
|
||||
}
|
||||
|
||||
// 诊疗处方号
|
||||
|
||||
@@ -78,11 +78,7 @@
|
||||
<select id="getRequestFormDetail" resultType="com.openhis.web.regdoctorstation.dto.RequestFormDetailQueryDto">
|
||||
SELECT wsr.quantity,
|
||||
wsr.unit_code,
|
||||
COALESCE(
|
||||
wad.NAME,
|
||||
wsr.content_json::jsonb->>'surgeryName',
|
||||
'检验项目'
|
||||
) AS advice_name,
|
||||
COALESCE(wad.NAME, wsr.content_json::jsonb->>'surgeryName') AS advice_name,
|
||||
aci.total_price
|
||||
FROM wor_service_request AS wsr
|
||||
LEFT JOIN wor_activity_definition AS wad ON wad.ID = wsr.activity_id
|
||||
@@ -92,7 +88,6 @@
|
||||
AND aci.delete_flag = '0'
|
||||
WHERE wsr.delete_flag = '0'
|
||||
AND wsr.prescription_no = #{prescriptionNo}
|
||||
ORDER BY wsr.id
|
||||
</select>
|
||||
|
||||
<select id="getActivityOrganizationConfig"
|
||||
|
||||
@@ -136,7 +136,7 @@
|
||||
currentDetail.patientName || '-'
|
||||
}}</el-descriptions-item>
|
||||
<el-descriptions-item label="申请单名称">{{
|
||||
buildApplicationName(currentDetail)
|
||||
currentDetail.name || '-'
|
||||
}}</el-descriptions-item>
|
||||
<el-descriptions-item label="创建时间">{{
|
||||
currentDetail.createTime || '-'
|
||||
|
||||
@@ -910,8 +910,9 @@ function handleFocus(row, index) {
|
||||
// 用 adviceType + categoryCode 组合查找匹配的选项
|
||||
const selectValue = (adviceType == 1 && row.categoryCode) ? '1-' + row.categoryCode : adviceType;
|
||||
const selectedItem = adviceTypeList.value.find(item => item.value === selectValue) || adviceTypeList.value.find(item => item.adviceType === adviceType);
|
||||
// 当行没有显式选择医嘱类型时,使用已配置的默认categoryCode,确保后端能返回结果
|
||||
const categoryCode = row.adviceType !== undefined ? (selectedItem ? selectedItem.categoryCode : '') : (adviceQueryParams.value.categoryCode || '');
|
||||
// 修复Bug #486:当行没有显式选择医嘱类型时(row.adviceType为undefined),
|
||||
// 不传categoryCode,让搜索在全药库中进行;只有行已选择类型时才用对应categoryCode过滤
|
||||
const categoryCode = row.adviceType !== undefined ? (selectedItem ? selectedItem.categoryCode : '') : '';
|
||||
const searchKey = row.adviceName || '';
|
||||
|
||||
nextTick(() => {
|
||||
@@ -948,8 +949,9 @@ function handleChange(value) {
|
||||
// 用 adviceType + categoryCode 组合查找匹配的选项
|
||||
const selectValue = (adviceType == 1 && row?.categoryCode) ? '1-' + row.categoryCode : adviceType;
|
||||
const selectedItem = adviceTypeList.value.find(item => item.value === selectValue) || adviceTypeList.value.find(item => item.adviceType === adviceType);
|
||||
// 当行没有显式选择医嘱类型时,使用已配置的默认categoryCode,确保后端能返回结果
|
||||
const categoryCode = row?.adviceType !== undefined ? (selectedItem ? selectedItem.categoryCode : '') : (adviceQueryParams.value.categoryCode || '');
|
||||
// 修复Bug #486:当行没有显式选择医嘱类型时(row?.adviceType为undefined),
|
||||
// 不传categoryCode,让搜索在全药库中进行;只有行已选择类型时才用对应categoryCode过滤
|
||||
const categoryCode = row?.adviceType !== undefined ? (selectedItem ? selectedItem.categoryCode : '') : '';
|
||||
// 修复Bug #453:当adviceType为空字符串或NaN时,不传具体类型,让refresh函数根据searchKey决定搜索范围
|
||||
const effectiveAdviceType = (adviceType && !isNaN(Number(adviceType))) ? adviceType : '';
|
||||
tableRef.refresh(effectiveAdviceType, categoryCode, value);
|
||||
|
||||
@@ -241,8 +241,6 @@ const loading = ref(false);
|
||||
const chooseAll = ref(false);
|
||||
// 独立维护选中行ID集合,避免el-table内部selection状态异常导致联动全选
|
||||
const selectedRowIds = ref(new Set());
|
||||
// 跳过选中事件级联:程序化调用 toggleRowSelection 时阻止 handleRowSelect 触发 selectAllCheckboxesInRow
|
||||
const skipSelectCascade = ref(false);
|
||||
const props = defineProps({
|
||||
exeStatus: {
|
||||
type: Number,
|
||||
@@ -486,13 +484,8 @@ function handleExecute() {
|
||||
if (hasServiceRequest) {
|
||||
// 仅传入选中医嘱对应的 encounterId,避免其他患者的耗材记录干扰
|
||||
const selectedEncounterIds = [...new Set(list.map((item) => item.encounterId).filter(Boolean))];
|
||||
// 仅传入诊疗类医嘱的 requestId,让后端仅校验与本次执行相关的耗材,避免其他未执行医嘱的耗材记录干扰
|
||||
const selectedRequestIds = list
|
||||
.filter((item) => String(item.adviceTable || '') === 'wor_service_request')
|
||||
.map((item) => item.requestId)
|
||||
.filter(Boolean);
|
||||
if (selectedEncounterIds.length > 0) {
|
||||
lotNumberMatch({ encounterIdList: selectedEncounterIds, requestIdList: selectedRequestIds }, { skipErrorMsg: true })
|
||||
lotNumberMatch({ encounterIdList: selectedEncounterIds }, { skipErrorMsg: true })
|
||||
.then((matchRes) => {
|
||||
if (matchRes && matchRes.code !== 200) {
|
||||
console.warn('lotNumberMatch returned error:', matchRes.msg);
|
||||
@@ -657,7 +650,6 @@ function handleRateChange(value, date, time, row, rateItem) {
|
||||
}
|
||||
|
||||
function handelSwicthChange(value) {
|
||||
skipSelectCascade.value = true;
|
||||
prescriptionList.value.forEach((item, index) => {
|
||||
const tableRef = proxy.$refs['tableRef' + index];
|
||||
if (tableRef && tableRef[0]) {
|
||||
@@ -678,15 +670,12 @@ function handelSwicthChange(value) {
|
||||
}
|
||||
}
|
||||
});
|
||||
skipSelectCascade.value = false;
|
||||
}
|
||||
|
||||
// 默认选中全部行
|
||||
function defaultSelectAllRows() {
|
||||
// 清空并重建选中集合
|
||||
selectedRowIds.value.clear();
|
||||
// 阻止 toggleRowSelection 触发 handleRowSelect 中的 selectAllCheckboxesInRow 级联
|
||||
skipSelectCascade.value = true;
|
||||
prescriptionList.value.forEach((item, index) => {
|
||||
const tableRef = proxy.$refs['tableRef' + index];
|
||||
if (tableRef && tableRef[0]) {
|
||||
@@ -699,7 +688,6 @@ function defaultSelectAllRows() {
|
||||
});
|
||||
}
|
||||
});
|
||||
skipSelectCascade.value = false;
|
||||
// 更新全选开关状态
|
||||
chooseAll.value = true;
|
||||
}
|
||||
@@ -776,7 +764,6 @@ function checkAndToggleRowSelection(row) {
|
||||
const isCurrentlySelected = selectedRowIds.value.has(row.requestId);
|
||||
|
||||
// 根据checkbox状态更新表格行选中状态
|
||||
skipSelectCascade.value = true;
|
||||
if (isAllSelected && !isCurrentlySelected) {
|
||||
selectedRowIds.value.add(row.requestId);
|
||||
tableRef[0].toggleRowSelection(row, true);
|
||||
@@ -784,7 +771,6 @@ function checkAndToggleRowSelection(row) {
|
||||
selectedRowIds.value.delete(row.requestId);
|
||||
tableRef[0].toggleRowSelection(row, false);
|
||||
}
|
||||
skipSelectCascade.value = false;
|
||||
}
|
||||
}
|
||||
});
|
||||
@@ -796,10 +782,8 @@ function handleRowSelect(selection, row, tableIndex) {
|
||||
|
||||
if (isSelected) {
|
||||
selectedRowIds.value.add(row.requestId);
|
||||
// 仅在非程序化选中时,联动选中该行内部的所有checkbox
|
||||
if (!skipSelectCascade.value) {
|
||||
selectAllCheckboxesInRow(row);
|
||||
}
|
||||
// 选中行时,选中该行内部的所有checkbox
|
||||
selectAllCheckboxesInRow(row);
|
||||
} else {
|
||||
selectedRowIds.value.delete(row.requestId);
|
||||
// 取消选中行时,取消选中该行内部的所有checkbox
|
||||
|
||||
Reference in New Issue
Block a user