cqp 2 ay önce
ebeveyn
işleme
11f6054014
2 değiştirilmiş dosya ile 44 ekleme ve 45 silme
  1. 19 15
      app/Service/DeviceWorkService.php
  2. 25 30
      app/Service/PersonWorkService.php

+ 19 - 15
app/Service/DeviceWorkService.php

@@ -1182,22 +1182,23 @@ class DeviceWorkService extends Service
         $month = $data['month'];
         $now = time();
 
-        // 1. 预加载设备名称映射,用于友好报错
+        // 1. 预加载设备名称映射 (使用 title 或 name 字段)
         $deviceIds = collect($list)->pluck('device_id')->unique()->toArray();
         $deviceMap = DB::table('device')
             ->whereIn('id', $deviceIds)
             ->pluck('title', 'id')
             ->toArray();
 
-        // --- 2. 重新分组:在分组的同时,利用原始索引 index 记录行号 ---
+        // --- 2. 重新分组:在分组的同时,利用原始索引记录行号 ---
         $groupedByOrder = [];
         foreach ($list as $index => $item) {
             $item['_line'] = $index + 1; // 记录原始行号(从1开始)
+            // 以日期字符串作为分组 Key 之一
             $groupKey = $item['order_time'] . '_' . $item['item_id'];
             $groupedByOrder[$groupKey][] = $item;
         }
 
-        // 冲突校验器容器:记录 [设备ID][日期] 下已占用的时间段
+        // 冲突校验器容器:记录 [设备ID][日期字符串] 下已占用的时间段
         $deviceTimeline = [];
 
         DB::beginTransaction();
@@ -1220,14 +1221,15 @@ class DeviceWorkService extends Service
             // B. 遍历重组后的分组,生成单据
             foreach ($groupedByOrder as $details) {
                 $first = $details[0];
-                $orderTime = $first['order_timestamp'];
+                // 【修正】统一将前端日期字符串转为时间戳入库
+                $orderTimestamp = strtotime($first['order_time']);
                 $itemId = $first['item_id'];
 
                 // 写入设备日工时主表
                 $mainId = DB::table('daily_dw_order')->insertGetId([
                     'code'          => '',
                     'item_id'       => $itemId,
-                    'order_time'    => $orderTime,
+                    'order_time'    => $orderTimestamp,
                     'top_depart_id' => $topDepartId,
                     'is_create'     => 1,
                     'crt_id'        => $user['id'],
@@ -1240,29 +1242,31 @@ class DeviceWorkService extends Service
                     $devId = $d['device_id'];
                     $devName = $deviceMap[$devId] ?? "设备(ID:{$devId})";
 
-                    // 时间转分钟数进行冲突校验
+                    // 【修正】强制后端计算分钟数,防止前端传错或篡改
                     $s = (int)$d['start_hour'] * 60 + (int)$d['start_min'];
                     $e = (int)$d['end_hour'] * 60 + (int)$d['end_min'];
+                    $calcTotalMin = $e - $s;
 
-                    // --- 核心校验:精准提示行号 ---
+                    // --- 校验逻辑 ---
 
                     // 校验1:逻辑合法性
-                    if ($e <= $s) {
+                    if ($calcTotalMin <= 0) {
                         return [false, "第 {$rowNum} 行:设备[{$devName}]在[{$d['order_time']}]的结束时间必须晚于开始时间"];
                     }
 
                     // 校验2:跨单据冲突校验
-                    if (isset($deviceTimeline[$devId][$orderTime])) {
-                        foreach ($deviceTimeline[$devId][$orderTime] as $exist) {
+                    $dateStr = $d['order_time'];
+                    if (isset($deviceTimeline[$devId][$dateStr])) {
+                        foreach ($deviceTimeline[$devId][$dateStr] as $exist) {
                             // 碰撞算法: (开始A < 结束B) 且 (结束A > 开始B)
                             if ($s < $exist['e'] && $e > $exist['s']) {
-                                return [false, "第 {$rowNum} 行:设备[{$devName}]在[{$d['order_time']}]的时间段({$d['start_time']}-{$d['end_time']})与其他项目存在冲突,请检查!"];
+                                return [false, "第 {$rowNum} 行:设备[{$devName}]在[{$dateStr}]存在时间冲突({$d['start_time']}-{$d['end_time']}),请检查!"];
                             }
                         }
                     }
 
-                    // 记录当前时间段用于后续校验
-                    $deviceTimeline[$devId][$orderTime][] = ['s' => $s, 'e' => $e];
+                    // 记录当前时间段
+                    $deviceTimeline[$devId][$dateStr][] = ['s' => $s, 'e' => $e];
 
                     $insertDetails[] = [
                         'main_id'         => $mainId,
@@ -1272,7 +1276,7 @@ class DeviceWorkService extends Service
                         'start_time_min'  => $d['start_min'],
                         'end_time_hour'   => $d['end_hour'],
                         'end_time_min'    => $d['end_min'],
-                        'total_work_min'  => $d['total_work_min'],
+                        'total_work_min'  => $calcTotalMin, // 使用后端计算结果
                         'crt_time'        => $now,
                     ];
                 }
@@ -1284,7 +1288,7 @@ class DeviceWorkService extends Service
                 $code = $this->generateBillNo([
                     'top_depart_id' => $topDepartId,
                     'type' => DailyDwOrder::Order_type,
-                    'period' => date("Ym", $orderTime)
+                    'period' => date("Ym", $orderTimestamp)
                 ]);
                 DB::table('daily_dw_order')->where('id', $mainId)->update(['code' => $code]);
             }

+ 25 - 30
app/Service/PersonWorkService.php

@@ -1238,27 +1238,24 @@ class PersonWorkService extends Service
         $month = $data['month'];
         $now = time();
 
-        // 1. 预加载员工姓名,用于精准报错
+        // 1. 预加载员工姓名 (注意字段名,如果是 employee 表通常用 title 或 name)
         $empIds = collect($list)->pluck('employee_id')->unique()->toArray();
-        $empMap = DB::table('employee')
-            ->whereIn('id', $empIds)
-            ->pluck('title', 'id')
-            ->toArray();
+        $empMap = DB::table('employee')->whereIn('id', $empIds)->pluck('title', 'id')->toArray();
 
-        // --- 2. 重新分组:在分组的同时,利用原始索引记录行号 ---
+        // --- 2. 重新分组并记录行号 ---
         $groupedByOrder = [];
         foreach ($list as $index => $item) {
-            $item['_line'] = $index + 1; // 记录原始行号(从1开始)
+            $item['_line'] = $index + 1;
+            // 确保使用日期字符串作为分组 Key
             $groupKey = $item['order_time'] . '_' . $item['item_id'];
             $groupedByOrder[$groupKey][] = $item;
         }
 
-        // 3. 跨单据冲突校验器:记录 [员工ID][日期] 的时间轴
         $empTimeline = [];
 
         DB::beginTransaction();
         try {
-            // A. 清理该月份旧数据 (is_create = 1 表示自动生成的)
+            // A. 清理该月份旧数据
             $monthStart = $this->changeDateToDate($month);
             $monthEnd = strtotime('+1 month', $monthStart) - 1;
 
@@ -1273,17 +1270,17 @@ class PersonWorkService extends Service
                 DB::table('daily_pw_order_details')->whereIn('main_id', $oldOrderIds)->update(['del_time' => $now]);
             }
 
-            // B. 遍历重组后的分组写入
+            // B. 遍历分组写入
             foreach ($groupedByOrder as $details) {
                 $first = $details[0];
-                $orderTime = $first['order_timestamp'];
+                // 【修正】统一将前端 order_time 日期字符串转为时间戳
+                $orderTimestamp = strtotime($first['order_time']);
                 $itemId = $first['item_id'];
 
-                // 写入主表
                 $mainId = DB::table('daily_pw_order')->insertGetId([
                     'code'          => '',
                     'item_id'       => $itemId,
-                    'order_time'    => $orderTime,
+                    'order_time'    => $orderTimestamp,
                     'top_depart_id' => $topDepartId,
                     'is_create'     => 1,
                     'crt_id'        => $user['id'],
@@ -1292,31 +1289,30 @@ class PersonWorkService extends Service
 
                 $insertDetails = [];
                 foreach ($details as $d) {
-                    $rowNum = $d['_line']; // 获取原始行号
+                    $rowNum = $d['_line'];
                     $empId = $d['employee_id'];
-                    $empName = $empMap[$empId] ?? "未知人员(ID:{$empId})";
+                    $empName = $empMap[$empId] ?? "人员(ID:{$empId})";
 
-                    // 计算分钟数
+                    // 【修正】强制由后端计算分钟数,防止前端篡改
                     $s = (int)$d['start_hour'] * 60 + (int)$d['start_min'];
                     $e = (int)$d['end_hour'] * 60 + (int)$d['end_min'];
-
-                    // --- 校验逻辑:精准提示行号 ---
+                    $calcTotalMin = $e - $s;
 
                     // 校验1:逻辑合法性
-                    if ($e <= $s) {
-                        return [false, "第 {$rowNum} 行:人员[{$empName}]在[{$d['order_time']}]的时间段无效:结束时间应晚于开始时间"];
+                    if ($calcTotalMin <= 0) {
+                        return [false, "第 {$rowNum} 行:人员[{$empName}]的结束时间必须晚于开始时间"];
                     }
 
-                    // 校验2:跨单据时间重叠校验
-                    if (isset($empTimeline[$empId][$orderTime])) {
-                        foreach ($empTimeline[$empId][$orderTime] as $exist) {
-                            // 碰撞判断: Max(S1, S2) < Min(E1, E2) 则重叠
+                    // 校验2:跨单据时间重叠校验 (使用 order_time 字符串作为 Timeline Key 即可)
+                    $dateStr = $d['order_time'];
+                    if (isset($empTimeline[$empId][$dateStr])) {
+                        foreach ($empTimeline[$empId][$dateStr] as $exist) {
                             if ($s < $exist['e'] && $e > $exist['s']) {
-                                return [false, "第 {$rowNum} 行:人员[{$empName}]在[{$d['order_time']}]存在时间重叠({$d['start_time']}-{$d['end_time']}),请检查!"];
+                                return [false, "第 {$rowNum} 行:人员[{$empName}]在[{$dateStr}]存在时间重叠({$d['start_time']}-{$d['end_time']}),请检查!"];
                             }
                         }
                     }
-                    $empTimeline[$empId][$orderTime][] = ['s' => $s, 'e' => $e];
+                    $empTimeline[$empId][$dateStr][] = ['s' => $s, 'e' => $e];
 
                     $insertDetails[] = [
                         'main_id'         => $mainId,
@@ -1326,25 +1322,24 @@ class PersonWorkService extends Service
                         'start_time_min'  => $d['start_min'],
                         'end_time_hour'   => $d['end_hour'],
                         'end_time_min'    => $d['end_min'],
-                        'total_work_min'  => $d['total_work_min'],
+                        'total_work_min'  => $calcTotalMin, // 使用计算出的分钟数
                         'crt_time'        => $now,
                     ];
                 }
 
-                // 批量写入明细
                 DB::table('daily_pw_order_details')->insert($insertDetails);
 
                 // C. 回填单号
                 $code = $this->generateBillNo([
                     'top_depart_id' => $topDepartId,
                     'type' => DailyPwOrder::Order_type,
-                    'period' => date("Ym", $orderTime)
+                    'period' => date("Ym", $orderTimestamp)
                 ]);
                 DB::table('daily_pw_order')->where('id', $mainId)->update(['code' => $code]);
             }
 
             DB::commit();
-            return [true, ''];
+            return [true, '保存成功'];
         } catch (\Exception $e) {
             DB::rollBack();
             return [false, "保存失败:" . $e->getMessage()];