批量修改 启用

main
鹿和sa0ChunLuyu 1 week ago
parent e0b82d5955
commit b8393898fb

@ -905,4 +905,200 @@ public function BatchDisableAdmin(Request $request)
return \Yz::echoError1('批量禁用失败');
}
}
//批量启用计划明细
public function BatchEnable(Request $request)
{
$userid = $request->get('userid');
$userInfo = DB::table('users')->where(['id' => $userid])->get();
$department_id = $userInfo[0]->department_id;
$ids = request('ids');
$u1 = DB::table('s_source_roster_detail')->where(['department_id' => $department_id])->whereIn('id', $ids)->update([
'status' => 1
]);
if ($u1) {
$firstId = !empty($ids) ? $ids[0] : 0;
DB::table('s_source_roster_detail_log')->insert([
'roster_detail_id' => $firstId,
'type' => '批量启用',
'content' => json_encode(['ids' => $ids, 'count' => count($ids)], JSON_UNESCAPED_UNICODE),
'userid' => $userid
]);
return \Yz::Return(true, '批量启用成功', []);
} else {
return \Yz::echoError1('批量启用失败');
}
}
//管理员批量启用计划明细
public function BatchEnableAdmin(Request $request)
{
$userid = $request->get('userid');
$department_id = request('department_id');
if (!$department_id) {
return \Yz::echoError1('科室信息不存在');
}
$ids = request('ids');
$u1 = DB::table('s_source_roster_detail')->where(['department_id' => $department_id])->whereIn('id', $ids)->update([
'status' => 1
]);
if ($u1) {
$firstId = !empty($ids) ? $ids[0] : 0;
DB::table('s_source_roster_detail_log')->insert([
'roster_detail_id' => $firstId,
'type' => '批量启用',
'content' => json_encode(['ids' => $ids, 'count' => count($ids)], JSON_UNESCAPED_UNICODE),
'userid' => $userid
]);
return \Yz::Return(true, '批量启用成功', []);
} else {
return \Yz::echoError1('批量启用失败');
}
}
//批量修改单个号源明细
public function DetailBatchUpdate(Request $request)
{
$userid = $request->get('userid');
$userInfo = DB::table('users')->where(['id' => $userid])->get();
$department_id = $userInfo[0]->department_id;
$id = request('id');
$max_total = request('max_total');
$coutsInfo = request('coutsInfo');
$check = DB::table('s_source_roster_detail')->where(['id' => $id])
->where('department_id', $department_id)
->where('is_del', 0)
->first();
if (!$check) return \Yz::echoError1('没有权限');
$i = 0;
foreach ($coutsInfo as $value) {
$u2 = DB::table('s_source_roster_detail_count')
->where('roster_detail_id', $id)
->where('appointment_type_id', $value['appointment_type_id'])
->update([
'count' => $value['count'] ?? 0,
'locked_count' => $value['locked_count'] ?? 0,
'max_total' => $max_total
]);
if ($u2) $i++;
}
if ($i > 0) {
return \Yz::Return(true, '修改成功', []);
} else {
return \Yz::echoError1('修改失败');
}
}
//管理员批量修改单个号源明细
public function DetailBatchUpdateAdmin(Request $request)
{
$userid = $request->get('userid');
$department_id = request('department_id');
if (!$department_id) {
return \Yz::echoError1('科室信息不存在');
}
$id = request('id');
$max_total = request('max_total');
$coutsInfo = request('coutsInfo');
$check = DB::table('s_source_roster_detail')->where(['id' => $id])
->where('department_id', $department_id)
->where('is_del', 0)
->first();
if (!$check) return \Yz::echoError1('没有权限');
$i = 0;
foreach ($coutsInfo as $value) {
$u2 = DB::table('s_source_roster_detail_count')
->where('roster_detail_id', $id)
->where('appointment_type_id', $value['appointment_type_id'])
->update([
'count' => $value['count'] ?? 0,
'locked_count' => $value['locked_count'] ?? 0,
'max_total' => $max_total
]);
if ($u2) $i++;
}
if ($i > 0) {
return \Yz::Return(true, '修改成功', []);
} else {
return \Yz::echoError1('修改失败');
}
}
//批量修改号源(统一提交)
public function BatchChangeInfo(Request $request)
{
$userid = $request->get('userid');
$userInfo = DB::table('users')->where(['id' => $userid])->get();
$department_id = $userInfo[0]->department_id;
$ids = request('ids');
$max_total = request('max_total');
$coutsInfo = request('coutsInfo');
if (empty($ids) || empty($coutsInfo)) {
return \Yz::echoError1('参数错误');
}
// 用 CASE WHEN 一次更新所有渠道
$appointmentTypeIds = array_column($coutsInfo, 'appointment_type_id');
$countSql = 'CASE appointment_type_id ';
$lockedSql = 'CASE appointment_type_id ';
foreach ($coutsInfo as $v) {
$countSql .= 'WHEN ' . intval($v['appointment_type_id']) . ' THEN ' . intval($v['count'] ?? 0) . ' ';
$lockedSql .= 'WHEN ' . intval($v['appointment_type_id']) . ' THEN ' . intval($v['locked_count'] ?? 0) . ' ';
}
$countSql .= 'END';
$lockedSql .= 'END';
$idsStr = implode(',', array_map('intval', $ids));
$atypeIdsStr = implode(',', array_map('intval', $appointmentTypeIds));
$sql = "UPDATE s_source_roster_detail_count
SET count = {$countSql},
locked_count = {$lockedSql},
max_total = {$max_total}
WHERE roster_detail_id IN ({$idsStr})
AND appointment_type_id IN ({$atypeIdsStr})";
$u2 = DB::update($sql);
if ($u2 > 0) {
return \Yz::Return(true, '批量修改成功', []);
} else {
return \Yz::echoError1('批量修改失败');
}
}
//管理员批量修改号源(统一提交)
public function BatchChangeInfoAdmin(Request $request)
{
$userid = $request->get('userid');
$department_id = request('department_id');
if (!$department_id) {
return \Yz::echoError1('科室信息不存在');
}
$ids = request('ids');
$max_total = request('max_total');
$coutsInfo = request('coutsInfo');
if (empty($ids) || empty($coutsInfo)) {
return \Yz::echoError1('参数错误');
}
// 用 CASE WHEN 一次更新所有渠道
$appointmentTypeIds = array_column($coutsInfo, 'appointment_type_id');
$countSql = 'CASE appointment_type_id ';
$lockedSql = 'CASE appointment_type_id ';
foreach ($coutsInfo as $v) {
$countSql .= 'WHEN ' . intval($v['appointment_type_id']) . ' THEN ' . intval($v['count'] ?? 0) . ' ';
$lockedSql .= 'WHEN ' . intval($v['appointment_type_id']) . ' THEN ' . intval($v['locked_count'] ?? 0) . ' ';
}
$countSql .= 'END';
$lockedSql .= 'END';
$idsStr = implode(',', array_map('intval', $ids));
$atypeIdsStr = implode(',', array_map('intval', $appointmentTypeIds));
$sql = "UPDATE s_source_roster_detail_count
SET count = {$countSql},
locked_count = {$lockedSql},
max_total = {$max_total}
WHERE roster_detail_id IN ({$idsStr})
AND appointment_type_id IN ({$atypeIdsStr})";
$u2 = DB::update($sql);
if ($u2 > 0) {
return \Yz::Return(true, '批量修改成功', []);
} else {
return \Yz::echoError1('批量修改失败');
}
}
}

@ -123,6 +123,12 @@
Route::post('admin/PlanListDel','App\Http\Controllers\API\Admin\YeWu\PlanListController@Del');//删除计划详情
Route::post('admin/PlanListBatchDisable','App\Http\Controllers\API\Admin\YeWu\PlanListController@BatchDisable');//批量禁用
Route::post('admin/PlanListBatchDisableAdmin','App\Http\Controllers\API\Admin\YeWu\PlanListController@BatchDisableAdmin');//管理员批量禁用
Route::post('admin/PlanListBatchEnable','App\Http\Controllers\API\Admin\YeWu\PlanListController@BatchEnable');//批量启用
Route::post('admin/PlanListBatchEnableAdmin','App\Http\Controllers\API\Admin\YeWu\PlanListController@BatchEnableAdmin');//管理员批量启用
Route::post('admin/PlanDetailBatchUpdate','App\Http\Controllers\API\Admin\YeWu\PlanListController@DetailBatchUpdate');//批量修改单个号源明细
Route::post('admin/PlanDetailBatchUpdateAdmin','App\Http\Controllers\API\Admin\YeWu\PlanListController@DetailBatchUpdateAdmin');//管理员批量修改单个号源明细
Route::post('admin/PlanListBatchChangeInfo','App\Http\Controllers\API\Admin\YeWu\PlanListController@BatchChangeInfo');//批量修改号源(统一提交)
Route::post('admin/PlanListBatchChangeInfoAdmin','App\Http\Controllers\API\Admin\YeWu\PlanListController@BatchChangeInfoAdmin');//管理员批量修改号源(统一提交)
Route::post('admin/SaveLockedCount','App\Http\Controllers\API\Admin\YeWu\PlanListController@SaveLockedCount');//保存占位数量
Route::post('admin/GetMainList','App\Http\Controllers\API\Admin\YeWu\WorkMainController@GetList');//获取主表列表
Route::post('admin/GetMainListByDept','App\Http\Controllers\API\Admin\YeWu\WorkMainController@GetListByDept');//管理员获取主表列表(支持科室切换)

@ -375,6 +375,30 @@ export const PlanListBatchDisable = (data = {}) => {
export const PlanListBatchDisableAdmin = (data = {}) => {
return axios({ url: import.meta.env.VITE_APP_API + 'v1/admin/PlanListBatchDisableAdmin', data: data })
}
//批量启用计划明细
export const PlanListBatchEnable = (data = {}) => {
return axios({ url: import.meta.env.VITE_APP_API + 'v1/admin/PlanListBatchEnable', data: data })
}
//批量启用计划明细(管理员接口)
export const PlanListBatchEnableAdmin = (data = {}) => {
return axios({ url: import.meta.env.VITE_APP_API + 'v1/admin/PlanListBatchEnableAdmin', data: data })
}
//批量修改单个号源明细
export const PlanDetailBatchUpdate = (data = {}) => {
return axios({ url: import.meta.env.VITE_APP_API + 'v1/admin/PlanDetailBatchUpdate', data: data })
}
//批量修改单个号源明细(管理员接口)
export const PlanDetailBatchUpdateAdmin = (data = {}) => {
return axios({ url: import.meta.env.VITE_APP_API + 'v1/admin/PlanDetailBatchUpdateAdmin', data: data })
}
//批量修改号源(统一提交)
export const PlanListBatchChangeInfo = (data = {}) => {
return axios({ url: import.meta.env.VITE_APP_API + 'v1/admin/PlanListBatchChangeInfo', data: data })
}
//批量修改号源(管理员统一提交)
export const PlanListBatchChangeInfoAdmin = (data = {}) => {
return axios({ url: import.meta.env.VITE_APP_API + 'v1/admin/PlanListBatchChangeInfoAdmin', data: data })
}
//admin获取主表列表
export const GetMainList = (data = {}) => {
return axios({ url: import.meta.env.VITE_APP_API + 'v1/admin/GetMainList', data: data })

@ -47,6 +47,8 @@
<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="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>
</div>
<div style="display: flex;" class="planInfo">
@ -80,7 +82,7 @@
<div>
<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,'planInfo_k_selected':isSelected(item2.id)}">
: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 class="icon_k" @click="getDetail(item2.id)">
<el-icon color="#409eff" size="20">
@ -297,11 +299,63 @@
</span>
</template>
</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>
</template>
<script setup>
import {
ref,
computed,
onMounted,
onUnmounted
} from 'vue'
@ -315,6 +369,9 @@
PlanListGetDetail,
PlanDetailPlanListDel,
PlanListBatchDisable,
PlanListBatchEnable,
PlanDetailBatchUpdate,
PlanListBatchChangeInfo,
GetPlanUsedList,
SaveLockedCount
} from '@/api/api.js'
@ -759,6 +816,172 @@
})
})
}
const BatchEnable = () => {
if (selectedPlanArr.value.length == 0) {
ElMessage.error('请至少勾选1条记录')
return false
}
ElMessageBox.confirm(
'确定批量启用勾选的号源吗?',
'提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning',
}
).then(() => {
loading.value = true
PlanListBatchEnable({
ids: selectedPlanArr.value
}).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 PlanListBatchChangeInfo({
ids: ids,
max_total: maxTotal,
coutsInfo: coutsInfo
})
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 MingXiLoading = ref(false)
let MingXiList = ref(null);
@ -1144,4 +1367,10 @@
outline-offset: -2px;
border-radius: 4px;
}
.planInfo_k_disabled_selected {
background-color: #f3e8ff;
outline: 2px solid #7c3aed;
outline-offset: -2px;
border-radius: 4px;
}
</style>

@ -47,6 +47,8 @@
<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="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>
</div>
<div style="display: flex;" class="planInfo">
@ -56,7 +58,7 @@
{{item.department_resources_name}}
</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>
<table class="planTable" v-if="planTableData.length>0">
<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>
</tr>
<tr v-for="(item,index) in planTableData" :key="index">
<td v-for="(item2,index2) in item" :key="index2" @mouseover="showTools(item2.id)"
@mouseleave="hideTools(item2.id)">
<td v-for="(item2,index2) in item" :key="index2"
:data-row="index" :data-col="index2"
@mouseover="onCellHover($event, item2, index, index2)"
@mouseleave="onCellLeave(item2.id)"
@mousedown="onCellMouseDown($event, item2, index, index2)">
<div>
<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}">
: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 class="icon_k" @click="getDetail(item2.id)">
<el-icon color="#409eff" size="20">
@ -121,7 +126,8 @@
</td>
</tr>
</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="暂无号源" />
</div>
</div>
@ -293,12 +299,65 @@
</span>
</template>
</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>
</template>
<script setup>
import {
ref,
onMounted
computed,
onMounted,
onUnmounted
} from 'vue'
import {
PlanListGetList,
@ -310,6 +369,9 @@
PlanListGetDetail,
PlanDetailPlanListDelAdmin,
PlanListBatchDisableAdmin,
PlanListBatchEnableAdmin,
PlanDetailBatchUpdateAdmin,
PlanListBatchChangeInfoAdmin,
GetPlanUsedList,
SaveLockedCount
} from '@/api/api.js'
@ -441,12 +503,100 @@
}
};
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) => {
hoverIndex.value = index
}
const hideTools = (index) => {
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) => {
ResourceActive.value = zhenshi
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 MingXiLoading = ref(false)
let MingXiList = ref(null);
@ -824,6 +1142,13 @@
searchInfo.value.dateRange = [todayStr, fifteenDaysLaterStr]
GetDepartmentEnableList()
GetEnableDeviceListFunc()
//
document.addEventListener('mousemove', onDocumentMouseMove)
document.addEventListener('mouseup', onDocumentMouseUp)
})
onUnmounted(() => {
document.removeEventListener('mousemove', onDocumentMouseMove)
document.removeEventListener('mouseup', onDocumentMouseUp)
})
</script>
<style lang="scss" scoped>
@ -984,6 +1309,8 @@
border-collapse: collapse;
/* 合并边框 */
color: #333;
user-select: none;
-webkit-user-select: none;
td {
border: 1px solid #f1f1f1;
@ -1039,4 +1366,26 @@
.bold-text{
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>
Loading…
Cancel
Save