fix(commission): 优化拓扑BFS防环遍历与升级考核直推有效品酒师指标
这个提交包含在:
@@ -121,24 +121,30 @@ class Agent extends Common
|
||||
*/
|
||||
private function getOperationalStats($detail, $id)
|
||||
{
|
||||
// 建立邻接表,使用广度优先遍历(BFS)安全获取全部后代节点,杜绝潜在脏数据循环引用死循环
|
||||
$allUsers = \think\Db::name('user')->column('parent_user_id', 'id');
|
||||
$getDesc = function ($uid) use (&$getDesc, $allUsers) {
|
||||
$res = [];
|
||||
foreach ($allUsers as $cid => $pid) {
|
||||
if ((int)$pid === (int)$uid) {
|
||||
$res[] = $cid;
|
||||
$res = array_merge($res, $getDesc($cid));
|
||||
}
|
||||
}
|
||||
return $res;
|
||||
};
|
||||
$descIds = $getDesc($id);
|
||||
$directIds = [];
|
||||
$children = [];
|
||||
foreach ($allUsers as $cid => $pid) {
|
||||
if ((int)$pid === (int)$id) {
|
||||
$directIds[] = $cid;
|
||||
if ($pid) {
|
||||
$children[$pid][] = (int)$cid;
|
||||
}
|
||||
}
|
||||
$descIds = [];
|
||||
$queue = [(int)$id];
|
||||
$visited = [(int)$id => true];
|
||||
while (!empty($queue)) {
|
||||
$curr = array_shift($queue);
|
||||
if (!empty($children[$curr])) {
|
||||
foreach ($children[$curr] as $cid) {
|
||||
if (!isset($visited[$cid])) {
|
||||
$visited[$cid] = true;
|
||||
$descIds[] = $cid;
|
||||
$queue[] = $cid;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
$directIds = $children[(int)$id] ?? [];
|
||||
|
||||
// 1. 团队角色拓扑
|
||||
$directCount = count($directIds);
|
||||
@@ -200,15 +206,28 @@ class Agent extends Common
|
||||
$targetDirectUsers = intval($nextRules['child_user_count_1'] ?? 0);
|
||||
$targetTeamOrders = intval($nextRules['child_order_count_all'] ?? 0);
|
||||
|
||||
// 解析直推有效品酒师/创客指标要求
|
||||
$targetDirectAgents = 0;
|
||||
if (!empty($nextRules['child_agent_level_1']) && is_array($nextRules['child_agent_level_1'])) {
|
||||
foreach ($nextRules['child_agent_level_1'] as $al) {
|
||||
$targetDirectAgents += intval($al['count'] ?? 0);
|
||||
}
|
||||
} elseif (!empty($nextRules['child_agent_count_1'])) {
|
||||
$targetDirectAgents = intval($nextRules['child_agent_count_1']);
|
||||
}
|
||||
|
||||
$currentDirectUsers = intval($detail->child_user_count_1 ?? $directCount);
|
||||
$currentDirectAgents = intval($detail->child_agent_count_1 ?? $directPaidCount);
|
||||
$currentTeamOrders = intval($detail->child_order_count_all ?? 0);
|
||||
$currentSelfMoney = (float)($detail->child_order_money_0 ?? 0);
|
||||
|
||||
$directUserGap = max(0, $targetDirectUsers - $currentDirectUsers);
|
||||
$directAgentGap = max(0, $targetDirectAgents - $currentDirectAgents);
|
||||
$teamOrderGap = max(0, $targetTeamOrders - $currentTeamOrders);
|
||||
$isSelfPaid = ($selfOrderCount > 0 || $currentSelfMoney >= 1398);
|
||||
|
||||
$directUserPercent = $targetDirectUsers > 0 ? min(100, (int)round(($currentDirectUsers / $targetDirectUsers) * 100)) : 100;
|
||||
$directAgentPercent = $targetDirectAgents > 0 ? min(100, (int)round(($currentDirectAgents / $targetDirectAgents) * 100)) : 100;
|
||||
$teamOrderPercent = $targetTeamOrders > 0 ? min(100, (int)round(($currentTeamOrders / $targetTeamOrders) * 100)) : 100;
|
||||
|
||||
$upgradeRadar = [
|
||||
@@ -221,13 +240,18 @@ class Agent extends Common
|
||||
'direct_user_gap' => $directUserGap,
|
||||
'direct_user_reached' => ($directUserGap === 0),
|
||||
'direct_user_percent' => $directUserPercent,
|
||||
'target_direct_agents' => $targetDirectAgents,
|
||||
'current_direct_agents' => $currentDirectAgents,
|
||||
'direct_agent_gap' => $directAgentGap,
|
||||
'direct_agent_reached' => ($directAgentGap === 0),
|
||||
'direct_agent_percent' => $directAgentPercent,
|
||||
'target_team_orders' => $targetTeamOrders,
|
||||
'current_team_orders' => $currentTeamOrders,
|
||||
'team_order_gap' => $teamOrderGap,
|
||||
'team_order_reached' => ($teamOrderGap === 0),
|
||||
'team_order_percent' => $teamOrderPercent,
|
||||
'self_paid_reached' => $isSelfPaid,
|
||||
'all_reached' => ($directUserGap === 0 && $teamOrderGap === 0 && $isSelfPaid),
|
||||
'all_reached' => ($directUserGap === 0 && $directAgentGap === 0 && $teamOrderGap === 0 && $isSelfPaid),
|
||||
'upgrade_lock' => intval($detail->upgrade_lock ?? 0)
|
||||
];
|
||||
} else {
|
||||
@@ -241,6 +265,11 @@ class Agent extends Common
|
||||
'direct_user_gap' => 0,
|
||||
'direct_user_reached' => true,
|
||||
'direct_user_percent' => 100,
|
||||
'target_direct_agents' => 0,
|
||||
'current_direct_agents' => intval($detail->child_agent_count_1 ?? $directPaidCount),
|
||||
'direct_agent_gap' => 0,
|
||||
'direct_agent_reached' => true,
|
||||
'direct_agent_percent' => 100,
|
||||
'target_team_orders' => 0,
|
||||
'current_team_orders' => intval($detail->child_order_count_all ?? 0),
|
||||
'team_order_gap' => 0,
|
||||
@@ -248,7 +277,6 @@ class Agent extends Common
|
||||
'team_order_percent' => 100,
|
||||
'self_paid_reached' => true,
|
||||
'all_reached' => true,
|
||||
'upgrade_lock' => intval($detail->upgrade_lock ?? 0)
|
||||
];
|
||||
}
|
||||
|
||||
|
||||
@@ -590,8 +590,30 @@
|
||||
</div>
|
||||
|
||||
<div class="op-radar-body" v-if="state.data.operational_stats.upgrade_radar.next_level > 0">
|
||||
<!-- 直推实名/购买用户考核 -->
|
||||
<div class="op-radar-metric">
|
||||
<!-- 直推实名/有效品酒师考核 -->
|
||||
<div class="op-radar-metric" v-if="state.data.operational_stats.upgrade_radar.target_direct_agents > 0">
|
||||
<div class="m-label">
|
||||
<span>
|
||||
直推有效品酒师
|
||||
<el-popover placement="top" trigger="hover" content="需直推用户完成首单自购(child_order_count_0 ≥ 1)激活为有效品酒师">
|
||||
<template #reference>
|
||||
<span style="cursor: pointer; color: #94a3b8; font-size: 11px;">ℹ️ 说明</span>
|
||||
</template>
|
||||
</el-popover>
|
||||
</span>
|
||||
<el-tag size="small" :type="state.data.operational_stats.upgrade_radar.direct_agent_reached ? 'success' : 'danger'">
|
||||
{{ state.data.operational_stats.upgrade_radar.direct_agent_reached ? '已达标' : '缺 ' + state.data.operational_stats.upgrade_radar.direct_agent_gap + ' 人' }}
|
||||
</el-tag>
|
||||
</div>
|
||||
<div class="m-val">
|
||||
{{ state.data.operational_stats.upgrade_radar.current_direct_agents }}
|
||||
<span style="font-size: 12px; color: #94a3b8; font-weight: normal;"> / {{ state.data.operational_stats.upgrade_radar.target_direct_agents }} 人</span>
|
||||
</div>
|
||||
<el-progress :percentage="state.data.operational_stats.upgrade_radar.direct_agent_percent"
|
||||
:status="state.data.operational_stats.upgrade_radar.direct_agent_reached ? 'success' : 'warning'"
|
||||
:stroke-width="6" style="margin-top: 6px;"></el-progress>
|
||||
</div>
|
||||
<div class="op-radar-metric" v-else>
|
||||
<div class="m-label">
|
||||
<span>有效直推人数指标</span>
|
||||
<el-tag size="small" :type="state.data.operational_stats.upgrade_radar.direct_user_reached ? 'success' : 'danger'">
|
||||
|
||||
在新工单中引用
屏蔽一个用户