Files
huangjingfen/.cursor/plans/fix_issues_0325-1_f8488785.plan.md
2026-03-28 11:26:32 +08:00

18 KiB
Raw Permalink Blame History

name, overview, todos, isProject
name overview todos isProject
Fix Issues 0325-1 修复 UniApp 移动端前端5 个 UI 问题)和 PHP 后端7 个业务逻辑问题)共 12 个问题,涉及会员码图片、海报生成、账单筛选、导航、资产数据展示、佣金周期轮巡、积分奖励、分销等级升级和 e2e 验收测试。
id content status
a1-member-code-image 修复会员码页面:小程序 image 标签加 v-if 防护API 返回值兜底 completed
id content status
a2-spread-poster 修复分销海报downloadFilestoreImage 失败时 Promise 需 resolve/reject增加错误处理 completed
id content status
a3-bill-remove-queue-refund 账单明细页移除"公排退款"标签和筛选项 completed
id content status
a4-queue-status-back-btn 佣金状态页左上角增加返回按钮NavBar completed
id content status
a5-assets-data-and-back 后端 HjfAssets 接口补充 total_points_earned 字段 + 资产页增加返回按钮 completed
id content status
b1-commission-guard 增加校验:推荐人自己必须有报单订单才能获得推荐返现佣金 completed
id content status
b2-points-pre-upgrade 升级为会员分销等级前,不给直推/伞下奖励积分 completed
id content status
b3-points-by-qty 积分奖励按订单中报单商品数量(而非订单数)发放 completed
id content status
b4-umbrella-points 修复伞下积分:创客无伞下积分,云店及以上才有伞下奖励积分,检查配置与级差逻辑 completed
id content status
b5-upgrade-count 修复创客升级getDirectQueueOrderCount 补充 refund_status 检查,核实任务配置 completed
id content status
b6-cycle-race 修复推荐返现循环并发竞态:用数据库锁或原子计数器序列化位次计算 completed
id content status
b7-e2e-verify e2e 测试验收分销员等级配置的奖励积分(直推/伞下)和等级升级任务是否正确 completed
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: ''
						});

修复方案:

  • downloadFilestoreImagefail 回调中添加 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 属性(iconColorisScrolling)和滚动事件处理

A5. 资产页 — 数据不显示 + 增加返回按钮 (pages/assets/index.vue)

问题反馈:

  1. "累计获得积分"不显示数据,是否没读取到数据?
  2. 左上角增加返回按钮

问题 1 分析: "累计获得积分"显示为 NaN。前端读取 assetsInfo.total_points_earned,但后端 HjfAssets::overview 接口未返回该字段。

  • 前端计算属性(约第 148 行):Number(this.assetsInfo.total_points_earned).toLocaleString() => NaN
  • 后端响应(HjfAssets.php 第 42-50 行):仅返回 frozen_pointsavailable_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
  • 确认 AgentLevelServicesgetUmbrellaRewardPoints()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=6number=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_leveleb_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.vueapp/controller/api/v1/hjf/HjfAssets.php
B1 app/services/order/StoreOrderCreateServices.phpapp/listener/order/Pay.php
B2 app/listener/order/Pay.phpapp/services/hjf/PointsRewardServices.php
B3 app/services/hjf/PointsRewardServices.phpapp/listener/order/Pay.phpapp/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 数据配置)