where('del_time', 0) ->first(); if ($mission) { if($mission->state == ItemNodeMission::TYPE_THREE){ $mission->progress = 100.0; $mission->save(); } self::handleNodeProgress($mission->item_node_id); } break; case self::TYPE_NODE: // 2. 如果是节点变了,直接计算该节点 self::handleNodeProgress($id); break; case self::TYPE_ITEM: // 3. 如果是项目层级触发,直接计算项目 self::handleItemProgress($id); break; } } /** * 核心逻辑:计算节点进度并自动向上触发项目计算(私有,不对外) */ private static function handleNodeProgress($nodeId) { // 严格限制:只有未删除的节点才参与计算 $node = ItemNode::where('id', $nodeId) ->where('del_time', 0) ->first(); if (!$node) return; // 查找该节点下所有未删除的任务 $missions = ItemNodeMission::where('item_node_id', $nodeId) ->where('del_time', 0) ->get(); if ($missions->isEmpty()) { // 无任务,进度由自身状态决定 $node->progress = ($node->state == ItemNodeMission::TYPE_THREE) ? 100.00 : 0.00; } else { $totalWeight = $missions->sum('mission_weight'); if ($totalWeight <= 0) { // 如果建了任务但权重全是 0,按任务个数平均分 $completedCount = $missions->where('state', 3)->count(); $node->progress = round(($completedCount / $missions->count()) * 100, 2); } else { // 已完成(state = 3)的任务权重和 $completedWeight = $missions->where('state', 3)->sum('mission_weight'); $node->progress = round(($completedWeight / $totalWeight) * 100, 2); } } $node->save(); // 【自动冒泡】节点算完,自动去算它所属的项目 self::handleItemProgress($node->item_id); } /** * 核心逻辑:计算项目进度(私有,不对外) */ private static function handleItemProgress($itemId) { // 严格限制:只有未删除的项目才参与计算 $item = Item::where('id', $itemId) ->where('del_time', 0) ->first(); if (!$item) return; // 查找该项目下所有未删除的节点 $nodes = ItemNode::where('item_id', $itemId) ->where('del_time', 0) ->get(); if ($nodes->isEmpty()) { // 无节点,进度由自身状态决定 $item->progress = ($item->state == ItemNode::TYPE_THREE) ? 100.00 : 0.00;; $item->save(); return; } $totalWeight = $nodes->sum('node_weight'); if ($totalWeight <= 0) { // 如果有节点但权重全写了 0,按节点个数平均分配 $currentSum = 0; foreach ($nodes as $node) { $currentSum += ($node->progress / 100); } $item->progress = round(($currentSum / $nodes->count()) * 100, 2); } else { // 采用复合算法:SUM(节点权重 * 节点自身的 progress) / 总权重 $currentSum = 0; foreach ($nodes as $node) { $currentSum += $node->node_weight * ($node->progress / 100); } $item->progress = round(($currentSum / $totalWeight) * 100, 2); } $item->save(); } }