diff --git a/docs/agent-specs/2026-06-11-community-biz前端入口-review.md b/docs/agent-specs/2026-06-11-community-biz前端入口-review.md new file mode 100644 index 00000000..6854e99e --- /dev/null +++ b/docs/agent-specs/2026-06-11-community-biz前端入口-review.md @@ -0,0 +1,451 @@ +# community / biz 前端入口 · 评审版 + +> 编号 **HJ-FE-CMBIZ-001** | 2026-06-11 | 类型:Review(结论先行,供创始人拍板;定稿后出 execution 版) +> 任务:为 **Wave4 已建后端**(community 通知底座 + biz 轻量 lead form,提交 `737e6d5`,集成门全绿、staging 两链路实测)**补前端入口**,闭合 no-orphan 铁律(AGENTS §6.7「残缺/孤儿设计」),并让 **B 端现金线可演示**(近期现金靠 B 端)。 +> 上游依赖:后端契约/端点已定稿冻结于 `contracts/api-schemas/community.yaml` + `biz.yaml`,建模块评审版/执行版见 `2026-06-11-Wave4-community-biz-review.md`(HJ-WAVE4-001)/ `2026-06-11-Wave4-community-biz-execution.md`(HJ-WAVE4-EXEC-001,创始人已拍 D-A/D-B/D-C)。 +> **本波边界:纯前端 UI,消费已入库契约,零后端改动。** 照搬 game-studio 五层范式 / game-admin wanxiang 范本,零创新。 +> 状态:**待创始人拍板**(§0.1 列 9 项 UX/产品口径待裁,其中 D1/D2/D3 是产品口径真决策、D5 是跨前后端契约缺口需 runtime owner 协调拍定、D9 是客户写动作微流程口径;其余 D4/D6/D7/D8 可由 execution 版单 agent 定)。本文是「须双 spec」铁律下的第一份(评审版),不含代码级细节以降认知负荷。 + +--- + +## 0. 结论(一句话) + +**Wave4 后端 19 个对外可封装端点-操作(community app 5 + biz app 7 + biz admin 7;另 community RPC 4 + mock-trigger 1 为同进程/联调投递工具,非前端封装)目前 0 前端入口=违反 no-orphan。本波按「已验证范式克隆」把它们接成可达 UI——零创新、零后端改动、零新依赖;唯一需要创始人拍的不是技术、而是 3 个产品口径:① biz 客户入口要不要在 studio 主导航露出(B 端是不是 studio 注册用户)② community 是否本波就做「等级/奖励」展示(还是只做消息中心)③ admin biz 队列是否本波就接(受 7 个权限点 system_menu 登记这道前置闸门约束)。** + +> **端点计数基准(全文统一)**:端点数一律以 **HTTP operation** 计——`/admin-api/biz/leads/{id}/quotes` 同一 path 含 POST(报价)+GET(报价历史) 计 **2** 个 operation。故 biz admin 端 = **7 operation / 6 URL path**;§3.3 操作表按 path 呈现 6 行(「报价(+历史)」一行承载 POST+GET 两 operation),§4.4 图把 quotes 拆 d4a/d4b 两节点显式呈现 7 operation——三处与「封 7」按 operation 计自洽。全文及 AC-FE-6 勾验一律用 **19**(=5+7+7),不再出现「17」。 + +**本波交付清单(3 块 / 推荐范围)**: + +| 块 | 前端仓 | 页面 | 消费端点 | P0 必交 vs 增强 | +|---|---|---|---|---| +| ① community 消息中心 | game-studio | 消息列表(四类 tab + 已读)/ 未读角标 / 我的等级 / 我的奖励 | community.yaml app 端 5 个 | 消息中心三件(列表/已读/角标)**本波必交**;等级/奖励**推荐本波做但属增强**(D-B 范围内,后端已就绪) | +| ② biz 客户询单看板 | game-studio | 提单表单 / 我的订单列表 / 询单详情(进度时间线+报价+demo 试玩)/ 反馈确认 | biz.yaml app 端 7 个 + runtime 双路由(复用) | **本波必交**(B 端现金线可演示是本波核心目标之一) | +| ③ biz admin 处理队列 | game-admin | 处理队列 / 代客发起 / 指派 / 报价(+历史)/ 推进状态机 / 线下签署 | biz.yaml admin 端 7 个 | **受权限点登记前置闸门约束**;闸门未过=本波**降级为增强**(详见 §0.1-D3、§6 风险) | + +**推荐 sequencing:① community 先(更简单、纯展示、被全链路 M5 依赖、无前置闸门)→ ② biz 客户侧(B 端价值高、复用 project 范式)→ ③ biz admin(受权限点闸门约束,闸门过了再接)。** 三块互不耦合,可并行三 worktree,但若要排优先级按此序。 + +> **交付范围分层(按前置闸门结果裁剪)**:**最小必交集 = ① 消息中心三件(列表/已读/角标)+ ② biz 客户侧全套**;**条件增强 = ③ admin 队列(前置=权限点 system_menu 闸门过,§4.2 可执行 SQL 校验)+ ① 等级/奖励(前置=D2 拍板)**。闸门未过/D2 不做时,对应增强项顺延,最小必交集不受影响。 + +**全文证据边界**:game-studio 五层范式 + 请求/守卫/Vant 用法、game-admin wanxiang 四页范本、两契约 19 端点、TabBar 现状(仅 3 入口无 badge 槽)、零前端桩(grep `biz/community/messages` 在 game-studio/src 零命中),均经 2026-06-11 实查仓库核实(见各节 file:line)。「demo 试玩走 play vs preview 路由」「站内信 bizRef 跳转映射」「admin 详情端点缺口」三处为契约未定项,已在 §0.1 / §5 标为待裁。 + +--- + +## 0.1 ⭐ 待创始人拍板的关键决策(汇总,详表见 §8) + +> 以下 **3 项是真正需要创始人拍的产品/口径决策**(D1/D2/D3);另有 **D5 是跨前后端契约缺口、必须在开 execution 前与 runtime owner 协调定死可执行契约**(不是前端单 agent 能自决的路由选择,详见下表与 §6.2 风险)。其余 4 项(D4/D6/D7/D8)+ D9(客户写动作微流程)属信息架构/交互细节,可由 execution 版单 agent 直接定,已在 §8 标注「execution 自决」。**D1/D2/D3 按推荐拍 + D5 与 runtime owner 对齐后即可开 execution 版。** + +| ⭐ | 关键决策 | 推荐 | 不这样做的代价 | +|---|---|---|---| +| **D1** | **biz 客户入口在 studio 的信息架构位置 + 「我的中心」承载页落点**(主导航露出 vs 「我的」二级;且现状 TabBar「我的」直指 `/project` 项目列表页、并无聚合入口容器,biz 入口/消息入口/等级奖励卡/角标四者无处可挂) | **不占 TabBar 第 4 格;承载页二选一(execution 起步先钉死)**:(a) **新建独立 `/me` 个人中心页**作为 biz 入口/消息入口/等级奖励卡/角标统一容器,TabBar 第三入口由 `/project` 改指 `/me`、`/project` 降为其二级;或 (b) **在 `Project.vue` 顶部新增聚合入口区 banner**。无论哪种都须改动「我的」承载页(Project.vue 或新增 /me),§2 非目标「不改既有导航」放宽为「不动 feed/create 两区、不重构既有公共组件;『我的』承载页允许新增聚合入口区」。B 端客户复用同一 user 登录体系(契约客户侧用同一 user Token,`getLoginUserId` 归属),但非主流量人群,故挂二级不占主导航 | 若强上 TabBar 第 4 格:3 入口变 4 入口,C 端竖屏导航被低频 B 端业务挤占;若不解决承载页:D1/D2/D6 四个二级入口无聚合落点、散挂各处=信息架构断层,实现者在「四入口挂哪」处 block;若纯邀请链:需独立落地页/独立登录态,本波工作量翻倍且 B 端获客本波不必做 | +| **D2** | **community 本波范围:只做消息中心 vs 含「等级/奖励」展示** | **含等级/奖励展示**(合并进「消息中心」单页分区或「我的」页卡片)——后端 `/community/level` + `/community/rewards` 已就绪(D-B 范围内),P-INC-01 新人激励是「能赚钱」叙事的可视化抓手,不做=后端能力孤儿 | 只做消息中心:`/level` + `/rewards` 两端点成孤儿(违反 no-orphan);P-INC-01 新人激励对用户不可见,「创作有成长有奖励」的产品故事缺一环 | +| **D3** | **admin biz 队列是否本波接(受 7 权限点 system_menu 登记闸门约束)** | **本波接,但前置=先确认 7 个 `biz:lead:*`/`biz:quote:*`/`biz:acceptance:sign` 权限点已 import 到 staging system_menu**(`biz_menu.sql` 已备父菜单 7100 + 7 权限点 7101-7107,共 8 行);闸门未过则本波只交付客户侧①②,admin③ 顺延。**闸门校验=可执行 SQL**(见 §4.2,对 staging 跑 `SELECT id,permission FROM system_menu WHERE id BETWEEN 7100 AND 7107` 期望 8 行,缺则先 import 再验) | 若权限点未登记就建 admin 页:超管可用、非超管角色 403(@PreAuthorize 兜底);若不接 admin:运营无法在 UI 报价/推进状态机,B 端闭环只有客户侧半环,「可演示」打折(演示需运营推进 demo 才能让客户试玩验收) | +| **D5⚠️** | **biz demo 客户试玩取包路径——跨前后端契约缺口(卡 AC-FE-4 这条 B 端现金线命脉,须开 execution 前与 runtime owner 钉死,不能留 execution 自决)** | **二选一钉死可执行契约**:(a) 约定运营代建 demo **走正式发布流使 `game_runtime_package.status=1` 后用 `scene=play` 取包**(不动后端契约面,但改变 demo 交付语义=demo 须入正式发布态);或 (b) **runtime 新增 owner-agnostic 的取包判定能力**(属后端改动,超本波「零后端改动」边界,须升级为跨模块协调项)。**在路径未通前 AC-FE-4 标记为受阻、本波 demo 试玩可能降级为占位** | runtime.yaml 当前只有两个 scene:`preview`(校验调用者为版本 owner,运营代建 demo 的 owner≠客户客户走 preview 必被 owner 校验拦)、`play`(仅放行 status=1 已发布),且明文「不在前端兜底」(runtime.yaml:239)。若不先定契约就开工:实现者拿到 `BizLeadDetailRespVO.demoPreviewable=true` 却无任何前端可调的 owner-agnostic 取包端点 → demo 试玩闭环不可达,B 端「可演示」目标落空 | + +> 另:D4 站内信 bizRef 跳转映射、D6 未读角标承载位、D7 时间线组件复用粒度、D8 金额/精度展示约定、D9 feedback/confirm 客户写动作先后约束——见 §8,均可 execution 自决(已给推荐),不阻塞拍板。**注:D5 已从 execution 自决升格为「开 execution 前须与 runtime owner 协调拍定」的硬前置(原评审低估为「路由选择/中风险」,实为契约面缺口)。** + +--- + +## 1. 背景与目标 + +### 1.1 现状:后端齐、前端缺 + +```mermaid +graph LR + subgraph BE["Wave4 后端(737e6d5 已建·集成门全绿·staging 两链路实测)"] + CM["community 通知底座
app 5 端点 + RPC 4 + mock-trigger 1"] + BZ["biz 轻量 lead form
app 7 端点 + admin 7 端点"] + end + subgraph FE["前端入口(本波)"] + S1["game-studio
消息中心 + 客户询单看板"] + A1["game-admin
biz 处理队列"] + end + CM -. "app 5 端点 0 入口" .-> S1 + BZ -. "app 7 端点 0 入口" .-> S1 + BZ -. "admin 7 端点 0 入口" .-> A1 + style BE fill:#1a3a4a,color:#cfeefe + style FE fill:#3a2a1a,color:#fde0c0 +``` + +- **现状确认(实查)**:`grep biz/community/messages` 在 `game-studio/src` **零命中**、在 `game-admin/src` biz 相关**零命中**——两侧全是净新建前端,无任何桩。后端端点已可经 Swagger/curl 验,但**用户在 UI 上无任何入口可达**=典型 no-orphan 违反(有 API 无入口)。 + +### 1.2 目标 + +1. **闭合 no-orphan(AGENTS §6.7)**:Wave4 每个对外业务端点都有前端入口可达(RPC/mock-trigger 除外,非对外)。 +2. **B 端现金线可演示**:客户提单 → 运营报价/推进 → demo 就绪 → 客户试玩/确认验收,一条 B 端闭环能在 staging 真人走查跑通(近期现金靠 B 端,AGENTS §1)。 +3. **community 通知触达可见**:生成完成/审核结果/收益变动三类站内信 + 新人激励成长,在 studio 可见。 + +### 1.3 非目标见 §2,技术落点见 §4,权衡见 §5,验收见 §7。 + +--- + +## 2. 非目标(明确不做,防 scope 蔓延) + +| 不做 | 理由 / 归属 | +|---|---| +| **改任何后端契约 / -api 包 / DDL** | 本波纯消费已冻结契约(community.yaml/biz.yaml);契约缺口(如 admin 详情端点 D3 备注)走待裁,不私自补后端 | +| **M4 资金流 UI**:在线收款入口 / 在线电子签章 / reward 真实到账明细 / 分账 | biz 资金流(T-BIZ-08 收款 / T-BIZ-03 签章)+ community reward 真实发放全留 M4(契约 biz.yaml:17、community.yaml:20)。本波报价区**禁出现「立即支付/下单」入口**,只「线下签署」兜底;奖励区文案**禁写「已发放/已到账」**,status=0 显示「已触发·待发放」 | +| **超 P0 增强**:community SOC/GRW 域(关系图谱/排行/成就/扇出/邮件,全 P1/P2);biz P-BIZ-05~07/09~11/13/14 | 仅做本波 11 P0(community 5 + biz 6)对应前端;后端只留接口桩的能力前端不做入口。**注:P0 功能数(biz 6)≠ 端点数(biz app 7)——两者口径不同,1 个 P0 可对应多端点**(如 P-BIZ-03 进度看板 = leads/my + leads/{id} + progress 三端点),勿误读为应相等 | +| **community RPC 4 端点 + mock-trigger 1 的前端封装** | RPC(`/rpc-api/community/notify/*`)是上游 aigc/project/trade 同进程调用,非对外;mock-trigger 是 staging 投递工具(admin 端,由后端/联调用),前端不封(community.yaml:4-7、153-251) | +| **biz 运营侧「公告 type=2」投递运营入口** | 后端四类 notify 只产 type1/3/4,公告 type2 靠 mock-trigger 手动;本波前端四类 tab 全列但 type2 可能恒空,不做公告投递台 | +| **下沉/重构既有公共组件**;**不动 feed/create 两区导航** | 最小改动;新页一律复用 `components/`(AppButton/EmptyState/LoadingBar 等)、新增路由不动既有 feed/create 两区。**例外(D1)**:「我的」承载页允许新增聚合入口区(新建 `/me` 或 Project.vue 顶部加 banner),以承载 biz/消息/等级奖励/角标四个二级入口——这不是「重构导航」,是为四个二级入口补一个聚合落点(详见 §0.1-D1、§6.1) | + +--- + +## 3. 页面与流程(三块) + +### 3.0 三块全景 + +```mermaid +graph TB + subgraph studio["game-studio(客户/创作者端·Vant·D4 深色·/app-api)"] + M["① community 消息中心
消息列表/角标/等级/奖励"] + B["② biz 客户询单看板
提单/我的订单/详情(时间线+报价+demo)/反馈确认"] + end + subgraph admin["game-admin(运营端·Element Plus·/admin-api)"] + Q["③ biz admin 处理队列
队列/代客发起/指派/报价/推进/签署"] + end + B <-. "同一询单·客户只读看 / 运营推进状态机" .-> Q + style studio fill:#1a2a2a,color:#cfeefe + style admin fill:#2a2a3a,color:#d8d0fe +``` + +> 客户侧②(看状态)与运营侧③(推状态机)是同一询单的两面:状态机唯一推进者=运营(admin advance);客户唯一写动作=确认验收(3待验收→4已交付)。 + +--- + +### 3.1 ① community 消息中心【game-studio】 + +**页面清单**(照 `/project` 范式,全 `meta:{requiresAuth:true}` 登录态私有): + +| 页面 | 路由(建议) | 消费端点 | P0 | +|---|---|---|---| +| 消息列表(四类 tab + 已读筛选) | `/messages` | GET `/app-api/community/messages` + POST `.../{id}/read` | 必交 | +| 未读角标(全局,非独立页) | 入口处挂 | GET `/app-api/community/messages/unread-count` | 必交 | +| 我的等级(成长进度) | 合并消息中心分区 或 `/me/level` | GET `/app-api/community/level` | 增强(D2) | +| 我的奖励(触发记录) | 合并 或 `/me/rewards` | GET `/app-api/community/rewards` | 增强(D2) | + +**消息列表数据形状**(CommunityMessageRespVO,community.yaml:262-273):id / type(1系统2公告3审核4收益) / bizRef(跳转键) / title / content(审核拒绝含原因) / readStatus(0未读1已读) / readTime / createTime;**游标分页**(nextCursor int64 nullable,对齐 feed cursor 模型,**非 project 的 total 模型**)。 + +> **type=2 公告 tab 恒空的处置(已知空态,须差异化)**:本波四类 notify 只产 type1/3/4,公告 type2 靠 mock-trigger 手动,正常运营下 type2 恒空(§2 非目标)。**推荐本波直接不渲染 type2 公告 tab**(待有公告投递台再加),避免给用户一个永远 EmptyState 的入口;若 execution 选择保留四 tab 全列,则 type2 须给**专属空态文案「暂无平台公告」**(区别于其他 tab 的「暂无消息」),不可与普通空态混用。 + +**用户流程(消息列表 → 已读 → 角标递减)**: + +```mermaid +sequenceDiagram + participant U as 用户 + participant V as 消息中心页 + participant API as /app-api/community + U->>V: 进入消息中心 + V->>API: GET messages?type&readStatus&cursor&size + API-->>V: {list, nextCursor} + V->>API: GET messages/unread-count + API-->>V: {total, byType} + Note over V: 三态:loading→空态(EmptyState)→列表;四类 tab 横滚筛选 + U->>V: 点击某条未读消息 + V->>API: POST messages/{id}/read(登录态写) + API-->>V: true + Note over V: 乐观置 readStatus=1 + 角标 total-- + V->>V: 据 type+bizRef 决定跳转(D4 映射,或本波先不跳) +``` + +**等级/奖励展示要点(D2 采纳则做)**: +- 等级(CommunityLevelRespVO,:274-282):level 恒=1(小白,MVP 仅此档);核心=进度条「publishedCount / nextMilestoneTarget(如 2/3)距下一新人奖励」;nextMilestone=null 显「已达成全部新人里程碑」。publishedCount 是「尽力计数」(勘误#3,可能少计),前端**不宣称「精确」**,按返回值如实展示。 +- 奖励(CommunityRewardRespVO,:283-293):奖励卡列表,status=0 显「已触发·待发放」(**本波终态,禁写「已发放/已到账」**,真实发放留 M4);rewardType 决定文案(1流量包=N 曝光 / 2现金=¥X.XX,金额分→元)。 + +--- + +### 3.2 ② biz 客户询单看板【game-studio】 + +**页面清单**(照 `/project` 列表+详情+子流程三联范式,全 `requiresAuth:true`): + +| 页面 | 路由(建议) | 消费端点 | P0 | +|---|---|---|---| +| 提单表单 | `/biz-orders/new` | POST `/app-api/biz/leads` + GET `/biz/templates`(选模板) | 必交(**提交后流向 + 字段引导见下**) | +| 我的订单列表(五态 tab) | `/biz-orders/my-orders` | GET `/app-api/biz/leads/my` | 必交(**列表态策略见下**) | +| 询单详情(时间线+报价+demo) | `/biz-orders/:id` | GET `/biz/leads/{id}` + `.../progress` | 必交 | +| 试玩反馈 + 确认验收(详情内动作) | 详情页内 | POST `/biz/acceptances/{leadId}/feedback` + `.../confirm` | 必交 | +| demo 试玩(详情内嵌/跳转) | 复用 runtime + `src/host/GamePlayer.vue`(照 `views/play/Play.vue:20` 挂载,非 components 复用) | GET `/app-api/runtime/package/{versionId}` + `/manifest` | 必交(**取包路径见 D5 跨前后端契约缺口**) | + +**biz 五态状态机**(单线性,仅相邻正向单跳,客户只读不能推进;推进=运营做): + +```mermaid +stateDiagram-v2 + [*] --> 待跟进0: 客户提单 + 待跟进0 --> 已报价1: 运营报价(admin) + 已报价1 --> 制作中2: 运营推进(admin) + 制作中2 --> 待验收3: 运营推进+demo就绪(admin) + 待验收3 --> 已交付4: 客户确认验收(✅客户唯一写动作) + note right of 待验收3: demoPreviewable=true 才亮「试玩 demo」 + note right of 待跟进0: 客户侧只读看状态/报价/进度 +``` + +> 五态色(照 project `status.ts` 范式建 biz 版 status.ts,D8/§5):0待跟进 muted、1已报价 cyan、2制作中 amber、3待验收 amber/cyan、4已交付 green。 + +> **列表→详情 demo 可用性一致性(实现纪律,防误判)**:列表项消费的 `BizLeadRespVO` **无 `demoPreviewable` 字段**(该字段仅在详情 `BizLeadDetailRespVO`)。故**列表态不预判 demo 是否可试玩**:对 `status=3 待验收` 单统一显「待验收·去试玩」引导(行动指引,让客户知道该点哪一单),进入详情后再由 `demoPreviewable` 决定试玩按钮亮/灰 +「暂不可预览」文案。**execution 勿令列表直接判 preview——列表无此字段。** + +**用户流程(客户视角全旅程)**: + +```mermaid +sequenceDiagram + participant C as 客户 + participant V as 客户看板(studio) + participant API as /app-api/biz + participant RT as /app-api/runtime + C->>V: 提单(bizType*+title*+场景+联系方式+选模板) + V->>API: POST /biz/leads + API-->>V: leadId(状态机开 status=0) + Note over C,V: 运营侧(admin)报价→推进→制作→demo 就绪→推进待验收 + C->>V: 进「我的订单」→ 点开询单详情 + V->>API: GET /biz/leads/{id}(含 latestQuote/progressList/demoPreviewable) + API-->>V: 详情(status=3 待验收, demoPreviewable=true) + Note over V: 时间线渲染 progressList;报价区标注「报价仅供参考·本波不支持在线支付」 + C->>V: 点「试玩 demo」 + V->>RT: GET /runtime/package/{versionId}(判就绪)+ /manifest(sha256 注入) + RT-->>V: 包就绪 → GamePlayer.vue 注入试玩 + C->>V: 提交反馈 + 确认验收 + V->>API: POST /acceptances/{leadId}/feedback → .../confirm + API-->>V: true(状态机 3→4 已交付) +``` + +**提单提交后流向 + 字段引导(B 端旅程唯一入口,须明确避免首体验断裂)**:`BizLeadCreateReqVO` 仅 `bizType/title` 必填,其余(sceneDesc/contactName/contactPhone/company/templateId)全可选。 +- **提交成功流向**:成功 Toast 后**跳 `/biz-orders/my-orders` 并高亮新单**(status=0),或直接进 `/biz-orders/:id` 详情看 status=0;二选一 execution 定,但**必须有明确落地页**,不可提交后停在原表单。 +- **模板选择**:纯可选(不做必选引导),templateId 来自 GET `/biz/templates`。 +- **联系方式软提示**:contactPhone 等契约可选,但**B 端运营跟进唯一靠它**(B 端获客本波不做,联系方式是运营触达客户的唯一抓手),表单层做**软提示引导填写**(不强制必填,不破契约)。 + +**关键 UX 降级态(AC-BIZ-2 R1 必验)**:demo 取包负路径(versionId 缺失/非法、无产物、编译失败 → runtime.yaml 现仅定义 `1-102-001-001`「无对应就绪运行包」一码)→ 看板降级显示「该 demo 暂不可预览」、按钮置灰,**不透传 500**。`BizLeadDetailRespVO.demoPreviewable=false`(后端 `validateDemoPreviewable` 判 demoVersionId 非空且 runtime 包就绪,**具体取包判定能力依赖 D5 钉定的契约**——runtime 当前无 owner-agnostic 判定端点,详见 §6.2/§0.1-D5)时同样置灰。**正常路径:待验收态恒为 demo 就绪(advance→3 硬守门保证);负路径仅覆盖「包就绪后被驱逐/失效」的少数情形**(消除「待验收必就绪」与「待验收要兜不就绪」的表观对立)。 + +--- + +### 3.3 ③ biz admin 处理队列【game-admin】 + +**页面清单**(照 `wanxiang/withdraw` + `review` 范本:ContentWrap 搜索栏 + el-table + Pagination + Dialog;落 `views/wanxiang/biz/`,与 dashboard/featured/withdraw/adSlot 并列)。**下表 6 行 = 6 URL path;其中「报价(+历史)」一行承载 POST+GET 两 operation,故 admin 封 7 operation(计数基准同 §0/§4.4)**: + +| 操作 | 端点 | 权限点 | 交互 | +|---|---|---|---| +| 处理队列(owner/status/bizType 筛选,total 分页) | GET `/admin-api/biz/leads/page` | biz:lead:query | el-table + 操作列按 status 条件渲染 | +| 代客发起 | POST `/admin-api/biz/leads` | biz:lead:create | 搜索栏 ep:plus 开 Dialog(8 字段) | +| 指派负责人 | PUT `/biz/leads/{id}/assign` | biz:lead:assign | 行内开小 Dialog(ownerUserId,D备注:裸 userId) | +| 报价(+历史) | POST/GET `/biz/leads/{id}/quotes` | biz:quote:create/query | Dialog(amountFen 元↔分换算 D8) | +| 推进状态机 | POST `/biz/leads/{id}/advance` | biz:lead:advance | Dialog(toStatus + note,→3 显 demoVersionId 必填);**demoVersionId 来源见下「demo 产出桥接」** | +| 线下签署兜底 | PUT `/biz/acceptances/{id}/sign-offline` | biz:acceptance:sign | 行内二次确认 | + +> **demo 产出桥接(运营旅程隐藏断点,须显式画进流程)**:契约里**没有「为某 lead 生成 demo」的端点**,advance→3 弹窗的 `demoVersionId` 由运营**手工回填**,其来源是运营**先去 game-studio 创作流(或 admin 既有创作入口)为该需求另行生成一个 game/version → 拿到 versionId → 复制回 biz advance 弹窗**。本波推荐**纯人工复制 versionId**(不做「从 biz 队列一键跳创作流并带 leadId 回链」的桥接增强,属超本波最小边界,标待裁顺延)。**实现者须知:这是跨页/跨系统运营动作,advance 弹窗只提供 demoVersionId 输入框 + 「去创作流生成 demo」文案提示,不在 biz 内造 demo 生成入口。** 见 §3.0 运营流程节点。 + +**运营处理流程(状态机唯一推进者)**: + +```mermaid +graph LR + Q["队列
默认 status=0 待跟进"] -->|指派| A["落 owner"] + A -->|报价 0→1| QU["已报价"] + QU -->|推进 1→2| MK["制作中"] + MK -.->|运营另去创作流生成 demo
拿 versionId 复制回 advance 弹窗| BR["demo 产出桥接
(跨页/跨系统·契约无生成端点·人工回填)"] + BR -->|推进 2→3
demoVersionId 必填+包就绪| WV["待验收"] + WV -.->|客户确认 3→4| DONE["已交付"] + WV -->|线下签署兜底| SIGN["signed_offline=1"] + style WV fill:#3a3520,color:#fde0c0 + style DONE fill:#1a3a2a,color:#c0fdd0 + style BR fill:#3a2030,color:#fec0d8 +``` + +**admin 侧硬约束**: +- **推进→3 待验收硬守门**:demoVersionId 必填且 runtime 包须就绪,后端 `validateDemoPreviewable` 守门,不就绪抛 BIZ_DEMO_NOT_READY(1-110-003-***);前端 advance 弹窗让运营填 demoVersionId,提交失败拦截器自动 Toast「该模板暂不可预览」。 +- **非法流转(跳级/回退)写前拒** BIZ_LEAD_STATUS_ILLEGAL_TRANSITION;前端推进 UI 按当前态只露下一合法态。 +- **详情端点缺口(D3 备注,最关键)**:admin 侧 `AdminBizLeadController` **无单询单详情 GET**(只有 `/leads/page` + `/leads/{id}/quotes`);app 侧 detail 端点带 customer_user_id 强归属校验(运营登录态≠客户,复用会抛 BIZ_LEAD_NOT_OWNER)。**本波推荐 (b) 前端不做独立详情、列表行 + GET quotes 报价历史拼装**(避免后端改动,守住「零后端改动」边界);若要进度时间线/最新报价/demo 三块完整详情,需后端补 admin 版无校验 detail(属后端改动,超本波边界,标待裁)。 + +--- + +## 4. 技术落点(照现有范式克隆,不另起炉灶) + +### 4.1 game-studio(①②)五层范式克隆 + +| 层 | 落点 | 范本 | 要点 | +|---|---|---|---| +| API | `src/api/community.ts` + `src/api/biz.ts` | `api/project.ts:20-89` | 每函数贴 yaml path(自带 `/app-api` 前缀),`request`(T=解包后 data);在 `api/index.ts:5-11` 加 `export * as communityApi/bizApi`(命名空间防同名冲突) | +| 类型 | `src/api/types.ts` 新增段 | `types.ts:1-16` 铁律 | 逐字段镜像 yaml VO,**禁造契约外字段**;int64→number | +| Store | `src/store/community.ts` + `biz.ts` | `store/project.ts:17-88` | Pinia setup store,ref 态 + load* action + loading 自管;`store/index.ts` 追加导出 | +| Mock | `src/mock/community.ts` + `biz.ts` | `mock/project.ts` | 导出 routes 数组,handler 返业务 data / 抛 MockError;`mock/index.ts:12-25` 注册 ALL_ROUTES;具体 path 排 :param 前 | +| View | `src/views/messages/` + `src/views/biz-orders/` | `views/project/{Project,Detail}.vue` | `