18 KiB
name, overview, todos, isProject
| name | overview | todos | isProject | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| Fix Issues 0325-1 | 修复 UniApp 移动端前端(5 个 UI 问题)和 PHP 后端(7 个业务逻辑问题)共 12 个问题,涉及会员码图片、海报生成、账单筛选、导航、资产数据展示、佣金周期轮巡、积分奖励、分销等级升级和 e2e 验收测试。 |
|
false |
修复 docs/issues-0325-1.md 中的问题
第一部分:UniApp 移动端前端问题
所有前端文件位于 pro_v3.5.1/view/uniapp/ 目录下。
A1. 会员码页面图片报错 (pages/users/user_member_code/index.vue)
问题反馈: 前端页面报错 Failed to load local image resource /pages/users/user_member_code/false
问题分析: 小程序端 <image :src="qrc"> 没有 v-if 防护。当 activityCodeApi 接口返回 routineUrl: false(布尔值)时,this.qrc 被赋值为 false,运行时将其字符串化为路径 /pages/users/user_member_code/false,导致图片加载 500 错误。
代码定位:
<!-- #ifdef MP -->
<image :src="qrc" class="qrcode"></image>
以及 API 回调处(约第 135 行):
this.qrc = routineUrl; // routineUrl 可能为 false/null
修复方案:
- 在小程序的
<image>标签上添加v-if="qrc"(第 18 行),与 H5 分支保持一致 - 在
activityCodeApi()中添加兜底:this.qrc = routineUrl || ''
A2. 分销海报加载不出来 (pages/users/user_spread_code/index.vue)
问题反馈: 海报加载不出来
问题分析: downloadFilestoreImage()(约第 354 行)返回的 Promise 在下载失败时既不 resolve 也不 reject,只调用了 Tips()。这导致 await 永久挂起,阻塞了整个海报生成流程。
fail: function() {
return that.$util.Tips({
title: ''
});
修复方案:
- 在
downloadFilestoreImage的fail回调中添加reject()(或resolve('')),让 Promise 正常结束 - 在
spreadMsg中,将下载后的图片路径传入userPosterCanvas前,增加空值/空字符串检查 - 可选:在海报生成循环外包 try/catch,确保
uni.hideLoading()始终执行
A3. 账单明细页 — 移除"公排退款" (pages/users/user_bill/index.vue)
问题反馈: 去掉公排退款
问题分析: 导航栏有"公排退款"筛选标签,列表项中也显示"公排退款"标记。需要全部移除。
修复方案: 从模板中删除以下内容:
- 导航栏中
queue_refund类型对应的<view>(第 23-27 行) - 列表项中的
<text v-if="vo.type === 'queue_refund'" ...>公排退款</text>标记(第 47-50 行)
A4. 佣金状态页 — 增加返回按钮 (pages/queue/status.vue)
问题反馈: 左上角增加返回按钮
问题分析: 页面顶部没有 NavBar 和返回按钮。
修复方案: 参照其他页面的已有模式(如 user_spread_user/index.vue):
- 从
@/components/NavBar.vue导入NavBar(小程序条件编译) - 在
components中注册 - 在模板中添加
<NavBar titleText="佣金状态" :iconColor="iconColor" :textColor="iconColor" showBack :isScrolling="isScrolling" />,用<!-- #ifdef MP -->条件编译包裹 - 添加对应的 data 属性(
iconColor、isScrolling)和滚动事件处理
A5. 资产页 — 数据不显示 + 增加返回按钮 (pages/assets/index.vue)
问题反馈:
- "累计获得积分"不显示数据,是否没读取到数据?
- 左上角增加返回按钮
问题 1 分析: "累计获得积分"显示为 NaN。前端读取 assetsInfo.total_points_earned,但后端 HjfAssets::overview 接口未返回该字段。
- 前端计算属性(约第 148 行):
Number(this.assetsInfo.total_points_earned).toLocaleString()=>NaN - 后端响应(HjfAssets.php 第 42-50 行):仅返回
frozen_points、available_points等,缺少total_points_earned
修复方案(后端): 在 HjfAssets::overview() 的响应中增加 total_points_earned 字段。其值应为 frozen_points + available_points(累计获得 = 当前待释放 + 已释放):
'total_points_earned' => $frozenPoints + (int)($user['available_points'] ?? 0),
问题 2: 左上角没有返回按钮(同 A4)。
修复方案: 按照 A4 相同的模式添加带 showBack 的 NavBar。
第二部分:后端业务逻辑问题
所有后端文件位于 pro_v3.5.1/app/ 目录下。
B1. 自己不报单,推荐没有返现佣金(测试问题 #1)
问题反馈: "自己不报单(没有购买过报单商品的订单),推荐没有返现佣金的"
问题分析: StoreOrderCreateServices.php(约第 998-1028 行)中的佣金周期逻辑在被推荐人下单报单商品时计算佣金,但没有校验推荐人自己是否也购买过报单商品。按业务规则,推荐人自己必须先报单(购买过报单商品),推荐下级报单才能获得返现佣金。
修复方案: 在 computeOrderProductTruePrice 中计算周期佣金之前(约第 1004 行),增加校验:若推荐人($spread_uid)自己没有任何已支付的 is_queue_goods=1 订单,则跳过佣金计算($oneBrokerage = 0)。或者在 Pay.php::compute() 中写入 one_brokerage 前做此校验。
B2. 升级成为会员分销等级前,不给奖励积分(测试问题 #2)
问题反馈: "判断升级成为会员分销等级前,不给奖励积分(直推奖励积分、伞下奖励积分)"
问题分析: 在 Pay.php(第 180-184 行)中,流程是:先检查升级、再发放积分。这意味着如果当前订单使推荐人从 grade 0 升级为创客,reward() 调用时已经看到了新等级,会在触发升级的同一笔订单上就发放直推奖励积分或伞下奖励积分。
根据 PRD,直推奖励积分和伞下奖励积分均应从推荐人已成为会员分销等级之后的订单才开始发放。触发升级的那笔订单本身不应给新升级的用户发积分。
修复方案: 在升级检查执行前,记录各上级用户的"升级前等级"快照,然后在 reward() 中使用升级前的等级判断是否有资格获得直推/伞下奖励积分。具体方式:
- 在 Pay.php 中
checkUserLevelFinish之前,快照相关用户的agent_level - 将升级前的等级信息传入
reward(),用于资格判断 - 或者在
reward()中检查用户的agent_level是否在同一事务/时间窗口内被更新,若是则跳过
B3. 积分应按订单中报单商品数量发放,而非按订单数(测试问题 #3)
问题反馈: "目前积分奖励是按订单数量来给了,需要调整为按报单商品数量,比如一次性下一个订单含3个报单商品,应该给1500积分,而不是500"
问题分析: PointsRewardServices::reward() 每笔订单只调用一次,发放基于等级的固定积分(如创客 500 分)。若一个订单内包含 3 个报单商品(商品数量=3),应发放 3x500=1500 分,而非 500 分。
修复方案:
- 修改
reward()增加$qty参数(默认为 1),表示该订单中报单商品的数量 - 在
grantFrozenPoints中将$points * $qty计算实际积分 - 在 Pay.php(第 184 行)中,从
$orderInfo的购物车信息计算订单内报单商品数量(is_queue_goods=1的商品cart_num之和),传入reward() - 在 HjfOrderPayJob.php 中做同样的修改
B4. 伞下奖励积分规则:创客无伞下积分,云店及以上才有(测试问题 #4)
问题反馈: "创客级别的分销员,伞下下单没有伞下奖励积分,升级为云店级别分销员之后,只要级别低于自己的,伞下下单都应有伞下奖励积分"
问题分析: 按 PRD 各等级积分配置:
| 等级 | 直推奖励积分 | 伞下奖励积分 |
|---|---|---|
| 创客 | 500 | 0 |
| 云店 | 800 | 300 |
| 服务中心(原PRD名:服务商) | 1000 | 200 |
| 合伙人(原PRD名:分公司) | 1300 | 300 |
注意: 数据库中等级名称已调整,"服务商"改为"服务中心","分公司"改为"合伙人"。后续代码及配置中以数据库实际名称为准。
创客的伞下奖励积分为 0,这是正确的设计(非 Bug)。问题焦点是:云店及以上级别的会员在伞下下单后应获得伞下奖励积分,但目前可能未正确发放。
在 PointsRewardServices.php 第 109 行,级差逻辑 $actual = max(0, $reward - $lowerReward) 可能导致云店的伞下积分被下级已获得的奖励抵消为 0。
修复方案:
- 核查
eb_agent_level表中各等级的umbrella_reward_points是否与 PRD 一致(创客=0、云店=300、服务中心=200、合伙人=300) - 确认
AgentLevelServices的getUmbrellaRewardPoints()和getDirectRewardPoints()正确读取该字段并返回 - 如果数据配置正确但云店仍未拿到伞下积分,检查级差计算中
$lowerReward的传递链是否正确——特别注意当中间层(如创客)的伞下积分为 0 时,传给上级的$lowerReward应为 0,云店的$actual应为max(0, 300 - 0) = 300 - 若中间层是以直推奖励积分(500)作为
$lowerReward传递的,则需修复propagateReward使其在递归中区分直推与伞下,确保向上传递的是伞下奖励而非直推奖励
B5. 用户 ID=14 只有 2 单就升级为创客(测试问题 #5)
问题反馈: "用户ID=14直推了2单就升级成为创客的分销等级了,但是目前分销等级中创客的升级任务配置的是直推3单?"
问题分析: AgentLevelTaskServices.php(第 431 行)中 getDirectQueueOrderCount() 统计推荐人直推下级的报单订单数。可能原因:
- 统计包含了已退款的订单(查询条件有
is_del=0,但缺少refund_status检查) no_assess=0过滤条件未正确生效eb_agent_level_task表中创客的任务number被配置为 2 而非 3- 竞态条件:并发订单处理可能触发两次升级检查
修复方案:
- 检查
eb_agent_level_task表确认创客的任务配置为type=6、number=3 - 在
getDirectQueueOrderCount查询中补充refund_status条件检查(目前缺失,而其他任务类型均有refund_status => [0, 3]的检查) - 在升级检查处增加日志,记录升级时刻的精确计数
B6. 推荐返现循环两次都给了 20%(测试问题 #6)
问题反馈: "推荐返现循环目前配置的是'[20,30,50]'。为何用户ID=14直推了2单出现了2次20%的返现佣金?"
问题分析: 在 StoreOrderCreateServices.php 第 1009-1015 行,位次计算通过统计推荐人下级所有已支付的报单订单数来确定。若两笔订单几乎同时处理,两次 compute() 调用可能看到相同的 completedCount,导致位次相同(都得到 20%)。正确行为应是:第 1 单 20%、第 2 单 30%、第 3 单 50%,然后循环。
$position = max(0, $completedCount - 1) % $cycleCount;
修复方案:
- 添加数据库级别的锁(如对 spread_uid 维度加
SELECT ... FOR UPDATE),序列化周期位次计算 - 或者在用户表中增加显式周期计数器字段(如
eb_user表添加brokerage_cycle_position列),原子递增,而非依赖 count 查询 - 或者使用
ORDER BY id ASC按订单排名确定位次,而非仅统计总数
B7. e2e 测试验收分销员等级配置(测试问题 #7).
问题反馈: "e2e测试验收一下分销员等级中配置的奖励积分(直推奖励积分、伞下奖励积分)和等级任务是否正确?"
问题分析: 需要端到端验证 eb_agent_level 和 eb_agent_level_task 表中的数据配置与 PRD 一致。
验收清单:
1) eb_agent_level 表 — 各等级奖励积分配置(PRD 3.2):
| 等级 | grade | direct_reward_points(直推) | umbrella_reward_points(伞下) |
|---|---|---|---|
| 创客 | 1 | 500 | 0 |
| 云店 | 2 | 800 | 300 |
| 服务中心 | 3 | 1000 | 200 |
| 合伙人 | 4 | 1300 | 300 |
2) eb_agent_level_task 表 — 各等级升级任务配置(PRD 3.2):
| 等级 | 任务类型 type | 任务要求 number | 说明 |
|---|---|---|---|
| 创客 | 6(直推报单单数) | 3 | 直推满 3 单 |
| 云店 | 7(伞下报单业绩) | 30 | 伞下满 30 单 |
| 云店 | 8(最低直推人数) | 3 | 至少 3 个直推 |
| 服务中心 | 7(伞下报单业绩) | 100 | 伞下满 100 单 |
| 服务中心 | 8(最低直推人数) | 3 | 至少 3 个直推 |
| 合伙人 | 7(伞下报单业绩) | 1000 | 伞下满 1000 单 |
| 合伙人 | 8(最低直推人数) | 3 | 至少 3 个直推 |
3) 功能验证场景(手动或脚本):
- 创客升级:模拟 3 笔直推报单订单,确认准确在第 3 笔时升级
- 积分发放:确认创客直推积分 500/单、伞下积分 0;云店直推 800/单、伞下 300/单
- 佣金轮巡:模拟 3 笔直推报单订单,确认佣金比例依次为 20%→30%→50%
- 批量报单:一个订单含多个报单商品时,积分按商品数量乘算
修复方案: 编写 SQL 查询脚本或 PHP 命令行工具验证上述配置,不一致则修正数据。
文件修改汇总
| 问题编号 | 主要需修改的文件 |
|---|---|
| A1 | view/uniapp/pages/users/user_member_code/index.vue |
| A2 | view/uniapp/pages/users/user_spread_code/index.vue |
| A3 | view/uniapp/pages/users/user_bill/index.vue |
| A4 | view/uniapp/pages/queue/status.vue |
| A5 | view/uniapp/pages/assets/index.vue、app/controller/api/v1/hjf/HjfAssets.php |
| B1 | app/services/order/StoreOrderCreateServices.php 或 app/listener/order/Pay.php |
| B2 | app/listener/order/Pay.php、app/services/hjf/PointsRewardServices.php |
| B3 | app/services/hjf/PointsRewardServices.php、app/listener/order/Pay.php、app/jobs/hjf/HjfOrderPayJob.php |
| B4 | app/services/hjf/PointsRewardServices.php,核查 eb_agent_level 数据 |
| B5 | app/services/agent/AgentLevelTaskServices.php,核查 eb_agent_level_task 数据 |
| B6 | app/services/order/StoreOrderCreateServices.php |
| B7 | 验证脚本 / SQL 查询(验收 eb_agent_level + eb_agent_level_task 数据配置) |