|
|
|
@ -47,6 +47,8 @@
|
|
|
|
<el-button @click="GetList()" style="margin-left: 10px;">搜索</el-button>
|
|
|
|
<el-button @click="GetList()" 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="warning" @click="BatchDisable()" style="margin-left: 10px;">批量禁用</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-row>
|
|
|
|
</el-row>
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
<div style="display: flex;" class="planInfo">
|
|
|
|
<div style="display: flex;" class="planInfo">
|
|
|
|
@ -56,7 +58,7 @@
|
|
|
|
{{item.department_resources_name}}
|
|
|
|
{{item.department_resources_name}}
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
<div v-loading="loading" style="border: 1px solid #efefef;width: 100%; overflow-x: auto;">
|
|
|
|
<div v-loading="loading" ref="scrollContainer" style="border: 1px solid #efefef;width: 100%; overflow-x: auto; position: relative;">
|
|
|
|
<div style="text-align: right; padding: 8px; font-size: 12px; color: #999;">数据格式:占位/已用/总数</div>
|
|
|
|
<div style="text-align: right; padding: 8px; font-size: 12px; color: #999;">数据格式:占位/已用/总数</div>
|
|
|
|
<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;">
|
|
|
|
@ -72,12 +74,15 @@
|
|
|
|
<td style="min-width: 120px;font-size: 14px;" v-for="(item,index) in date_list">{{item.substring(5,10)}} {{getWeekday(item)}}</td>
|
|
|
|
<td style="min-width: 120px;font-size: 14px;" v-for="(item,index) in date_list">{{item.substring(5,10)}} {{getWeekday(item)}}</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)">
|
|
|
|
<div>
|
|
|
|
<div>
|
|
|
|
<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"
|
|
|
|
<div v-if="item2.countsInfo && item2.countsInfo.length>0"
|
|
|
|
:class="{'planInfo_k':item2.status==1,'planInfo_k planInfo_k_disabled':item2.status==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="getDetail(item2.id)">
|
|
|
|
<div class="icon_k" @click="getDetail(item2.id)">
|
|
|
|
<el-icon color="#409eff" size="20">
|
|
|
|
<el-icon color="#409eff" size="20">
|
|
|
|
@ -121,7 +126,8 @@
|
|
|
|
</td>
|
|
|
|
</td>
|
|
|
|
</tr>
|
|
|
|
</tr>
|
|
|
|
</table>
|
|
|
|
</table>
|
|
|
|
<div v-if="planTableData.length==0" style="width: 100%;background-color: #fff;">
|
|
|
|
<div v-if="isDragging" class="drag-selection-overlay" :style="dragOverlayStyle"></div>
|
|
|
|
|
|
|
|
<div v-if="planTableData.length==0" style="width: 100%;background-color: #fff;">>
|
|
|
|
<el-empty description="暂无号源" />
|
|
|
|
<el-empty description="暂无号源" />
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
@ -293,12 +299,65 @@
|
|
|
|
</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="4">渠道名称</el-col>
|
|
|
|
|
|
|
|
<el-col :span="8">数量</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="4" 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-col :span="8">
|
|
|
|
|
|
|
|
<el-input v-model.number="batchForm[ci].locked_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="4" style="line-height: 32px; font-weight: 600;">合计</el-col>
|
|
|
|
|
|
|
|
<el-col :span="8" style="line-height: 32px; font-weight: 600;">数量: {{ batchTotalCount }}</el-col>
|
|
|
|
|
|
|
|
<el-col :span="8" style="line-height: 32px; font-weight: 600;">占用: {{ batchTotalLocked }}</el-col>
|
|
|
|
|
|
|
|
</el-row>
|
|
|
|
|
|
|
|
</el-form>
|
|
|
|
|
|
|
|
</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="BatchErrorDialogVisible" title="修改结果" width="40%">
|
|
|
|
|
|
|
|
<div>
|
|
|
|
|
|
|
|
<div style="margin-bottom: 10px;">
|
|
|
|
|
|
|
|
成功: <span style="color: #67c23a; font-weight: 600;">{{ batchSuccessCount }}</span> 条
|
|
|
|
|
|
|
|
失败: <span style="color: #f56c6c; font-weight: 600;">{{ batchErrorList.length }}</span> 条
|
|
|
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
<div v-if="batchErrorList.length > 0">
|
|
|
|
|
|
|
|
<div v-for="(err, ei) in batchErrorList" :key="ei"
|
|
|
|
|
|
|
|
style="padding: 4px 0; font-size: 13px; color: #f56c6c;">
|
|
|
|
|
|
|
|
第 {{ err.index + 1 }} 条(ID: {{ err.id }}) → {{ err.msg }}
|
|
|
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
<template #footer>
|
|
|
|
|
|
|
|
<el-button type="primary" @click="BatchErrorDialogVisible = false; GetList()">确定</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 {
|
|
|
|
PlanListGetList,
|
|
|
|
PlanListGetList,
|
|
|
|
@ -310,6 +369,9 @@
|
|
|
|
PlanListGetDetail,
|
|
|
|
PlanListGetDetail,
|
|
|
|
PlanDetailPlanListDelAdmin,
|
|
|
|
PlanDetailPlanListDelAdmin,
|
|
|
|
PlanListBatchDisableAdmin,
|
|
|
|
PlanListBatchDisableAdmin,
|
|
|
|
|
|
|
|
PlanListBatchEnableAdmin,
|
|
|
|
|
|
|
|
PlanDetailBatchUpdateAdmin,
|
|
|
|
|
|
|
|
PlanListBatchChangeInfoAdmin,
|
|
|
|
GetPlanUsedList,
|
|
|
|
GetPlanUsedList,
|
|
|
|
SaveLockedCount
|
|
|
|
SaveLockedCount
|
|
|
|
} from '@/api/api.js'
|
|
|
|
} from '@/api/api.js'
|
|
|
|
@ -441,12 +503,100 @@
|
|
|
|
}
|
|
|
|
}
|
|
|
|
};
|
|
|
|
};
|
|
|
|
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,
|
|
|
|
|
|
|
|
y: event.clientY - containerRect.top
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
// 清空原有选中,选中当前格子
|
|
|
|
|
|
|
|
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
|
|
|
|
|
|
|
|
const currentY = event.clientY - containerRect.top
|
|
|
|
|
|
|
|
// 更新拖拽矩形样式
|
|
|
|
|
|
|
|
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 = date_list.value[c - 1]
|
|
|
|
|
|
|
|
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 = {}
|
|
|
|
|
|
|
|
}
|
|
|
|
const zhenshiClick = (zhenshi) => {
|
|
|
|
const zhenshiClick = (zhenshi) => {
|
|
|
|
ResourceActive.value = zhenshi
|
|
|
|
ResourceActive.value = zhenshi
|
|
|
|
PlanSelectedAll.value = 0
|
|
|
|
PlanSelectedAll.value = 0
|
|
|
|
@ -679,6 +829,174 @@
|
|
|
|
})
|
|
|
|
})
|
|
|
|
})
|
|
|
|
})
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
const BatchEnable = () => {
|
|
|
|
|
|
|
|
if (selectedPlanArr.value.length == 0) {
|
|
|
|
|
|
|
|
ElMessage.error('请至少勾选1条记录')
|
|
|
|
|
|
|
|
return false
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
ElMessageBox.confirm(
|
|
|
|
|
|
|
|
'确定批量启用勾选的号源吗?',
|
|
|
|
|
|
|
|
'提示', {
|
|
|
|
|
|
|
|
confirmButtonText: '确定',
|
|
|
|
|
|
|
|
cancelButtonText: '取消',
|
|
|
|
|
|
|
|
type: 'warning',
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
).then(() => {
|
|
|
|
|
|
|
|
loading.value = true
|
|
|
|
|
|
|
|
PlanListBatchEnableAdmin({
|
|
|
|
|
|
|
|
ids: selectedPlanArr.value,
|
|
|
|
|
|
|
|
department_id: searchInfo.value.department_id
|
|
|
|
|
|
|
|
}).then(res => {
|
|
|
|
|
|
|
|
loading.value = false
|
|
|
|
|
|
|
|
if (res.status) {
|
|
|
|
|
|
|
|
ElMessage({
|
|
|
|
|
|
|
|
message: '批量启用成功',
|
|
|
|
|
|
|
|
type: 'success',
|
|
|
|
|
|
|
|
})
|
|
|
|
|
|
|
|
GetList()
|
|
|
|
|
|
|
|
} else {
|
|
|
|
|
|
|
|
ElMessage.error(res.msg)
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
})
|
|
|
|
|
|
|
|
})
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
// 批量修改状态
|
|
|
|
|
|
|
|
let BatchModifyDialogVisible = ref(false)
|
|
|
|
|
|
|
|
let batchModifyRunning = ref(false)
|
|
|
|
|
|
|
|
let batchProgress = ref(0)
|
|
|
|
|
|
|
|
let batchCurrent = ref(0)
|
|
|
|
|
|
|
|
let batchTotal = ref(0)
|
|
|
|
|
|
|
|
let batchSuccessCount = ref(0)
|
|
|
|
|
|
|
|
let BatchErrorDialogVisible = ref(false)
|
|
|
|
|
|
|
|
let batchErrorList = ref([])
|
|
|
|
|
|
|
|
const batchChannels = [
|
|
|
|
|
|
|
|
{ name: '医生', id: 1 },
|
|
|
|
|
|
|
|
{ name: '护士站', id: 4 },
|
|
|
|
|
|
|
|
{ name: '微信', id: 2 },
|
|
|
|
|
|
|
|
{ name: '自助机', id: 3 }
|
|
|
|
|
|
|
|
]
|
|
|
|
|
|
|
|
let batchForm = ref([])
|
|
|
|
|
|
|
|
const initBatchForm = () => {
|
|
|
|
|
|
|
|
batchForm.value = batchChannels.map(ch => ({
|
|
|
|
|
|
|
|
appointment_type_id: ch.id,
|
|
|
|
|
|
|
|
count: '',
|
|
|
|
|
|
|
|
locked_count: ''
|
|
|
|
|
|
|
|
}))
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
initBatchForm()
|
|
|
|
|
|
|
|
const batchTotalCount = computed(() => {
|
|
|
|
|
|
|
|
return batchForm.value.reduce((s, item) => s + (Number(item.count) || 0), 0)
|
|
|
|
|
|
|
|
})
|
|
|
|
|
|
|
|
const batchTotalLocked = computed(() => {
|
|
|
|
|
|
|
|
return batchForm.value.reduce((s, item) => s + (Number(item.locked_count) || 0), 0)
|
|
|
|
|
|
|
|
})
|
|
|
|
|
|
|
|
const openBatchModify = () => {
|
|
|
|
|
|
|
|
if (selectedPlanArr.value.length == 0) {
|
|
|
|
|
|
|
|
ElMessage.error('请至少勾选1条记录')
|
|
|
|
|
|
|
|
return
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
initBatchForm()
|
|
|
|
|
|
|
|
// 从 planTableData 中提取已选号源的各渠道值
|
|
|
|
|
|
|
|
const selectedIds = new Set(selectedPlanArr.value)
|
|
|
|
|
|
|
|
const channelValues = {} // { appointment_type_id: { count: [], locked_count: [] } }
|
|
|
|
|
|
|
|
batchChannels.forEach(ch => {
|
|
|
|
|
|
|
|
channelValues[ch.id] = { count: [], locked_count: [] }
|
|
|
|
|
|
|
|
})
|
|
|
|
|
|
|
|
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 (channelValues[ci.appointment_type_id]) {
|
|
|
|
|
|
|
|
channelValues[ci.appointment_type_id].count.push(ci.count)
|
|
|
|
|
|
|
|
channelValues[ci.appointment_type_id].locked_count.push(ci.locked_count)
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
})
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
})
|
|
|
|
|
|
|
|
// 回填:同值回填,异值留空
|
|
|
|
|
|
|
|
batchForm.value = batchChannels.map(ch => {
|
|
|
|
|
|
|
|
const vals = channelValues[ch.id]
|
|
|
|
|
|
|
|
const allSame = arr => arr.length > 0 && arr.every(v => v === arr[0])
|
|
|
|
|
|
|
|
return {
|
|
|
|
|
|
|
|
appointment_type_id: ch.id,
|
|
|
|
|
|
|
|
count: vals.count.length > 0 && allSame(vals.count) ? vals.count[0] : '',
|
|
|
|
|
|
|
|
locked_count: vals.locked_count.length > 0 && allSame(vals.locked_count) ? vals.locked_count[0] : ''
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
})
|
|
|
|
|
|
|
|
batchProgress.value = 0
|
|
|
|
|
|
|
|
batchCurrent.value = 0
|
|
|
|
|
|
|
|
batchTotal.value = selectedPlanArr.value.length
|
|
|
|
|
|
|
|
batchSuccessCount.value = 0
|
|
|
|
|
|
|
|
batchErrorList.value = []
|
|
|
|
|
|
|
|
batchModifyRunning.value = false
|
|
|
|
|
|
|
|
BatchModifyDialogVisible.value = true
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
const execBatchModify = async () => {
|
|
|
|
|
|
|
|
// 校验
|
|
|
|
|
|
|
|
for (const item of batchForm.value) {
|
|
|
|
|
|
|
|
const count = Number(item.count)
|
|
|
|
|
|
|
|
const locked = Number(item.locked_count)
|
|
|
|
|
|
|
|
if (count < 0 || locked < 0) {
|
|
|
|
|
|
|
|
ElMessage.error('数量不能为负数')
|
|
|
|
|
|
|
|
return
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
if (locked > count) {
|
|
|
|
|
|
|
|
const chName = batchChannels.find(c => c.id === item.appointment_type_id)?.name || ''
|
|
|
|
|
|
|
|
ElMessage.error(`${chName} 的占用数量不能大于数量`)
|
|
|
|
|
|
|
|
return
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
// 全部为 0 或空时二次确认
|
|
|
|
|
|
|
|
const allZero = batchForm.value.every(item => Number(item.count) === 0)
|
|
|
|
|
|
|
|
if (allZero) {
|
|
|
|
|
|
|
|
const confirm = await ElMessageBox.confirm(
|
|
|
|
|
|
|
|
'所有渠道数量均为0,确定继续修改吗?',
|
|
|
|
|
|
|
|
'提示',
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
confirmButtonText: '确定',
|
|
|
|
|
|
|
|
cancelButtonText: '取消',
|
|
|
|
|
|
|
|
type: 'warning'
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
).then(() => true).catch(() => false)
|
|
|
|
|
|
|
|
if (!confirm) return
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
const maxTotal = batchTotalCount.value
|
|
|
|
|
|
|
|
batchModifyRunning.value = true
|
|
|
|
|
|
|
|
batchProgress.value = 0
|
|
|
|
|
|
|
|
batchCurrent.value = 0
|
|
|
|
|
|
|
|
batchErrorList.value = []
|
|
|
|
|
|
|
|
batchSuccessCount.value = 0
|
|
|
|
|
|
|
|
const ids = [...selectedPlanArr.value]
|
|
|
|
|
|
|
|
const coutsInfo = batchForm.value.map(item => ({
|
|
|
|
|
|
|
|
appointment_type_id: item.appointment_type_id,
|
|
|
|
|
|
|
|
count: Number(item.count) || 0,
|
|
|
|
|
|
|
|
locked_count: Number(item.locked_count) || 0
|
|
|
|
|
|
|
|
}))
|
|
|
|
|
|
|
|
batchModifyRunning.value = true
|
|
|
|
|
|
|
|
try {
|
|
|
|
|
|
|
|
const res = await PlanListBatchChangeInfoAdmin({
|
|
|
|
|
|
|
|
ids: ids,
|
|
|
|
|
|
|
|
max_total: maxTotal,
|
|
|
|
|
|
|
|
coutsInfo: coutsInfo,
|
|
|
|
|
|
|
|
department_id: searchInfo.value.department_id
|
|
|
|
|
|
|
|
})
|
|
|
|
|
|
|
|
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('请求异常')
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
let MingXiDialogVisible = ref(false);
|
|
|
|
let MingXiDialogVisible = ref(false);
|
|
|
|
let MingXiLoading = ref(false)
|
|
|
|
let MingXiLoading = ref(false)
|
|
|
|
let MingXiList = ref(null);
|
|
|
|
let MingXiList = ref(null);
|
|
|
|
@ -824,6 +1142,13 @@
|
|
|
|
searchInfo.value.dateRange = [todayStr, fifteenDaysLaterStr]
|
|
|
|
searchInfo.value.dateRange = [todayStr, fifteenDaysLaterStr]
|
|
|
|
GetDepartmentEnableList()
|
|
|
|
GetDepartmentEnableList()
|
|
|
|
GetEnableDeviceListFunc()
|
|
|
|
GetEnableDeviceListFunc()
|
|
|
|
|
|
|
|
// 拖拽全局监听
|
|
|
|
|
|
|
|
document.addEventListener('mousemove', onDocumentMouseMove)
|
|
|
|
|
|
|
|
document.addEventListener('mouseup', onDocumentMouseUp)
|
|
|
|
|
|
|
|
})
|
|
|
|
|
|
|
|
onUnmounted(() => {
|
|
|
|
|
|
|
|
document.removeEventListener('mousemove', onDocumentMouseMove)
|
|
|
|
|
|
|
|
document.removeEventListener('mouseup', onDocumentMouseUp)
|
|
|
|
})
|
|
|
|
})
|
|
|
|
</script>
|
|
|
|
</script>
|
|
|
|
<style lang="scss" scoped>
|
|
|
|
<style lang="scss" scoped>
|
|
|
|
@ -984,6 +1309,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;
|
|
|
|
@ -1039,4 +1366,26 @@
|
|
|
|
.bold-text{
|
|
|
|
.bold-text{
|
|
|
|
font-weight: bold;
|
|
|
|
font-weight: bold;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* 拖拽框选 */
|
|
|
|
|
|
|
|
.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>
|