--- name: toBalance 清零分析 overview: 产品要求 To Balance 后客户端仍展示领取金额。推荐**保留 my_amount_qf 清零**(进度已兑现),在 status 接口对已提取用户用 cashout_record 回填 myAmountDisplay;并禁止已提取用户继续 Spin 污染状态。 todos: - id: build-state-withdrawn-display content: buildStateEntity:playerStatus=已提取时,myAmountDisplay 取自 lucky_reward_cashout_record.amount_qf(大单位) status: completed - id: block-spin-after-withdrawn content: executeManualSpin:status=已提取时拒绝 Spin(防 status/my_amount 被改回可提取) status: completed - id: keep-zero-my-amount content: toBalance 事务内保留 my_amount_qf=0 + status=已提取(不改删除清零逻辑) status: completed - id: sync-docs-yapi content: 更新 lucky_reward_api.md、04 需求 §7、YApi status: completed isProject: false --- # To Balance 后展示领取金额 — 方案(迭代) ## 产品诉求(新增) 客户端 To Balance **成功之后**,仍要在活动页展示**领取时的金额**(含刷新 status、再次进入活动,不能只靠 toBalance 响应本地缓存)。 当前问题:`toBalance` 把 `my_amount_qf = 0` 后,`POST /api/lucky-reward/status` 的 `myAmountDisplay` 变为 `0.00`,客户端无法继续展示 $10.00 等已领取金额。 --- ## 推荐方案:库内清零 + status 展示回填(推荐) **不改为「不清零 my_amount_qf」**,而是区分「活动进度」与「展示金额」: | 层 | 行为 | | --- | --- | | DB `my_amount_qf` | **继续清零** — 表示本轮可 Spin 累积的进度已兑现,避免尾差/Spin 叠加 | | DB `status` | **已提取(3)** — 客户端据此隐藏 To Balance 按钮 | | status 响应 `myAmountDisplay` | **已提取时**从 [`LuckyRewardCashoutRecordModel::findSuccessByUidAndCycle`](slot_console/app/model/common/LuckyRewardCashoutRecordModel.php) 读 `amount_qf`,经 `formatAmountDisplay()` 返回 | 改动点:[`LuckyRewardLogic::buildStateEntity()`](slot_console/app/api/logic/LuckyRewardLogic.php)(约 788–806 行) ```php // 伪代码 if ($hasOpenedBox && (int)$activityPlayer->status === STATUS_WITHDRAWN) { $cashout = LuckyRewardCashoutRecordModel::findSuccessByUidAndCycle($uid, $cycleId); $myAmountQf = $cashout !== null ? (int)$cashout->amount_qf : 0; } else { $myAmountQf = $hasOpenedBox ? (int)$activityPlayer->my_amount_qf : 0; } ``` 展示值为**实际入账金额**(`floor(my_amount/10)*10` 后的值),与 toBalance 响应 `amountDisplay` 一致,语义正确。 ```mermaid flowchart TD toBalance[toBalance 成功] --> zero["my_amount_qf=0\nstatus=已提取"] zero --> cashoutRow[cashout_record 保留 amount_qf] cashoutRow --> statusPoll[客户端调 status] statusPoll --> display["myAmountDisplay=提取金额\nplayerStatus=3"] ``` --- ## 备选方案:取消清零(不推荐单独使用) 删除 `my_amount_qf = 0` 一行,status 直接读库内 `my_amount_qf` 即可展示。 **缺点**(见原分析): - 尾差残留(转入 floor 后库内仍 > 转入额) - 提取后若还有 Spin,[`executeManualSpin`](slot_console/app/api/logic/LuckyRewardLogic.php) 会改 `my_amount_qf` / 把 `status` 改回可提取(2) - 与需求文档 §7「my_amount 本笔归零」不一致 若走此方案,**必须**同步加 Spin 拦截,否则状态机会脏。 --- ## 必须配套:已提取用户禁止 Spin 无论是否清零,[`executeManualSpin()`](slot_console/app/api/logic/LuckyRewardLogic.php) 当前**不校验** `STATUS_WITHDRAWN`。提取后若 `spin_available > 0`(邀请 Spin 等),仍可能: - 增加 `my_amount_qf` - 把 `status` 从 3 改回 2 建议在 Spin 入口增加: ```php if ((int)$activityPlayer->status === LuckyRewardPlayerModel::STATUS_WITHDRAWN) { throw new BusinessException('Already withdrawn this cycle'); } ``` 资金安全仍由 `cashout_record` 幂等保证;此拦截主要为**状态一致 + 展示正确**。 --- ## 客户端约定(无需新字段) 沿用现有 [`LuckyRewardStateEntity`](slot_console/app/entity/luckyReward/LuckyRewardStateEntity.php): - `playerStatus === 3`(已提取)→ 隐藏 To Balance / 展示「已领取」态 - `myAmountDisplay` → 仍展示进度条/金额数字(提取后由服务端回填为领取金额) - toBalance 当场成功仍可用响应 `amountDisplay`;之后以 status 为准 **不新增** `withdrawnAmountDisplay` 字段,除非客户端希望区分「当前可提进度」与「历史已提」——当前产品只需展示领取金额,复用 `myAmountDisplay` 即可。 --- ## 需求文档调整 [`04_slot_console_活动主流程方案.md`](docs/requirements/lucky_rewards/04_slot_console_活动主流程方案.md) §7 第 6 步建议改为: > 成功:写 cashout_record;`player.status=已提取`、**`my_amount_qf` 归零(进度清空)**;**status 接口对已提取用户 `myAmountDisplay` 取 cashout_record.amount_qf 展示**。 --- ## 实施范围(待你确认后执行) | 文件 | 改动 | | --- | --- | | [`LuckyRewardLogic.php`](slot_console/app/api/logic/LuckyRewardLogic.php) | `buildStateEntity` 已提取回填;`executeManualSpin` 拦截已提取 | | 集成测 | 新增/扩展:toBalance 后 status 的 `myAmountDisplay` 等于提取额 | | [`lucky_reward_api.md`](slot_console/doc/lucky_reward_api.md) + YApi #554/#561 | status 字段说明:已提取时 myAmountDisplay 含义 | | 需求 §7 | 与实现对齐 | **不改动**:`toBalance` 内 `my_amount_qf = 0`(保留)。 --- ## 原分析问题答复(更新结论) | 问题 | 更新结论 | | --- | --- | | 必须清零吗? | **库内建议继续清零**;展示不清零,改由 status 回填 | | 不清零唯一目的「展示金额」? | **否**;用 cashout_record 回填更干净 | | 重复打款? | 仍靠 cashout_record,与是否清零无关 |