预约优化

main
鹿和sa0ChunLuyu 2 weeks ago
parent 5b4862ba49
commit 8c42dcc4f5

@ -399,21 +399,36 @@ public function CheckIsDaiJian()
{
$reg_num= request('reg_num');
$planid=request('planid');
$plan=DB::table('s_source_roster_detail')->where(['id'=>$planid])->first();
if(!$plan) return \Yz::JsonReturn(true,'可以预约',[]);
$planTime=[$plan->date.' '.$plan->begin_time,$plan->date.' '.$plan->end_time];
$query=DB::table('s_list')->where(['reg_num'=>$reg_num,'list_status'=>1,'is_nullify'=>0])
->select('s_list.*','s_period.period_begin_time','s_period.period_end_time')
->select('s_list.*','s_period.period_begin_time','s_period.period_end_time','s_department_resources.department_resources_name')
->leftJoin('s_period','s_list.reservation_time','=','s_period.id')
->leftJoin('s_department_resources','s_list.reservation_sources','=','s_department_resources.id')
->get();
if(count($query)>0){
$plan=DB::table('s_source_roster_detail')->where(['id'=>$planid])->first();
foreach ($query as $key=>$value){
$conflicts = [];
foreach ($query as $value){
$entrustTime=[$value->reservation_date.' '.$value->period_begin_time,$value->reservation_date.' '.$value->period_end_time];
$planTime=[$plan->date.' '.$plan->begin_time,$plan->date.' '.$plan->end_time];
if ($entrustTime[0] <= $planTime[1] && $planTime[0] <= $entrustTime[1]) {
return \Yz::echoError1('当前时段存在待检项目:'.$value->entrust.',时间:'.$value->reservation_date.' '.substr($value->period_begin_time, 0, 5).'-'.substr($value->period_end_time, 0, 5).' 请确认是否继续预约');
$conflicts[] = [
'entrust' => $value->entrust,
'date' => $value->reservation_date,
'begin_time' => substr($value->period_begin_time, 0, 5),
'end_time' => substr($value->period_end_time, 0, 5),
'room_name' => $value->department_resources_name ?? '',
];
}
}
if (!empty($conflicts)) {
return \Yz::JsonReturn(false, '存在时段冲突', ['conflicts' => $conflicts]);
}
return \Yz::Return(true,'可以预约',[]);
return \Yz::JsonReturn(true,'可以预约',[]);
}
public function NoPayCancel()
{

@ -466,6 +466,7 @@ private function doOptimalTimeAssign($startDate, $endDate, $regnum, $entrustids,
while ($currentDate <= $endDate && !empty($remainingGroups)) {
$nowdate = $currentDate->format('Y-m-d');
$newRemainingGroups = [];
$globalAssignedPlans = []; // 跨科室组的全局已分配时间段
foreach ($remainingGroups as $deptCode => $group) {
$groupEntrustids = $group['entrustids'];
@ -502,6 +503,8 @@ private function doOptimalTimeAssign($startDate, $endDate, $regnum, $entrustids,
// 冲突检查:同一科室组内,不同排班时间不能重叠
if ($this->isTimeConflict($assignedPlans, $plan)) continue;
// 冲突检查:跨科室组,时间段不能重叠
if ($this->isTimeConflict($globalAssignedPlans, $plan)) continue;
$result[] = [
'id' => $item['id'],
@ -517,6 +520,11 @@ private function doOptimalTimeAssign($startDate, $endDate, $regnum, $entrustids,
'begin_time' => $plan->begin_time,
'end_time' => $plan->end_time
];
$globalAssignedPlans[] = [
'resource_name' => $plan->department_resources_name,
'begin_time' => $plan->begin_time,
'end_time' => $plan->end_time
];
$assigned = true;
break;
}

@ -179,6 +179,22 @@
<el-button type="primary" @click="crossTimeDialogVisible = false">确定</el-button>
</template>
</el-dialog>
<el-dialog v-model="conflictDialogVisible" title="时段冲突" width="800">
<div style="display: flex; align-items: flex-start; gap: 12px;">
<el-icon style="color: #F56C6C; font-size: 24px; flex-shrink: 0; margin-top: 2px;">
<WarningFilled />
</el-icon>
<div>
<p style="margin: 0 0 12px 0; font-weight: 700;">
以下项目与当前选择的时间段存在冲突请确认是否继续预约
</p>
<div v-html="conflictDialogHtml"></div>
</div>
</div>
<template #footer>
<el-button type="primary" @click="conflictDialogVisible = false">确定</el-button>
</template>
</el-dialog>
<el-dialog v-model="resultDialogVisible" title="预约结果" width="800">
<div style="display: flex; align-items: flex-start; gap: 12px;">
<el-icon style="color: #e6a23c; font-size: 24px; flex-shrink: 0; margin-top: 2px;">
@ -276,6 +292,8 @@
let crossTimeDialogVisible = ref(false)
let crossTimeDialogHtml = ref('')
let cachedCrossDialogData = ref(null) // dialog { html, idx }
let conflictDialogVisible = ref(false)
let conflictDialogHtml = ref('')
let resultDialogVisible = ref(false)
let resultDialogHtml = ref('')
const getWeekday = (date1) => {
@ -1231,28 +1249,67 @@
}
const checkDaijianFuc = () => {
planLoading.value = true
//
const selectedPlan = cachedPlans.value.find(p => p.id === selectedPlanId.value)
if (!selectedPlan) {
planLoading.value = false
return
}
const planStart = selectedPlan.date + ' ' + selectedPlan.begin_time
const planEnd = selectedPlan.date + ' ' + selectedPlan.end_time
const currentRoom = selectedPlan.department_resources_name
CheckIsDaiJian({
reg_num: props.reg_num,
planid: selectedPlanId.value
}).then(res => {
planLoading.value = false
if (res.status) {
let allConflicts = []
} else {
ElMessageBox.confirm(
res.msg,
'提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning',
}
//
if (!res.status && res.data?.conflicts) {
allConflicts = allConflicts.concat(
res.data.conflicts.filter(c => c.room_name !== currentRoom)
)
.then(() => {
}
//
entrustTableDate.value.forEach(item => {
if (item.list_status !== 0 || !item.temp_plan_id || !item.reservation_date) return
const itemRoom = item.department_resources?.department_resources_name
if (itemRoom === currentRoom) return //
const itemStart = item.reservation_date + ' ' + item.period_begin_time
const itemEnd = item.reservation_date + ' ' + item.period_end_time
if (itemStart <= planEnd && planStart <= itemEnd) {
const exists = allConflicts.some(c =>
c.entrust === item.entrust && c.date === item.reservation_date
)
if (!exists) {
allConflicts.push({
entrust: item.entrust,
date: item.reservation_date,
begin_time: item.period_begin_time?.substring(0, 5),
end_time: item.period_end_time?.substring(0, 5),
room_name: item.department_resources?.department_resources_name || '',
})
}
}
})
.catch(() => {
// 使 dialog
if (allConflicts.length > 0) {
let msg = '<table style="width:100%;border-collapse:collapse;font-size:14px;">'
msg += '<tr style="background:#f5f5f5;"><td style="padding:4px 8px;border:1px solid #ddd;font-weight:700;">序号</td><td style="padding:4px 8px;border:1px solid #ddd;font-weight:700;">项目名称</td><td style="padding:4px 8px;border:1px solid #ddd;font-weight:700;">检查室</td><td style="padding:4px 8px;border:1px solid #ddd;font-weight:700;">日期</td><td style="padding:4px 8px;border:1px solid #ddd;font-weight:700;">时间段</td></tr>'
allConflicts.forEach((c, i) => {
msg += '<tr><td style="padding:4px 8px;border:1px solid #ddd;">' + (i + 1) + '</td><td style="padding:4px 8px;border:1px solid #ddd;">' + c.entrust + '</td><td style="padding:4px 8px;border:1px solid #ddd;">' + (c.room_name || '') + '</td><td style="padding:4px 8px;border:1px solid #ddd;">' + c.date + '</td><td style="padding:4px 8px;border:1px solid #ddd;">' + c.begin_time + '-' + c.end_time + '</td></tr>'
})
msg += '</table>'
conflictDialogHtml.value = msg
conflictDialogVisible.value = true
} else {
//
//
}
})
}

Loading…
Cancel
Save