diff --git a/Laravel/app/Services/Admin/YeWu/PlanListService.php b/Laravel/app/Services/Admin/YeWu/PlanListService.php
index a7999a9..0245836 100644
--- a/Laravel/app/Services/Admin/YeWu/PlanListService.php
+++ b/Laravel/app/Services/Admin/YeWu/PlanListService.php
@@ -427,97 +427,189 @@ public function GetOptimalPlan($type, $regnum, $entrustids, $episodeid, $appoint
{
date_default_timezone_set('PRC');
$dateRange = config('app.globals.可用号源查询范围');
- $result = [];
- $usedCapacity = []; // 记录已分配的号源容量,key: roster_detail_id, value: 已分配数
- // 遍历日期范围
$startDate = new DateTime();
$endDate = new DateTime();
$endDate->modify('+' . $dateRange . ' day');
+
+ if ($type === 'full_day') {
+ return $this->doFullDayAssign($startDate, $endDate, $regnum, $entrustids, $episodeid, $appointment_type, $items, $scope, $userDeptId);
+ } else {
+ return $this->doOptimalTimeAssign($startDate, $endDate, $regnum, $entrustids, $episodeid, $appointment_type, $items, $scope, $userDeptId);
+ }
+ }
+
+ // 最优时间分配:逐个 item 找最早可用号源,可跨天
+ private function doOptimalTimeAssign($startDate, $endDate, $regnum, $entrustids, $episodeid, $appointment_type, $items, $scope, $userDeptId)
+ {
+ $result = [];
+ $usedCapacity = [];
+ $assignedPlans = []; // 已分配的时间段 [{resource_name, begin, end}]
$currentDate = clone $startDate;
+ $remainingItems = $items;
- while ($currentDate <= $endDate) {
+ while ($currentDate <= $endDate && !empty($remainingItems)) {
$nowdate = $currentDate->format('Y-m-d');
+ $availablePlans = $this->getAvailablePlansForDate($regnum, $entrustids, $episodeid, $appointment_type, $nowdate, $scope, $userDeptId);
- // 获取当前日期的可用号源
- $s = $this->GetEnablePlan($regnum, $entrustids, $episodeid, $appointment_type, $nowdate, $scope, $userDeptId);
-
- if (!$s['status']) {
+ if (empty($availablePlans)) {
$currentDate->modify('+1 day');
continue;
}
- $planList = $s['data']['plan_list'] ?? [];
- if (count($planList) == 0) {
- $currentDate->modify('+1 day');
- continue;
- }
+ $newRemaining = [];
+ foreach ($remainingItems as $item) {
+ $assigned = false;
+ foreach ($availablePlans as $plan) {
+ $planId = $plan->id;
+ $remaining = ($plan->count ?? 0) - ($plan->used_count ?? 0) - ($plan->locked_count ?? 0);
+ $used = $usedCapacity[$planId] ?? 0;
- // 筛选未过期的、可用的号源
- $nowtime = date('Y-m-d H:i:s');
- $availablePlans = [];
- foreach ($planList as $plan) {
- $planEndTime = $plan->date . ' ' . $plan->end_time;
- if ($planEndTime > $nowtime && $plan->plan_enable) {
- $availablePlans[] = $plan;
+ if (($remaining - $used) <= 0) continue;
+
+ // 冲突检查:不同排班且时间段重叠
+ if ($this->isTimeConflict($assignedPlans, $plan)) continue;
+
+ // 分配
+ $result[] = [
+ 'id' => $item['id'],
+ 'plan_id' => $planId,
+ 'department_resources_name' => $plan->department_resources_name,
+ 'date' => $plan->date,
+ 'begin_time' => $plan->begin_time,
+ 'end_time' => $plan->end_time
+ ];
+ $usedCapacity[$planId] = ($usedCapacity[$planId] ?? 0) + 1;
+ $assignedPlans[] = [
+ 'resource_name' => $plan->department_resources_name,
+ 'begin_time' => $plan->begin_time,
+ 'end_time' => $plan->end_time
+ ];
+ $assigned = true;
+ break;
+ }
+ if (!$assigned) {
+ $newRemaining[] = $item;
}
}
+ $remainingItems = $newRemaining;
+ $currentDate->modify('+1 day');
+ }
+
+ return \Yz::Return(true, '获取成功', $result);
+ }
+
+ // 单天全检分配:所有 item 必须在同一天完成
+ private function doFullDayAssign($startDate, $endDate, $regnum, $entrustids, $episodeid, $appointment_type, $items, $scope, $userDeptId)
+ {
+ $currentDate = clone $startDate;
+
+ while ($currentDate <= $endDate) {
+ $nowdate = $currentDate->format('Y-m-d');
+ $availablePlans = $this->getAvailablePlansForDate($regnum, $entrustids, $episodeid, $appointment_type, $nowdate, $scope, $userDeptId);
- if (count($availablePlans) == 0) {
+ if (empty($availablePlans)) {
$currentDate->modify('+1 day');
continue;
}
- // 按日期、时间排序
- usort($availablePlans, function($a, $b) {
- $timeA = $a->date . ' ' . ($a->begin_time ?? '00:00:00');
- $timeB = $b->date . ' ' . ($b->begin_time ?? '00:00:00');
- return $timeA <=> $timeB;
- });
+ $result = [];
+ $usedCapacity = [];
+ $assignedPlans = [];
+ $allAssigned = true;
- // 遍历 items,逐个分配
foreach ($items as $item) {
- // 如果该 item 已经分配,跳过
- $alreadyAssigned = false;
- foreach ($result as $r) {
- if ($r['id'] == $item['id']) {
- $alreadyAssigned = true;
- break;
- }
- }
- if ($alreadyAssigned) continue;
-
- // 找可用号源
+ $assigned = false;
foreach ($availablePlans as $plan) {
$planId = $plan->id;
$remaining = ($plan->count ?? 0) - ($plan->used_count ?? 0) - ($plan->locked_count ?? 0);
$used = $usedCapacity[$planId] ?? 0;
- if (($remaining - $used) > 0) {
- // 分配此号源
- $result[] = [
- 'id' => $item['id'],
- 'plan_id' => $planId,
- 'department_resources_name' => $plan->department_resources_name,
- 'date' => $plan->date,
- 'begin_time' => $plan->begin_time,
- 'end_time' => $plan->end_time
- ];
- $usedCapacity[$planId] = ($usedCapacity[$planId] ?? 0) + 1;
- break;
- }
+ if (($remaining - $used) <= 0) continue;
+
+ // 冲突检查:不同排班且时间段重叠
+ if ($this->isTimeConflict($assignedPlans, $plan)) continue;
+
+ $result[] = [
+ 'id' => $item['id'],
+ 'plan_id' => $planId,
+ 'department_resources_name' => $plan->department_resources_name,
+ 'date' => $plan->date,
+ 'begin_time' => $plan->begin_time,
+ 'end_time' => $plan->end_time
+ ];
+ $usedCapacity[$planId] = ($usedCapacity[$planId] ?? 0) + 1;
+ $assignedPlans[] = [
+ 'resource_name' => $plan->department_resources_name,
+ 'begin_time' => $plan->begin_time,
+ 'end_time' => $plan->end_time
+ ];
+ $assigned = true;
+ break;
+ }
+ if (!$assigned) {
+ $allAssigned = false;
+ break;
}
}
- // 如果所有 items 都已分配,停止遍历
- if (count($result) >= count($items)) {
- break;
+ if ($allAssigned) {
+ return \Yz::Return(true, '获取成功', $result);
}
$currentDate->modify('+1 day');
}
- return \Yz::Return(true, '获取成功', $result);
+ return \Yz::Return(true, '获取成功', []);
+ }
+
+ // 获取指定日期的可用号源(已排序)
+ private function getAvailablePlansForDate($regnum, $entrustids, $episodeid, $appointment_type, $date, $scope, $userDeptId)
+ {
+ $s = $this->GetEnablePlan($regnum, $entrustids, $episodeid, $appointment_type, $date, $scope, $userDeptId);
+ if (!$s['status']) return [];
+
+ $planList = $s['data']['plan_list'] ?? [];
+ if (count($planList) == 0) return [];
+
+ $nowtime = date('Y-m-d H:i:s');
+ $availablePlans = [];
+ foreach ($planList as $plan) {
+ $planEndTime = $plan->date . ' ' . $plan->end_time;
+ if ($planEndTime > $nowtime && $plan->plan_enable) {
+ $availablePlans[] = $plan;
+ }
+ }
+
+ if (count($availablePlans) == 0) return [];
+
+ usort($availablePlans, function($a, $b) {
+ $timeA = $a->date . ' ' . ($a->begin_time ?? '00:00:00');
+ $timeB = $b->date . ' ' . ($b->begin_time ?? '00:00:00');
+ return $timeA <=> $timeB;
+ });
+
+ return $availablePlans;
+ }
+
+ // 冲突检查:同一排班资源允许重叠,不同排班时间不能重叠
+ private function isTimeConflict($assignedPlans, $plan)
+ {
+ foreach ($assignedPlans as $assigned) {
+ if ($assigned['resource_name'] === $plan->department_resources_name) {
+ continue; // 同排班,允许重叠
+ }
+ // 不同排班:检查时间段是否重叠
+ $aStart = $assigned['begin_time'];
+ $aEnd = $assigned['end_time'];
+ $bStart = $plan->begin_time;
+ $bEnd = $plan->end_time;
+ // [aStart, aEnd) ∩ [bStart, bEnd) ≠ ∅ → 冲突
+ if ($aStart < $bEnd && $bStart < $aEnd) {
+ return true;
+ }
+ }
+ return false;
}
//开始预约占用名额
diff --git a/YiJi-admin/src/components/Yewu/YuYue202506.vue b/YiJi-admin/src/components/Yewu/YuYue202506.vue
index a0ebf88..7e0c5e3 100644
--- a/YiJi-admin/src/components/Yewu/YuYue202506.vue
+++ b/YiJi-admin/src/components/Yewu/YuYue202506.vue
@@ -85,7 +85,7 @@