fix(fsgx): 积分释放定时任务、佣金轮巡与 UniApp 体验

- PointsReleaseServices: 使用 Db::table 查询与更新,构造函数注入 UserDao;日志与账单独立 try/catch\n- SystemTimer: implement_timer 捕获后重新抛出异常,便于 run_now 返回错误\n- SystemTimerServices / 控制器: runNow 返回任务结果并在 API 中带回 result\n- StoreOrderCreateServices: 报单佣金位次修正与多件轮巡\n- UniApp: 佣金记录跳转 type=2、余额提现免手续费展示、状态页与资产页头部渐变与提现页一致\n- docs: 增加 fsgx-issues-0328-1 问题跟踪

Made-with: Cursor
This commit is contained in:
panchengyong
2026-03-29 10:36:52 +08:00
parent 1418377b35
commit 965ac7bc86
9 changed files with 141 additions and 102 deletions

View File

@@ -926,6 +926,9 @@ class StoreOrderCreateServices extends BaseServices
$storeBrokerageTwo = $spread_two_uid = 0;
}
// fsgx B-2B: 同一订单内多个报单商品件数累计偏移,保证位次轮巡
$queueGoodsOffset = 0;
foreach ($cartInfo as &$cart) {
$oneBrokerage = '0';//一级返佣金额
$twoBrokerage = '0';//二级返佣金额
@@ -1002,8 +1005,12 @@ class StoreOrderCreateServices extends BaseServices
$useCycleBrokerage = ($cycleCount > 0 && is_array($cycleRates) && count($cycleRates) > 0 && $isQueueGoods === 1);
if ($useCycleBrokerage && $spread_uid > 0) {
// fsgx B1 + B6用事务锁序列化位次计算防止并发竞态导致两笔订单拿到相同位次
$brokerageResult = \think\facade\Db::transaction(function () use ($spread_uid, $cycleCount, $cycleRates, $price) {
// fsgx B1 + B6 + B-2B:用事务锁序列化位次计算,支持多件商品逐件轮巡
$cartNumInt = (int)$cartNum;
// 计算单件价格,用于逐件计算佣金
$unitPrice = $cartNumInt > 0 ? bcdiv((string)$price, (string)$cartNumInt, 4) : '0';
$currentOffset = $queueGoodsOffset;
$brokerageResult = \think\facade\Db::transaction(function () use ($spread_uid, $cycleCount, $cycleRates, $unitPrice, $cartNumInt, $currentOffset) {
// 锁定推荐人行,确保同一推荐人同时只有一个事务在计算位次
\think\facade\Db::name('user')
->where('uid', $spread_uid)
@@ -1021,8 +1028,7 @@ class StoreOrderCreateServices extends BaseServices
return '0';
}
// fsgx B6按 id ASC 排序取位次,比 count 更精确且在锁保护下无竞态
// 当前订单在 paid=1 后已写入,这里取所有已完成订单并按序找到本单排名
// fsgx B6统计推荐人已完成的报单订单数,作为起始位次基准
$completedCount = (int)\think\facade\Db::name('store_order')
->where('spread_uid', $spread_uid)
->where('is_queue_goods', 1)
@@ -1030,14 +1036,20 @@ class StoreOrderCreateServices extends BaseServices
->where('is_del', 0)
->count();
$position = max(0, $completedCount - 1) % $cycleCount;
$cycleRatePercent = isset($cycleRates[$position]) ? (int)$cycleRates[$position] : (int)($cycleRates[0] ?? 0);
if ($cycleRatePercent > 0) {
return bcmul((string)$price, bcdiv((string)$cycleRatePercent, '100', 4), 2);
// fsgx B-2B逐件轮巡每件商品取下一个位次的佣金比例后累加
$total = '0';
for ($i = 0; $i < $cartNumInt; $i++) {
$position = ($completedCount + $currentOffset + $i) % $cycleCount;
$cycleRatePercent = isset($cycleRates[$position]) ? (int)$cycleRates[$position] : (int)($cycleRates[0] ?? 0);
if ($cycleRatePercent > 0) {
$total = bcadd($total, bcmul((string)$unitPrice, bcdiv((string)$cycleRatePercent, '100', 4), 2), 2);
}
}
return '0';
return $total;
});
$oneBrokerage = $brokerageResult;
// 当前购物车项的件数已消费,累加到偏移量
$queueGoodsOffset += $cartNumInt;
} else {
//一级返佣比例 小于等于零时直接返回 不返佣
if ($storeBrokerageRatio > 0) {