1 Commits

16 changed files with 195 additions and 232 deletions

View File

@@ -633,9 +633,9 @@ public class OutpatientRegistrationAppServiceImpl implements IOutpatientRegistra
Order updateOrder = new Order(); Order updateOrder = new Order();
updateOrder.setId(appointmentOrder.getId()); updateOrder.setId(appointmentOrder.getId());
updateOrder.setStatus(CommonConstants.AppointmentOrderStatus.RETURNED); updateOrder.setStatus(CommonConstants.AppointmentOrderStatus.RETURNED);
updateOrder.setPayStatus(0);
updateOrder.setCancelTime(now); updateOrder.setCancelTime(now);
updateOrder.setCancelReason("门诊退号"); updateOrder.setCancelReason(
StringUtils.isNotEmpty(reason) ? reason : "门诊退号");
updateOrder.setUpdateTime(now); updateOrder.setUpdateTime(now);
orderService.updateById(updateOrder); orderService.updateById(updateOrder);
} }

View File

@@ -178,26 +178,22 @@ public class AdviceUtils {
// 生命提示信息集合 // 生命提示信息集合
List<String> tipsList = new ArrayList<>(); List<String> tipsList = new ArrayList<>();
for (MedicationRequestUseExe medicationRequestUseExe : medUseExeList) { for (MedicationRequestUseExe medicationRequestUseExe : medUseExeList) {
// 聚合同一位置所有批次的库存总量 Optional<AdviceInventoryDto> matchedInventory = adviceInventory.stream()
List<AdviceInventoryDto> matchedInventories = adviceInventory.stream()
.filter(inventoryDto -> medicationRequestUseExe.getMedicationId().equals(inventoryDto.getItemId()) .filter(inventoryDto -> medicationRequestUseExe.getMedicationId().equals(inventoryDto.getItemId())
&& CommonConstants.TableName.MED_MEDICATION_DEFINITION.equals(inventoryDto.getItemTable()) && CommonConstants.TableName.MED_MEDICATION_DEFINITION.equals(inventoryDto.getItemTable())
&& medicationRequestUseExe.getPerformLocation().equals(inventoryDto.getLocationId()) && medicationRequestUseExe.getPerformLocation().equals(inventoryDto.getLocationId())
// 如果选择了具体的批次号,校验库存时需要加上批次号的匹配条件 // 如果选择了具体的批次号,校验库存时需要加上批次号的匹配条件
&& (StringUtils.isEmpty(medicationRequestUseExe.getLotNumber()) && (StringUtils.isEmpty(medicationRequestUseExe.getLotNumber())
|| medicationRequestUseExe.getLotNumber().equals(inventoryDto.getLotNumber()))) || medicationRequestUseExe.getLotNumber().equals(inventoryDto.getLotNumber())))
.collect(Collectors.toList()); .findFirst();
// 匹配到库存信息 // 匹配到库存信息
if (!matchedInventories.isEmpty()) { if (matchedInventory.isPresent()) {
// 聚合所有批次的可用库存 AdviceInventoryDto inventoryDto = matchedInventory.get();
BigDecimal totalQuantity = matchedInventories.stream() if ((medicationRequestUseExe.getExecuteTimesNum()
.map(dto -> dto.getQuantity() != null ? dto.getQuantity() : BigDecimal.ZERO) .multiply(medicationRequestUseExe.getMinUnitQuantity()))
.reduce(BigDecimal.ZERO, BigDecimal::add); .compareTo(inventoryDto.getQuantity()) > 0) {
BigDecimal requestQuantity = medicationRequestUseExe.getExecuteTimesNum()
.multiply(medicationRequestUseExe.getMinUnitQuantity());
if (requestQuantity.compareTo(totalQuantity) > 0) {
tipsList tipsList
.add("" + medicationRequestUseExe.getBusNo() + "】在" + matchedInventories.get(0).getLocationName() + "库存不足"); .add("" + medicationRequestUseExe.getBusNo() + "】在" + inventoryDto.getLocationName() + "库存不足");
} }
} else { } else {
tipsList.add("" + medicationRequestUseExe.getBusNo() + "】未匹配到库存信息"); tipsList.add("" + medicationRequestUseExe.getBusNo() + "】未匹配到库存信息");

View File

@@ -511,9 +511,6 @@ public class AdviceManageAppServiceImpl implements IAdviceManageAppService {
// 签发操作 // 签发操作
boolean is_sign = AdviceOpType.SIGN_ADVICE.getCode().equals(adviceOpType); boolean is_sign = AdviceOpType.SIGN_ADVICE.getCode().equals(adviceOpType);
// 收集已处理的requestId用于批量更新状态
List<Long> processedRequestIds = new ArrayList<>();
// 声明长期医嘱诊疗请求 // 声明长期医嘱诊疗请求
ServiceRequest longServiceRequest; ServiceRequest longServiceRequest;
// 新增 + 修改 (长期医嘱) // 新增 + 修改 (长期医嘱)
@@ -558,9 +555,6 @@ public class AdviceManageAppServiceImpl implements IAdviceManageAppService {
} }
} }
iServiceRequestService.saveOrUpdate(longServiceRequest); iServiceRequestService.saveOrUpdate(longServiceRequest);
if (longServiceRequest.getId() != null) {
processedRequestIds.add(longServiceRequest.getId());
}
} }
// 声明临时医嘱诊疗请求 // 声明临时医嘱诊疗请求
@@ -609,9 +603,6 @@ public class AdviceManageAppServiceImpl implements IAdviceManageAppService {
} }
} }
iServiceRequestService.saveOrUpdate(tempServiceRequest); iServiceRequestService.saveOrUpdate(tempServiceRequest);
if (tempServiceRequest.getId() != null) {
processedRequestIds.add(tempServiceRequest.getId());
}
// 保存时,保存诊疗费用项 // 保存时,保存诊疗费用项
if (is_save) { if (is_save) {
@@ -663,14 +654,6 @@ public class AdviceManageAppServiceImpl implements IAdviceManageAppService {
} }
} }
// 批量更新诊疗医嘱状态(使用 update 确保状态字段必定更新)
if (!processedRequestIds.isEmpty()) {
iServiceRequestService.update(null,
new LambdaUpdateWrapper<ServiceRequest>()
.set(ServiceRequest::getStatusEnum,
is_save ? RequestStatus.DRAFT.getValue() : RequestStatus.ACTIVE.getValue())
.in(ServiceRequest::getId, processedRequestIds));
}
} }
/** /**

View File

@@ -95,13 +95,6 @@ public class RequestFormManageAppServiceImpl implements IRequestFormManageAppSer
prescriptionNo = assignSeqUtil.getSeq(AssignSeqEnum.ACTIVITY_PSYCHOTROPIC_NO.getPrefix(), 8); prescriptionNo = assignSeqUtil.getSeq(AssignSeqEnum.ACTIVITY_PSYCHOTROPIC_NO.getPrefix(), 8);
} }
// 诊疗执行科室配置校验(必须在数据库操作之前执行)
List<ActivityOrganizationConfigDto> activityOrganizationConfig =
requestFormManageAppMapper.getActivityOrganizationConfig(typeCode);
if (activityOrganizationConfig.isEmpty()) {
throw new ServiceException("请先配置当前时间段的执行科室");
}
// 当前时间 // 当前时间
Date curDate = new Date(); Date curDate = new Date();
// 请求类型 // 请求类型
@@ -146,6 +139,12 @@ public class RequestFormManageAppServiceImpl implements IRequestFormManageAppSer
// 诊疗集合 // 诊疗集合
List<ActivitySaveDto> activityList = requestFormSaveDto.getActivityList(); List<ActivitySaveDto> activityList = requestFormSaveDto.getActivityList();
log.info("保存申请单typeCode={}, activityListSize={}, encounterId={}", typeCode, activityList != null ? activityList.size() : 0, encounterId); 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) { for (ActivitySaveDto activitySaveDto : activityList) {
serviceRequest = new ServiceRequest(); serviceRequest = new ServiceRequest();

View File

@@ -41,7 +41,43 @@
</el-col> </el-col>
</el-row> </el-row>
<!-- 性别出生日期实足年龄 -->
<el-row :gutter="16" class="form-row align-bottom">
<el-col :span="6" class="form-item">
<span class="form-label required">性别</span>
<el-radio-group v-model="form.sex">
<el-radio label="男"></el-radio>
<el-radio label="女"></el-radio>
<el-radio label="未知">未知</el-radio>
</el-radio-group>
</el-col>
<el-col :span="10" class="form-item birth-date">
<span class="form-label required">出生日期</span>
<div class="date-inputs">
<el-input v-model="form.birthYear" class="underline-input small" maxlength="4" @change="calculateAge" />
<span></span>
<el-input v-model="form.birthMonth" class="underline-input small" maxlength="2" @change="calculateAge" />
<span></span>
<el-input v-model="form.birthDay" class="underline-input small" maxlength="2" @change="calculateAge" />
<span></span>
</div>
</el-col>
<el-col :span="8" class="form-item age-item">
<span class="form-label"> 实足年龄</span>
<div class="age-inputs">
<el-input v-model="form.age" class="underline-input small"/>
<el-select v-model="form.ageUnit" class="age-unit-select">
<el-option label="岁" value="岁" />
<el-option label="月" value="月" />
<el-option label="天" value="天" />
</el-select>
</div>
</el-col>
</el-row>
<!-- 工作单位 -->
<el-row :gutter="16" class="form-row">
<el-col :span="24" class="form-item full-width">
<span class="form-label">工作单位学校</span> <span class="form-label">工作单位学校</span>
<el-input v-model="form.workplace" class="underline-input" /> <el-input v-model="form.workplace" class="underline-input" />
</el-col> </el-col>

View File

@@ -313,7 +313,6 @@
data-prop="dispensePerDuration"> data-prop="dispensePerDuration">
<el-input-number v-model="scope.row.dispensePerDuration" style="width: 80px" :min="1" <el-input-number v-model="scope.row.dispensePerDuration" style="width: 80px" :min="1"
controls-position="right" :controls="false" :ref="(el) => (inputRefs.dispensePerDuration = el)" controls-position="right" :controls="false" :ref="(el) => (inputRefs.dispensePerDuration = el)"
@change="calculateTotalAmount(scope.row, scope.$index)"
@keyup.enter.prevent=" @keyup.enter.prevent="
handleEnter('dispensePerDuration', scope.row, scope.$index) handleEnter('dispensePerDuration', scope.row, scope.$index)
"> ">

View File

@@ -86,11 +86,7 @@
</template> </template>
<el-table-column type="index" label="序号" width="60" align="center" /> <el-table-column type="index" label="序号" width="60" align="center" />
<el-table-column prop="patientName" label="患者姓名" width="120" /> <el-table-column prop="patientName" label="患者姓名" width="120" />
<el-table-column label="申请单名称" width="140"> <el-table-column prop="name" label="申请单名称" width="140" />
<template #default="scope">
<span>{{ getItemName(scope.row) }}</span>
</template>
</el-table-column>
<el-table-column prop="createTime" label="创建时间" width="160" /> <el-table-column prop="createTime" label="创建时间" width="160" />
<el-table-column prop="prescriptionNo" label="处方号" width="140" /> <el-table-column prop="prescriptionNo" label="处方号" width="140" />
<el-table-column prop="requesterId_dictText" label="申请者" width="120" /> <el-table-column prop="requesterId_dictText" label="申请者" width="120" />
@@ -163,7 +159,7 @@
currentDetail.patientName || '-' currentDetail.patientName || '-'
}}</el-descriptions-item> }}</el-descriptions-item>
<el-descriptions-item label="申请单名称">{{ <el-descriptions-item label="申请单名称">{{
getItemName(currentDetail) currentDetail.name || '-'
}}</el-descriptions-item> }}</el-descriptions-item>
<el-descriptions-item label="申请单状态">{{ <el-descriptions-item label="申请单状态">{{
parseStatus(currentDetail.status) parseStatus(currentDetail.status)
@@ -403,28 +399,6 @@ const parseStatus = (status) => {
return statusMap[String(status)] || '-'; return statusMap[String(status)] || '-';
}; };
/**
* 获取申请单展示名称:优先使用具体医嘱名称列表
*/
const getItemName = (row) => {
const items = row?.requestFormDetailList;
if (items && items.length > 0) {
return items.map(item => item.adviceName).filter(Boolean).join('、') || row.name || '-';
}
return row.name || '-';
};
/**
* 构建打印用项目名称字符串(同步函数,用于模板字符串)
*/
const buildItemNames = (row) => {
const items = row?.requestFormDetailList;
if (items && items.length > 0) {
return items.map(item => item.adviceName).filter(Boolean).join('、') || row.name || '';
}
return row.name || '';
};
const labelMap = { const labelMap = {
categoryType: '项目类别', categoryType: '项目类别',
targetDepartment: '发往科室', targetDepartment: '发往科室',
@@ -457,27 +431,20 @@ const getLocationInfo = () => {
}; };
const recursionFun = (targetDepartment) => { const recursionFun = (targetDepartment) => {
if (!targetDepartment) return '';
if (!Array.isArray(orgOptions.value) || orgOptions.value.length === 0) return '';
let name = ''; let name = '';
for (let index = 0; index < orgOptions.value.length; index++) { for (let index = 0; index < orgOptions.value.length; index++) {
const obj = orgOptions.value[index]; const obj = orgOptions.value[index];
if (obj.id == targetDepartment) { if (obj.id == targetDepartment) {
name = obj.name; name = obj.name;
break;
} }
const subObjArray = obj['children']; const subObjArray = obj['children'];
if (Array.isArray(subObjArray)) { for (let index = 0; index < subObjArray.length; index++) {
for (let i = 0; i < subObjArray.length; i++) { const item = subObjArray[index];
const item = subObjArray[i];
if (item.id == targetDepartment) { if (item.id == targetDepartment) {
name = item.name; name = item.name;
break;
} }
} }
} }
if (name) break;
}
return name; return name;
}; };
@@ -489,10 +456,7 @@ const handleViewDetail = (row) => {
if (row.descJson) { if (row.descJson) {
try { try {
const obj = JSON.parse(row.descJson); const obj = JSON.parse(row.descJson);
if (obj.targetDepartment) { obj.targetDepartment = recursionFun(obj.targetDepartment);
const deptName = recursionFun(obj.targetDepartment);
obj.targetDepartment = deptName || obj.targetDepartment;
}
descJsonData.value = obj; descJsonData.value = obj;
} catch (e) { } catch (e) {
console.error('解析 descJson 失败:', e); console.error('解析 descJson 失败:', e);
@@ -687,7 +651,7 @@ const buildPrintContent = (row) => {
return ` return `
<h2>检查申请单</h2> <h2>检查申请单</h2>
<div class="info-row"><span class="label">患者姓名:</span>${row.patientName || '-'}</div> <div class="info-row"><span class="label">患者姓名:</span>${row.patientName || '-'}</div>
<div class="info-row"><span class="label">申请单名称:</span>${buildItemNames(row) || '-'}</div> <div class="info-row"><span class="label">申请单名称:</span>${row.name || '-'}</div>
<div class="info-row"><span class="label">创建时间:</span>${row.createTime || '-'}</div> <div class="info-row"><span class="label">创建时间:</span>${row.createTime || '-'}</div>
<div class="info-row"><span class="label">处方号:</span>${row.prescriptionNo || '-'}</div> <div class="info-row"><span class="label">处方号:</span>${row.prescriptionNo || '-'}</div>
<div class="info-row"><span class="label">申请者:</span>${row.requesterId_dictText || '-'}</div> <div class="info-row"><span class="label">申请者:</span>${row.requesterId_dictText || '-'}</div>

View File

@@ -173,7 +173,7 @@ import {computed, getCurrentInstance, ref, watch} from 'vue';
import {Refresh, Search} from '@element-plus/icons-vue'; import {Refresh, Search} from '@element-plus/icons-vue';
import {patientInfo} from '../../store/patient.js'; import {patientInfo} from '../../store/patient.js';
import {getInspection} from './api'; import {getInspection} from './api';
import {getDepartmentList} from '@/api/public.js'; import {getOrgList} from '@/views/doctorstation/components/api.js';
const { proxy } = getCurrentInstance(); const { proxy } = getCurrentInstance();
@@ -332,8 +332,8 @@ const hasMatchedFields = computed(() => {
/** 查询科室 */ /** 查询科室 */
const getLocationInfo = () => { const getLocationInfo = () => {
getDepartmentList().then((res) => { getOrgList().then((res) => {
orgOptions.value = res.data || []; orgOptions.value = res.data.records;
}); });
}; };
@@ -345,15 +345,13 @@ const recursionFun = (targetDepartment) => {
name = obj.name; name = obj.name;
} }
const subObjArray = obj['children']; const subObjArray = obj['children'];
if (subObjArray && subObjArray.length > 0) { for (let index = 0; index < subObjArray.length; index++) {
for (let i = 0; i < subObjArray.length; i++) { const item = subObjArray[index];
const item = subObjArray[i];
if (item.id == targetDepartment) { if (item.id == targetDepartment) {
name = item.name; name = item.name;
} }
} }
} }
}
return name; return name;
}; };

View File

@@ -122,6 +122,7 @@
<el-table-column label="类型" align="center" prop="" width="120"> <el-table-column label="类型" align="center" prop="" width="120">
<template #default="scope"> <template #default="scope">
{{ console.log(scope.row, 1111) }}
<el-radio-group <el-radio-group
v-model="scope.row.therapyEnum" v-model="scope.row.therapyEnum"
size="small" size="small"
@@ -269,6 +270,7 @@
</el-table-column> </el-table-column>
<el-table-column label="频次/用法" align="center" prop="" width="180"> <el-table-column label="频次/用法" align="center" prop="" width="180">
<template #default="scope"> <template #default="scope">
{{ console.log(scope.row) }}
<span v-if="!scope.row.isEdit && scope.row.adviceType == 1" style="text-align: right"> <span v-if="!scope.row.isEdit && scope.row.adviceType == 1" style="text-align: right">
{{ {{
[ [
@@ -1210,8 +1212,12 @@ function handleSave() {
getListInfo(false); getListInfo(false);
bindMethod.value = {}; bindMethod.value = {};
nextId.value == 1; nextId.value == 1;
// 处方保存成功后,自动将医嘱信息同步至患者处置记录
// handleEmrTreatment();
} else { } else {
proxy.$modal.msgError(res.message); proxy.$modal.msgError(res.message);
conso;
isSaving.value = false; isSaving.value = false;
} }
}) })
@@ -1311,9 +1317,6 @@ function handleCancelEdit(row, index) {
function handleSaveSign(row, index) { function handleSaveSign(row, index) {
if (row.adviceType != 2) { if (row.adviceType != 2) {
let itemNo = row.adviceType == 1 ? row.methodCode : row.adviceDefinitionId; let itemNo = row.adviceType == 1 ? row.methodCode : row.adviceDefinitionId;
if (!itemNo) {
console.warn('绑定设备检查跳过itemNo为空adviceType=' + row.adviceType + ', adviceName=' + row.adviceName + '');
} else {
getBindDevice({ typeCode: row.adviceType, itemNo: itemNo }).then((res) => { getBindDevice({ typeCode: row.adviceType, itemNo: itemNo }).then((res) => {
if (res.data.length == 0) { if (res.data.length == 0) {
return; return;
@@ -1331,7 +1334,6 @@ function handleSaveSign(row, index) {
} }
}); });
} }
}
// 更新UI状态 // 更新UI状态
row.isEdit = false; row.isEdit = false;

View File

@@ -16,12 +16,14 @@
<Advice ref="adviceRef" /> <Advice ref="adviceRef" />
</el-tab-pane> </el-tab-pane>
<!-- <el-tab-pane label="医技报告" name="fourth">Task</el-tab-pane> --> <!-- <el-tab-pane label="医技报告" name="fourth">Task</el-tab-pane> -->
<el-tab-pane label="检验申请" name="test"> <el-tab-pane label="检验申请" name="test">
<TestApplication ref="testApplicationRef" :show-status-column="false" /> <TestApplication ref="testApplicationRef" :show-status-column="true" />
</el-tab-pane> </el-tab-pane>
```vue
<el-tab-pane label="检查申请" name="examine"> <el-tab-pane label="检查申请" name="examine">
<ExamineApplication ref="examineApplicationRef" /> <ExamineApplication ref="examineApplicationRef" />
</el-tab-pane> </el-tab-pane>
```
<el-tab-pane label="汇总发药申请" name="summaryDrug"> <el-tab-pane label="汇总发药申请" name="summaryDrug">
<SummaryDrugApplication ref="summaryDrugApplicationRef" /> <SummaryDrugApplication ref="summaryDrugApplicationRef" />
</el-tab-pane> </el-tab-pane>
@@ -46,10 +48,6 @@
<script setup> <script setup>
import {computed, onBeforeMount, onMounted, provide, reactive, ref, watch,} from 'vue'; import {computed, onBeforeMount, onMounted, provide, reactive, ref, watch,} from 'vue';
import Emr from './emr/index.vue';
import inPatientBarDoctorFold from '@/component
```
import Emr from './emr/index.vue'; import Emr from './emr/index.vue';
import inPatientBarDoctorFold from '@/components/patientBar/inPatientBarDoctorFold.vue'; import inPatientBarDoctorFold from '@/components/patientBar/inPatientBarDoctorFold.vue';
import PatientList from '@/components/PatientList/patient-list.vue'; import PatientList from '@/components/PatientList/patient-list.vue';

View File

@@ -273,9 +273,8 @@ function handleSearch() {
// 清除缓存(搜索时需要重新加载) // 清除缓存(搜索时需要重新加载)
patientDataCache.value.clear(); patientDataCache.value.clear();
// 通过递增 key 强制重新渲染树组件,触发重新加载所有病区患者列表 // 重新加载所有已展开病区患者列表
// 此时 searchKey 已有值,loadPatientList 会将 searchKey 传给后端进行过滤 reloadAllPatients();
treeKey.value += 1;
} }
// 暴露方法供外部调用 // 暴露方法供外部调用

View File

@@ -68,6 +68,8 @@
</div> </div>
</div> </div>
</div> </div>
</template>
</div>
<div <div
style="padding: 10px; background-color: #eef9fd; height: 100%; overflow-y: auto" style="padding: 10px; background-color: #eef9fd; height: 100%; overflow-y: auto"
v-loading="loading" v-loading="loading"
@@ -230,7 +232,7 @@ import {adviceCancel, adviceExecute, adviceNoExecute, getPrescriptionList} from
import {patientInfoList} from '../../components/store/patient.js'; import {patientInfoList} from '../../components/store/patient.js';
import {lotNumberMatch} from '@/api/public'; import {lotNumberMatch} from '@/api/public';
import {formatDateStr} from '@/utils/index'; import {formatDateStr} from '@/utils/index';
import {getCurrentInstance, nextTick, ref, provide} from 'vue'; import {getCurrentInstance, nextTick, ref} from 'vue';
const activeNames = ref([]); const activeNames = ref([]);
const prescriptionList = ref([]); const prescriptionList = ref([]);
@@ -240,8 +242,6 @@ const therapyEnum = ref(undefined);
const { proxy } = getCurrentInstance(); const { proxy } = getCurrentInstance();
const loading = ref(false); const loading = ref(false);
const chooseAll = ref(false); const chooseAll = ref(false);
// 独立维护选中行ID集合避免el-table内部selection状态异常导致联动全选
const selectedRowIds = ref(new Set());
const props = defineProps({ const props = defineProps({
exeStatus: { exeStatus: {
type: Number, type: Number,
@@ -283,10 +283,9 @@ function handleGetPrescription() {
exeStatus: props.exeStatus, exeStatus: props.exeStatus,
requestStatus: props.requestStatus, requestStatus: props.requestStatus,
}).then((res) => { }).then((res) => {
try { // try {
const records = res?.data?.records || [];
// 根据encounterId分组 // 根据encounterId分组
const groupedPrescriptions = records.reduce((groups, prescription) => { const groupedPrescriptions = res.data.records.reduce((groups, prescription) => {
// 获取当前医嘱全部执行频次 // 获取当前医嘱全部执行频次
let rate; let rate;
let times; let times;
@@ -431,26 +430,18 @@ function handleGetPrescription() {
// 将分组结果转换为数组形式 // 将分组结果转换为数组形式
prescriptionList.value = Object.values(groupedPrescriptions); prescriptionList.value = Object.values(groupedPrescriptions);
loading.value = false;
// 默认选中全部行 // 默认选中全部行
nextTick(() => { nextTick(() => {
defaultSelectAllRows(); defaultSelectAllRows();
}); });
} catch (error) { // } catch {
console.error('医嘱执行-获取处方列表数据处理失败:', error); // loading.value = false;
prescriptionList.value = []; // }
} finally {
loading.value = false;
}
}).catch((error) => {
console.error('医嘱执行-获取处方列表接口失败:', error);
prescriptionList.value = [];
loading.value = false;
}); });
chooseAll.value = false; chooseAll.value = false;
} else { } else {
prescriptionList.value = []; prescriptionList.value = [];
selectedRowIds.value.clear();
loading.value = false;
// proxy.$message.warning('请选择患者'); // proxy.$message.warning('请选择患者');
} }
} }
@@ -539,14 +530,10 @@ function handleCancel() {
} }
function getSelectRows() { function getSelectRows() {
// 优先从独立维护的selectedRowIds集合中获取选中行避免el-table内部selection状态异常 // 获取选中的医嘱信息
const list = []; let list = [];
prescriptionList.value.forEach((item) => { prescriptionList.value.forEach((item, index) => {
item.forEach((row) => { list = [...list, ...proxy.$refs['tableRef' + index][0].getSelectionRows()];
if (selectedRowIds.value.has(row.requestId)) {
list.push(row);
}
});
}); });
return list; return list;
} }
@@ -622,14 +609,12 @@ function handelSwicthChange(value) {
if (value) { if (value) {
// 全选选中所有行并联动checkbox // 全选选中所有行并联动checkbox
item.forEach((row) => { item.forEach((row) => {
selectedRowIds.value.add(row.requestId);
tableRef[0].toggleRowSelection(row, true); tableRef[0].toggleRowSelection(row, true);
selectAllCheckboxesInRow(row); selectAllCheckboxesInRow(row);
}); });
} else { } else {
// 取消全选取消选中所有行并联动checkbox // 取消全选取消选中所有行并联动checkbox
item.forEach((row) => { item.forEach((row) => {
selectedRowIds.value.delete(row.requestId);
tableRef[0].toggleRowSelection(row, false); tableRef[0].toggleRowSelection(row, false);
unselectAllCheckboxesInRow(row); unselectAllCheckboxesInRow(row);
}); });
@@ -640,14 +625,11 @@ function handelSwicthChange(value) {
// 默认选中全部行 // 默认选中全部行
function defaultSelectAllRows() { function defaultSelectAllRows() {
// 清空并重建选中集合
selectedRowIds.value.clear();
prescriptionList.value.forEach((item, index) => { prescriptionList.value.forEach((item, index) => {
const tableRef = proxy.$refs['tableRef' + index]; const tableRef = proxy.$refs['tableRef' + index];
if (tableRef && tableRef[0]) { if (tableRef && tableRef[0]) {
// 选中该表格的所有行 // 选中该表格的所有行
item.forEach((row) => { item.forEach((row) => {
selectedRowIds.value.add(row.requestId);
tableRef[0].toggleRowSelection(row, true); tableRef[0].toggleRowSelection(row, true);
// 同时选中该行内部的所有checkbox // 同时选中该行内部的所有checkbox
selectAllCheckboxesInRow(row); selectAllCheckboxesInRow(row);
@@ -727,14 +709,13 @@ function checkAndToggleRowSelection(row) {
const tableRef = proxy.$refs['tableRef' + tableIndex]; const tableRef = proxy.$refs['tableRef' + tableIndex];
if (tableRef && tableRef[0]) { if (tableRef && tableRef[0]) {
const isAllSelected = isAllCheckboxesSelected(row); const isAllSelected = isAllCheckboxesSelected(row);
const isCurrentlySelected = selectedRowIds.value.has(row.requestId); const selectedRows = tableRef[0].getSelectionRows();
const isCurrentlySelected = selectedRows.some((r) => r.requestId === row.requestId);
// 根据checkbox状态更新表格行选中状态 // 根据checkbox状态更新表格行选中状态
if (isAllSelected && !isCurrentlySelected) { if (isAllSelected && !isCurrentlySelected) {
selectedRowIds.value.add(row.requestId);
tableRef[0].toggleRowSelection(row, true); tableRef[0].toggleRowSelection(row, true);
} else if (!isAllSelected && isCurrentlySelected) { } else if (!isAllSelected && isCurrentlySelected) {
selectedRowIds.value.delete(row.requestId);
tableRef[0].toggleRowSelection(row, false); tableRef[0].toggleRowSelection(row, false);
} }
} }
@@ -747,11 +728,9 @@ function handleRowSelect(selection, row, tableIndex) {
const isSelected = selection.some((item) => item.requestId === row.requestId); const isSelected = selection.some((item) => item.requestId === row.requestId);
if (isSelected) { if (isSelected) {
selectedRowIds.value.add(row.requestId);
// 选中行时选中该行内部的所有checkbox // 选中行时选中该行内部的所有checkbox
selectAllCheckboxesInRow(row); selectAllCheckboxesInRow(row);
} else { } else {
selectedRowIds.value.delete(row.requestId);
// 取消选中行时取消选中该行内部的所有checkbox // 取消选中行时取消选中该行内部的所有checkbox
unselectAllCheckboxesInRow(row); unselectAllCheckboxesInRow(row);
} }
@@ -768,13 +747,11 @@ function handleSelectAll(selection, tableIndex) {
if (selection.length > 0) { if (selection.length > 0) {
// 全选时选中所有行内部的所有checkbox // 全选时选中所有行内部的所有checkbox
tableData.forEach((row) => { tableData.forEach((row) => {
selectedRowIds.value.add(row.requestId);
selectAllCheckboxesInRow(row); selectAllCheckboxesInRow(row);
}); });
} else { } else {
// 取消全选时取消选中所有行内部的所有checkbox // 取消全选时取消选中所有行内部的所有checkbox
tableData.forEach((row) => { tableData.forEach((row) => {
selectedRowIds.value.delete(row.requestId);
unselectAllCheckboxesInRow(row); unselectAllCheckboxesInRow(row);
}); });
} }
@@ -786,12 +763,16 @@ function handleSelectAll(selection, tableIndex) {
// 更新全选开关状态 // 更新全选开关状态
function updateChooseAllStatus() { function updateChooseAllStatus() {
let allSelected = true; let allSelected = true;
prescriptionList.value.forEach((item) => { prescriptionList.value.forEach((item, index) => {
item.forEach((row) => { const tableRef = proxy.$refs['tableRef' + index];
if (!selectedRowIds.value.has(row.requestId)) { if (tableRef && tableRef[0]) {
const selectedRows = tableRef[0].getSelectionRows();
if (selectedRows.length !== item.length) {
allSelected = false;
}
} else {
allSelected = false; allSelected = false;
} }
});
}); });
chooseAll.value = allSelected; chooseAll.value = allSelected;
} }

View File

@@ -51,7 +51,7 @@
</template> </template>
<script setup> <script setup>
import {getCurrentInstance, ref, nextTick, provide} from 'vue'; import {getCurrentInstance} from 'vue';
import PatientList from '../components/patientList.vue'; import PatientList from '../components/patientList.vue';
import PrescriptionList from './components/prescriptionList.vue'; import PrescriptionList from './components/prescriptionList.vue';
import { RequestStatus } from '@/utils/medicalConstants'; import { RequestStatus } from '@/utils/medicalConstants';

View File

@@ -181,7 +181,7 @@ function handleGetPrescription() {
getPrescriptionList({ getPrescriptionList({
encounterIds: encounterIds, encounterIds: encounterIds,
requestStatus: props.requestStatus, requestStatus: props.requestStatus,
...(type.value !== undefined ? { therapyEnum: type.value } : {}), therapyEnum: type.value === 1 ? undefined : type.value === 2 ? 1 : 2, // 1=全部(不传), 2=长期(1), 3=临时(2)
pageSize: 10000, pageSize: 10000,
pageNo: 1, pageNo: 1,
}).then((res) => { }).then((res) => {

View File

@@ -112,19 +112,6 @@
<el-form ref="dynamicForm" :model="formData" label-width="100px" :rules="formRules"> <el-form ref="dynamicForm" :model="formData" label-width="100px" :rules="formRules">
<div class="page-bottom"> <div class="page-bottom">
<el-row :gutter="24"> <el-row :gutter="24">
<el-col :span="8">
<el-form-item style="margin-top: 15px" label="录入日期">
<el-date-picker
v-model="formData.recordingDate"
type="date"
placeholder="请选择日期"
size="small"
format="YYYY/MM/DD"
value-format="YYYY-MM-DD"
style="width: 100%"
/>
</el-form-item>
</el-col>
<el-col :span="8"> <el-col :span="8">
<el-form-item style="margin-top: 15px" label="录入时间"> <el-form-item style="margin-top: 15px" label="录入时间">
<div class="input-time-inline"> <div class="input-time-inline">
@@ -779,7 +766,6 @@ const receptionTime = ref(null);
// 表单数据 - 体征录入 // 表单数据 - 体征录入
const formData = ref({ const formData = ref({
recordingDate: '',
timePoint: '', timePoint: '',
temperature: '', temperature: '',
systolicPressure: '', systolicPressure: '',
@@ -886,7 +872,6 @@ function getPatientDetial() {
// 默认查询今天的数据 // 默认查询今天的数据
const today = moment().format('YYYY-MM-DD'); const today = moment().format('YYYY-MM-DD');
receptionTime.value = [today, today]; receptionTime.value = [today, today];
formData.value.recordingDate = today;
// 自动加载数据 // 自动加载数据
getPatientList(); getPatientList();
listPatient(queryParams.value).then((res) => { listPatient(queryParams.value).then((res) => {
@@ -935,7 +920,6 @@ function handleRowClick(row) {
formData.value = { formData.value = {
...formData.value, ...formData.value,
id: row.id, id: row.id,
recordingDate: row.recordingDate || '',
timePoint: convertTimePoint(row.timePoint) || '', timePoint: convertTimePoint(row.timePoint) || '',
temperature: row.temperature || '', temperature: row.temperature || '',
systolicPressure: row.systolicPressure || '', systolicPressure: row.systolicPressure || '',
@@ -1054,7 +1038,7 @@ function confirmCharge() {
params.vitalSignsCode = vitalSignsCode; params.vitalSignsCode = vitalSignsCode;
params.vitalSignsValues = vitalSignsValues; params.vitalSignsValues = vitalSignsValues;
params.recordingDate = formData.value.recordingDate || moment(new Date()).format('YYYY-MM-DD'); params.recordingDate = moment(new Date()).format('YYYY-MM-DD');
addVitalSigns(params).then(res => { addVitalSigns(params).then(res => {
console.log('保存成功:', res); console.log('保存成功:', res);
@@ -1063,7 +1047,6 @@ function confirmCharge() {
getPatientList(); getPatientList();
// 清空表单 // 清空表单
formData.value = { formData.value = {
recordingDate: '',
timePoint: '', timePoint: '',
temperature: '', temperature: '',
systolicPressure: '', systolicPressure: '',

View File

@@ -220,15 +220,15 @@
<!-- 底部控制面板 --> <!-- 底部控制面板 -->
<div class="footer-section"> <div class="footer-section">
<!-- 室快速过滤栏 --> <!-- 就诊科室快速过滤栏 -->
<div class="filter-section"> <div class="filter-section">
<div class="filter-label"> <div class="filter-label">
室快速过滤栏 就诊科室快速过滤栏
</div> </div>
<div class="filter-select-wrapper"> <div class="filter-select-wrapper">
<el-select <el-select
v-model="selectedClinicRoom" v-model="selectedDept"
placeholder="请选择室" placeholder="请选择就诊科室"
clearable clearable
filterable filterable
style="width: 100%" style="width: 100%"
@@ -239,10 +239,10 @@
value="all" value="all"
/> />
<el-option <el-option
v-for="room in clinicRoomList" v-for="dept in departmentList"
:key="room" :key="dept.id"
:label="room" :label="dept.name"
:value="room" :value="dept.id"
/> />
</el-select> </el-select>
</div> </div>
@@ -648,6 +648,7 @@ import { Refresh } from '@element-plus/icons-vue'
import { ElMessage } from 'element-plus' import { ElMessage } from 'element-plus'
import { import {
getCandidatePool, getCandidatePool,
getLocationTree,
getTriageQueueList, getTriageQueueList,
addToQueue, addToQueue,
removeFromQueue, removeFromQueue,
@@ -680,10 +681,10 @@ const selectedCandidates = ref([])
// 显示选项 // 显示选项
const showOnlyWaiting = ref(false) const showOnlyWaiting = ref(false)
// 室过滤(按诊室维度筛选 // 室过滤(改为使用就诊科室
const selectedClinicRoom = ref('all') const selectedDept = ref('all')
// 诊室列表(从数据中动态提取) // 就诊科室列表
const clinicRoomList = ref([]) const departmentList = ref([])
// 修复【#397】动态获取当前科室名称 // 修复【#397】动态获取当前科室名称
const currentDeptName = computed(() => { const currentDeptName = computed(() => {
@@ -906,11 +907,13 @@ const mapFrontendStatusToBackend = (status) => {
// 从数据库加载队列 // 从数据库加载队列
const loadQueueFromDb = async () => { const loadQueueFromDb = async () => {
try { try {
// 使用当前登录人科室 // 如果选择了具体科室,就按科室加载;否则加载当前登录人科室(后端默认)
const organizationId = selectedDept.value !== 'all' ? selectedDept.value : undefined
// 只查询今天的患者
const today = new Date() const today = new Date()
const todayStr = `${today.getFullYear()}-${String(today.getMonth() + 1).padStart(2, '0')}-${String(today.getDate()).padStart(2, '0')}` const todayStr = `${today.getFullYear()}-${String(today.getMonth() + 1).padStart(2, '0')}-${String(today.getDate()).padStart(2, '0')}`
console.log('【心内科】loadQueueFromDb 开始:date=', todayStr) console.log('【心内科】loadQueueFromDb 开始:organizationId=', organizationId, 'date=', todayStr, 'selectedDept=', selectedDept.value)
const res = await getTriageQueueList({ date: todayStr }).catch((err) => { const res = await getTriageQueueList({ organizationId, date: todayStr }).catch((err) => {
console.error('【心内科】loadQueueFromDb 请求异常:', err) console.error('【心内科】loadQueueFromDb 请求异常:', err)
return { code: 500, msg: err?.message || '请求失败', data: null } return { code: 500, msg: err?.message || '请求失败', data: null }
}) })
@@ -1138,8 +1141,6 @@ const loadDataFromApi = async () => {
// 同步当前呼叫(队列从 DB 加载后已同步;这里再兜底一次) // 同步当前呼叫(队列从 DB 加载后已同步;这里再兜底一次)
syncCurrentCallFromQueue() syncCurrentCallFromQueue()
// 提取诊室列表供过滤栏使用
extractClinicRooms()
console.log('【心内科】数据加载完成:候选池', originalCandidatePoolList.value.length, '条,队列', originalQueueList.value.length, '条') console.log('【心内科】数据加载完成:候选池', originalCandidatePoolList.value.length, '条,队列', originalQueueList.value.length, '条')
ElMessage.success('【心内科】已从门诊挂号接口加载数据') ElMessage.success('【心内科】已从门诊挂号接口加载数据')
} catch (e) { } catch (e) {
@@ -1151,37 +1152,56 @@ const loadDataFromApi = async () => {
totalSignedIn.value = originalCandidatePoolList.value.length totalSignedIn.value = originalCandidatePoolList.value.length
totalInQueue.value = originalQueueList.value.length totalInQueue.value = originalQueueList.value.length
syncCurrentCallFromQueue() syncCurrentCallFromQueue()
extractClinicRooms()
} }
} }
// 原始数据存储(用于过滤) // 原始数据存储(用于过滤)
const originalCandidatePoolList = ref(getInitialCandidatePoolList()) const originalCandidatePoolList = ref(getInitialCandidatePoolList())
// 提取诊室列表(从队列和候选池数据中动态获取) // 辅助函数:扁平化科室树形结构
const extractClinicRooms = () => { const flattenDepartmentTree = (tree, result = []) => {
const roomSet = new Set() if (!Array.isArray(tree)) return result
// 从队列中提取 tree.forEach(node => {
originalQueueList.value.forEach(item => { if (node.id && node.name) {
if (item.room && item.room !== '-') { result.push({ id: node.id, name: node.name })
roomSet.add(item.room) }
if (node.children && Array.isArray(node.children)) {
flattenDepartmentTree(node.children, result)
} }
}) })
// 从候选池中提取 return result
originalCandidatePoolList.value.forEach(item => { }
if (item.room && item.room !== '-') {
roomSet.add(item.room) // 加载就诊科室列表
const loadDepartmentList = async () => {
try {
const response = await getLocationTree()
if (response && response.data) {
// 扁平化树形结构
departmentList.value = flattenDepartmentTree(response.data)
console.log('【心内科】已加载就诊科室列表:', departmentList.value.length, '个科室')
} }
}) } catch (error) {
clinicRoomList.value = Array.from(roomSet).sort() console.error('【心内科】加载就诊科室列表失败:', error)
ElMessage.warning('加载就诊科室列表失败,使用默认数据')
}
}
// 获取选中科室的名称
const getSelectedDeptName = () => {
if (selectedDept.value === 'all') return null
const dept = departmentList.value.find(d => d.id === selectedDept.value)
return dept ? dept.name : null
} }
// 过滤后的智能候选池数据 // 过滤后的智能候选池数据
const filteredCandidatePoolList = computed(() => { const filteredCandidatePoolList = computed(() => {
if (selectedClinicRoom.value === 'all') { if (selectedDept.value === 'all') {
return originalCandidatePoolList.value return originalCandidatePoolList.value
} }
return originalCandidatePoolList.value.filter(item => item.room === selectedClinicRoom.value) const deptName = getSelectedDeptName()
if (!deptName) return originalCandidatePoolList.value
return originalCandidatePoolList.value.filter(item => item.room === deptName)
}) })
// 原始队列数据存储(用于过滤) // 原始队列数据存储(用于过滤)
@@ -1203,16 +1223,19 @@ const formatSecondsToMmSs = (totalSeconds) => {
return `${mm}:${ss}` return `${mm}:${ss}`
} }
// 过滤后的智能队列数据(同时考虑室过滤和状态过滤) // 过滤后的智能队列数据(同时考虑室过滤和状态过滤)
const filteredQueueList = computed(() => { const filteredQueueList = computed(() => {
let filtered = originalQueueList.value let filtered = originalQueueList.value
// 先过滤掉"已完成"状态的患者(无论什么情况都不显示) // 先过滤掉"已完成"状态的患者(无论什么情况都不显示)
filtered = filtered.filter(item => item.status !== '已完成') filtered = filtered.filter(item => item.status !== '已完成')
// 再按室过滤 // 再按室过滤
if (selectedClinicRoom.value !== 'all') { if (selectedDept.value !== 'all') {
filtered = filtered.filter(item => item.room === selectedClinicRoom.value) const deptName = getSelectedDeptName()
if (deptName) {
filtered = filtered.filter(item => item.room === deptName)
}
} }
// 再按状态过滤(只显示等待) // 再按状态过滤(只显示等待)
@@ -1724,9 +1747,9 @@ const handleNextPatient = async () => {
reqData.organizationId = selectedQueueRow.value.organizationId reqData.organizationId = selectedQueueRow.value.organizationId
} else { } else {
// 如果没有选中患者,使用查询条件(兼容旧逻辑) // 如果没有选中患者,使用查询条件(兼容旧逻辑)
// 全科模式:优先用"当前叫号中/第一个等待"所在科室 let orgId = selectedDept.value !== 'all' ? selectedDept.value : undefined
let orgId = null // "全科"模式:优先用"当前叫号中/第一个等待"所在科室
{ if (orgId == null) {
const calling = originalQueueList.value.find((i) => i.status === '叫号中') const calling = originalQueueList.value.find((i) => i.status === '叫号中')
const waiting = originalQueueList.value.find((i) => i.status === '等待') const waiting = originalQueueList.value.find((i) => i.status === '等待')
console.log('【心内科】handleNextPatient 查找:叫号中=', calling?.patientName, '等待=', waiting?.patientName) console.log('【心内科】handleNextPatient 查找:叫号中=', calling?.patientName, '等待=', waiting?.patientName)
@@ -1762,9 +1785,9 @@ const handleSkip = async () => {
reqData.organizationId = selectedQueueRow.value.organizationId reqData.organizationId = selectedQueueRow.value.organizationId
} else { } else {
// 如果没有选中患者,使用查询条件(兼容旧逻辑) // 如果没有选中患者,使用查询条件(兼容旧逻辑)
// 全科模式:优先用”当前叫号中”所在科室 let orgId = selectedDept.value !== 'all' ? selectedDept.value : undefined
let orgId = null // “全科”模式:优先用“当前叫号中”所在科室
{ if (orgId == null) {
const calling = originalQueueList.value.find((i) => i.status === '叫号中') const calling = originalQueueList.value.find((i) => i.status === '叫号中')
orgId = calling?.organizationId orgId = calling?.organizationId
} }
@@ -1796,9 +1819,9 @@ const handleComplete = async () => {
reqData.organizationId = selectedQueueRow.value.organizationId reqData.organizationId = selectedQueueRow.value.organizationId
} else { } else {
// 如果没有选中患者,使用查询条件(兼容旧逻辑) // 如果没有选中患者,使用查询条件(兼容旧逻辑)
// 全科模式:优先用”当前叫号中”所在科室 let orgId = selectedDept.value !== 'all' ? selectedDept.value : undefined
let orgId = null // “全科”模式:优先用“当前叫号中”所在科室
{ if (orgId == null) {
const calling = originalQueueList.value.find((i) => i.status === '叫号中') const calling = originalQueueList.value.find((i) => i.status === '叫号中')
orgId = calling?.organizationId orgId = calling?.organizationId
} }
@@ -1830,9 +1853,9 @@ const handleRequeue = async () => {
reqData.organizationId = selectedQueueRow.value.organizationId reqData.organizationId = selectedQueueRow.value.organizationId
} else { } else {
// 如果没有选中患者,使用查询条件(兼容旧逻辑) // 如果没有选中患者,使用查询条件(兼容旧逻辑)
// 全科模式:优先用”当前叫号中”所在科室 let orgId = selectedDept.value !== 'all' ? selectedDept.value : undefined
let orgId = null // “全科”模式:优先用“当前叫号中”所在科室
{ if (orgId == null) {
const calling = originalQueueList.value.find((i) => i.status === '叫号中') const calling = originalQueueList.value.find((i) => i.status === '叫号中')
orgId = calling?.organizationId orgId = calling?.organizationId
} }
@@ -2098,6 +2121,8 @@ const handleTestRule = () => {
// 组件挂载 // 组件挂载
onMounted(() => { onMounted(() => {
// 加载就诊科室列表
loadDepartmentList()
// 初始化:优先从后端加载,失败则回退本地假数据 // 初始化:优先从后端加载,失败则回退本地假数据
loadDataFromApi() loadDataFromApi()
startWaitingTimer() startWaitingTimer()