diff --git a/Laravel/app/Services/Admin/YeWu/PlanListService.php b/Laravel/app/Services/Admin/YeWu/PlanListService.php index 811c106..1256632 100644 --- a/Laravel/app/Services/Admin/YeWu/PlanListService.php +++ b/Laravel/app/Services/Admin/YeWu/PlanListService.php @@ -156,46 +156,49 @@ public function GetEnablePlan($regnum, $entrustids, $episodeid, $appointment_typ $appointment_dates_placeholders = implode(',', array_fill(0, count($appointment_date_arr), '?')); if ($isDeviceMode) { - //设备模式:不限制科室,只按单渠道查号源,渠道合路后置处理 + //设备模式:以排班资源为主表,LEFT JOIN 排班明细 + $patientType = $commPatientType[0] ?? '0'; if ($useScopeDept && !empty($deptIds)) { $deptPlaceholders = implode(',', array_fill(0, count($deptIds), '?')); - $canshu = array_merge($commonDevice, $appointment_date_arr, $deptIds, [$appointment_type]); - $deptCondition = "AND a.department_id IN ($deptPlaceholders)"; + $canshu = array_merge($commonDevice, [$patientType], $appointment_date_arr, [$appointment_type], $commonDevice, $deptIds); + $deptCondition = "AND b.department_id IN ($deptPlaceholders)"; } else { - $canshu = array_merge($commonDevice, $appointment_date_arr, [$appointment_type]); + $canshu = array_merge($commonDevice, [$patientType], $appointment_date_arr, [$appointment_type], $commonDevice); $deptCondition = ''; } $plan = DB::select("SELECT - a.*, - dd.devices, + b.id AS resource_id, b.department_resources_name, + b.department_id AS resource_department_id, + dept.department_number, + a.*, c.roster_detail_id, c.count, c.used_count, - c.locked_count + c.locked_count, + dd.devices FROM - s_source_roster_detail AS a - LEFT JOIN s_department_resources AS b ON a.resources_id = b.id - LEFT JOIN s_source_roster_detail_count AS c ON a.id = c.roster_detail_id - JOIN ( + s_department_resources AS b + JOIN s_department_resources_device AS rd ON b.id = rd.rsourece_id AND rd.device_id IN ($placeholders) + LEFT JOIN s_department AS dept ON b.department_id = dept.id + LEFT JOIN s_source_roster_detail AS a ON a.resources_id = b.id AND FIND_IN_SET(?, a.patient_type) AND a.date IN ($appointment_dates_placeholders) AND a.is_del = 0 + LEFT JOIN s_source_roster_detail_count AS c ON c.roster_detail_id = a.id AND c.appointment_type_id = ? + LEFT JOIN ( SELECT - roster_detail_id, + rd2.rsourece_id, GROUP_CONCAT( e.device_name SEPARATOR ', ' ) AS devices FROM - s_source_roster_detail_device AS d - LEFT JOIN s_devices AS e ON d.device_id = e.id + s_department_resources_device AS rd2 + LEFT JOIN s_devices AS e ON rd2.device_id = e.id WHERE - d.device_id IN ($placeholders) + rd2.device_id IN ($placeholders) GROUP BY - d.roster_detail_id - ) AS dd ON a.id = dd.roster_detail_id + rd2.rsourece_id + ) AS dd ON b.id = dd.rsourece_id WHERE - a.date IN ($appointment_dates_placeholders) - $deptCondition - AND a.STATUS = 1 - AND a.is_del = 0 - AND b.is_del = 0 + b.is_del = 0 AND b.appointment_enabled = 1 + $deptCondition AND ( b.execute_department_id IS NULL OR b.execute_department_id = 0 @@ -206,55 +209,59 @@ public function GetEnablePlan($regnum, $entrustids, $episodeid, $appointment_typ AND appointment_enabled = 1 AND department_status = 1 ) - ) - AND c.appointment_type_id = ?", $canshu); + )", $canshu); foreach ($plan as $p) { - $p->used_count = $p->used_count + ($p->locked_count ?? 0); + if (!empty($p->id)) { + $p->used_count = $p->used_count + ($p->locked_count ?? 0); + } } $plan = $this->mergeChannelsPerDepartment($plan, $appointment_type); } else { - //科室模式:原有逻辑 + //科室模式:以排班资源为主表,LEFT JOIN 排班明细 + $patientType = $commPatientType[0] ?? '0'; if ($useScopeDept) { $deptPlaceholders = implode(',', array_fill(0, count($deptIds), '?')); - $canshu = array_merge($commonDevice, $deptIds, $appointment_date_arr, $appointment_types); - $deptCondition = "a.department_id IN ($deptPlaceholders)"; + $canshu = array_merge($commonDevice, [$patientType], $appointment_date_arr, $appointment_types, $commonDevice, $deptIds); + $deptCondition = "b.department_id IN ($deptPlaceholders)"; } else { - $canshu = array_merge($commonDevice, [$department_id->id], $appointment_date_arr, $appointment_types); - $deptCondition = "a.department_id = ?"; + $canshu = array_merge($commonDevice, [$patientType], $appointment_date_arr, $appointment_types, $commonDevice, [$department_id->id]); + $deptCondition = "b.department_id = ?"; } $plan = DB::select("SELECT - a.*, - dd.devices, + b.id AS resource_id, b.department_resources_name, + b.department_id AS resource_department_id, + dept.department_number, + a.*, c.roster_detail_id, c.count, c.used_count, - c.locked_count + c.locked_count, + dd.devices FROM - s_source_roster_detail AS a - LEFT JOIN s_department_resources AS b ON a.resources_id = b.id - LEFT JOIN s_source_roster_detail_count AS c ON a.id = c.roster_detail_id - JOIN ( + s_department_resources AS b + JOIN s_department_resources_device AS rd ON b.id = rd.rsourece_id AND rd.device_id IN ($placeholders) + LEFT JOIN s_department AS dept ON b.department_id = dept.id + LEFT JOIN s_source_roster_detail AS a ON a.resources_id = b.id AND FIND_IN_SET(?, a.patient_type) AND a.date IN ($appointment_dates_placeholders) AND a.is_del = 0 + LEFT JOIN s_source_roster_detail_count AS c ON c.roster_detail_id = a.id AND c.appointment_type_id IN ($appointment_types_placeholders) + LEFT JOIN ( SELECT - roster_detail_id, + rd2.rsourece_id, GROUP_CONCAT( e.device_name SEPARATOR ', ' ) AS devices FROM - s_source_roster_detail_device AS d - LEFT JOIN s_devices AS e ON d.device_id = e.id + s_department_resources_device AS rd2 + LEFT JOIN s_devices AS e ON rd2.device_id = e.id WHERE - d.device_id IN ($placeholders) + rd2.device_id IN ($placeholders) GROUP BY - d.roster_detail_id - ) AS dd ON a.id = dd.roster_detail_id + rd2.rsourece_id + ) AS dd ON b.id = dd.rsourece_id WHERE - $deptCondition - AND a.date IN ($appointment_dates_placeholders) - AND a.STATUS = 1 - AND a.is_del = 0 - AND b.is_del = 0 + b.is_del = 0 AND b.appointment_enabled = 1 + AND $deptCondition AND ( b.execute_department_id IS NULL OR b.execute_department_id = 0 @@ -265,17 +272,21 @@ public function GetEnablePlan($regnum, $entrustids, $episodeid, $appointment_typ AND appointment_enabled = 1 AND department_status = 1 ) - ) - AND c.appointment_type_id IN ($appointment_types_placeholders)", $canshu); + )", $canshu); $mergedPlan = []; foreach ($plan as $key => $p) { - $p->used_count = $p->used_count + ($p->locked_count ?? 0); - if (isset($mergedPlan[$p->roster_detail_id])) { - $mergedPlan[$p->roster_detail_id]->count += $p->count; - $mergedPlan[$p->roster_detail_id]->used_count += $p->used_count; + if (!empty($p->id)) { + $p->used_count = $p->used_count + ($p->locked_count ?? 0); + if (isset($mergedPlan[$p->roster_detail_id])) { + $mergedPlan[$p->roster_detail_id]->count += $p->count; + $mergedPlan[$p->roster_detail_id]->used_count += $p->used_count; + } else { + $mergedPlan[$p->roster_detail_id] = $p; + } } else { - $mergedPlan[$p->roster_detail_id] = $p; + // 排班明细为 NULL(暂无号源),不参与渠道合并,直接保留 + $mergedPlan[] = $p; } } @@ -293,6 +304,8 @@ public function GetEnablePlan($regnum, $entrustids, $episodeid, $appointment_typ $debugPassed = []; // 记录通过的 $pl1 = []; $pl2 = []; + $disabledPlans = []; // status=0 的排班明细 + $enabledResourceIds = []; // 有 status=1 明细的排班资源ID集合 $pp = []; $nowtime = date('Y-m-d H:i:s'); @@ -320,14 +333,25 @@ public function GetEnablePlan($regnum, $entrustids, $episodeid, $appointment_typ ]); foreach ($plan as $key => $p) { -// //病人类型不符合的过滤掉 - $planPatientType = explode(",", $p->patient_type); - $diff = array_diff($commPatientType, $planPatientType); - if (!empty($diff)) { - $debugSkipped[] = ['rid' => $p->resources_id, 'reason' => 'patient_type', 'planTypes' => $p->patient_type, 'commTypes' => $commPatientType, 'diff' => array_values($diff)]; + // 排班明细为 NULL(无排班明细或患者类型不匹配):直接丢弃 + if (empty($p->id)) { + continue; + } + $p->no_plan = false; + + // status=0 的排班明细:强制 0/0,标记不可用,暂存等待分组判定 + if ($p->status == 0) { + $p->count = 0; + $p->used_count = 0; + $p->locked_count = 0; + $p->plan_enable = false; + $disabledPlans[] = $p; continue; } + // 记录该排班资源存在 status=1 的明细 + $enabledResourceIds[$p->resource_id] = true; + //检查项目时段规则过滤 if (!empty($allItemRules)) { $rulePass = $this->checkPlanAgainstRules($p, $allItemRules); @@ -353,6 +377,18 @@ public function GetEnablePlan($regnum, $entrustids, $episodeid, $appointment_typ } } + // status=0 的排班明细分流:同资源存在 status=1 的归入 $pl2,全部 status=0 的归入第二段 + $allDisabledPlans = []; // 第二段:排班资源全部明细 status=0 + foreach ($disabledPlans as $dp) { + if (isset($enabledResourceIds[$dp->resource_id])) { + // 该资源还有 status=1 的明细 → 部分禁用,参与正常排序 + $pl2[] = $dp; + } else { + // 该资源全部明细 status=0 → 全部禁用,进入第二段 + $allDisabledPlans[] = $dp; + } + } + usort($pl1, function($a, $b) { $timeA = $a->date . ' ' . ($a->start_time ?? $a->end_time); // 兼容性处理 $timeB = $b->date . ' ' . ($b->start_time ?? $b->end_time); @@ -371,33 +407,47 @@ public function GetEnablePlan($regnum, $entrustids, $episodeid, $appointment_typ $pp = array_merge($pl1, $pl2); // 诊室排序:按最早可用时间升序 → 最早时段剩余号源降序 → 随机 + // 统一构建诊室分组:第一段 + 第二段 + 第三段 $grouped = []; $nowTimestamp = time(); - foreach ($pp as $plan) { - $name = $plan->department_resources_name; - if (!isset($grouped[$name])) { - $grouped[$name] = ['plans' => [], 'remaining' => 0, 'earliest_remaining' => 0]; - } - $grouped[$name]['plans'][] = $plan; - - // 累计全天总剩余 - $remaining = ($plan->count ?? 0) - ($plan->used_count ?? 0); - $grouped[$name]['remaining'] += max($remaining, 0); - - // 判断是否未过期,收集最早开始时间及该时段剩余 - $endDateTime = $plan->date . ' ' . ($plan->end_time ?? '23:59:59'); - if (strtotime($endDateTime) > $nowTimestamp) { - $startDateTime = $plan->date . ' ' . ($plan->begin_time ?? '00:00:00'); - $ts = strtotime($startDateTime); - if (!isset($grouped[$name]['earliest']) || $ts < $grouped[$name]['earliest']) { - $grouped[$name]['earliest'] = $ts; - $grouped[$name]['earliest_remaining'] = max($remaining, 0); - } elseif ($ts == $grouped[$name]['earliest']) { - // 同一 earliest 时段,累加该时段剩余 - $grouped[$name]['earliest_remaining'] += max($remaining, 0); + + // 辅助函数:把一批记录加入 $grouped + $addToGrouped = function($records, $priority) use (&$grouped, $nowTimestamp) { + foreach ($records as $plan) { + $name = $plan->department_resources_name; + if (!isset($grouped[$name])) { + $grouped[$name] = ['plans' => [], 'remaining' => 0, 'earliest_remaining' => 0, 'priority' => $priority]; + } + // priority 取最小值(如果有同名的记录分属不同段,以更靠前的段为准) + if ($priority < $grouped[$name]['priority']) { + $grouped[$name]['priority'] = $priority; + } + $grouped[$name]['plans'][] = $plan; + + // 累计全天总剩余 + $remaining = ($plan->count ?? 0) - ($plan->used_count ?? 0); + $grouped[$name]['remaining'] += max($remaining, 0); + + // 收集 earliest:仅 status=1 且 remaining>0 且未过期 + if (($plan->status ?? 1) == 1 && $remaining > 0) { + $endDateTime = $plan->date . ' ' . ($plan->end_time ?? '23:59:59'); + if (strtotime($endDateTime) > $nowTimestamp) { + $startDateTime = $plan->date . ' ' . ($plan->begin_time ?? '00:00:00'); + $ts = strtotime($startDateTime); + if (!isset($grouped[$name]['earliest']) || $ts < $grouped[$name]['earliest']) { + $grouped[$name]['earliest'] = $ts; + $grouped[$name]['earliest_remaining'] = max($remaining, 0); + } elseif ($ts == $grouped[$name]['earliest']) { + // 同一 earliest 时段,累加该时段剩余 + $grouped[$name]['earliest_remaining'] += max($remaining, 0); + } + } } } - } + }; + + $addToGrouped($pp, 0); // 第一段:可用 + 部分禁用 + $addToGrouped($allDisabledPlans, 1); // 第二段:全部 status=0 // 诊室排序:先转为索引数组,再手动排序 $grouped = array_values($grouped); @@ -408,27 +458,34 @@ public function GetEnablePlan($regnum, $entrustids, $episodeid, $appointment_typ $hasEarliest[$idx] = isset($g['earliest']); } - // 简单冒泡排序(只有 2 个诊室时足够) + // 简单冒泡排序 for ($i = 0; $i < count($grouped) - 1; $i++) { for ($j = $i + 1; $j < count($grouped); $j++) { $a = $grouped[$i]; $b = $grouped[$j]; - $aHas = isset($a['earliest']); - $bHas = isset($b['earliest']); $swap = false; - if ($aHas != $bHas) { - $swap = $bHas; // 有可用号源的排前面 - } elseif ($aHas) { - if ($a['earliest'] != $b['earliest']) { - $swap = ($a['earliest'] > $b['earliest']); // 最早时间升序 - } elseif ($a['earliest_remaining'] != $b['earliest_remaining']) { - $swap = ($a['earliest_remaining'] < $b['earliest_remaining']); // 最早时段剩余号源降序 + // 1. priority 不同 → 小的排前面 + if ($a['priority'] != $b['priority']) { + $swap = ($a['priority'] > $b['priority']); + } else { + $aHas = isset($a['earliest']); + $bHas = isset($b['earliest']); + // 2. 同 priority,有 earliest 排前面 + if ($aHas != $bHas) { + $swap = $bHas; + } elseif ($aHas) { + // 3. 都有 earliest → 时间升序 → remaining 降序 → 随机 + if ($a['earliest'] != $b['earliest']) { + $swap = ($a['earliest'] > $b['earliest']); + } elseif ($a['earliest_remaining'] != $b['earliest_remaining']) { + $swap = ($a['earliest_remaining'] < $b['earliest_remaining']); + } else { + $swap = (rand(0, 1) == 1); + } } else { - $swap = (rand(0, 1) == 1); // 随机 + $swap = (rand(0, 1) == 1); } - } else { - $swap = (rand(0, 1) == 1); // 都无可用号源,随机 } if ($swap) { @@ -2351,7 +2408,13 @@ private function mergeChannelsPerDepartment($plan, $appointment_type) } $mergedPlan = []; + $noPlanRecords = []; // 排班明细为 NULL 的记录,不参与渠道合并 foreach ($plan as $p) { + // 排班明细为 NULL(暂无号源),不参与渠道合并,直接保留 + if (empty($p->roster_detail_id)) { + $noPlanRecords[] = $p; + continue; + } $rid = $p->roster_detail_id; $deptChannels = $mergeConfigs[$p->department_id] ?? []; @@ -2378,7 +2441,7 @@ private function mergeChannelsPerDepartment($plan, $appointment_type) } } - return array_values($mergedPlan); + return array_merge(array_values($mergedPlan), $noPlanRecords); } //判断是否在互斥组内 diff --git a/YiJi-admin/src/components/Yewu/YuYue202506.vue b/YiJi-admin/src/components/Yewu/YuYue202506.vue index d1b7f1f..fe1a50c 100644 --- a/YiJi-admin/src/components/Yewu/YuYue202506.vue +++ b/YiJi-admin/src/components/Yewu/YuYue202506.vue @@ -159,6 +159,7 @@ title="提示" width="500" > +