feat(hjf): 公排入队可配置,默认关闭时同步发放积分奖励
- 新增 hjf_queue_pool_enable(迁移 SQL),后台公排配置读写统一为该键 - Pay 监听:关闭公排时同步执行等级检查与 PointsRewardServices::reward,开启时仍派发 HjfOrderPayJob - PointsRewardServices: bcInc 增量传 string,避免 PHP 类型错误 - hjf:patch-rewards 补偿命令补充等级检查与正确的幂等条件 - uniapp vue.config.js 本地 API 代理调整(H5 开发) - docs/issues-0323-1 更新 Made-with: Cursor
This commit is contained in:
@@ -36,7 +36,7 @@
|
|||||||
1. **已修复**点击获取验证,去除安全验证,直接发送验证码
|
1. **已修复**点击获取验证,去除安全验证,直接发送验证码
|
||||||
|
|
||||||
## 佣金记录页面,uniapp/pages/users/user_spread_money
|
## 佣金记录页面,uniapp/pages/users/user_spread_money
|
||||||
1. 团队业绩统计数据的伞下人数不显示
|
1. **已修复**团队业绩统计数据的伞下人数不显示
|
||||||
|
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|||||||
@@ -3,7 +3,9 @@ declare(strict_types=1);
|
|||||||
|
|
||||||
namespace app\command;
|
namespace app\command;
|
||||||
|
|
||||||
|
use app\services\agent\AgentLevelServices;
|
||||||
use app\services\hjf\PointsRewardServices;
|
use app\services\hjf\PointsRewardServices;
|
||||||
|
use app\services\user\UserServices;
|
||||||
use think\console\Command;
|
use think\console\Command;
|
||||||
use think\console\Input;
|
use think\console\Input;
|
||||||
use think\console\input\Option;
|
use think\console\input\Option;
|
||||||
@@ -57,21 +59,22 @@ class HjfPatchMissingRewards extends Command
|
|||||||
|
|
||||||
/** @var PointsRewardServices $pointsService */
|
/** @var PointsRewardServices $pointsService */
|
||||||
$pointsService = app()->make(PointsRewardServices::class);
|
$pointsService = app()->make(PointsRewardServices::class);
|
||||||
|
/** @var AgentLevelServices $agentLevelServices */
|
||||||
|
$agentLevelServices = app()->make(AgentLevelServices::class);
|
||||||
|
/** @var UserServices $userServices */
|
||||||
|
$userServices = app()->make(UserServices::class);
|
||||||
|
|
||||||
$patched = 0;
|
$patched = 0;
|
||||||
$skipped = 0;
|
$skipped = 0;
|
||||||
|
|
||||||
foreach ($orders as $order) {
|
foreach ($orders as $order) {
|
||||||
|
// 幂等检查:points_release_log 中是否已有 reward_direct/reward_umbrella 记录
|
||||||
$hasRewardLog = Db::name('points_release_log')
|
$hasRewardLog = Db::name('points_release_log')
|
||||||
->where('order_id', $order['order_id'])
|
->where('order_id', $order['order_id'])
|
||||||
->where('type', 'reward_direct')
|
->whereIn('type', ['reward_direct', 'reward_umbrella'])
|
||||||
->count();
|
->count();
|
||||||
|
|
||||||
$hasRewardBill = Db::name('user_bill')
|
if ($hasRewardLog > 0) {
|
||||||
->where('link_id', $order['id'])
|
|
||||||
->where('type', 'hjf_frozen_direct')
|
|
||||||
->count();
|
|
||||||
|
|
||||||
if ($hasRewardLog > 0 || $hasRewardBill > 0) {
|
|
||||||
$skipped++;
|
$skipped++;
|
||||||
$output->writeln(sprintf(' [SKIP] 订单 #%d (%s) 已有积分奖励记录', $order['id'], $order['order_id']));
|
$output->writeln(sprintf(' [SKIP] 订单 #%d (%s) 已有积分奖励记录', $order['id'], $order['order_id']));
|
||||||
continue;
|
continue;
|
||||||
@@ -93,11 +96,23 @@ class HjfPatchMissingRewards extends Command
|
|||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
$pointsService->reward((int)$order['uid'], (string)$order['order_id'], (int)$order['id']);
|
$uid = (int)$order['uid'];
|
||||||
|
// 先执行等级升级检查,确保积分奖励使用正确的 agent_level
|
||||||
|
$userCacheInfo = $userServices->getUserCacheInfo($uid);
|
||||||
|
$spreadUid = $userCacheInfo ? (int)($userCacheInfo['spread_uid'] ?? 0) : (int)$order['spread_uid'];
|
||||||
|
$twoSpreadUid = 0;
|
||||||
|
if ($spreadUid > 0 && $oneUserInfo = $userServices->getUserCacheInfo($spreadUid)) {
|
||||||
|
$twoSpreadUid = $userServices->getSpreadUid($spreadUid, $oneUserInfo, false);
|
||||||
|
}
|
||||||
|
$uids = array_values(array_filter(array_unique([$uid, $spreadUid, $twoSpreadUid])));
|
||||||
|
$agentLevelServices->checkUserLevelFinish($uid, $uids);
|
||||||
|
|
||||||
|
// 发放积分奖励(PointsRewardServices 内部已做幂等检查)
|
||||||
|
$pointsService->reward($uid, (string)$order['order_id'], (int)$order['id']);
|
||||||
$patched++;
|
$patched++;
|
||||||
$output->writeln(sprintf(
|
$output->writeln(sprintf(
|
||||||
' [PATCHED] 订单 #%d (%s) 已补发积分奖励',
|
' [PATCHED] 订单 #%d (%s) uid=%d 等级检查+积分奖励已补发',
|
||||||
$order['id'], $order['order_id']
|
$order['id'], $order['order_id'], $uid
|
||||||
));
|
));
|
||||||
} catch (\Throwable $e) {
|
} catch (\Throwable $e) {
|
||||||
$output->writeln(sprintf(
|
$output->writeln(sprintf(
|
||||||
|
|||||||
@@ -54,7 +54,7 @@ class QueueController extends AuthController
|
|||||||
'trigger_multiple' => (int)SystemConfigService::get('hjf_trigger_multiple', 4),
|
'trigger_multiple' => (int)SystemConfigService::get('hjf_trigger_multiple', 4),
|
||||||
'release_rate' => (int)SystemConfigService::get('hjf_release_rate', 4),
|
'release_rate' => (int)SystemConfigService::get('hjf_release_rate', 4),
|
||||||
'withdraw_fee_rate' => (int)SystemConfigService::get('hjf_withdraw_fee_rate', 7),
|
'withdraw_fee_rate' => (int)SystemConfigService::get('hjf_withdraw_fee_rate', 7),
|
||||||
'enabled' => (bool)SystemConfigService::get('hjf_queue_enabled', 1),
|
'enabled' => (bool)SystemConfigService::get('hjf_queue_pool_enable', 0),
|
||||||
];
|
];
|
||||||
return $this->success($config);
|
return $this->success($config);
|
||||||
}
|
}
|
||||||
@@ -75,7 +75,7 @@ class QueueController extends AuthController
|
|||||||
'hjf_trigger_multiple' => (int)$data['trigger_multiple'],
|
'hjf_trigger_multiple' => (int)$data['trigger_multiple'],
|
||||||
'hjf_release_rate' => (int)$data['release_rate'],
|
'hjf_release_rate' => (int)$data['release_rate'],
|
||||||
'hjf_withdraw_fee_rate' => (int)$data['withdraw_fee_rate'],
|
'hjf_withdraw_fee_rate' => (int)$data['withdraw_fee_rate'],
|
||||||
'hjf_queue_enabled' => (int)$data['enabled'],
|
'hjf_queue_pool_enable' => (int)$data['enabled'],
|
||||||
];
|
];
|
||||||
|
|
||||||
foreach ($map as $key => $value) {
|
foreach ($map as $key => $value) {
|
||||||
|
|||||||
@@ -14,6 +14,8 @@ namespace app\listener\order;
|
|||||||
|
|
||||||
use app\jobs\agent\AgentJob;
|
use app\jobs\agent\AgentJob;
|
||||||
use app\jobs\hjf\HjfOrderPayJob;
|
use app\jobs\hjf\HjfOrderPayJob;
|
||||||
|
use app\services\agent\AgentLevelServices;
|
||||||
|
use app\services\hjf\PointsRewardServices;
|
||||||
use app\jobs\order\OrderCreateAfterJob;
|
use app\jobs\order\OrderCreateAfterJob;
|
||||||
use app\jobs\order\OrderDeliveryJob;
|
use app\jobs\order\OrderDeliveryJob;
|
||||||
use app\jobs\order\OrderJob;
|
use app\jobs\order\OrderJob;
|
||||||
@@ -149,13 +151,43 @@ class Pay implements ListenerInterface
|
|||||||
//对外接口推送事件
|
//对外接口推送事件
|
||||||
event('out.outPush', ['order_pay_push', ['order_id' => (int)$orderInfo['id']]]);
|
event('out.outPush', ['order_pay_push', ['order_id' => (int)$orderInfo['id']]]);
|
||||||
|
|
||||||
// 公排入队 + 积分奖励 + 等级升级(仅报单商品订单)
|
// 报单商品订单:等级检查 + 积分奖励 + 公排入队(受 hjf_queue_pool_enable 控制)
|
||||||
if (!empty($orderInfo['is_queue_goods'])) {
|
if (!empty($orderInfo['is_queue_goods'])) {
|
||||||
|
$queuePoolEnable = (int)sys_config('hjf_queue_pool_enable', 0);
|
||||||
|
if ($queuePoolEnable) {
|
||||||
|
// 公排模式(开启):异步派发,含公排入队 + 等级检查 + 积分奖励
|
||||||
HjfOrderPayJob::dispatch([
|
HjfOrderPayJob::dispatch([
|
||||||
(int)$orderInfo['uid'],
|
(int)$orderInfo['uid'],
|
||||||
(string)$orderInfo['order_id'],
|
(string)$orderInfo['order_id'],
|
||||||
(float)($orderInfo['pay_price'] ?? 3600.00),
|
(float)($orderInfo['pay_price'] ?? 3600.00),
|
||||||
]);
|
]);
|
||||||
|
} else {
|
||||||
|
// 非公排模式(默认关闭):同步执行等级检查 + 积分奖励,不入公排池,不依赖队列
|
||||||
|
try {
|
||||||
|
$uid = (int)$orderInfo['uid'];
|
||||||
|
/** @var UserServices $userServices */
|
||||||
|
$userServices = app()->make(UserServices::class);
|
||||||
|
$userCacheInfo = $userServices->getUserCacheInfo($uid);
|
||||||
|
$spreadUid = $userCacheInfo ? (int)($userCacheInfo['spread_uid'] ?? 0) : 0;
|
||||||
|
$twoSpreadUid = 0;
|
||||||
|
if ($spreadUid > 0 && $oneUserInfo = $userServices->getUserCacheInfo($spreadUid)) {
|
||||||
|
$twoSpreadUid = $userServices->getSpreadUid($spreadUid, $oneUserInfo, false);
|
||||||
|
}
|
||||||
|
$uids = array_filter(array_unique([$uid, $spreadUid, $twoSpreadUid]));
|
||||||
|
|
||||||
|
/** @var AgentLevelServices $agentLevelServices */
|
||||||
|
$agentLevelServices = app()->make(AgentLevelServices::class);
|
||||||
|
$agentLevelServices->checkUserLevelFinish($uid, array_values($uids));
|
||||||
|
|
||||||
|
/** @var PointsRewardServices $pointsService */
|
||||||
|
$pointsService = app()->make(PointsRewardServices::class);
|
||||||
|
$pointsService->reward($uid, (string)$orderInfo['order_id'], (int)$orderInfo['id']);
|
||||||
|
|
||||||
|
Log::info('[Pay] 同步积分奖励发放完成 uid=' . $uid . ' order_id=' . $orderInfo['id']);
|
||||||
|
} catch (\Throwable $e) {
|
||||||
|
Log::error('[Pay] 同步积分奖励失败 order_id=' . $orderInfo['id'] . ': ' . $e->getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
//自动打标签
|
//自动打标签
|
||||||
event('user.auto.label', [$orderInfo['uid'], '', [], []]);
|
event('user.auto.label', [$orderInfo['uid'], '', [], []]);
|
||||||
|
|||||||
@@ -143,7 +143,7 @@ class PointsRewardServices extends BaseServices
|
|||||||
int $orderDbId = 0
|
int $orderDbId = 0
|
||||||
): void {
|
): void {
|
||||||
Db::transaction(function () use ($uid, $points, $orderId, $type, $mark, $orderDbId) {
|
Db::transaction(function () use ($uid, $points, $orderId, $type, $mark, $orderDbId) {
|
||||||
$this->userDao->bcInc($uid, 'frozen_points', $points, 'uid');
|
$this->userDao->bcInc($uid, 'frozen_points', (string)$points, 'uid');
|
||||||
|
|
||||||
$this->logDao->save([
|
$this->logDao->save([
|
||||||
'uid' => $uid,
|
'uid' => $uid,
|
||||||
|
|||||||
@@ -341,7 +341,11 @@ VALUES
|
|||||||
|
|
||||||
(0, 'hjf_fee_rate', 'text', 'input', 0,
|
(0, 'hjf_fee_rate', 'text', 'input', 0,
|
||||||
'', 0, '', 100, 0,
|
'', 0, '', 100, 0,
|
||||||
'7', '提现手续费率(%)', '申请提现时收取的手续费比例,默认7%', 30, 1);
|
'7', '提现手续费率(%)', '申请提现时收取的手续费比例,默认7%', 30, 1),
|
||||||
|
|
||||||
|
(0, 'hjf_queue_pool_enable', 'text', 'input', 0,
|
||||||
|
'', 0, '', 100, 0,
|
||||||
|
'0', '公排入队开关', '0=关闭(积分同步发放) 1=开启(通过队列异步处理)', 5, 1);
|
||||||
|
|
||||||
|
|
||||||
-- ============================================================
|
-- ============================================================
|
||||||
|
|||||||
@@ -4,15 +4,15 @@ module.exports = {
|
|||||||
port: 8080,
|
port: 8080,
|
||||||
proxy: {
|
proxy: {
|
||||||
'/api': {
|
'/api': {
|
||||||
target: 'http://127.0.0.1',
|
target: 'http://127.0.0.1:20199',
|
||||||
changeOrigin: true
|
changeOrigin: true
|
||||||
},
|
},
|
||||||
'/uploads': {
|
'/uploads': {
|
||||||
target: 'http://127.0.0.1',
|
target: 'http://127.0.0.1:20199',
|
||||||
changeOrigin: true
|
changeOrigin: true
|
||||||
},
|
},
|
||||||
'/statics': {
|
'/statics': {
|
||||||
target: 'http://127.0.0.1',
|
target: 'http://127.0.0.1:20199',
|
||||||
changeOrigin: true
|
changeOrigin: true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user