每日免费发放额为 0 时前端隐藏该池

- 后端:module-runtime 的 daily_free_points_per_day 校验由「必须大于 0」放宽为只校验上界,错误变体改名 DailyFreePointsPerDayOverflow
- 前端共享层:mudPoints 新增 shouldShowProfileDailyFreePool,判定 remaining > 0 || reset > 0,判定收口一处
- 钱包入口:PlatformMudPointWalletEntry 在每日免费发放额为 0 且无存量时隐藏该行
- 充值弹层:PlatformProfileRechargeModal 池概览按可见池渲染(三列变两列),扣点顺序提示与泥点确认页文案随可见性切换
- Admin Web:账号配置页每日免费泥点允许填 0(校验、min 与文案同步)
- 测试:删除「每日免费必然存在」断言,新增隐藏 / 有存量仍显示 / 发放额为正三类用例,并修正钱包入口测试在 HEAD 上失效的选择器
- 文档:更新会员与泥点前端改造设计文档 §14 与 shared-memory 决策记录
This commit is contained in:
2026-10-03 16:48:12 +08:00
parent 43f0c51120
commit 1a106eadef
14 changed files with 326 additions and 55 deletions
@@ -1,4 +1,14 @@
# 决策记录
## 2026-10-03 每日免费发放额为 0 时前端隐藏该池
- 背景:运营需要一个可逆的「不提供每日免费泥点」状态。不给它新增 `retired` 状态位或新字段,直接把后台配置 `daily_free_points_per_day` 配成 0,让「每日免费发放额」这个普通数值自己表达;前端据此隐藏每日免费相关入口。
- 决策(信号取 `dailyFreeResetPoints` 而非剩余):`ProfileMudPointBalance.dailyFreeResetPoints <= 0` 表示不提供该池。`dailyFreePoints`(当天剩余)为 0 是每天用完后的正常状态,不能当信号。
- 决策(显示规则 `remaining > 0 || reset > 0`):当天仍有存量(配置中途改成 0,但当天已发未用完)时必须继续展示——扣点顺序不变,这部分存量会被优先扣减,隐藏后用户会「有余额看不见、还被先扣」。判定收口到 `packages/shared/src/utils/mudPoints.ts` 的 `shouldShowProfileDailyFreePool`,三端共享组件共用,消费方 controller 不改。
- 决策(后端放开校验、不新增契约字段):`server-rs/crates/module-runtime/src/commands.rs` 的 `daily_free_points_per_day` 由「必须 > 0」放宽为 `0..=i64::MAX`,错误变体改名为 `DailyFreePointsPerDayOverflow`;`0` 本就是 `u64` 合法值,`shared-contracts` / ts-rs 生成物 / OpenAPI 不改。发放与账本逻辑不变(`amount_delta == 0` 时后端本就跳过写账)。
- 影响范围:`packages/shared/src/utils/mudPoints.ts`、`PlatformMudPointWalletEntry`、`PlatformProfileRechargeModal`(池概览 3 列变 2 列、扣点顺序提示与泥点确认页文案随可见性切换)、`apps/admin-web/src/pages/AdminProfileWalletConfigPage.tsx`(每日免费允许填 0)、`server-rs/crates/module-runtime/{commands,errors,lib}.rs`;`daily_free_grant` / `daily_free_reset` 账本文案保留,历史流水不改写。
- 验证:`cargo check -p module-runtime`、`cargo test -p module-runtime profile_wallet_config_allows_zero_daily_free_points`、`cargo fmt --check`、根 `npm run typecheck`、`npm run admin-web:typecheck`、共享层与 admin 定向 vitest 22/22、`npm run check:encoding`、`git diff --check` 通过。
## 2026-10-02 资源编辑远端失败的原始原因穿出到工具错误,资源编辑错误通道补一层 typed
- 背景:轮询到 `status=failed` 时客户端只读 `status`,丢掉平台在同一个响应里给的 `error`(契约 `ExternalEditorGenerationJobResponse.error`),统一写 `terminal_failure_code = remote-generation-failed` 并返回「remote-terminal-failed: 资源编辑生成失败」。平台的可行动原因就此消失:模型与用户卡片只看到一句「失败了」,重试路径(`ensure_resource_edit_phase_resumable`)也只有分类码。这违反 `pitfalls.md`「远端资源编辑终态必须指出唯一出口」里已写下的口径——「首次失败的原始拒绝说明继续由当次错误文案承担」;提交期 HTTP 400 分支(`editor_api_rejection_reason`)兑现了,轮询分支没有。另外 `remote-terminal-failed:` 只是文案前缀(全仓没有 `starts_with` 解析它),在第一句失败文案里与「失败」重复。
@@ -300,3 +300,43 @@ onConfirmMembershipPayment: () => void;
### 13.3 既有问题(非本次引入)
- `ImageCanvasEditorView.test.tsx > shows the breakdown read failure without inventing rows` 在改动前的基线同样失败(已用 `git stash` 对照验证):弹层打开时仍处于 loading 分支,断言未等待错误态。属既有时序问题,本次未修改该行为。
---
## 14. 追加变更:每日免费发放额为 0 时隐藏(2026-10-03)
### 14.1 语义
- **不引入** `retired` / 状态位 / 新字段;每日免费只是一个普通数值,发放额可以是 0。
- **唯一信号**:`ProfileMudPointBalance.dailyFreeResetPoints <= 0`(后端每日发放额,来自后台配置 `daily_free_points_per_day`)。
- **可逆**:后台把配置改回 > 0,前端下次读取自动恢复展示,无需额外开关。
- **契约不变**:`ProfileMudPointBalanceResponse` 字段仍是必填 `u64`,`0` 本就合法;不改 `shared-contracts`、ts-rs 生成物与 OpenAPI。
- **扣减与账本逻辑不变**:每日免费为 0 时不再产生发放账本(`profile.rs` 在 `amount_delta == 0` 时直接返回),创作扣点顺序仍为每日免费 → 月度 → 永久。
### 14.2 显示规则
```
showDailyFreePool = dailyFreePoints > 0 || dailyFreeResetPoints > 0
```
| 场景 | dailyFreePoints | dailyFreeResetPoints | 表现 |
|---|---|---|---|
| 当天正常用完 | 0 | 20 | 显示("每天重置为 20") |
| 每日免费发放额为 0 | 0 | 0 | 隐藏 |
| 配置中途改为 0,当天仍有存量 | > 0 | 0 | 显示(存量仍会被优先扣减,不能隐身) |
判定收敛到 `packages/shared/src/utils/mudPoints.ts` 的纯函数,三端共享组件共用,消费方 controller 不改。
### 14.3 改动点
- 后端 `server-rs/crates/module-runtime/src/commands.rs`:`daily_free_points_per_day` 由"必须 > 0"放宽为 `0..=i64::MAX`;`errors.rs` 对应文案同步。
- Admin Web `apps/admin-web/src/pages/AdminProfileWalletConfigPage.tsx`:每日免费泥点允许填 0。
- 共享层 `packages/shared/src/utils/mudPoints.ts`:新增 `shouldShowProfileDailyFreePool`。
- 共享层 `PlatformMudPointWalletEntry`:为 0 时隐藏"每日免费泥点"行。
- 共享层 `PlatformProfileRechargeModal`:池概览按可见池动态渲染(三列变两列)、隐藏扣点顺序提示中与每日免费相关的口径。
- 账本来源文案 `daily_free_grant` / `daily_free_reset` 保留,历史流水不改写。
### 14.4 测试
- 删除"每日免费必然存在"的断言(`PlatformMudPointWalletEntry`、`ImageCanvasTopbarView`、`ImageCanvasEditorView`),改为在共享层新增"发放额为 0 隐藏 / 有存量仍显示"的行为用例。
- 后端与 Admin 追加"允许 0"的用例。