后台模型定价保存去掉版本比对:保存即整段覆盖
- shared-contracts:删掉 `EDITOR_GENERATION_PRICING_VERSION_CONFLICT` 常量 - spacetime-module:`EditorGenerationPricingConfigUpsertInput` 去掉期望版本字段,删掉版本比对方法与它的用例,入库只按请求内容整段覆盖 - spacetime-client:重新生成定价 upsert input 绑定(少一个字段),记录映射同步去掉版本 - api-server:进程内缓存去掉版本字段与 409 冲突错误,`editor_generation_pricing()` / `save_editor_generation_pricing()` 只返回配置本身,`EditorGenerationPricingStore::replace` 注释写明「只是缓存刷新、不做版本校验、不是拦截点」 - api-server admin/app:后台 GET 不再返回 `updatedAtMicros`,POST 不再读 `expectedUpdatedAtMicros`,删掉 409 映射与「旧版本被拒」用例,新增「连续保存两次以后一次为准」 - admin-web:定价类型去掉版本字段,保存请求不再回传版本,删掉 409 分支与「重新读取」提示及其用例 - docs:主规范新增「保存语义」段(整段覆盖、同时只有一个管理员在操作、缓存替换不是拦截点),后端数据契约、ADR 0005、里程碑 / 实施计划、决策记录与 pitfalls 同步为删除版本比对
This commit is contained in:
@@ -1,8 +1,9 @@
|
||||
# 3D 生成定价后台可编辑实施计划
|
||||
|
||||
Version: 1.0
|
||||
Version: 1.1
|
||||
Status: active
|
||||
Date: 2026-09-23
|
||||
修订: 2026-09-24 —— 保存删除定价版本比对:`SpacetimeType` input 去掉 `expected_updated_at_micros`,后台 GET 不再返回 `updatedAtMicros`,admin-web 去掉 409 分支与「重新读取」提示,改为整段覆盖;见 `docs/project-memory/shared-memory/decision-log.md`。
|
||||
Milestone Spec: `docs/project-memory/plans/【里程碑】3D生成定价后台可编辑-2026-09-23.md`
|
||||
|
||||
## 边界
|
||||
@@ -13,16 +14,16 @@ Milestone Spec: `docs/project-memory/plans/【里程碑】3D生成定价后台
|
||||
|
||||
| 文件 | 职责 |
|
||||
| --- | --- |
|
||||
| `server-rs/crates/spacetime-module/src/editor_project_storage.rs` | 表追加两列,新增按端点分段的 `SpacetimeType` 行类型(版本价行 / 加价项行),upsert input / snapshot 扩字段,事务内做期望版本 CAS |
|
||||
| `server-rs/crates/spacetime-module/src/editor_project_storage.rs` | 表追加两列,新增按端点分段的 `SpacetimeType` 行类型(版本价行 / 加价项行),upsert input / snapshot 扩字段(2026-09-24 修订后 input 不再有期望版本) |
|
||||
| `server-rs/crates/spacetime-module/src/migration.rs` | 行形状变更的迁移登记与白名单 |
|
||||
| `server-rs/crates/spacetime-client/src/module_bindings/**`、`src/active/mapper/editor_project.rs` | 生成绑定的记录映射:两段行、定价版本字段 |
|
||||
| `server-rs/crates/spacetime-client/src/module_bindings/**`、`src/active/mapper/editor_project.rs` | 生成绑定的记录映射:两段行 |
|
||||
| `server-rs/crates/api-server/src/tripo3d/pricing.rs` | 两段强类型定价、按段强校验、按端点段查价 |
|
||||
| `server-rs/crates/api-server/config/editor-generation-pricing.default.json` | 两段并列的受控默认价 |
|
||||
| `server-rs/crates/api-server/src/editor_generation_config.rs` | 两段解析 / 校验 / `model3d_price` / 定价版本字段与 `with_previous_model3d` 的退役 |
|
||||
| `server-rs/crates/api-server/src/state.rs` | `to_records` / `from_record` 的两段序列化与契约归一化、保存路径接入 CAS |
|
||||
| `server-rs/crates/api-server/src/admin.rs` | GET 返回定价版本、POST 两段必填、409 错误映射 |
|
||||
| `apps/admin-web/src/api/adminApiTypes.ts`、`adminApiClient.ts` | 两段类型与 409 透出 |
|
||||
| `apps/admin-web/src/pages/AdminEditorGenerationPricingPage.tsx` | 3D 区块、本地校验、409 / 400 提示 |
|
||||
| `server-rs/crates/api-server/src/editor_generation_config.rs` | 两段解析 / 校验 / `model3d_price` 与 `with_previous_model3d` 的退役(2026-09-24 修订后进程内缓存只剩配置本身,不含版本) |
|
||||
| `server-rs/crates/api-server/src/state.rs` | `to_records` / `from_record` 的两段序列化与契约归一化、保存路径接入入库(2026-09-24 修订后不做版本比对) |
|
||||
| `server-rs/crates/api-server/src/admin.rs` | GET 返回两段定价、POST 两段必填(2026-09-24 修订后不再有定价版本与 409 映射) |
|
||||
| `apps/admin-web/src/api/adminApiTypes.ts`、`adminApiClient.ts` | 两段类型(2026-09-24 修订后不再有定价版本字段) |
|
||||
| `apps/admin-web/src/pages/AdminEditorGenerationPricingPage.tsx` | 3D 区块、本地校验、400 提示(2026-09-24 修订后删除 409 提示) |
|
||||
|
||||
## 步骤
|
||||
|
||||
@@ -42,13 +43,13 @@ Milestone Spec: `docs/project-memory/plans/【里程碑】3D生成定价后台
|
||||
- 验收:结构体 record 往返不丢 3D;手工从 record 删掉一个版本键后读取仍成功且补齐该键;塞入契约外键后读取成功且该键被剔除并告警。
|
||||
|
||||
4. **后台契约**
|
||||
- GET 响应加定价版本;POST 要求两段显式给出,带期望版本做事务内 CAS,不匹配返回 409 与中文文案。
|
||||
- GET 响应给两段定价;POST 要求两段显式给出,合法即整段覆盖(2026-09-24 修订:不再带期望版本、不返回 409)。
|
||||
- 退役 `with_previous_model3d` 与其用例,改为「缺段即 400」。
|
||||
- 验收:缺段 400、段内缺键 400、版本不匹配 409 且不落库;保存后公开路由立即返回新价。
|
||||
- 验收:缺段 400、段内缺键 400 且不落库;保存后公开路由立即返回新价,连续保存以来后一次为准。
|
||||
|
||||
5. **admin-web 3D 区块**
|
||||
- 类型补两段;页面按端点渲染版本 × 两档价与加价项输入;提交前校验全部数值 ≥ 1;409 提示重新读取。
|
||||
- 验收:组件用例覆盖渲染、校验、保存 payload 与 409 提示。
|
||||
- 类型补两段;页面按端点渲染版本 × 两档价与加价项输入;提交前校验全部数值 ≥ 1。
|
||||
- 验收:组件用例覆盖渲染、校验与保存 payload。
|
||||
|
||||
6. **文档与验收**
|
||||
- 同步主规范、表目录、`CONTEXT.md`、ADR 0005 的实现状态,必要时补 `pitfalls.md`(例如「不要把省略即沿用重新引入」)。
|
||||
@@ -61,7 +62,7 @@ Milestone Spec: `docs/project-memory/plans/【里程碑】3D生成定价后台
|
||||
| 1 schema 两列 | 完成 | `774b74d3d`;module 表尾部追加两列与展平行类型,绑定重新生成,`npm run check:spacetime-schema` 通过 |
|
||||
| 2 定价类型与默认文件 | 完成 | `9f4a71d2e`;`Model3dPricingConfig` 两段并列 + `Model3dEndpointPricing`,默认 JSON 同步 |
|
||||
| 3 记录转换与归一化 | 完成 | `5e47f0c41`、`952bc1cca`;新增 `editor_generation_model3d_records` 深模块,覆盖文件降级为种子与兜底 |
|
||||
| 4 后台契约 | 完成 | `ee4a9434f`;GET 带版本、POST 两段必填 + 事务内 CAS → 409,退役 `with_previous_model3d` |
|
||||
| 4 后台契约 | 完成 | `ee4a9434f`;GET 两段、POST 两段必填并整段覆盖(2026-09-24 删除版本 CAS / 409),退役 `with_previous_model3d` |
|
||||
| 5 admin-web 3D 区块 | 完成 | `c901f6954`;`AdminEditorGenerationModel3dPricingSection` + `adminEditorGenerationPricing` 纯模块 |
|
||||
| 6 文档与验收 | 完成 | 本文件、主规范、ADR 0005、`pitfalls.md`、`decision-log.md` |
|
||||
|
||||
@@ -74,13 +75,13 @@ Milestone Spec: `docs/project-memory/plans/【里程碑】3D生成定价后台
|
||||
|
||||
| 判据 | 证据 |
|
||||
| --- | --- |
|
||||
| 1 后台 GET 带版本、公开 GET 形状不变 | `cargo test -p api-server app::tests::admin_editor_generation_pricing_route_saves_config_and_updates_public_route`、`app::tests::public_editor_generation_pricing_route_returns_default_config` |
|
||||
| 2 缺段 400 / 版本不匹配 409 且不落库 | `app::tests::admin_editor_generation_pricing_route_rejects_missing_model3d_section`、`..._rejects_stale_version`、`state::tests::saving_pricing_with_stale_version_is_rejected` |
|
||||
| 1 后台 GET 两段、公开 GET 形状不变 | `cargo test -p api-server app::tests::admin_editor_generation_pricing_route_saves_config_and_updates_public_route`、`app::tests::public_editor_generation_pricing_route_returns_default_config` |
|
||||
| 2 缺段 400 且不落库、合法保存整段覆盖 | `app::tests::admin_editor_generation_pricing_route_rejects_missing_model3d_section`、`state::tests::saving_pricing_applies_explicit_model3d` / `saving_pricing_twice_keeps_last_write` |
|
||||
| 3 保存后公开路由立即返回新价 | 同上第一条用例在保存后重读公开路由断言新价 |
|
||||
| 4 缺键补齐、契约外键剔除告警 | `editor_generation_model3d_records::tests::{missing_keys_and_missing_sections_are_backfilled_from_local_config,out_of_contract_keys_are_dropped,missing_key_without_local_value_fails_closed,half_configured_sections_are_rejected,duplicate_keys_are_rejected,writing_requires_the_complete_contract_key_set}` |
|
||||
| 5 覆盖文件兜底与缺段补齐 | `editor_generation_config::tests::editor_generation_pricing_legacy_override_backfills_missing_model3d_section`、`..._default_path_falls_back_to_legacy_override_seed` |
|
||||
| 6 未配置仍 fail closed | `editor_generation_config::tests::editor_generation_pricing_fails_closed_when_model3d_section_is_absent` |
|
||||
| 7 admin-web 3D 区块渲染 / 校验 / 409 | `npx vitest run apps/admin-web`(210 passed):`AdminEditorGenerationPricingPage.test.tsx`、`adminEditorGenerationPricing.test.ts` |
|
||||
| 7 admin-web 3D 区块渲染 / 校验 / 保存 payload | `npx vitest run apps/admin-web`(210 passed):`AdminEditorGenerationPricingPage.test.tsx`、`adminEditorGenerationPricing.test.ts` |
|
||||
| 8 门禁 | `cargo test --locked -p api-server`(1183 passed,另有一条与本改动无关的时序敏感用例在整包并行下偶发失败、单跑通过)、`cargo test --locked -p spacetime-module editor_generation`、`npm run check:spacetime-schema`、`npm run check:encoding`、`node scripts/check-doc-index.mjs`、`git diff --check` |
|
||||
|
||||
尚未执行(需真实环境):手工验收「后台改 3D 价 → 不重启 → 画布 3D 面板价随之变化 → 重启后仍是保存值」;需要在发布 Stdb 模块与 API 后按开发运维文档执行。
|
||||
|
||||
@@ -1,8 +1,9 @@
|
||||
# 3D 生成定价后台可编辑
|
||||
|
||||
Version: 1.0
|
||||
Version: 1.1
|
||||
Status: 已实现,待真实环境手工验收与发布
|
||||
Date: 2026-09-23
|
||||
修订: 2026-09-24 —— 后台保存删除定价版本比对(不再有 `updatedAtMicros` / `expectedUpdatedAtMicros` / 409),改为整段覆盖;理由见 `docs/project-memory/shared-memory/decision-log.md`「模型定价保存去掉版本比对」。下文「范围 / 验收判据」中涉及版本 CAS 与 409 的表述已按此修订。
|
||||
Parent Spec: `docs/【编辑器】模型定价配置管理方案-2026-06-22.md`
|
||||
Implementation Plan: `docs/project-memory/plans/【实施计划】3D生成定价后台可编辑-2026-09-23.md`
|
||||
Related: `docs/adr/【ADR】0005-3D生成定价迁入SpacetimeDB与后台编辑-2026-09-23.md`、`docs/technical/【技术方案】Tripo 3D生成API集成-2026-09-21.md`
|
||||
@@ -16,8 +17,8 @@ Related: `docs/adr/【ADR】0005-3D生成定价迁入SpacetimeDB与后台编辑-
|
||||
- 表新增 `text_to_model_pricing` / `image_to_model_pricing` 两列,沿用 `models` 的展平风格;同步 `migration.rs`、表目录文档与生成绑定。
|
||||
- 定价文件的 3D 段改成两段并列形状,受控默认 JSON 与定向用例同步。
|
||||
- 读取方向契约归一化:表内缺键用默认 JSON / 覆盖文件同段值补齐,契约之外的遗留键剔除并告警。
|
||||
- 后台 GET / POST:两段必填,携带读取时得到的定价版本做 CAS,不一致返回 409;保存成功后返回权威快照。
|
||||
- admin-web「模型定价」页新增 3D 区块:按端点分组,模型版本 × 两档价 + 六个加价项;提交前本地校验与 400 / 409 中文提示。
|
||||
- 后台 GET / POST:两段必填;保存是整段覆盖、不做版本比对(2026-09-24 修订后不再携带定价版本、不返回 409),保存成功后返回权威快照。
|
||||
- admin-web「模型定价」页新增 3D 区块:按端点分组,模型版本 × 两档价 + 六个加价项;提交前本地校验与 400 中文提示。
|
||||
- 覆盖文件降级为种子与兜底,不再是 3D 改价的生效路径。
|
||||
|
||||
## 不做
|
||||
@@ -29,13 +30,13 @@ Related: `docs/adr/【ADR】0005-3D生成定价迁入SpacetimeDB与后台编辑-
|
||||
|
||||
## 验收标准
|
||||
|
||||
1. 后台 GET 返回两段 3D 定价与定价版本;公开 GET 的 3D 段形状与本期之前逐字段一致。
|
||||
2. 后台 POST 缺少任一段 → 400;段内任一键缺失或非法 → 400;版本不匹配 → 409,且两段与 `models` 均不落库。
|
||||
1. 后台 GET 返回两段 3D 定价;公开 GET 的 3D 段形状与本期之前逐字段一致。
|
||||
2. 后台 POST 缺少任一段 → 400;段内任一键缺失或非法 → 400,且两段与 `models` 均不落库;合法请求整段覆盖,连续保存两次以后一次为准。
|
||||
3. 保存成功后不重启进程,`GET /api/editor/generation-pricing` 立即反映新价;重启后仍是保存后的值。
|
||||
4. 表内两段缺键(模拟发布新增模型版本)时读取自动补齐并记录告警,读取不失败;契约之外的遗留键被剔除并记录告警。
|
||||
5. 表为空或 SpacetimeDB 不可达时,3D 定价用默认 JSON / 覆盖文件同段值兜底;override 文件的存在不再导致「重启覆盖已保存价格」。
|
||||
6. 3D 定价未配置时提交仍 fail closed(503 `model3d-pricing-unavailable`),不扣费、不入队。
|
||||
7. admin-web 3D 区块渲染两个端点各 5 行 × 2 档价与 6 个加价项;存在 0 或空值时禁用保存并给出中文提示;收到 409 时提示重新读取。
|
||||
7. admin-web 3D 区块渲染两个端点各 5 行 × 2 档价与 6 个加价项;存在 0 或空值时禁用保存并给出中文提示。
|
||||
8. `npm run check:spacetime-schema`、`npm run check:encoding`、`cargo test --locked -p api-server` 定向用例、admin-web 定向 vitest、`node scripts/check-doc-index.mjs`、`git diff --check` 全部通过。
|
||||
|
||||
## 实现与验收记录(2026-09-23)
|
||||
|
||||
@@ -1,5 +1,15 @@
|
||||
# 决策记录
|
||||
|
||||
## 2026-09-24 模型定价保存去掉版本比对:后台同时只有一个管理员在操作
|
||||
|
||||
- 背景:2026-09-23 引入的「行内 `updated_at` 版本比对」(后台 GET 回 `updatedAtMicros`、POST 带 `expectedUpdatedAtMicros`、procedure 在事务内比对、不一致返回 409)落地后暴露两件事。一是这个版本号没有真实并发场景支撑:后台定价页同时只有一个管理员在操作,409 的后果只是「刷新一下再保存」,却给前后端都加了一条无从处理的失败路径。二是读内容与读版本号原本是两个分开的动作,在「读数据库失败、退回进程内缓存」这条少见分支上,两次读之间若有人写入,调用方会拿到旧内容配新版本号——本该被拦下的写入会被放行,本该能保存的反而被当成版本冲突。
|
||||
- 决策:整体删除版本比对与版本号。`EditorGenerationPricingConfigUpsertInput` 去掉 `expected_updated_at_micros`;`EditorGenerationPricingStore` 去掉版本字段与对应方法;后台 GET 不再返回 `updatedAtMicros`、POST 不再带 `expectedUpdatedAtMicros`,冲突 409 分支与前端「重新读取」提示一并删除;`save_editor_generation_pricing` 与 `editor_generation_pricing()` 只返回配置本身。保存语义固定为「整段覆盖」:请求里的 `models` 与两段 3D 价格就是新的最终状态,后一次保存整体取代前一次。`EditorGenerationPricingStore::replace` 明确记为「只刷新进程内缓存,不做版本校验、不是拦截点」,写入判断只发生在 procedure 的入库事务里。
|
||||
- 原因:**没有并发就没有版本号的价值**——加它只是把一次普通的覆盖保存变成需要用户处理的中断;**两次读本来就是错的形状**,正确做法是「保存即覆盖」而不是把内容和版本号拆开再拼回去;**拦截点唯一**,写入合法性只在 procedure 的入库事务里判断一次,进程内缓存不该有第二份判断逻辑。
|
||||
- 代价与取舍:放弃「两个人同时编辑时提示冲突」的能力,靠「同时只有一个管理员在操作」这个前提兜住;前提一旦不成立(例如以后开多人同时改价),必须重新设计,而不是把版本号加回来。后台不再能区分「我读到的是不是最新」,页面只能在保存后重新读取确认。
|
||||
- 影响面:`server-rs/crates/shared-contracts/src/editor_generation.rs`、`server-rs/crates/spacetime-module/src/editor_project_storage.rs`、`server-rs/crates/spacetime-client/src/active/mapper/editor_project.rs` 与生成绑定、`server-rs/crates/api-server/src/{editor_generation_config.rs,state.rs,admin.rs,app.rs}`、`apps/admin-web/src/{api/adminApiTypes.ts,pages/AdminEditorGenerationPricingPage.tsx,pages/adminEditorGenerationPricing.ts}` 及对应测试、主规范「保存语义」段、后端数据契约文档、ADR 0005、`pitfalls.md`。
|
||||
- 验证方式:`cargo test --locked -p api-server -- editor_generation_pricing saving_pricing`、`cargo test --locked -p spacetime-module -- editor_generation_pricing`、`npx vitest run apps/admin-web/src/pages/AdminEditorGenerationPricingPage.test.tsx apps/admin-web/src/pages/adminEditorGenerationPricing.test.ts`、`npm run admin-web:typecheck`、`npm run check:encoding`、`git diff --check`。
|
||||
- 关联文档:[ADR 0005](../../adr/【ADR】0005-3D生成定价迁入SpacetimeDB与后台编辑-2026-09-23.md)、[编辑器模型定价配置管理方案](../../【编辑器】模型定价配置管理方案-2026-06-22.md)、[后端架构 server-rs 与 SpacetimeDB 数据契约](../../【后端架构】server-rs与SpacetimeDB数据契约-2026-05-15.md)。
|
||||
|
||||
## 2026-09-24 3D 参数面板开放模型选择:版本取「本端点有底价」的键,能力规则抄 provider,端点与提交体由类型绑死
|
||||
|
||||
- 背景:3D 面板此前把请求体与报价里的 `model` 一起写死成 `DEFAULT_MODEL3D_MODEL_VERSION`(`v3.1-20260211`),而公开读模型的定价段是按 `endpoint × modelVersion` 展开的;后端加载即校验「每个契约版本 × 两个端点都必须有底价」,于是定价表里已配好的 `v3.0` / `v2.5` / `P1` / `P2` 四个版本在前端永远不可达,用户也看不到任何模型选择入口。同一轮还暴露两个类型层面的口子:提交函数签名是「endpoint 联合 + 提交体联合」两个彼此独立的字段,把图生请求体发到文生地址照样编译通过;`Model3dPricingConfig.basePrices` 内层键写成 `string`,写错的版本号在编译期没有任何反馈。
|
||||
@@ -9389,6 +9399,7 @@ CI 上 `background_agent_runtime_recovers_stale_running_before_pending_task` 在
|
||||
- 影响面:`server-rs/crates/api-server/src/{tripo3d/pricing.rs,editor_generation_config.rs,editor_generation_model3d_records.rs,state.rs,admin.rs,app.rs,editor_project.rs}`、`server-rs/crates/spacetime-module/src/editor_project_storage.rs`、`server-rs/crates/spacetime-client/src/active/mapper/editor_project.rs` 与生成绑定、`server-rs/crates/shared-contracts/src/editor_generation.rs`、`apps/admin-web/src/{api/adminApiTypes.ts,api/adminApiClient.ts,pages/AdminEditorGenerationPricingPage.tsx,pages/AdminEditorGenerationModel3dPricingSection.tsx,pages/adminEditorGenerationPricing.ts}`、主规范、里程碑与实施计划、`pitfalls.md`。
|
||||
- 验证方式:`cargo test --locked -p api-server`(1183 passed;另有一条与本改动无关的时序敏感用例在整包并行下偶发失败、单跑通过)、`cargo test --locked -p spacetime-module editor_generation`、`npm run check:spacetime-schema`、`npm run check:encoding`、`node scripts/check-doc-index.mjs`、`git diff --check`、`npx vitest run apps/admin-web`(210 passed)、`npx tsc --noEmit -p apps/admin-web/tsconfig.json` 与改动文件 eslint。真实环境手工验收与发布尚未执行。
|
||||
- 关联文档:[ADR 0005](../../adr/【ADR】0005-3D生成定价迁入SpacetimeDB与后台编辑-2026-09-23.md)、[编辑器模型定价配置管理方案](../../【编辑器】模型定价配置管理方案-2026-06-22.md)、[实施计划](../plans/【实施计划】3D生成定价后台可编辑-2026-09-23.md)。
|
||||
- 后续修订(2026-09-24):本条 ② 的版本比对与 409 已整体删除,保存改为整段覆盖,见同日决策「模型定价保存去掉版本比对」。
|
||||
|
||||
## 2026-09-23 3D 提交落点改为平坦可选字段:`target` tagged enum 作废,服务端按二选一校验
|
||||
|
||||
|
||||
@@ -6004,9 +6004,9 @@ Cocos Creator 根目录由 `package.json.creator.version` 与普通 `assets/`
|
||||
|
||||
- **现象**:admin-web 把后台读取到的整份定价原样回传保存;当 3D 段只在进程内存(文件配置)里时,陈旧的浏览器标签页保存图片价格会把旧的 3D 段一并写回,价格在无人察觉的情况下回滚。
|
||||
- **成因**:后端把「`model3d` 缺席或为 null」解释成「沿用当前 3D 段」(`with_previous_model3d`),于是 payload 的形状本身携带了两种语义:给值是覆盖,不给是沿用;而前端是整份回传,两种语义在真实浏览器里无法区分。
|
||||
- **处理(现行口径)**:定价保存不再有隐含沿用语义——`models` 与 3D 两段都必须显式给出,缺段即 400;同时用读取时拿到的定价版本做事务内乐观锁,不一致返回 409。3D 定价存进 SpacetimeDB 与 `models` 同事务后,任何一次保存写的都是页面当时看到的完整状态。
|
||||
- **易错点**:① 不要为了「顺手支持只改一个字段」再引入任何「省略 = 沿用」分支,缺段就该报错;② 乐观锁的版本必须由读取回包带出并原样回传,不能在前端自造或缓存;③ 首次种子写入(表为空)显式不带期望版本,表内没有行时不允许凭兜底版本直接创建。
|
||||
- **验证**:`server-rs/crates/api-server/src/app.rs` 的 `admin_editor_generation_pricing_route_rejects_missing_model3d_section` / `..._rejects_stale_version` / `..._saves_config_and_updates_public_route`;`state::tests::saving_pricing_with_stale_version_is_rejected`;module 侧 `editor_generation_pricing_expected_version_must_match_current_row`。
|
||||
- **处理(现行口径,2026-09-24 修订)**:定价保存不再有隐含沿用语义——`models` 与 3D 两段都必须显式给出,缺段即 400。3D 定价存进 SpacetimeDB 与 `models` 同事务后,任何一次保存写的都是页面当时看到的完整状态;保存本身不做版本比对,写进去的整段直接成为新状态(后台定价同时只有一个管理员在操作,所以不再需要版本号;原先的版本号比对已删除)。
|
||||
- **易错点**:① 不要为了「顺手支持只改一个字段」再引入任何「省略 = 沿用」分支,缺段就该报错;② 不要再把版本号加回来——后台定价假设同时只有一个管理员在线,保存是整段覆盖,读到的旧版本号只会制造 409 这类无从处理的失败;③ 表为空时的种子写入仍由 procedure 的入库事务负责,不靠「先读空、再无脑写」的两步流程。
|
||||
- **验证**:`server-rs/crates/api-server/src/app.rs` 的 `admin_editor_generation_pricing_route_rejects_missing_model3d_section` / `admin_editor_generation_pricing_route_saves_config_and_updates_public_route`;`state::tests::saving_pricing_applies_explicit_model3d` / `saving_pricing_twice_keeps_last_write`(后一次保存直接覆盖前一次)。
|
||||
- **关联**:`docs/【编辑器】模型定价配置管理方案-2026-06-22.md`、`docs/adr/【ADR】0005-3D生成定价迁入SpacetimeDB与后台编辑-2026-09-23.md`。
|
||||
|
||||
## 2026-09-23 公开读模型改了存储形状就等于在两条发布线上做破坏性变更
|
||||
|
||||
Reference in New Issue
Block a user