Explorar o código

微信小程序

cqp hai 3 semanas
pai
achega
5587c23a38

+ 9 - 5
app/Service/Statistic/StatisticCommonService.php

@@ -94,18 +94,22 @@ class StatisticCommonService extends Service
     public function getItemEmployeeDayWorkList($user, $data, $month_start, $month_end)
     {
         $month_employee = DailyPwOrderDetails::Clear($user, $data);
-        return $month_employee->where("order_time", ">=", $month_start)->where("order_time", "<", $month_end)
+        return $month_employee->where("order_time", ">=", $month_start)
+            ->where("order_time", "<", $month_end)
             ->where('del_time', 0)
             ->select(
                 "item_id",
                 "employee_id",
-                // 将时间戳转为 Y-m-d 格式并起别名
+                // 保持别名输出
                 DB::raw("FROM_UNIXTIME(order_time, '%Y-%m-%d') as order_date"),
-                // 聚合求和
                 DB::raw("SUM(total_work_min) as total_work")
             )
-            ->groupBy(DB::raw("FROM_UNIXTIME(order_time, '%Y-%m-%d')"), "item_id", "employee_id")
-            ->orderby("order_date", "asc")->get()->toArray();
+            // 2. 优化:不加索引时,把离散度高的字段(id)放前面,
+            // 让 MySQL 在临时表里 hash 归类时能快一点点
+            ->groupBy("item_id", "employee_id", DB::raw("FROM_UNIXTIME(order_time, '%Y-%m-%d')"))
+            ->orderBy("order_date", "asc")
+            ->get()
+            ->toArray();
     }
 
     /**

+ 65 - 4
app/Service/StatisticService.php

@@ -3,8 +3,6 @@
 namespace App\Service;
 
 use App\Model\AuxiliaryAccountDetails;
-use App\Model\DailyDwOrderDetails;
-use App\Model\DailyPwOrderDetails;
 use App\Model\Depart;
 use App\Model\Device;
 use App\Model\DeviceDepartDetails;
@@ -14,8 +12,6 @@ use App\Model\ExpenseClaimsDetails;
 use App\Model\Fee;
 use App\Model\Item;
 use App\Model\ItemDetails;
-use App\Model\MonthlyDdOrder;
-use App\Model\MonthlyDdOrderDetails;
 use App\Model\MonthlyPsOrder;
 use App\Model\MonthlyPsOrderDetails;
 use App\Service\Statistic\StatisticCommonService;
@@ -24,6 +20,71 @@ use Illuminate\Support\Facades\DB;
 class StatisticService extends StatisticCommonService
 {
     public function employeeDayHourStatistic($data, $user)
+    {
+        // 1. 验证并获取月份边界
+        list($status, $month_start, $month_end) = $this->commonRule($data);
+        if (!$status) return [false, $month_start];
+
+        // 2. 获取原始数据
+        $dayEmployeeList = $this->getItemEmployeeDayWorkList($user, $data, $month_start, $month_end);
+        if (empty($dayEmployeeList)) {
+            return [true, []];
+        }
+
+        // 3. 提取 ID 批量查询关联数据(合并 Item 查询)
+        $itemIds = array_unique(array_filter(array_column($dayEmployeeList, 'item_id')));
+        $employeeIds = array_unique(array_filter(array_column($dayEmployeeList, 'employee_id')));
+
+        $items = Item::whereIn('id', $itemIds)->get(['id', 'title', 'code'])->keyBy('id');
+        $employeeKeyList = Employee::whereIn('id', $employeeIds)->pluck('title', 'id')->toArray();
+
+        // 4. 【核心优化】单次遍历:同时计算 count、sum 并补全基础信息
+        $employeeCounts = [];
+        $sums = [];
+
+        foreach ($dayEmployeeList as &$item) {
+            $employeeId = $item['employee_id'] ?? null;
+            $itemId = $item['item_id'] ?? null;
+            $orderDate = $item['order_date'] ?? '';
+
+            // 补全名称(避免在 map 里重复调用集合)
+            $item['employee_name'] = $employeeKeyList[$employeeId] ?? "未知员工({$employeeId})";
+            $itemProject = $items->get($itemId);
+            $item['item_title'] = $itemProject->title ?? "未知项目({$itemId})";
+            $item['item_code'] = $itemProject->code ?? "未知项目({$itemId})";
+
+            // 组装唯一 Key: "employeeId_orderDate"
+            $groupKey = "{$employeeId}_{$orderDate}";
+
+            // 累加计数
+            $employeeCounts['employee_work_count'][$groupKey] = ($employeeCounts['employee_work_count'][$groupKey] ?? 0) + 1;
+
+            // 累加小时工时(转为分位整数存储,防止浮点数失真)
+            $hours = round(($item['total_work'] ?? 0) / 60, 2);
+            $sums['employee_work_count'][$groupKey] = ($sums['employee_work_count'][$groupKey] ?? 0) + (int)round($hours * 100);
+        }
+        unset($item); // 释放引用避免后续污染
+
+        $wordKeys = [
+            "employee_work_count" => [
+                "key" => "total_work",
+                "value" => "total_work_hours",
+                "type" => "hour",
+            ]
+        ];
+
+        // 5. 第二次遍历:倒扣尾差计算
+        // 因为这里需要倒扣,必须按顺序执行 calculateClosure
+        foreach ($dayEmployeeList as &$item) {
+            $groupKey = "{$item['employee_id']}_{$item['order_date']}";
+            $this->calculateClosure($groupKey, $item, $employeeCounts, $sums, $wordKeys);
+        }
+        unset($item);
+
+        return [true, $dayEmployeeList];
+    }
+
+    public function employeeDayHourStatistic1($data, $user)
     {
         //传参月份、项目编码、项目名称 不允许跨年查询月份
         //项目编码、项目名称、人员名称、工时、日期