cqp 2 месяцев назад
Родитель
Сommit
c7ac9abc30
1 измененных файлов с 35 добавлено и 25 удалено
  1. 35 25
      app/Service/DeviceWorkService.php

+ 35 - 25
app/Service/DeviceWorkService.php

@@ -1029,48 +1029,61 @@ class DeviceWorkService extends Service
 
     private function calculateDailyDeviceAllocation($monthStart, $topDepartId, $user)
     {
-        $monthEnd = strtotime('+1 month', $monthStart) - 1;
-
-        // --- 1. 基础数据预加载 ---
-        // 月度明细 & 设备名称
+        // 加载月度设备明细
         $monthlyOrder = DB::table('monthly_dw_order_details as d')
             ->join('monthly_dw_order as m', 'm.id', '=', 'd.main_id')
-            ->leftJoin('device as dv', 'dv.id', '=', 'd.device_id') // 假设设备表是 device
-            ->where('m.month', $monthStart)->where('m.top_depart_id', $topDepartId)
-            ->where('m.del_time', 0)->where('d.del_time', 0)
-            ->select('d.*', 'dv.name as device_title')->get();
+            ->where('m.month', $monthStart)
+            ->where('m.top_depart_id', $topDepartId)
+            ->where('m.del_time', 0)
+            ->where('d.del_time', 0)
+            ->select('d.*')
+            ->get();
 
         if ($monthlyOrder->isEmpty()) return ['status' => false, 'msg' => '未找到设备月度工时明细'];
 
-        // 项目名称映射
-        $itemMap = DB::table('items')->pluck('name', 'id')->toArray();
+        $usedDeviceIds = $monthlyOrder->pluck('device_id')->unique()->toArray();
+
+        // 【优化点】按需查询设备名称
+        $deviceMap = DB::table('device')
+        ->whereIn('id', $usedDeviceIds)
+            ->pluck('title', 'id')
+            ->toArray();
 
-        // 设备分配比例规则
+        // 加载分配规则
         $ruleSet = DB::table('rule_set_details as rd')
             ->join('rule_set as r', 'r.id', '=', 'rd.main_id')
             ->where('r.month', $monthStart)
-            ->where('rd.type', 2) // 假设 2 是设备规则
-            ->where('r.del_time', 0)->where('rd.del_time', 0)
-            ->select('rd.*')->get()->groupBy('data_id');
+            ->where('rd.type', 2) // 设备类型
+            ->where('r.del_time', 0)
+            ->where('rd.del_time', 0)
+            ->select('rd.*')
+            ->get();
+
+        // 【优化点】按需查询项目名称
+        $usedItemIds = $ruleSet->pluck('item_id')->unique()->toArray();
+        $itemMap = DB::table('item')
+            ->whereIn('id', $usedItemIds)
+            ->pluck('title', 'id') // 这里的 title 对应你之前的需求
+            ->toArray();
+
+        $ruleSetGrouped = $ruleSet->groupBy('data_id'); // 按 device_id 分组
 
-        // 标准班次
+        // 标准班次 & 日历 (逻辑同前)
         $standardWorkRanges = DB::table('work_range_details')
             ->where('top_depart_id', $topDepartId)->where('del_time', 0)->get();
-
         $dayMaxAvail = (int)$standardWorkRanges->sum('total_work_min');
 
-        // 工作日历
         $workDays = DB::table('calendar_details')
             ->where('month', $monthStart)->where('is_work', 1)->where('del_time', 0)
             ->orderBy('time', 'asc')->get();
 
         if ($workDays->isEmpty()) return ['status' => false, 'msg' => '未配置工作日历'];
 
-        // --- 2. 阶段一:计算每天每台设备在每个项目下的整数分钟数 ---
+        // --- 2. 阶段一:计算每天每台设备分配的项目分钟数 ---
         $finalAlloc = [];
         foreach ($monthlyOrder as $mDetail) {
             $deviceId = $mDetail->device_id;
-            $deviceRules = $ruleSet->get($deviceId);
+            $deviceRules = $ruleSetGrouped->get($deviceId);
             if (!$deviceRules) continue;
 
             $remainingMin = (int)round((float)$mDetail->rd_total_hours * 60);
@@ -1085,7 +1098,6 @@ class DeviceWorkService extends Service
 
                 foreach ($deviceRules as $index => $rule) {
                     $rate = (float)$rule->rate / 100;
-                    // 最后一个项目拿差额,防止精度流失
                     if ($index === $ruleCount - 1) {
                         $projectMin = $canAllocToday - $allocatedInDay;
                     } else {
@@ -1101,7 +1113,7 @@ class DeviceWorkService extends Service
             }
         }
 
-        // --- 3. 阶段二:打散到具体时段并生成预览行 ---
+        // --- 3. 阶段二:生成预览行 ---
         $previewList = [];
         $dailyDevicePools = [];
         $tempMainIdCounter = 1;
@@ -1113,7 +1125,6 @@ class DeviceWorkService extends Service
                 $itemTitle = $itemMap[$itemId] ?? '未知项目';
 
                 foreach ($devices as $deviceId => $toAllocMin) {
-                    // 初始化该设备当天的标准班次池
                     if (!isset($dailyDevicePools[$dayTs][$deviceId])) {
                         $pool = [];
                         foreach ($standardWorkRanges as $swr) {
@@ -1128,7 +1139,6 @@ class DeviceWorkService extends Service
                     $tempRem = (int)$toAllocMin;
                     foreach ($dailyDevicePools[$dayTs][$deviceId] as &$p) {
                         if ($tempRem <= 0) break;
-
                         $pMax = $p['e'] - $p['s'];
                         if ($pMax <= 0) continue;
 
@@ -1143,7 +1153,7 @@ class DeviceWorkService extends Service
                             'item_id'         => $itemId,
                             'item_title'      => $itemTitle,
                             'device_id'       => $deviceId,
-                            'device_title'    => $monthlyOrder->where('device_id', $deviceId)->first()->device_title ?? '未知设备',
+                            'device_title'    => $deviceMap[$deviceId] ?? '未知设备',
                             'start_time'      => sprintf('%02d:%02d', floor($start / 60), $start % 60),
                             'end_time'        => sprintf('%02d:%02d', floor($end / 60), $end % 60),
                             'start_hour'      => (int)floor($start / 60),
@@ -1154,7 +1164,7 @@ class DeviceWorkService extends Service
                         ];
 
                         $tempRem -= $take;
-                        $p['s'] = $end; // 时间指针向后推,确保不重叠
+                        $p['s'] = $end;
                     }
                 }
             }