>, total_target: float} */ public static function monthMatrix(string $yearMonth): array { $tree = DeptLogic::getAllData(); $rowsDb = DeptPerformanceTarget::where('year_month', $yearMonth) ->select() ->toArray(); $targets = []; foreach ($rowsDb as $r) { $targets[(int) ($r['dept_id'] ?? 0)] = $r; } $rows = self::attachTargetsToTree(is_array($tree) ? $tree : [], $targets); $total = self::sumTargetsInTree($rows); return [ 'year_month' => $yearMonth, 'rows' => $rows, 'total_target' => round($total, 2), ]; } /** * @param array $items */ public static function batchSave(string $yearMonth, array $items, int $adminId, string $adminName): bool { try { Db::transaction(function () use ($yearMonth, $items, $adminId, $adminName): void { foreach ($items as $item) { if (!is_array($item)) { continue; } $deptId = (int) ($item['dept_id'] ?? 0); if ($deptId <= 0) { continue; } $dept = Dept::where('id', $deptId)->whereNull('delete_time')->find(); if (!$dept) { continue; } $deptName = trim((string) ($dept->name ?? '')); $amt = round((float) ($item['target_amount'] ?? 0), 2); $remark = mb_substr(trim((string) ($item['remark'] ?? '')), 0, 255); if ($amt <= 0) { DeptPerformanceTarget::where('dept_id', $deptId) ->where('year_month', $yearMonth) ->delete(); continue; } $row = DeptPerformanceTarget::where('dept_id', $deptId) ->where('year_month', $yearMonth) ->find(); if ($row) { $row->dept_name = $deptName; $row->target_amount = $amt; $row->remark = $remark; $row->updater_id = $adminId; $row->updater_name = $adminName; $row->save(); } else { DeptPerformanceTarget::create([ 'dept_id' => $deptId, 'dept_name' => $deptName, 'year_month' => $yearMonth, 'target_amount' => $amt, 'remark' => $remark, 'creator_id' => $adminId, 'creator_name' => $adminName, 'updater_id' => $adminId, 'updater_name' => $adminName, ]); } } }); return true; } catch (\Throwable $e) { self::setError($e->getMessage()); return false; } } /** * @param array> $nodes DeptLogic::getAllData 子树 * @param array> $targets keyed by dept_id * * @return array> */ private static function attachTargetsToTree(array $nodes, array $targets, string $prefix = ''): array { $out = []; foreach ($nodes as $n) { if (!is_array($n)) { continue; } $id = (int) ($n['id'] ?? 0); $name = trim((string) ($n['name'] ?? '')); if ($id <= 0) { continue; } $path = $prefix === '' ? $name : $prefix . ' / ' . $name; $t = $targets[$id] ?? null; $amt = $t ? round((float) $t['target_amount'], 2) : 0.0; $node = [ 'dept_id' => $id, 'dept_name' => $name, 'dept_path' => $path, 'target_id' => $t ? (int) $t['id'] : 0, 'target_amount' => $amt, 'remark' => $t ? (string) ($t['remark'] ?? '') : '', ]; $rawChildren = $n['children'] ?? []; $childList = is_array($rawChildren) && $rawChildren !== [] ? self::attachTargetsToTree($rawChildren, $targets, $path) : []; if ($childList !== []) { $node['children'] = $childList; } $out[] = $node; } return $out; } /** * @param array> $nodes */ private static function sumTargetsInTree(array $nodes): float { $s = 0.0; foreach ($nodes as $n) { $s += (float) ($n['target_amount'] ?? 0); $ch = $n['children'] ?? []; if (is_array($ch) && $ch !== []) { $s += self::sumTargetsInTree($ch); } } return $s; } }