Files
huangjingfen/pro_v3.5.1/app/services/hjf/PointsRewardServices.php
apple 8592243d36 feat(hjf): H5路由修复、分销等级显示优化、个人中心等级徽章
H5 部署与路由:
- manifest.json: router.base 改为 "/" 适配 public/ 根目录部署
- nginx-crmeb.conf: 恢复与 feature/fsgx 一致的原始配置
- App.vue: PC端重定向路径改为动态推导,修复死循环加载问题
- static/html/pc.html: 动态推导 H5 根路径,适配本地/云端两种部署

H5登录:
- pages/users/login/index.vue: H5端获取验证码跳过安全验证(条件编译)

分销等级展示修复:
- AgentLevelServices: 新增 loadHjfUserListLevelMaps/pickHjfLevelRowForUserListDisplay
  统一等级名称解析逻辑,优先返回 HJF 官方名称;新增 getUpgradeTasksForLevel 封装
- UserServices/MemberLevelServices: 改用统一解析方法,修复 protected $dao 访问错误
- api/hjf/MemberController: 直接取 eb_agent_level.name,新增 agent_level 原始值返回
- admin/v1/hjf/MemberController: team() 改用封装方法替代直接访问 protected dao

个人中心等级徽章:
- pages/user/index.vue + member/index.vue: memberInfo 沿链路透传
- member/template1.vue: UID右侧显示HjfMemberBadge,直接读 userInfo.agent_level_name
  无需等待异步 memberInfo,agentLevelGrade 计算属性从名称推导颜色等级

商品列表修复:
- BaseController.php/Common.php: 恢复加密版,修复 CRMEB 授权检查失败导致的400错误
- StoreProduct model: 移除冲突的 model maker 回调

数据库:
- hjf_migration.sql: 完善会员等级体系迁移脚本
- eb_agent_level.sql: 新增等级初始数据脚本

Made-with: Cursor
2026-03-22 01:43:36 +08:00

136 lines
4.1 KiB
PHP
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<?php
declare(strict_types=1);
namespace app\services\hjf;
use app\dao\hjf\PointsReleaseLogDao;
use app\dao\user\UserDao;
use app\services\agent\AgentLevelServices;
use app\services\BaseServices;
use think\annotation\Inject;
use think\facade\Db;
use think\facade\Log;
/**
* 积分奖励服务(级差计算)—— 改造复用版
*
* 改造要点PRD 3.2.2
* - 使用 eb_user.agent_level (FK → eb_agent_level.id) 获取会员等级
* - 从 eb_agent_level 表的 direct_reward_points / umbrella_reward_points 字段读取奖励积分
* - 不再使用独立的 member_level 字段和系统配置表中的 hjf_reward_* 键
*
* Class PointsRewardServices
* @package app\services\hjf
*/
class PointsRewardServices extends BaseServices
{
#[Inject]
protected PointsReleaseLogDao $logDao;
#[Inject]
protected UserDao $userDao;
#[Inject]
protected AgentLevelServices $agentLevelServices;
/**
* 对一笔报单订单发放积分奖励
*/
public function reward(int $orderUid, string $orderId): void
{
try {
$buyer = $this->userDao->get($orderUid);
if (!$buyer || !$buyer['spread_uid']) {
return;
}
$this->propagateReward($buyer['spread_uid'], $orderUid, $orderId, 0);
} catch (\Throwable $e) {
Log::error("[PointsReward] 积分奖励失败 orderUid={$orderUid} orderId={$orderId}: " . $e->getMessage());
}
}
/**
* 向上递归发放级差积分
*
* @param int $uid 当前被奖励用户
* @param int $fromUid 触发方(下级)用户 ID
* @param string $orderId 来源订单号
* @param int $lowerReward 下级已获得的直推/伞下奖励积分(用于级差扣减)
* @param int $depth 递归深度
*/
private function propagateReward(
int $uid,
int $fromUid,
string $orderId,
int $lowerReward,
int $depth = 0
): void {
if ($depth >= 10 || $uid <= 0) {
return;
}
$user = $this->userDao->get($uid);
if (!$user) {
return;
}
$agentLevelId = (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);
}
return;
}
$isDirect = ($depth === 0);
$reward = $isDirect
? $this->agentLevelServices->getDirectRewardPoints($agentLevelId)
: $this->agentLevelServices->getUmbrellaRewardPoints($agentLevelId);
$actual = max(0, $reward - $lowerReward);
if ($actual > 0) {
$this->grantFrozenPoints(
$uid,
$actual,
$orderId,
$isDirect ? 'reward_direct' : 'reward_umbrella',
($isDirect ? '直推奖励' : '伞下奖励(级差)') . " - 来源订单 {$orderId}"
);
}
if ($user['spread_uid']) {
$this->propagateReward(
(int)$user['spread_uid'],
$uid,
$orderId,
$reward,
$depth + 1
);
}
}
/**
* 写入待释放积分frozen_points并记录明细
*/
private function grantFrozenPoints(int $uid, int $points, string $orderId, string $type, string $mark): void
{
Db::transaction(function () use ($uid, $points, $orderId, $type, $mark) {
$this->userDao->bcInc($uid, 'frozen_points', $points, 'uid');
$this->logDao->save([
'uid' => $uid,
'points' => $points,
'pm' => 1,
'type' => $type,
'title' => ($type === 'reward_direct') ? '直推奖励' : '伞下奖励',
'mark' => $mark,
'status' => 'frozen',
'order_id' => $orderId,
]);
});
}
}