根因分析:handleCancel 函数从 exePerformRecordList 提取 procedureId 时, 未过滤 null/空值,导致无效 procedureId 被发送到后端,引发 SQL 异常。 同时 therapyEnum 可能存在类型不一致问题。 修复内容: 1. 提取 procedureId 后增加 filter 过滤空值 2. 构建请求参数时再次过滤,确保不发无效 procedureId 3. therapyEnum 显式转为 Number 类型确保后端正确匹配过滤 4. producerIds 为空时增加用户提示 5. 增加 .catch 错误处理避免未捕获的 Promise rejection
837 lines
28 KiB
Vue
Executable File
837 lines
28 KiB
Vue
Executable File
<template>
|
||
<div style="height: calc(100vh - 126px)">
|
||
<div
|
||
style="
|
||
height: 51px;
|
||
border-bottom: 2px solid #e4e7ed;
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: space-between;
|
||
"
|
||
>
|
||
<div>
|
||
<span class="descriptions-item-label">截止时间:</span>
|
||
<el-date-picker
|
||
v-model="deadline"
|
||
type="datetime"
|
||
format="YYYY-MM-DD HH:mm:ss"
|
||
value-format="YYYY-MM-DD HH:mm:ss"
|
||
:clearable="false"
|
||
@change="handleGetPrescription"
|
||
/>
|
||
<el-radio-group v-model="therapyEnum" class="ml20" @change="handleRadioChange">
|
||
<el-radio :value="undefined">全部</el-radio>
|
||
<el-radio :value="1">长期</el-radio>
|
||
<el-radio :value="2">临时</el-radio>
|
||
</el-radio-group>
|
||
<el-button class="ml20" type="primary" plain @click="handleGetPrescription">
|
||
查询
|
||
</el-button>
|
||
</div>
|
||
<div>
|
||
<span class="descriptions-item-label">实际执行时间:</span>
|
||
<el-date-picker
|
||
v-model="exeDate"
|
||
type="datetime"
|
||
format="YYYY-MM-DD HH:mm:ss"
|
||
value-format="YYYY-MM-DD HH:mm:ss"
|
||
:clearable="false"
|
||
@change="handleGetPrescription"
|
||
/>
|
||
<span class="descriptions-item-label">全选:</span>
|
||
<el-switch v-model="chooseAll" @change="handelSwicthChange" />
|
||
<el-button
|
||
class="ml20"
|
||
type="primary"
|
||
@click="handleExecute"
|
||
:disabled="props.exeStatus == 6"
|
||
>
|
||
执行选中
|
||
</el-button>
|
||
<el-button
|
||
class="ml20"
|
||
type="primary"
|
||
@click="handleNoExecute"
|
||
:disabled="props.exeStatus == 6"
|
||
>
|
||
不执行
|
||
</el-button>
|
||
<el-button
|
||
class="ml20 mr20"
|
||
type="danger"
|
||
:disabled="props.exeStatus != 6"
|
||
plain
|
||
@click="handleCancel"
|
||
>
|
||
取消执行
|
||
</el-button>
|
||
</div>
|
||
</div>
|
||
<div
|
||
style="padding: 10px; background-color: #eef9fd; height: 100%; overflow-y: auto"
|
||
v-loading="loading"
|
||
>
|
||
<el-collapse
|
||
v-model="activeNames"
|
||
expand-icon-position="left"
|
||
v-if="prescriptionList.length > 0"
|
||
style="
|
||
border-bottom: 0px;
|
||
border-top: 0px;
|
||
border-radius: 0px;
|
||
overflow-y: auto;
|
||
max-height: calc(100vh - 200px);
|
||
"
|
||
>
|
||
<el-collapse-item
|
||
v-for="(item, index) in prescriptionList"
|
||
:key="index"
|
||
:name="item[0].encounterId"
|
||
style="
|
||
border: 2px solid #e4e7ed;
|
||
border-radius: 8px;
|
||
margin-bottom: 10px;
|
||
overflow: hidden;
|
||
"
|
||
>
|
||
<template #title>
|
||
<div style="display: flex; justify-content: space-between; align-items: center">
|
||
<div>
|
||
<span>{{ item[0].bedName + '【' + item[0].busNo + '】' }}</span>
|
||
<span>
|
||
{{
|
||
item[0].patientName + ' / ' + item[0].genderEnum_enumText + ' / ' + item[0].age
|
||
}}
|
||
</span>
|
||
<el-tag style="margin-left: 10px">{{ item[0].contractName }}</el-tag>
|
||
<span style="margin-left: 30px; font-weight: 600">
|
||
{{ item[0].conditionNames }}
|
||
</span>
|
||
</div>
|
||
<div
|
||
style="
|
||
display: flex;
|
||
justify-content: space-between;
|
||
gap: 20px;
|
||
align-items: center;
|
||
margin-right: 20px;
|
||
"
|
||
>
|
||
<div style="display: inline-block; margin-right: 10px">
|
||
<span class="descriptions-item-label">住院医生:</span>
|
||
<span>{{ item[0].requesterId_dictText }}</span>
|
||
</div>
|
||
<div style="display: inline-block; margin-right: 10px">
|
||
<div
|
||
class="descriptions-item-label"
|
||
style="height: 20px; line-height: 20px; text-align: center; margin: 0"
|
||
>
|
||
预交金额
|
||
</div>
|
||
<div
|
||
style="
|
||
height: 20px;
|
||
line-height: 20px;
|
||
text-align: center;
|
||
font-size: 15px;
|
||
color: #ec8c43;
|
||
"
|
||
>
|
||
{{ item[0].balanceAmount?.toFixed(2) }}
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</template>
|
||
<el-table
|
||
:data="item"
|
||
border
|
||
:ref="'tableRef' + index"
|
||
:header-cell-style="{ background: '#eef9fd !important' }"
|
||
@select="(selection, row) => handleRowSelect(selection, row, index)"
|
||
@select-all="(selection) => handleSelectAll(selection, index)"
|
||
>
|
||
<el-table-column type="selection" align="center" width="50" />
|
||
<el-table-column label="类型" align="center" prop="therapyEnum_enumText" width="80">
|
||
<template #default="scope">
|
||
<span :style="scope.row.therapyEnum == '1' ? 'color: #a6745c' : 'color: #3787a5'">
|
||
{{ scope.row.therapyEnum_enumText }}
|
||
</span>
|
||
</template>
|
||
</el-table-column>
|
||
<el-table-column label="医嘱内容" prop="adviceName">
|
||
<template #default="scope">
|
||
<span>
|
||
{{ scope.row.adviceName }}
|
||
</span>
|
||
<template v-if="scope.row.adviceTable == 'med_medication_request'">
|
||
<span>
|
||
{{ ' 【' + scope.row.volume + '】' }}
|
||
</span>
|
||
<span style="color: #447c95 !important">
|
||
{{
|
||
'(' +
|
||
scope.row.methodCode_dictText +
|
||
' ' +
|
||
scope.row.dose +
|
||
scope.row.doseUnitCode_dictText +
|
||
' ' +
|
||
scope.row.rateCode_dictText +
|
||
')'
|
||
}}
|
||
</span>
|
||
</template>
|
||
</template>
|
||
</el-table-column>
|
||
<el-table-column label="开始/终止" prop="requestTime" width="200" />
|
||
<el-table-column :label="props.exeStatus == 1 ? '预计执行' : '执行时间'" prop="times">
|
||
<template #default="scope">
|
||
<div
|
||
v-for="(item, timeIndex) in scope.row.times"
|
||
:key="timeIndex"
|
||
style="padding-bottom: 5px"
|
||
>
|
||
<span>{{ item }}</span>
|
||
<el-checkbox-group
|
||
v-model="scope.row.checkedRates[timeIndex]"
|
||
style="display: inline-block; margin-left: 15px"
|
||
>
|
||
<el-checkbox
|
||
v-for="(rateItem, rateIndex) in scope.row.rate[item]"
|
||
:key="rateIndex"
|
||
:value="rateItem.rate"
|
||
@change="
|
||
(value) => handleRateChange(value, item, rateItem.rate, scope.row, rateItem)
|
||
"
|
||
border
|
||
size="small"
|
||
style="margin-right: 15px"
|
||
>
|
||
{{ rateItem.rate }}
|
||
<template v-if="rateItem.practitionerName">
|
||
{{ rateItem.practitionerName }}
|
||
</template>
|
||
</el-checkbox>
|
||
</el-checkbox-group>
|
||
</div>
|
||
</template>
|
||
</el-table-column>
|
||
</el-table>
|
||
</el-collapse-item>
|
||
</el-collapse>
|
||
<el-empty v-else description="点击查询获取患者医嘱信息"></el-empty>
|
||
</div>
|
||
</div>
|
||
</template>
|
||
|
||
<script setup>
|
||
import {adviceCancel, adviceExecute, adviceNoExecute, getPrescriptionList} from './api';
|
||
import {patientInfoList} from '../../components/store/patient.js';
|
||
import {lotNumberMatch} from '@/api/public';
|
||
import {formatDateStr} from '@/utils/index';
|
||
import {getCurrentInstance, nextTick, ref, provide} from 'vue';
|
||
|
||
const activeNames = ref([]);
|
||
const prescriptionList = ref([]);
|
||
const deadline = ref(formatDateStr(new Date(), 'YYYY-MM-DD') + ' 23:59:59');
|
||
const exeDate = ref(formatDateStr(new Date(), 'YYYY-MM-DD') + ' 23:59:59');
|
||
const therapyEnum = ref(undefined);
|
||
const { proxy } = getCurrentInstance();
|
||
const loading = ref(false);
|
||
const chooseAll = ref(false);
|
||
// 独立维护选中行ID集合,避免el-table内部selection状态异常导致联动全选
|
||
const selectedRowIds = ref(new Set());
|
||
const props = defineProps({
|
||
exeStatus: {
|
||
type: Number,
|
||
default: 1,
|
||
},
|
||
requestStatus: {
|
||
type: Number,
|
||
default: 1,
|
||
},
|
||
});
|
||
|
||
function handleRadioChange() {
|
||
handleGetPrescription();
|
||
}
|
||
|
||
/** 频次时间规整为 HH:mm(与 formatDateStr 得到的时分一致,避免 8:00 vs 08:00 对不上) */
|
||
function normalizeDayTimeHm(part) {
|
||
if (part == null || String(part).trim() === '') {
|
||
return '00:00';
|
||
}
|
||
const s = String(part).trim();
|
||
const [hRaw, mRaw = '0'] = s.split(':').map((x) => String(x).trim());
|
||
const hNum = Number.parseInt(hRaw || '0', 10);
|
||
const mNum = Number.parseInt(mRaw || '0', 10);
|
||
const h = Number.isNaN(hNum) ? '00' : String(hNum).padStart(2, '0');
|
||
const m = Number.isNaN(mNum) ? '00' : String(mNum).padStart(2, '0');
|
||
return `${h}:${m}`;
|
||
}
|
||
|
||
function handleGetPrescription() {
|
||
if (patientInfoList.value.length > 0) {
|
||
loading.value = true;
|
||
let encounterIds = patientInfoList.value.map((i) => i.encounterId).join(',');
|
||
getPrescriptionList({
|
||
encounterIds: encounterIds,
|
||
pageSize: 10000,
|
||
pageNo: 1,
|
||
therapyEnum: therapyEnum.value,
|
||
exeStatus: props.exeStatus,
|
||
requestStatus: props.requestStatus,
|
||
}).then((res) => {
|
||
try {
|
||
const records = res?.data?.records || [];
|
||
// 根据encounterId分组
|
||
const groupedPrescriptions = records.reduce((groups, prescription) => {
|
||
// 获取当前医嘱全部执行频次
|
||
let rate;
|
||
let times;
|
||
if (prescription.therapyEnum == 1) {
|
||
// 长期医嘱:dayTimes 可能为「8:00,12:00」未补零,需与后端 occurrenceTime 格式化后对齐
|
||
rate = prescription.dayTimes
|
||
?.split(',')
|
||
.map((x) => x.trim())
|
||
.filter((x) => x !== '')
|
||
.map((x) => normalizeDayTimeHm(x));
|
||
// 用截止时间和医嘱签发时间算出全部执行日期
|
||
times = getDateRange(prescription.requestTime, deadline.value);
|
||
} else {
|
||
// 临时医嘱 直接取医嘱签发时间截取执行时间和执行日期
|
||
rate = [formatDateStr(prescription.requestTime, 'HH:mm')];
|
||
times = [formatDateStr(prescription.requestTime, 'MM-DD')];
|
||
}
|
||
prescription.year = formatDateStr(prescription.requestTime, 'YYYY');
|
||
// 初始化执行时间列表
|
||
prescription.executeTimes = [];
|
||
// 初始化取消执行Id列表
|
||
prescription.procedureIds = [];
|
||
// 添加复选框状态管理
|
||
prescription.checkedRates = {};
|
||
// 已执行时间点列表
|
||
let exeTimeList = prescription.exePerformRecordList.map((item) => {
|
||
return formatDateStr(item.occurrenceTime, 'YYYY-MM-DD HH:mm:ss');
|
||
});
|
||
// 不执行时间点列表
|
||
let stopTimeList = prescription.stopPerformRecordList.map((item) => {
|
||
return formatDateStr(item.occurrenceTime, 'YYYY-MM-DD HH:mm:ss');
|
||
});
|
||
// 取消执行时间点列表
|
||
let cancelTimeList = prescription.cancelPerformRecordList.map((item) => {
|
||
return formatDateStr(item.occurrenceTime, 'YYYY-MM-DD HH:mm:ss');
|
||
});
|
||
if (rate) {
|
||
// 拼成日期加全部时间点的形式,显示示例:03-01 [09:00, 10:00, 11:00]
|
||
// 重构后的逻辑
|
||
let validTimes = [];
|
||
let validRates = {};
|
||
let newCheckedRates = {};
|
||
|
||
times.forEach((time, timeIndex) => {
|
||
let checkedRatesForTime = [];
|
||
let rateItems = [];
|
||
rate.forEach((rateItem) => {
|
||
let dateStr = prescription.year + '-' + time + ' ' + rateItem + ':00';
|
||
switch (props.exeStatus) {
|
||
case 1: // 待执行tab
|
||
// 如果该时间点未执行并且不在不执行列表中,则加入待选中列表
|
||
if (!exeTimeList.includes(dateStr) && !stopTimeList.includes(dateStr)) {
|
||
rateItems.push({
|
||
rate: rateItem,
|
||
});
|
||
checkedRatesForTime.push(rateItem);
|
||
prescription.executeTimes.push(dateStr);
|
||
}
|
||
break;
|
||
case 6: // 已执行tab
|
||
let index = exeTimeList.findIndex((item) => {
|
||
return item == dateStr;
|
||
});
|
||
if (index != -1) {
|
||
// 显示执行人practitionerName
|
||
rateItems.push({
|
||
procedureId: prescription.exePerformRecordList[index].procedureId,
|
||
practitionerName: prescription.exePerformRecordList[index].practitionerName,
|
||
rate: rateItem,
|
||
});
|
||
checkedRatesForTime.push(rateItem);
|
||
}
|
||
// 这里把时间点都加到执行时间列表中,后续遍历全部执行者id用
|
||
prescription.executeTimes.push(dateStr);
|
||
break;
|
||
case 5: // 不执行tab
|
||
let index1 = stopTimeList.findIndex((item) => {
|
||
return item == dateStr;
|
||
});
|
||
if (stopTimeList.includes(dateStr)) {
|
||
// 显示执行人practitionerName
|
||
rateItems.push({
|
||
practitionerName: prescription.stopPerformRecordList[index1].practitionerName,
|
||
rate: rateItem,
|
||
});
|
||
checkedRatesForTime.push(rateItem);
|
||
}
|
||
break;
|
||
case 9: // 取消执行tab
|
||
let index2 = cancelTimeList.findIndex((item) => {
|
||
return item == dateStr;
|
||
});
|
||
if (cancelTimeList.includes(dateStr)) {
|
||
rateItems.push({
|
||
practitionerName:
|
||
prescription.cancelPerformRecordList[index2].practitionerName,
|
||
rate: rateItem,
|
||
});
|
||
checkedRatesForTime.push(rateItem);
|
||
}
|
||
break;
|
||
}
|
||
});
|
||
validRates[time] = rateItems;
|
||
|
||
// 只有当该时间点有待执行的项目时,才保留该时间点
|
||
if (checkedRatesForTime.length > 0) {
|
||
let newIndex = validTimes.length;
|
||
validTimes.push(time);
|
||
newCheckedRates[newIndex] = checkedRatesForTime;
|
||
}
|
||
});
|
||
|
||
console.log(validRates, '111');
|
||
// 更新处方对象
|
||
prescription.times = validTimes;
|
||
prescription.rate = validRates;
|
||
prescription.checkedRates = newCheckedRates;
|
||
// 处理已执行记录,拿到全部的执行人id,取消执行时候要传id
|
||
prescription.exePerformRecordList.forEach((item) => {
|
||
if (prescription.executeTimes.includes(item.occurrenceTime)) {
|
||
prescription.procedureIds.push(item.procedureId);
|
||
}
|
||
});
|
||
}
|
||
// 「待执行」tab 下医嘱所有时间点都已执行/不执行时,跳过该医嘱
|
||
// (后端待执行查询未做该过滤,需要前端补充;其他 tab 后端已按记录列表过滤,不再处理)
|
||
if (props.exeStatus === 1 && (!prescription.times || prescription.times.length === 0)) {
|
||
return groups;
|
||
}
|
||
// 把相同encounterId的医嘱放在同一个数组中
|
||
const encounterId = prescription.encounterId;
|
||
if (!groups[encounterId]) {
|
||
groups[encounterId] = [];
|
||
}
|
||
if (!activeNames.value.includes(encounterId)) {
|
||
activeNames.value.push(encounterId);
|
||
}
|
||
groups[encounterId].push(prescription);
|
||
return groups;
|
||
}, {});
|
||
|
||
// 将分组结果转换为数组形式
|
||
prescriptionList.value = Object.values(groupedPrescriptions);
|
||
// 默认选中全部行
|
||
nextTick(() => {
|
||
defaultSelectAllRows();
|
||
});
|
||
} catch (error) {
|
||
console.error('医嘱执行-获取处方列表数据处理失败:', error);
|
||
prescriptionList.value = [];
|
||
} finally {
|
||
loading.value = false;
|
||
}
|
||
}).catch((error) => {
|
||
console.error('医嘱执行-获取处方列表接口失败:', error);
|
||
prescriptionList.value = [];
|
||
loading.value = false;
|
||
});
|
||
chooseAll.value = false;
|
||
} else {
|
||
prescriptionList.value = [];
|
||
selectedRowIds.value.clear();
|
||
loading.value = false;
|
||
// proxy.$message.warning('请选择患者');
|
||
}
|
||
}
|
||
|
||
// 执行
|
||
function handleExecute() {
|
||
let list = getSelectRows();
|
||
let encounterIds = patientInfoList.value.map((i) => i.encounterId).join(',');
|
||
list = list.map((item) => {
|
||
return {
|
||
requestId: item.requestId,
|
||
accountId: item.accountId,
|
||
adviceTable: item.adviceTable,
|
||
executeTimes: item.executeTimes,
|
||
};
|
||
});
|
||
console.log(list, 'list');
|
||
adviceExecute({ exeDate: exeDate.value, adviceExecuteDetailList: list }).then((res) => {
|
||
if (res.code == 200) {
|
||
proxy.$modal.msgSuccess(res.msg || '医嘱执行成功');
|
||
handleGetPrescription();
|
||
lotNumberMatch({ encounterIdList: encounterIds }, { skipErrorMsg: true }).catch((error) => {
|
||
console.warn('lotNumberMatch failed after adviceExecute:', error);
|
||
});
|
||
} else {
|
||
proxy.$modal.msgError(res.msg || '医嘱执行失败');
|
||
}
|
||
});
|
||
}
|
||
|
||
// 不执行
|
||
function handleNoExecute() {
|
||
let list = getSelectRows();
|
||
list = list.map((item) => {
|
||
return {
|
||
requestId: item.requestId,
|
||
encounterId: item.encounterId,
|
||
patientId: item.patientId,
|
||
adviceTable: item.adviceTable,
|
||
executeTimes: item.executeTimes,
|
||
};
|
||
});
|
||
console.log(list, 'list');
|
||
adviceNoExecute({ adviceExecuteDetailList: list }).then((res) => {
|
||
if (res.code == 200) {
|
||
proxy.$modal.msgSuccess(res.msg || '操作成功');
|
||
handleGetPrescription();
|
||
} else {
|
||
proxy.$modal.msgError(res.msg || '操作失败');
|
||
}
|
||
});
|
||
}
|
||
|
||
// 取消执行
|
||
function handleCancel() {
|
||
let list = getSelectRows();
|
||
let producerIds = [];
|
||
list.forEach((item) => {
|
||
// 从 exePerformRecordList 直接提取 procedureId,过滤空值避免后端SQL异常
|
||
const procedureIds = (item.exePerformRecordList || [])
|
||
.map((record) => record.procedureId)
|
||
.filter((id) => id != null && id !== '');
|
||
if (procedureIds.length === 0 && (!item.procedureIds || item.procedureIds.length === 0)) {
|
||
proxy.$modal.msgError('请选择已执行的医嘱记录');
|
||
return;
|
||
}
|
||
const ids = procedureIds.length > 0 ? procedureIds : item.procedureIds;
|
||
producerIds.push(
|
||
...ids
|
||
.filter((value) => value != null && value !== '')
|
||
.map((value) => {
|
||
return {
|
||
procedureId: value,
|
||
therapyEnum: Number(item.therapyEnum),
|
||
};
|
||
})
|
||
);
|
||
});
|
||
if (producerIds.length === 0) {
|
||
proxy.$modal.msgError('未找到有效的执行记录,无法取消执行');
|
||
return;
|
||
}
|
||
adviceCancel({ adviceExecuteDetailList: producerIds }).then((res) => {
|
||
if (res.code == 200) {
|
||
proxy.$modal.msgSuccess(res.msg || '取消执行成功');
|
||
handleGetPrescription();
|
||
} else {
|
||
proxy.$modal.msgError(res.msg || '取消执行失败');
|
||
}
|
||
}).catch(() => {
|
||
proxy.$modal.msgError('取消执行失败,请稍后重试');
|
||
});
|
||
}
|
||
|
||
function getSelectRows() {
|
||
// 优先从独立维护的selectedRowIds集合中获取选中行,避免el-table内部selection状态异常
|
||
const list = [];
|
||
prescriptionList.value.forEach((item) => {
|
||
item.forEach((row) => {
|
||
if (selectedRowIds.value.has(row.requestId)) {
|
||
list.push(row);
|
||
}
|
||
});
|
||
});
|
||
return list;
|
||
}
|
||
|
||
/**
|
||
* 计算两个日期之间的所有日期(包含起始和结束日期)
|
||
* @param {string|Date} startDate - 开始日期
|
||
* @param {string|Date} endDate - 结束日期
|
||
* @returns {Array<string>} 格式为MM-DD的日期数组
|
||
*/
|
||
function getDateRange(startDate, endDate) {
|
||
const start = new Date(startDate);
|
||
const end = new Date(endDate);
|
||
|
||
// 重置时间部分,只保留日期
|
||
start.setHours(0, 0, 0, 0);
|
||
end.setHours(0, 0, 0, 0);
|
||
|
||
const dates = [];
|
||
const current = new Date(start);
|
||
|
||
// 循环添加日期直到结束日期
|
||
while (current <= end) {
|
||
// 格式化为MM-DD
|
||
const month = String(current.getMonth() + 1).padStart(2, '0');
|
||
const day = String(current.getDate()).padStart(2, '0');
|
||
dates.push(`${month}-${day}`);
|
||
|
||
// 移动到下一天
|
||
current.setDate(current.getDate() + 1);
|
||
}
|
||
return dates;
|
||
}
|
||
|
||
function handleRateChange(value, date, time, row, rateItem) {
|
||
// 拼接当前选中时间
|
||
let timeStr = row.year + '-' + date + ' ' + time + ':00';
|
||
let timeIndex = row.executeTimes.indexOf(timeStr);
|
||
|
||
if (value) {
|
||
// 选中checkbox:如果时间不在执行时间列表中,则添加
|
||
if (timeIndex === -1) {
|
||
row.executeTimes.push(timeStr);
|
||
}
|
||
// 如果有procedureId,添加到列表中
|
||
if (rateItem.procedureId && !row.procedureIds.includes(rateItem.procedureId)) {
|
||
row.procedureIds.push(rateItem.procedureId);
|
||
}
|
||
} else {
|
||
// 取消选中checkbox:从执行时间列表中移除
|
||
if (timeIndex !== -1) {
|
||
row.executeTimes.splice(timeIndex, 1);
|
||
}
|
||
// 移除对应的procedureId
|
||
if (rateItem.procedureId) {
|
||
const procedureIndex = row.procedureIds.indexOf(rateItem.procedureId);
|
||
if (procedureIndex !== -1) {
|
||
row.procedureIds.splice(procedureIndex, 1);
|
||
}
|
||
}
|
||
}
|
||
|
||
// 检查该行所有checkbox是否全部选中,联动表格行选中状态
|
||
nextTick(() => {
|
||
checkAndToggleRowSelection(row);
|
||
});
|
||
}
|
||
|
||
function handelSwicthChange(value) {
|
||
prescriptionList.value.forEach((item, index) => {
|
||
const tableRef = proxy.$refs['tableRef' + index];
|
||
if (tableRef && tableRef[0]) {
|
||
if (value) {
|
||
// 全选:选中所有行并联动checkbox
|
||
item.forEach((row) => {
|
||
selectedRowIds.value.add(row.requestId);
|
||
tableRef[0].toggleRowSelection(row, true);
|
||
selectAllCheckboxesInRow(row);
|
||
});
|
||
} else {
|
||
// 取消全选:取消选中所有行并联动checkbox
|
||
item.forEach((row) => {
|
||
selectedRowIds.value.delete(row.requestId);
|
||
tableRef[0].toggleRowSelection(row, false);
|
||
unselectAllCheckboxesInRow(row);
|
||
});
|
||
}
|
||
}
|
||
});
|
||
}
|
||
|
||
// 默认选中全部行
|
||
function defaultSelectAllRows() {
|
||
// 清空并重建选中集合
|
||
selectedRowIds.value.clear();
|
||
prescriptionList.value.forEach((item, index) => {
|
||
const tableRef = proxy.$refs['tableRef' + index];
|
||
if (tableRef && tableRef[0]) {
|
||
// 选中该表格的所有行
|
||
item.forEach((row) => {
|
||
selectedRowIds.value.add(row.requestId);
|
||
tableRef[0].toggleRowSelection(row, true);
|
||
// 同时选中该行内部的所有checkbox
|
||
selectAllCheckboxesInRow(row);
|
||
});
|
||
}
|
||
});
|
||
// 更新全选开关状态
|
||
chooseAll.value = true;
|
||
}
|
||
|
||
// 选中行内部的所有checkbox
|
||
function selectAllCheckboxesInRow(row) {
|
||
if (!row.times || !row.rate) return;
|
||
|
||
// 遍历所有时间点,选中所有checkbox
|
||
row.times.forEach((time, timeIndex) => {
|
||
const rateItems = row.rate[time] || [];
|
||
if (rateItems.length > 0) {
|
||
// 获取该时间点的所有rate值
|
||
const allRates = rateItems.map((item) => item.rate);
|
||
// 设置为全选
|
||
row.checkedRates[timeIndex] = [...allRates];
|
||
|
||
// 更新执行时间列表
|
||
allRates.forEach((rate) => {
|
||
const timeStr = row.year + '-' + time + ' ' + rate + ':00';
|
||
if (!row.executeTimes.includes(timeStr)) {
|
||
row.executeTimes.push(timeStr);
|
||
}
|
||
// 添加procedureId
|
||
const rateItem = rateItems.find((item) => item.rate === rate);
|
||
if (rateItem && rateItem.procedureId && !row.procedureIds.includes(rateItem.procedureId)) {
|
||
row.procedureIds.push(rateItem.procedureId);
|
||
}
|
||
});
|
||
}
|
||
});
|
||
}
|
||
|
||
// 取消选中行内部的所有checkbox
|
||
function unselectAllCheckboxesInRow(row) {
|
||
if (!row.times) return;
|
||
|
||
// 清空所有checkbox选中状态
|
||
row.times.forEach((time, timeIndex) => {
|
||
row.checkedRates[timeIndex] = [];
|
||
});
|
||
|
||
// 清空执行时间列表和procedureIds
|
||
row.executeTimes = [];
|
||
row.procedureIds = [];
|
||
}
|
||
|
||
// 检查行内部所有checkbox是否全部选中
|
||
function isAllCheckboxesSelected(row) {
|
||
if (!row.times || !row.rate) return false;
|
||
|
||
// 遍历所有时间点,检查是否全部选中
|
||
for (let timeIndex = 0; timeIndex < row.times.length; timeIndex++) {
|
||
const time = row.times[timeIndex];
|
||
const rateItems = row.rate[time] || [];
|
||
const checkedRates = row.checkedRates[timeIndex] || [];
|
||
|
||
// 如果该时间点的checkbox没有全部选中,返回false
|
||
if (rateItems.length > 0 && checkedRates.length !== rateItems.length) {
|
||
return false;
|
||
}
|
||
}
|
||
return true;
|
||
}
|
||
|
||
// 检查并联动表格行选中状态
|
||
function checkAndToggleRowSelection(row) {
|
||
prescriptionList.value.forEach((item, tableIndex) => {
|
||
const rowIndex = item.findIndex((r) => r.requestId === row.requestId);
|
||
if (rowIndex !== -1) {
|
||
const tableRef = proxy.$refs['tableRef' + tableIndex];
|
||
if (tableRef && tableRef[0]) {
|
||
const isAllSelected = isAllCheckboxesSelected(row);
|
||
const isCurrentlySelected = selectedRowIds.value.has(row.requestId);
|
||
|
||
// 根据checkbox状态更新表格行选中状态
|
||
if (isAllSelected && !isCurrentlySelected) {
|
||
selectedRowIds.value.add(row.requestId);
|
||
tableRef[0].toggleRowSelection(row, true);
|
||
} else if (!isAllSelected && isCurrentlySelected) {
|
||
selectedRowIds.value.delete(row.requestId);
|
||
tableRef[0].toggleRowSelection(row, false);
|
||
}
|
||
}
|
||
}
|
||
});
|
||
}
|
||
|
||
// 处理表格行选中事件
|
||
function handleRowSelect(selection, row, tableIndex) {
|
||
const isSelected = selection.some((item) => item.requestId === row.requestId);
|
||
|
||
if (isSelected) {
|
||
selectedRowIds.value.add(row.requestId);
|
||
// 选中行时,选中该行内部的所有checkbox
|
||
selectAllCheckboxesInRow(row);
|
||
} else {
|
||
selectedRowIds.value.delete(row.requestId);
|
||
// 取消选中行时,取消选中该行内部的所有checkbox
|
||
unselectAllCheckboxesInRow(row);
|
||
}
|
||
|
||
// 更新全选开关状态
|
||
updateChooseAllStatus();
|
||
}
|
||
|
||
// 处理表格全选事件
|
||
function handleSelectAll(selection, tableIndex) {
|
||
const tableData = prescriptionList.value[tableIndex];
|
||
if (!tableData) return;
|
||
|
||
if (selection.length > 0) {
|
||
// 全选时,选中所有行内部的所有checkbox
|
||
tableData.forEach((row) => {
|
||
selectedRowIds.value.add(row.requestId);
|
||
selectAllCheckboxesInRow(row);
|
||
});
|
||
} else {
|
||
// 取消全选时,取消选中所有行内部的所有checkbox
|
||
tableData.forEach((row) => {
|
||
selectedRowIds.value.delete(row.requestId);
|
||
unselectAllCheckboxesInRow(row);
|
||
});
|
||
}
|
||
|
||
// 更新全选开关状态
|
||
updateChooseAllStatus();
|
||
}
|
||
|
||
// 更新全选开关状态
|
||
function updateChooseAllStatus() {
|
||
let allSelected = true;
|
||
prescriptionList.value.forEach((item) => {
|
||
item.forEach((row) => {
|
||
if (!selectedRowIds.value.has(row.requestId)) {
|
||
allSelected = false;
|
||
}
|
||
});
|
||
});
|
||
chooseAll.value = allSelected;
|
||
}
|
||
|
||
// 处理后端返回的时间集合
|
||
function handleTime() {}
|
||
|
||
defineExpose({
|
||
handleGetPrescription,
|
||
});
|
||
</script>
|
||
|
||
<style scoped>
|
||
.el-collapse-icon-position-left :deep(.el-collapse-item__header) {
|
||
padding: 10px;
|
||
}
|
||
|
||
:deep(.el-collapse-item__wrap) {
|
||
padding: 10px;
|
||
}
|
||
|
||
/* 表头背景色 */
|
||
:deep(.prescription-table .el-table__header th) {
|
||
background-color: #eef9fd !important;
|
||
}
|
||
|
||
:deep(.el-table__row:hover > td) {
|
||
background-color: #eef9fd !important;
|
||
}
|
||
|
||
.item-value {
|
||
color: #606266;
|
||
font-size: 15px;
|
||
font-weight: 500;
|
||
}
|
||
</style>
|