fix(fsgx): 修复 issues-0325-1 前端与后端问题

UniApp:会员码图片兜底、海报下载 Promise、账单移除公排退款、
佣金状态与资产页 NavBar、资产接口 total_points_earned。

后端:推荐人须自报单才得周期佣金;升级前快照等级再发积分;
积分按报单商品数量倍乘;伞下级差按伞下基数传递;直推/伞下任务
统计补充 refund_status;周期佣金在事务内锁推荐人行防竞态;
新增 hjf:verify-agent-config 命令做等级与任务 e2e 验收。

Made-with: Cursor
This commit is contained in:
panchengyong
2026-03-28 10:23:20 +08:00
parent 8d109cbc01
commit ec56ae3286
13 changed files with 437 additions and 126 deletions

View File

@@ -40,10 +40,13 @@ class PointsRewardServices extends BaseServices
/**
* 对一笔报单订单发放积分奖励
*
* @param int $orderDbId 订单表主键 id用于 user_bill.link_id 关联后台订单
* @param int $orderDbId 订单表主键 id用于 user_bill.link_id 关联后台订单
* @param array $preUpgradeLevels 升级前各用户的 agent_level 快照 [uid => level_id],用于 B2 校验
* @param int $qty 订单中报单商品数量积分按数量倍乘B3
*/
public function reward(int $orderUid, string $orderId, int $orderDbId = 0): void
public function reward(int $orderUid, string $orderId, int $orderDbId = 0, array $preUpgradeLevels = [], int $qty = 1): void
{
$qty = max(1, $qty);
try {
// 幂等检查:若该订单已有积分奖励记录则跳过,防止重复发放
$exists = Db::name('points_release_log')
@@ -59,7 +62,7 @@ class PointsRewardServices extends BaseServices
if (!$buyer || !$buyer['spread_uid']) {
return;
}
$this->propagateReward($buyer['spread_uid'], $orderUid, $orderId, 0, 0, $orderDbId);
$this->propagateReward($buyer['spread_uid'], $orderUid, $orderId, 0, 0, $orderDbId, $preUpgradeLevels, $qty);
} catch (\Throwable $e) {
Log::error("[PointsReward] 积分奖励失败 orderUid={$orderUid} orderId={$orderId}: " . $e->getMessage());
}
@@ -68,11 +71,13 @@ class PointsRewardServices extends BaseServices
/**
* 向上递归发放级差积分
*
* @param int $uid 当前被奖励用户
* @param int $fromUid 触发方(下级)用户 ID
* @param string $orderId 来源订单号
* @param int $lowerReward 下级已获得的直推/伞下奖励积分(用于级差扣减)
* @param int $depth 递归深度
* @param int $uid 当前被奖励用户
* @param int $fromUid 触发方(下级)用户 ID
* @param string $orderId 来源订单号
* @param int $lowerReward 下级已获得的伞下奖励积分(用于级差扣减)
* @param int $depth 递归深度
* @param array $preUpgradeLevels 升级前各用户的 agent_level 快照 [uid => level_id]
* @param int $qty 报单商品数量积分按数量倍乘B3
*/
private function propagateReward(
int $uid,
@@ -80,7 +85,9 @@ class PointsRewardServices extends BaseServices
string $orderId,
int $lowerReward,
int $depth = 0,
int $orderDbId = 0
int $orderDbId = 0,
array $preUpgradeLevels = [],
int $qty = 1
): void {
if ($depth >= 10 || $uid <= 0) {
return;
@@ -91,22 +98,33 @@ class PointsRewardServices extends BaseServices
return;
}
$agentLevelId = (int)($user['agent_level'] ?? 0);
// fsgx B2使用升级前的 agent_level 判断资格,避免触发升级的那笔订单就给新等级积分
$agentLevelId = array_key_exists($uid, $preUpgradeLevels)
? $preUpgradeLevels[$uid]
: (int)($user['agent_level'] ?? 0);
$grade = $this->agentLevelServices->getGradeByLevelId($agentLevelId);
if ($grade === 0) {
if ($user['spread_uid']) {
$this->propagateReward((int)$user['spread_uid'], $uid, $orderId, 0, $depth + 1, $orderDbId);
$this->propagateReward((int)$user['spread_uid'], $uid, $orderId, 0, $depth + 1, $orderDbId, $preUpgradeLevels, $qty);
}
return;
}
$isDirect = ($depth === 0);
$reward = $isDirect
? $this->agentLevelServices->getDirectRewardPoints($agentLevelId)
: $this->agentLevelServices->getUmbrellaRewardPoints($agentLevelId);
// fsgx B4直推奖励和伞下奖励分别读取级差计算只用伞下奖励做扣减
// 这样当中间层如创客umbrella=0上报时上级云店umbrella=300
// 计算 max(0, 300-0)=300而不会被直推奖励 500 错误抵消
$directReward = $this->agentLevelServices->getDirectRewardPoints($agentLevelId);
$umbrellaReward = $this->agentLevelServices->getUmbrellaRewardPoints($agentLevelId);
$actual = max(0, $reward - $lowerReward);
if ($isDirect) {
// fsgx B3直推奖励按报单商品数量倍乘
$actual = $directReward * $qty;
} else {
// 级差:基于单件奖励做差值,再乘以数量
$actual = max(0, $umbrellaReward - $lowerReward) * $qty;
}
if ($actual > 0) {
$this->grantFrozenPoints(
@@ -114,7 +132,7 @@ class PointsRewardServices extends BaseServices
$actual,
$orderId,
$isDirect ? 'reward_direct' : 'reward_umbrella',
($isDirect ? '直推奖励' : '伞下奖励(级差)') . " - 来源订单 {$orderId}",
($isDirect ? '直推奖励' : '伞下奖励(级差)') . " x{$qty} - 来源订单 {$orderId}",
$orderDbId
);
}
@@ -124,9 +142,11 @@ class PointsRewardServices extends BaseServices
(int)$user['spread_uid'],
$uid,
$orderId,
$reward,
$umbrellaReward, // 向上传单件伞下奖励(级差基数),让上级自行乘以 $qty
$depth + 1,
$orderDbId
$orderDbId,
$preUpgradeLevels,
$qty
);
}
}