|
|
|
@ -41,6 +41,10 @@
|
|
|
|
<el-button type="primary" @click="Add()" style="margin-left: 10px;">添加</el-button>
|
|
|
|
<el-button type="primary" @click="Add()" style="margin-left: 10px;">添加</el-button>
|
|
|
|
<el-button type="danger" @click="Del()" style="margin-left: 10px;">删除</el-button>
|
|
|
|
<el-button type="danger" @click="Del()" style="margin-left: 10px;">删除</el-button>
|
|
|
|
<el-button type="success" @click="CreatedPlanClick()" style="margin-left: 20px;">生成选中的计划</el-button>
|
|
|
|
<el-button type="success" @click="CreatedPlanClick()" style="margin-left: 20px;">生成选中的计划</el-button>
|
|
|
|
|
|
|
|
<el-button type="warning" @click="BatchDisable()" style="margin-left: 10px;">批量禁用</el-button>
|
|
|
|
|
|
|
|
<el-button type="success" @click="BatchEnable()" style="margin-left: 10px;">批量启用</el-button>
|
|
|
|
|
|
|
|
<el-button type="primary" @click="openBatchModify()" style="margin-left: 10px;">批量修改</el-button>
|
|
|
|
|
|
|
|
<el-button type="warning" @click="openBatchOccupy()" style="margin-left: 10px;">批量占用</el-button>
|
|
|
|
</el-row>
|
|
|
|
</el-row>
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
<el-row>
|
|
|
|
<el-row>
|
|
|
|
@ -60,7 +64,7 @@
|
|
|
|
{{item.resources_name}}
|
|
|
|
{{item.resources_name}}
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
<div v-loading="loading" style="border: 1px solid #efefef;width: 100%;">
|
|
|
|
<div ref="scrollContainer" v-loading="loading" style="border: 1px solid #efefef;width: 100%;position: relative;overflow-x: auto;">
|
|
|
|
<table class="planTable" v-if="planTableData.length>0" >
|
|
|
|
<table class="planTable" v-if="planTableData.length>0" >
|
|
|
|
<tr style="background-color: #f1f1f1;position: relative;">
|
|
|
|
<tr style="background-color: #f1f1f1;position: relative;">
|
|
|
|
<td style="width: 120px;display: flex;font-size: 12px;">
|
|
|
|
<td style="width: 120px;display: flex;font-size: 12px;">
|
|
|
|
@ -73,10 +77,14 @@
|
|
|
|
<td style="font-weight: 700;" v-for="(item,index) in xingqi">{{item.label}}</td>
|
|
|
|
<td style="font-weight: 700;" v-for="(item,index) in xingqi">{{item.label}}</td>
|
|
|
|
</tr>
|
|
|
|
</tr>
|
|
|
|
<tr v-for="(item,index) in planTableData" :key="index">
|
|
|
|
<tr v-for="(item,index) in planTableData" :key="index">
|
|
|
|
<td v-for="(item2,index2) in item" :key="index2" @mouseover="showTools(item2.id)"
|
|
|
|
<td v-for="(item2,index2) in item" :key="index2"
|
|
|
|
@mouseleave="hideTools(item2.id)">
|
|
|
|
:data-row="index" :data-col="index2"
|
|
|
|
|
|
|
|
@mouseover="onCellHover($event, item2, index, index2)"
|
|
|
|
|
|
|
|
@mouseleave="onCellLeave(item2?.id)"
|
|
|
|
|
|
|
|
@mousedown="onCellMouseDown($event, item2, index, index2)">
|
|
|
|
<span v-if="index2=='time_range'">{{item2}}</span>
|
|
|
|
<span v-if="index2=='time_range'">{{item2}}</span>
|
|
|
|
<div v-if="item2.countsInfo && item2.countsInfo.length>0" :class="{'planInfo_k':item2.status==1,'planInfo_k planInfo_k_disabled':item2.status==0}">
|
|
|
|
<div v-if="item2.countsInfo && item2.countsInfo.length>0"
|
|
|
|
|
|
|
|
:class="{'planInfo_k':item2.status==1,'planInfo_k planInfo_k_disabled':item2.status==0,'planInfo_k_selected':isSelected(item2.id) && item2.status==1,'planInfo_k_disabled_selected':isSelected(item2.id) && item2.status==0}">
|
|
|
|
<div v-if="hoverIndex==item2.id" class="hoverTools">
|
|
|
|
<div v-if="hoverIndex==item2.id" class="hoverTools">
|
|
|
|
<div class="icon_k" @click="Add(item2)">
|
|
|
|
<div class="icon_k" @click="Add(item2)">
|
|
|
|
<el-icon color="#409eff" size="20">
|
|
|
|
<el-icon color="#409eff" size="20">
|
|
|
|
@ -116,6 +124,7 @@
|
|
|
|
</td>
|
|
|
|
</td>
|
|
|
|
</tr>
|
|
|
|
</tr>
|
|
|
|
</table>
|
|
|
|
</table>
|
|
|
|
|
|
|
|
<div v-if="isDragging" class="drag-selection-overlay" :style="dragOverlayStyle"></div>
|
|
|
|
<div v-if="planTableData.length==0" style="width: 100%;background-color: #fff;">
|
|
|
|
<div v-if="planTableData.length==0" style="width: 100%;background-color: #fff;">
|
|
|
|
<el-empty description="暂无" />
|
|
|
|
<el-empty description="暂无" />
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
@ -379,13 +388,85 @@
|
|
|
|
</span>
|
|
|
|
</span>
|
|
|
|
</template>
|
|
|
|
</template>
|
|
|
|
</el-dialog>
|
|
|
|
</el-dialog>
|
|
|
|
|
|
|
|
<!-- 批量修改弹窗 -->
|
|
|
|
|
|
|
|
<el-dialog v-model="BatchModifyDialogVisible" title="批量修改" width="45%" :close-on-click-modal="false">
|
|
|
|
|
|
|
|
<div>
|
|
|
|
|
|
|
|
<div style="margin-bottom: 16px; color: #666;">已选 {{ selectedPlanArr.length }} 条号源明细</div>
|
|
|
|
|
|
|
|
<el-form label-width="100px">
|
|
|
|
|
|
|
|
<el-row :gutter="10" style="margin-bottom: 6px; font-weight: 600; color: #333; font-size: 13px;">
|
|
|
|
|
|
|
|
<el-col :span="6">渠道名称</el-col>
|
|
|
|
|
|
|
|
<el-col :span="8">数量</el-col>
|
|
|
|
|
|
|
|
</el-row>
|
|
|
|
|
|
|
|
<el-row v-for="(ch, ci) in batchChannels" :key="ci" :gutter="10" style="margin-bottom: 10px;">
|
|
|
|
|
|
|
|
<el-col :span="6" style="line-height: 32px;">{{ ch.name }}</el-col>
|
|
|
|
|
|
|
|
<el-col :span="8">
|
|
|
|
|
|
|
|
<el-input v-model.number="batchForm[ci].count" placeholder="数量" size="default"
|
|
|
|
|
|
|
|
oninput="value=value.replace(/[^0-9]/g,'')" />
|
|
|
|
|
|
|
|
</el-col>
|
|
|
|
|
|
|
|
</el-row>
|
|
|
|
|
|
|
|
<el-row :gutter="10" style="border-top: 1px solid #eee; padding-top: 10px;">
|
|
|
|
|
|
|
|
<el-col :span="6" style="line-height: 32px; font-weight: 600;">合计</el-col>
|
|
|
|
|
|
|
|
<el-col :span="8" style="line-height: 32px; font-weight: 600;">数量: {{ batchTotalCount }}</el-col>
|
|
|
|
|
|
|
|
</el-row>
|
|
|
|
|
|
|
|
</el-form>
|
|
|
|
|
|
|
|
<div style="margin-top: 16px; padding-top: 12px; border-top: 1px solid #eee;">
|
|
|
|
|
|
|
|
<div style="margin-bottom: 8px; font-weight: 600; color: #333; font-size: 13px;">病人类型</div>
|
|
|
|
|
|
|
|
<el-checkbox-group v-model="batchPatientType">
|
|
|
|
|
|
|
|
<el-checkbox label="0">住院</el-checkbox>
|
|
|
|
|
|
|
|
<el-checkbox label="1">门诊</el-checkbox>
|
|
|
|
|
|
|
|
<el-checkbox label="2">急诊</el-checkbox>
|
|
|
|
|
|
|
|
<el-checkbox label="3">体检</el-checkbox>
|
|
|
|
|
|
|
|
</el-checkbox-group>
|
|
|
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
<template #footer>
|
|
|
|
|
|
|
|
<el-button @click="BatchModifyDialogVisible = false" :disabled="batchModifyRunning">取消</el-button>
|
|
|
|
|
|
|
|
<el-button type="primary" @click="execBatchModify()" :disabled="batchModifyRunning">确定修改</el-button>
|
|
|
|
|
|
|
|
</template>
|
|
|
|
|
|
|
|
</el-dialog>
|
|
|
|
|
|
|
|
<!-- 批量占用弹窗 -->
|
|
|
|
|
|
|
|
<el-dialog v-model="BatchOccupyDialogVisible" title="批量占用" width="45%" :close-on-click-modal="false">
|
|
|
|
|
|
|
|
<div>
|
|
|
|
|
|
|
|
<div style="margin-bottom: 16px; color: #666;">已选 {{ selectedPlanArr.length }} 条号源明细</div>
|
|
|
|
|
|
|
|
<el-form label-width="100px">
|
|
|
|
|
|
|
|
<el-row :gutter="10" style="margin-bottom: 6px; font-weight: 600; color: #333; font-size: 13px;">
|
|
|
|
|
|
|
|
<el-col :span="6">渠道名称</el-col>
|
|
|
|
|
|
|
|
<el-col :span="8">占用数量</el-col>
|
|
|
|
|
|
|
|
<el-col :span="8">提示</el-col>
|
|
|
|
|
|
|
|
</el-row>
|
|
|
|
|
|
|
|
<el-row v-for="(ch, ci) in batchOccupyChannels" :key="ci" :gutter="10" style="margin-bottom: 10px;">
|
|
|
|
|
|
|
|
<el-col :span="6" style="line-height: 32px;">{{ ch.name }}</el-col>
|
|
|
|
|
|
|
|
<el-col :span="8">
|
|
|
|
|
|
|
|
<el-input v-model.number="batchOccupyForm[ci].locked_count" placeholder="占用数量" size="default"
|
|
|
|
|
|
|
|
oninput="value=value.replace(/[^0-9]/g,'')"
|
|
|
|
|
|
|
|
@input="onOccupyInput(ci, $event)" />
|
|
|
|
|
|
|
|
</el-col>
|
|
|
|
|
|
|
|
<el-col :span="8" style="line-height: 32px; font-size: 12px; color: #999;">
|
|
|
|
|
|
|
|
<template v-if="batchOccupyLimits[ch.id]?.maxValue !== null">
|
|
|
|
|
|
|
|
最大可占: {{ batchOccupyLimits[ch.id].maxValue }}
|
|
|
|
|
|
|
|
</template>
|
|
|
|
|
|
|
|
</el-col>
|
|
|
|
|
|
|
|
</el-row>
|
|
|
|
|
|
|
|
<el-row :gutter="10" style="border-top: 1px solid #eee; padding-top: 10px;">
|
|
|
|
|
|
|
|
<el-col :span="6" style="line-height: 32px; font-weight: 600;">合计</el-col>
|
|
|
|
|
|
|
|
<el-col :span="8" style="line-height: 32px; font-weight: 600;">占用: {{ batchOccupyTotalLocked }}</el-col>
|
|
|
|
|
|
|
|
</el-row>
|
|
|
|
|
|
|
|
</el-form>
|
|
|
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
<template #footer>
|
|
|
|
|
|
|
|
<el-button @click="BatchOccupyDialogVisible = false" :disabled="batchOccupyRunning">取消</el-button>
|
|
|
|
|
|
|
|
<el-button type="warning" @click="execBatchOccupy()" :disabled="batchOccupyRunning">确定占用</el-button>
|
|
|
|
|
|
|
|
</template>
|
|
|
|
|
|
|
|
</el-dialog>
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
</template>
|
|
|
|
</template>
|
|
|
|
|
|
|
|
|
|
|
|
<script setup>
|
|
|
|
<script setup>
|
|
|
|
import {
|
|
|
|
import {
|
|
|
|
ref,
|
|
|
|
ref,
|
|
|
|
onMounted
|
|
|
|
computed,
|
|
|
|
|
|
|
|
onMounted,
|
|
|
|
|
|
|
|
onUnmounted
|
|
|
|
} from 'vue'
|
|
|
|
} from 'vue'
|
|
|
|
import {
|
|
|
|
import {
|
|
|
|
PlanModelSaveAdmin,
|
|
|
|
PlanModelSaveAdmin,
|
|
|
|
@ -398,6 +479,10 @@
|
|
|
|
ResourceGetBindDeviceList,
|
|
|
|
ResourceGetBindDeviceList,
|
|
|
|
GetPlanModelDetailInfo,
|
|
|
|
GetPlanModelDetailInfo,
|
|
|
|
PlanModelDelAdmin,
|
|
|
|
PlanModelDelAdmin,
|
|
|
|
|
|
|
|
PlanModelBatchDisableAdmin,
|
|
|
|
|
|
|
|
PlanModelBatchEnableAdmin,
|
|
|
|
|
|
|
|
PlanModelBatchChangeAdmin,
|
|
|
|
|
|
|
|
PlanModelBatchOccupyAdmin,
|
|
|
|
GetEnableDeviceList,
|
|
|
|
GetEnableDeviceList,
|
|
|
|
CreatePlanListAdmin,
|
|
|
|
CreatePlanListAdmin,
|
|
|
|
GetServiceDateTime,
|
|
|
|
GetServiceDateTime,
|
|
|
|
@ -480,12 +565,118 @@
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
let hoverIndex = ref(null)
|
|
|
|
let hoverIndex = ref(null)
|
|
|
|
|
|
|
|
// 拖拽框选状态
|
|
|
|
|
|
|
|
let isDragging = ref(false)
|
|
|
|
|
|
|
|
let dragStart = ref({ row: 0, col: 0, x: 0, y: 0 })
|
|
|
|
|
|
|
|
let dragOverlayStyle = ref({})
|
|
|
|
|
|
|
|
let scrollContainer = ref(null)
|
|
|
|
const showTools = (index) => {
|
|
|
|
const showTools = (index) => {
|
|
|
|
hoverIndex.value = index
|
|
|
|
hoverIndex.value = index
|
|
|
|
}
|
|
|
|
}
|
|
|
|
const hideTools = (index) => {
|
|
|
|
const hideTools = (index) => {
|
|
|
|
hoverIndex.value = null
|
|
|
|
hoverIndex.value = null
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
const onCellHover = (event, cellData, rowIdx, colKey) => {
|
|
|
|
|
|
|
|
if (isDragging.value) return
|
|
|
|
|
|
|
|
showTools(cellData?.id)
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
const onCellLeave = (cellId) => {
|
|
|
|
|
|
|
|
if (isDragging.value) return
|
|
|
|
|
|
|
|
hideTools(cellId)
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
const onCellMouseDown = (event, cellData, rowIdx, colKey) => {
|
|
|
|
|
|
|
|
// 点击勾选框不触发拖拽
|
|
|
|
|
|
|
|
if (event.target.closest('.plan_checkbox')) return
|
|
|
|
|
|
|
|
// time_range 列或无数据不触发
|
|
|
|
|
|
|
|
if (colKey === 'time_range' || !cellData || !cellData.id) return
|
|
|
|
|
|
|
|
const td = event.currentTarget
|
|
|
|
|
|
|
|
const tr = td.closest('tr')
|
|
|
|
|
|
|
|
if (!tr) return
|
|
|
|
|
|
|
|
const container = scrollContainer.value
|
|
|
|
|
|
|
|
if (!container) return
|
|
|
|
|
|
|
|
const containerRect = container.getBoundingClientRect()
|
|
|
|
|
|
|
|
isDragging.value = true
|
|
|
|
|
|
|
|
dragStart.value = {
|
|
|
|
|
|
|
|
row: tr.rowIndex,
|
|
|
|
|
|
|
|
col: td.cellIndex,
|
|
|
|
|
|
|
|
x: event.clientX - containerRect.left + container.scrollLeft,
|
|
|
|
|
|
|
|
y: event.clientY - containerRect.top + container.scrollTop
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
// 清空原有选中,选中当前格子
|
|
|
|
|
|
|
|
selectedPlanArr.value = [cellData.id]
|
|
|
|
|
|
|
|
PlanSelectedAll.value = 0
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
const onDocumentMouseMove = (event) => {
|
|
|
|
|
|
|
|
if (!isDragging.value) return
|
|
|
|
|
|
|
|
const container = scrollContainer.value
|
|
|
|
|
|
|
|
if (!container) return
|
|
|
|
|
|
|
|
const containerRect = container.getBoundingClientRect()
|
|
|
|
|
|
|
|
const currentX = event.clientX - containerRect.left + container.scrollLeft
|
|
|
|
|
|
|
|
const currentY = event.clientY - containerRect.top + container.scrollTop
|
|
|
|
|
|
|
|
// 更新拖拽矩形样式
|
|
|
|
|
|
|
|
dragOverlayStyle.value = {
|
|
|
|
|
|
|
|
left: Math.min(dragStart.value.x, currentX) + 'px',
|
|
|
|
|
|
|
|
top: Math.min(dragStart.value.y, currentY) + 'px',
|
|
|
|
|
|
|
|
width: Math.abs(currentX - dragStart.value.x) + 'px',
|
|
|
|
|
|
|
|
height: Math.abs(currentY - dragStart.value.y) + 'px'
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
// 用 elementFromPoint 找到鼠标下的 td
|
|
|
|
|
|
|
|
const el = document.elementFromPoint(event.clientX, event.clientY)
|
|
|
|
|
|
|
|
if (!el) return
|
|
|
|
|
|
|
|
const td = el.closest('td')
|
|
|
|
|
|
|
|
if (!td) return
|
|
|
|
|
|
|
|
const tr = td.closest('tr')
|
|
|
|
|
|
|
|
if (!tr) return
|
|
|
|
|
|
|
|
// 跳过表头行
|
|
|
|
|
|
|
|
if (tr.parentElement?.tagName === 'THEAD') return
|
|
|
|
|
|
|
|
const endRow = tr.rowIndex
|
|
|
|
|
|
|
|
const endCol = td.cellIndex
|
|
|
|
|
|
|
|
if (endCol === 0) return // 跳过 time_range 列
|
|
|
|
|
|
|
|
const startRow = dragStart.value.row
|
|
|
|
|
|
|
|
const startCol = dragStart.value.col
|
|
|
|
|
|
|
|
const minRow = Math.min(startRow, endRow)
|
|
|
|
|
|
|
|
const maxRow = Math.max(startRow, endRow)
|
|
|
|
|
|
|
|
const minCol = Math.min(startCol, endCol)
|
|
|
|
|
|
|
|
const maxCol = Math.max(startCol, endCol)
|
|
|
|
|
|
|
|
// 重建选中列表
|
|
|
|
|
|
|
|
selectedPlanArr.value = []
|
|
|
|
|
|
|
|
for (let r = minRow; r <= maxRow; r++) {
|
|
|
|
|
|
|
|
const dataRow = planTableData.value[r - 1]
|
|
|
|
|
|
|
|
if (!dataRow) continue
|
|
|
|
|
|
|
|
for (let c = minCol; c <= maxCol; c++) {
|
|
|
|
|
|
|
|
if (c === 0) continue
|
|
|
|
|
|
|
|
const colKey = xingqi.value[c - 1]?.label
|
|
|
|
|
|
|
|
if (!colKey) continue
|
|
|
|
|
|
|
|
const cellData = dataRow[colKey]
|
|
|
|
|
|
|
|
if (cellData && cellData.id) {
|
|
|
|
|
|
|
|
selectedPlanArr.value.push(cellData.id)
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
const onDocumentMouseUp = () => {
|
|
|
|
|
|
|
|
if (!isDragging.value) return
|
|
|
|
|
|
|
|
isDragging.value = false
|
|
|
|
|
|
|
|
dragOverlayStyle.value = {}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
// 批量修改状态
|
|
|
|
|
|
|
|
let BatchModifyDialogVisible = ref(false)
|
|
|
|
|
|
|
|
let batchModifyRunning = ref(false)
|
|
|
|
|
|
|
|
let batchChannels = ref([])
|
|
|
|
|
|
|
|
let batchForm = ref([])
|
|
|
|
|
|
|
|
let batchPatientType = ref([])
|
|
|
|
|
|
|
|
const batchTotalCount = computed(() => {
|
|
|
|
|
|
|
|
return batchForm.value.reduce((s, item) => s + (Number(item.count) || 0), 0)
|
|
|
|
|
|
|
|
})
|
|
|
|
|
|
|
|
// 批量占用状态
|
|
|
|
|
|
|
|
let BatchOccupyDialogVisible = ref(false)
|
|
|
|
|
|
|
|
let batchOccupyRunning = ref(false)
|
|
|
|
|
|
|
|
let batchOccupyChannels = ref([])
|
|
|
|
|
|
|
|
let batchOccupyForm = ref([])
|
|
|
|
|
|
|
|
let batchOccupyLimits = ref({})
|
|
|
|
|
|
|
|
const batchOccupyTotalLocked = computed(() => {
|
|
|
|
|
|
|
|
return batchOccupyForm.value.reduce((s, item) => s + (Number(item.locked_count) || 0), 0)
|
|
|
|
|
|
|
|
})
|
|
|
|
const isSelected = (id) => {
|
|
|
|
const isSelected = (id) => {
|
|
|
|
return selectedPlanArr.value.includes(id)
|
|
|
|
return selectedPlanArr.value.includes(id)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
@ -497,6 +688,164 @@
|
|
|
|
selectedPlanArr.value = selectedPlanArr.value.filter(item => item !== id);
|
|
|
|
selectedPlanArr.value = selectedPlanArr.value.filter(item => item !== id);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
};
|
|
|
|
};
|
|
|
|
|
|
|
|
// 批量禁用
|
|
|
|
|
|
|
|
const BatchDisable = () => {
|
|
|
|
|
|
|
|
if (selectedPlanArr.value.length == 0) {
|
|
|
|
|
|
|
|
ElMessage.error('请至少勾选1条记录')
|
|
|
|
|
|
|
|
return false
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
ElMessageBox.confirm(
|
|
|
|
|
|
|
|
'确定批量禁用勾选的计划模板吗?',
|
|
|
|
|
|
|
|
'提示', {
|
|
|
|
|
|
|
|
confirmButtonText: '确定',
|
|
|
|
|
|
|
|
cancelButtonText: '取消',
|
|
|
|
|
|
|
|
type: 'warning',
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
).then(() => {
|
|
|
|
|
|
|
|
loading.value = true
|
|
|
|
|
|
|
|
PlanModelBatchDisableAdmin({
|
|
|
|
|
|
|
|
ids: selectedPlanArr.value
|
|
|
|
|
|
|
|
}).then(res => {
|
|
|
|
|
|
|
|
loading.value = false
|
|
|
|
|
|
|
|
if (res.status) {
|
|
|
|
|
|
|
|
ElMessage({
|
|
|
|
|
|
|
|
message: '批量禁用成功',
|
|
|
|
|
|
|
|
type: 'success',
|
|
|
|
|
|
|
|
})
|
|
|
|
|
|
|
|
GetList()
|
|
|
|
|
|
|
|
} else {
|
|
|
|
|
|
|
|
ElMessage.error(res.msg)
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
})
|
|
|
|
|
|
|
|
})
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
// 批量启用
|
|
|
|
|
|
|
|
const BatchEnable = () => {
|
|
|
|
|
|
|
|
if (selectedPlanArr.value.length == 0) {
|
|
|
|
|
|
|
|
ElMessage.error('请至少勾选1条记录')
|
|
|
|
|
|
|
|
return false
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
ElMessageBox.confirm(
|
|
|
|
|
|
|
|
'确定批量启用勾选的计划模板吗?',
|
|
|
|
|
|
|
|
'提示', {
|
|
|
|
|
|
|
|
confirmButtonText: '确定',
|
|
|
|
|
|
|
|
cancelButtonText: '取消',
|
|
|
|
|
|
|
|
type: 'warning',
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
).then(() => {
|
|
|
|
|
|
|
|
loading.value = true
|
|
|
|
|
|
|
|
PlanModelBatchEnableAdmin({
|
|
|
|
|
|
|
|
ids: selectedPlanArr.value
|
|
|
|
|
|
|
|
}).then(res => {
|
|
|
|
|
|
|
|
loading.value = false
|
|
|
|
|
|
|
|
if (res.status) {
|
|
|
|
|
|
|
|
ElMessage({
|
|
|
|
|
|
|
|
message: '批量启用成功',
|
|
|
|
|
|
|
|
type: 'success',
|
|
|
|
|
|
|
|
})
|
|
|
|
|
|
|
|
GetList()
|
|
|
|
|
|
|
|
} else {
|
|
|
|
|
|
|
|
ElMessage.error(res.msg)
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
})
|
|
|
|
|
|
|
|
})
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
// 批量修改
|
|
|
|
|
|
|
|
const openBatchModify = () => {
|
|
|
|
|
|
|
|
if (selectedPlanArr.value.length == 0) {
|
|
|
|
|
|
|
|
ElMessage.error('请至少勾选1条记录')
|
|
|
|
|
|
|
|
return
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
// 从 planTableData 中提取已选号源的各渠道数量
|
|
|
|
|
|
|
|
const selectedIds = new Set(selectedPlanArr.value)
|
|
|
|
|
|
|
|
// 收集渠道信息
|
|
|
|
|
|
|
|
const channelMap = new Map()
|
|
|
|
|
|
|
|
const patientTypeSets = []
|
|
|
|
|
|
|
|
planTableData.value.forEach(row => {
|
|
|
|
|
|
|
|
for (const key in row) {
|
|
|
|
|
|
|
|
if (key === 'time_range') continue
|
|
|
|
|
|
|
|
const cell = row[key]
|
|
|
|
|
|
|
|
if (cell && cell.id && selectedIds.has(cell.id) && cell.countsInfo) {
|
|
|
|
|
|
|
|
cell.countsInfo.forEach(ci => {
|
|
|
|
|
|
|
|
if (!channelMap.has(ci.appointment_type_id)) {
|
|
|
|
|
|
|
|
channelMap.set(ci.appointment_type_id, {
|
|
|
|
|
|
|
|
name: ci.name,
|
|
|
|
|
|
|
|
jiancheng: ci.jiancheng,
|
|
|
|
|
|
|
|
counts: []
|
|
|
|
|
|
|
|
})
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
channelMap.get(ci.appointment_type_id).counts.push(ci.count)
|
|
|
|
|
|
|
|
})
|
|
|
|
|
|
|
|
// 收集病人类型
|
|
|
|
|
|
|
|
if (cell.patient_type) {
|
|
|
|
|
|
|
|
patientTypeSets.push(new Set(cell.patient_type))
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
})
|
|
|
|
|
|
|
|
// 构建渠道列表
|
|
|
|
|
|
|
|
batchChannels.value = []
|
|
|
|
|
|
|
|
batchForm.value = []
|
|
|
|
|
|
|
|
for (const [id, info] of channelMap) {
|
|
|
|
|
|
|
|
batchChannels.value.push({ id, name: info.name })
|
|
|
|
|
|
|
|
const allSame = info.counts.length > 0 && info.counts.every(v => v === info.counts[0])
|
|
|
|
|
|
|
|
batchForm.value.push({
|
|
|
|
|
|
|
|
appointment_type_id: id,
|
|
|
|
|
|
|
|
count: allSame ? info.counts[0] : ''
|
|
|
|
|
|
|
|
})
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
// 病人类型回填:同值勾选,异值留空
|
|
|
|
|
|
|
|
if (patientTypeSets.length > 0) {
|
|
|
|
|
|
|
|
const commonTypes = patientTypeSets.reduce((acc, set) => {
|
|
|
|
|
|
|
|
const result = new Set()
|
|
|
|
|
|
|
|
for (const val of acc) {
|
|
|
|
|
|
|
|
if (set.has(val)) result.add(val)
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
return result
|
|
|
|
|
|
|
|
})
|
|
|
|
|
|
|
|
batchPatientType.value = Array.from(commonTypes)
|
|
|
|
|
|
|
|
} else {
|
|
|
|
|
|
|
|
batchPatientType.value = []
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
batchModifyRunning.value = false
|
|
|
|
|
|
|
|
BatchModifyDialogVisible.value = true
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
const execBatchModify = async () => {
|
|
|
|
|
|
|
|
// 校验
|
|
|
|
|
|
|
|
for (const item of batchForm.value) {
|
|
|
|
|
|
|
|
if (Number(item.count) < 0) {
|
|
|
|
|
|
|
|
ElMessage.error('数量不能为负数')
|
|
|
|
|
|
|
|
return
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
const maxTotal = batchTotalCount.value
|
|
|
|
|
|
|
|
batchModifyRunning.value = true
|
|
|
|
|
|
|
|
const ids = [...selectedPlanArr.value]
|
|
|
|
|
|
|
|
const coutsInfo = batchForm.value.map(item => ({
|
|
|
|
|
|
|
|
appointment_type_id: item.appointment_type_id,
|
|
|
|
|
|
|
|
count: Number(item.count) || 0
|
|
|
|
|
|
|
|
}))
|
|
|
|
|
|
|
|
try {
|
|
|
|
|
|
|
|
const res = await PlanModelBatchChangeAdmin({
|
|
|
|
|
|
|
|
ids: ids,
|
|
|
|
|
|
|
|
max_total: maxTotal,
|
|
|
|
|
|
|
|
coutsInfo: coutsInfo,
|
|
|
|
|
|
|
|
patientType: batchPatientType.value
|
|
|
|
|
|
|
|
})
|
|
|
|
|
|
|
|
batchModifyRunning.value = false
|
|
|
|
|
|
|
|
if (res && res.status) {
|
|
|
|
|
|
|
|
BatchModifyDialogVisible.value = false
|
|
|
|
|
|
|
|
ElMessage.success('批量修改完成')
|
|
|
|
|
|
|
|
GetList()
|
|
|
|
|
|
|
|
} else {
|
|
|
|
|
|
|
|
ElMessage.error(res?.msg || '批量修改失败')
|
|
|
|
|
|
|
|
batchModifyRunning.value = false
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
} catch (e) {
|
|
|
|
|
|
|
|
batchModifyRunning.value = false
|
|
|
|
|
|
|
|
ElMessage.error('请求异常')
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
const CreatedPlanAction = () => { //调用生成计划明细接口
|
|
|
|
const CreatedPlanAction = () => { //调用生成计划明细接口
|
|
|
|
if (dateRange.value.length === 0) {
|
|
|
|
if (dateRange.value.length === 0) {
|
|
|
|
ElMessage.error("请选择日期范围")
|
|
|
|
ElMessage.error("请选择日期范围")
|
|
|
|
@ -780,6 +1129,90 @@
|
|
|
|
})
|
|
|
|
})
|
|
|
|
})
|
|
|
|
})
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// 批量占用
|
|
|
|
|
|
|
|
const initBatchOccupyForm = () => {
|
|
|
|
|
|
|
|
batchOccupyForm.value = batchOccupyChannels.value.map(ch => ({
|
|
|
|
|
|
|
|
appointment_type_id: ch.id,
|
|
|
|
|
|
|
|
locked_count: ''
|
|
|
|
|
|
|
|
}))
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
const onOccupyInput = (ci, val) => {
|
|
|
|
|
|
|
|
const ch = batchOccupyChannels.value[ci]
|
|
|
|
|
|
|
|
const limit = batchOccupyLimits.value[ch.id]
|
|
|
|
|
|
|
|
if (limit?.limited && Number(val) > limit.maxValue) {
|
|
|
|
|
|
|
|
batchOccupyForm.value[ci].locked_count = limit.maxValue
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
const openBatchOccupy = () => {
|
|
|
|
|
|
|
|
if (selectedPlanArr.value.length == 0) {
|
|
|
|
|
|
|
|
ElMessage.error('请至少勾选1条记录')
|
|
|
|
|
|
|
|
return
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
// 从 planTableData 中提取已选号源的各渠道 count 值,取最小值作为上限
|
|
|
|
|
|
|
|
const selectedIds = new Set(selectedPlanArr.value)
|
|
|
|
|
|
|
|
const channelMap = new Map()
|
|
|
|
|
|
|
|
planTableData.value.forEach(row => {
|
|
|
|
|
|
|
|
for (const key in row) {
|
|
|
|
|
|
|
|
if (key === 'time_range') continue
|
|
|
|
|
|
|
|
const cell = row[key]
|
|
|
|
|
|
|
|
if (cell && cell.id && selectedIds.has(cell.id) && cell.countsInfo) {
|
|
|
|
|
|
|
|
cell.countsInfo.forEach(ci => {
|
|
|
|
|
|
|
|
if (!channelMap.has(ci.appointment_type_id)) {
|
|
|
|
|
|
|
|
channelMap.set(ci.appointment_type_id, {
|
|
|
|
|
|
|
|
name: ci.name,
|
|
|
|
|
|
|
|
counts: []
|
|
|
|
|
|
|
|
})
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
channelMap.get(ci.appointment_type_id).counts.push(ci.count)
|
|
|
|
|
|
|
|
})
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
})
|
|
|
|
|
|
|
|
// 构建渠道列表,取每个渠道的最小 count 作为上限
|
|
|
|
|
|
|
|
batchOccupyChannels.value = []
|
|
|
|
|
|
|
|
const limits = {}
|
|
|
|
|
|
|
|
for (const [id, info] of channelMap) {
|
|
|
|
|
|
|
|
batchOccupyChannels.value.push({ id, name: info.name })
|
|
|
|
|
|
|
|
const minVal = Math.min(...info.counts)
|
|
|
|
|
|
|
|
limits[id] = { limited: true, maxValue: minVal }
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
batchOccupyLimits.value = limits
|
|
|
|
|
|
|
|
initBatchOccupyForm()
|
|
|
|
|
|
|
|
batchOccupyRunning.value = false
|
|
|
|
|
|
|
|
BatchOccupyDialogVisible.value = true
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
const execBatchOccupy = async () => {
|
|
|
|
|
|
|
|
for (const item of batchOccupyForm.value) {
|
|
|
|
|
|
|
|
if (Number(item.locked_count) < 0) {
|
|
|
|
|
|
|
|
ElMessage.error('占用数量不能为负数')
|
|
|
|
|
|
|
|
return
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
batchOccupyRunning.value = true
|
|
|
|
|
|
|
|
const ids = [...selectedPlanArr.value]
|
|
|
|
|
|
|
|
const coutsInfo = batchOccupyForm.value.map(item => ({
|
|
|
|
|
|
|
|
appointment_type_id: item.appointment_type_id,
|
|
|
|
|
|
|
|
locked_count: Number(item.locked_count) || 0
|
|
|
|
|
|
|
|
}))
|
|
|
|
|
|
|
|
try {
|
|
|
|
|
|
|
|
const res = await PlanModelBatchOccupyAdmin({
|
|
|
|
|
|
|
|
ids: ids,
|
|
|
|
|
|
|
|
coutsInfo: coutsInfo
|
|
|
|
|
|
|
|
})
|
|
|
|
|
|
|
|
batchOccupyRunning.value = false
|
|
|
|
|
|
|
|
if (res && res.status) {
|
|
|
|
|
|
|
|
BatchOccupyDialogVisible.value = false
|
|
|
|
|
|
|
|
ElMessage.success('批量占用完成')
|
|
|
|
|
|
|
|
GetList()
|
|
|
|
|
|
|
|
} else {
|
|
|
|
|
|
|
|
ElMessage.error(res?.msg || '批量占用失败')
|
|
|
|
|
|
|
|
batchOccupyRunning.value = false
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
} catch (e) {
|
|
|
|
|
|
|
|
batchOccupyRunning.value = false
|
|
|
|
|
|
|
|
ElMessage.error('请求异常')
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
//获取可用服务组
|
|
|
|
//获取可用服务组
|
|
|
|
let EnableDeviceList = ref([])
|
|
|
|
let EnableDeviceList = ref([])
|
|
|
|
const GetEnableDeviceListFunc = () => {
|
|
|
|
const GetEnableDeviceListFunc = () => {
|
|
|
|
@ -1171,7 +1604,13 @@
|
|
|
|
GetDepartmentEnableList()
|
|
|
|
GetDepartmentEnableList()
|
|
|
|
GetEnableDeviceListFunc()
|
|
|
|
GetEnableDeviceListFunc()
|
|
|
|
setMonthRange()
|
|
|
|
setMonthRange()
|
|
|
|
|
|
|
|
// 拖拽全局监听
|
|
|
|
|
|
|
|
document.addEventListener('mousemove', onDocumentMouseMove)
|
|
|
|
|
|
|
|
document.addEventListener('mouseup', onDocumentMouseUp)
|
|
|
|
|
|
|
|
})
|
|
|
|
|
|
|
|
onUnmounted(() => {
|
|
|
|
|
|
|
|
document.removeEventListener('mousemove', onDocumentMouseMove)
|
|
|
|
|
|
|
|
document.removeEventListener('mouseup', onDocumentMouseUp)
|
|
|
|
})
|
|
|
|
})
|
|
|
|
</script>
|
|
|
|
</script>
|
|
|
|
|
|
|
|
|
|
|
|
@ -1206,6 +1645,8 @@
|
|
|
|
border-collapse: collapse;
|
|
|
|
border-collapse: collapse;
|
|
|
|
/* 合并边框 */
|
|
|
|
/* 合并边框 */
|
|
|
|
color: #333;
|
|
|
|
color: #333;
|
|
|
|
|
|
|
|
user-select: none;
|
|
|
|
|
|
|
|
-webkit-user-select: none;
|
|
|
|
|
|
|
|
|
|
|
|
td {
|
|
|
|
td {
|
|
|
|
border: 1px solid #f1f1f1;
|
|
|
|
border: 1px solid #f1f1f1;
|
|
|
|
@ -1386,4 +1827,26 @@
|
|
|
|
display: flex;
|
|
|
|
display: flex;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* 拖拽框选 */
|
|
|
|
|
|
|
|
.drag-selection-overlay {
|
|
|
|
|
|
|
|
position: absolute;
|
|
|
|
|
|
|
|
top: 0;
|
|
|
|
|
|
|
|
left: 0;
|
|
|
|
|
|
|
|
background: rgba(64, 158, 255, 0.12);
|
|
|
|
|
|
|
|
border: 1px solid rgba(64, 158, 255, 0.5);
|
|
|
|
|
|
|
|
pointer-events: none;
|
|
|
|
|
|
|
|
z-index: 10;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
.planInfo_k_selected {
|
|
|
|
|
|
|
|
background-color: #e6f7ff;
|
|
|
|
|
|
|
|
outline: 2px solid #409eff;
|
|
|
|
|
|
|
|
outline-offset: -2px;
|
|
|
|
|
|
|
|
border-radius: 4px;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
.planInfo_k_disabled_selected {
|
|
|
|
|
|
|
|
background-color: #f3e8ff;
|
|
|
|
|
|
|
|
outline: 2px solid #7c3aed;
|
|
|
|
|
|
|
|
outline-offset: -2px;
|
|
|
|
|
|
|
|
border-radius: 4px;
|
|
|
|
|
|
|
|
}
|
|
|
|
</style>
|
|
|
|
</style>
|