Files
Neo-ZQYY/docs/_overview/04b-feedback/P1-3-4-cross-page-params.md
Neo 509cf43284 chore(docs): Wave 0 调研产出 + P0/P1/P2 反馈调研
建立项目级标杆文档 docs/_overview/ 作为产品全景索引,
解决"PRD 零碎、文档膨胀、跨子系统调研无入口"的问题。

主要内容:
- 00-index 总索引 + 维护协议 + 与 CLAUDE.md 关系
- 01-product-overview 产品全景脑图(6 角色 / 6 子系统 / 数据流 /
  7 业务概念 / 8+1 AI 矩阵 / 22 术语)
- 02a-miniprogram-page-matrix 小程序 21 页业务指纹
- 02b-adminweb-page-matrix admin-web 19 路由业务指纹
- 03-test-spec 测试规范 (L1-L5 分层 + 走查模板 + 75-95 case 估算)
- 04-doc-conflicts 39 条冲突索引(P0×8 / P1×13 / P2×13 + 5 子项)
- 04a/b/c-conflicts-*-detail 业务故事卡(7 字段:关联/逻辑/影响/选项/判定)
- 05-orphan-pages-cleanup admin-web 6 孤儿页面处置(1 归档 + 4 保留)
- WAVES-MASTER-PLAN.md 全 Wave 主计划(0-5,共 22-32 工作日)
- WAVE-1-KICKOFF.md Wave 1 实施 kickoff
- GLOBAL-DECISION-DASHBOARD.md 全局决策仪表板

反馈调研产物:
- 04a-feedback/ P0 两轮反馈(8+8 项决策 + D-1/2/3 + F-1/2 子代理产出)
- 04b-feedback/ P1 两轮反馈(13+1+5 项 + E-1/2/3/4 + G-1/2 子代理产出)
- 04c-feedback/ P2 反馈(13 项 + 5 子项 + H-1/2/3 子代理产出)
- NEO-DECISIONS-LOG 累积决策记录

关键追加发现 8 处 D Bug(原蓝本 0):
- P0-3 看板沙箱接入(Wave 1 W1-T1)
- P0-5 致命 1 (4 处 fdw_etl 残留, 已修 commit 17f045a)
- P0-5 致命 2 (JWT aud 缺失, 已修 commit 17f045a)
- P0-6 clearAllTasks 守卫 (Wave 3)
- P0-8 DBViewer 黑名单漏 (已修 commit 17f045a)
- P1-3 task-detail 跳转传 task_id 而非 customer_id
- P2-7 board-finance 隐式 null
- 2 个独立 Bug (page_context.created_at + ClueCategory 字典)

参考: docs/_overview/00-index.md
2026-05-04 07:38:28 +08:00

24 KiB

小程序跨页传值规范性深度调研(P1-3 + P1-4 触发)

日期: 2026-05-04 触发: Neo 在 04b P1-3 + P1-4 反馈"同意初步判断,但谨慎起见,要从页面和产品设计出发,对业务进行理解的情况下,深入调研这个问题(尤其整个 APP 页面与角色的传值规范性方面)" 范围: 小程序 21 页全部跨页跳转 + 角色权限相关传值 + 公共组件 ai-float-button / board-tab-bar 调研口径: 只读不改, 单文档产出 状态机考量: 仅 5 类跳转 API: wx.navigateTo / wx.redirectTo / wx.switchTab / wx.reLaunch / wx.navigateBack


一、跳转矩阵全表

下表覆盖小程序 21 页全部 wx.navigateTo / wx.redirectTo / wx.switchTab / wx.reLaunch 调用(wx.navigateBack 仅在"目标页期望"列出现)。

代号约定:

  • id 默认指资源主键(taskId / customerId / coachId / historyId, 视目标页而定)
  • -- 表示无参数(空 URL)
  • onLoad 期望字段以代码实际读取为准
# 源页 跳转方法 目标页 参数 key:value 目标页 onLoad 期望字段 是否一致 问题类型
1 login reLaunch task-list / board-finance / my-profile (动态首页) -- -- 一致 --
2 login reLaunch reviewing -- -- 一致 --
3 login reLaunch apply -- -- 一致 --
4 login reLaunch no-permission -- -- 一致 --
5 apply reLaunch login (兜底) -- -- 一致 --
6 apply reLaunch reviewing -- -- 一致 --
7 apply reLaunch no-permission -- -- 一致 --
8 apply reLaunch <动态首页 by getRoleHome> -- -- 一致 --
9 apply navigateBack(fail→reLaunch login) 上一页 / login -- -- 一致 --
10 reviewing reLaunch <动态首页> / no-permission / apply / login siteCode + role + phone + employeeNumber (cancel 重申请) apply.onLoad 解 4 字段 一致 --
11 no-permission reLaunch login -- -- 一致 --
12 no-permission reLaunch <动态首页> -- -- 一致 --
13 no-permission reLaunch apply siteCode + role + phone + employeeNumber apply.onLoad 同上 一致 --
14 no-permission reLaunch reviewing -- -- 一致 --
15 task-list navigateTo task-detail id=<task.id> id 或 memberId 一致 --
16 task-list navigateTo performance -- scrollToBottom 可选 一致 --
17 task-list navigateTo performance scrollToBottom=1 scrollToBottom 解析 '1' 一致 --
18 task-list navigateTo chat taskId=<task.id> taskId 分支 一致 --
19 my-profile navigateTo (utils/router.navigateTo) chat-history / performance / notes -- -- 一致 --
20 my-profile reLaunch login -- -- 一致 --
21 task-detail navigateBack 上一页 -- -- 一致 --
22 task-detail navigateTo chat taskId=<detail.id> taskId 分支(contextType=task) 一致 --
23 task-detail navigateTo customer-service-records customerId=<detail.customerId 或 fallback 到 detail.id> customerId 或 id 不一致(B) P1-3
24 performance navigateBack(fail→switchTab task-list) 上一页 / 任务 tab -- -- 一致 --
25 performance navigateTo performance-records -- -- 一致 --
26 performance navigateTo task-detail memberId=<member.memberId> id 或 memberId 一致(2026-03-25 修复) 历史 P1-4
27 performance navigateTo task-detail id=<rec.taskId> 或 memberId=<rec.memberId> id 或 memberId 一致 --
28 performance navigateTo performance-records -- -- 一致 --
29 performance-records navigateBack(fail→switchTab) 上一页 -- -- 一致 --
30 performance-records navigateTo task-detail memberId=<row.memberId> id 或 memberId 一致 --
31 board-finance switchTab/redirectTo board-finance / board-customer / board-coach -- -- 一致 --
32 board-customer switchTab/redirectTo 同上 -- -- 一致 --
33 board-customer navigateTo customer-detail id=<row.id> id 或 customerId 一致 --
34 board-coach switchTab/redirectTo 同上 -- -- 一致 --
35 board-coach navigateTo coach-detail id=<row.id> id (仅) 一致 --
36 customer-detail navigateTo customer-records customerId=<detail.id> customerId 或 id 一致 D(命名/语义混乱) P1-10
37 customer-detail navigateTo chat customerId=<detail.id> customerId 分支 一致 --
38 customer-records -- (无下游跳转) -- -- -- --
39 customer-service-records navigateBack 上一页 -- -- 一致 --
40 coach-detail navigateTo customer-detail id= (3 个不同入口: 最近服务客户/收藏客户/常客) id 或 customerId 一致 --
41 coach-detail navigateTo coach-service-records coachId= coachId(必填,缺失则退回) 一致 --
42 coach-detail navigateTo chat coachId= coachId 分支 一致 --
43 coach-service-records navigateBack(fail→switchTab board-finance) 上一页 / 看板 -- -- 一致 --
44 coach-service-records navigateTo customer-detail id= id 或 customerId 一致(memberId<=0 拦截) 关联 P1-12
45 chat navigateBack 上一页 -- -- 一致 --
46 chat navigateTo <动态 link>(消息内可点链接) -- -- 取决于 link 内容 D(无校验)
47 chat-history navigateBack 上一页 -- -- 一致 --
48 chat-history navigateTo chat historyId=<row.id> historyId 分支 一致 --
49 dev-tools reLaunch <任意页 by dataset.url> (跟随 url 拼接) -- 一致 --
50 ai-float-button(组件,被 6 页引用) navigateTo chat sourcePage / pageFilters / customerId(可选) sourcePage 分支(看板类) 一致 --
51 board-tab-bar(组件) switchTab task-list / board-finance / my-profile -- -- 一致 --
52 dev-fab(组件) navigateTo dev-tools -- -- 一致 --
53 notes navigateBack 上一页 -- -- 一致 --

合计: 53 条跳转(合并重复入口后), 其中 2 条不一致 / 命名混乱(行 23、36), 1 条无校验(行 46)。


二、规范性问题清单(按严重度)

P0 级(语义错位,功能不通)

问题 P0-1: task-detail → customer-service-records 传 detail.id 当 customerId 用 (即 P1-3 后半段)

  • 源页: pages/task-detail/task-detail.ts L437-441
  • 目标页: pages/customer-service-records/customer-service-records.ts
  • 现状:
    const customerId = (this.data.detail as any)?.customerId || this.data.detail?.id || ''
    wx.navigateTo({ url: `/pages/customer-service-records/customer-service-records?customerId=${customerId}` })
    
    当 TASK-2 响应未返回 customerId 字段时, fallback 拿 detail.id(taskId), 把 taskId 当作 customerId 拼到 URL.
  • 目标页 onLoad: const id = options?.customerId || options?.id || '', 拿到的是 taskId, 后续按 taskId 调 fetchCustomerServiceRecords 必然返回空或错乱.
  • 期望: TASK-2 响应里加 customer_id / member_id 字段, 前端不再用 fallback.
  • 修复方案:
    • 后端: GET /api/xcx/tasks/{id} 响应增加 customerId(JOIN dim_member);
    • 前端: 删除 || this.data.detail?.id 的 fallback, 拿不到 customerId 时显式 toast"客户信息缺失".

问题 P0-2: chat 多入口路由当前实现一致性不足 (P1-11)

  • 源页: 3 入口
    • task-detailchat?taskId=(已正确, 走 contextType=task)
    • customer-detailchat?customerId=(已正确, contextType=customer)
    • coach-detailchat?coachId=(已正确, contextType=coach)
    • chat-historychat?historyId=(走历史 chatId)
    • task-list 上下文菜单"问问助手"chat?taskId=(已正确)
    • ai-float-buttonchat?sourcePage=...&pageFilters=...&customerId=...(看板类入口)
  • 目标页 onLoad: 已经根据 historyId / taskId / customerId / coachId / sourcePage / 无参 6 分支处理
  • 现状评估: 与 04b P1-11 描述存在偏差 — chat.ts L214-263 已经做了 6 分支, P1-11 描述的"loadMessages 仅用 customerId"已不适用(代码已演进)
  • 残留风险:
    • 后端接口侧: fetchChatMessagesByContext(contextType, contextId) 是否后端已支持 4 种 contextType(task / customer / coach / general / board-*) 待验证
    • general / board-* 几个 contextType 的 chatId 派生策略是否后端已实现待与后端核对
  • 修复方案: 与后端核对 GET /api/xcx/chat/messages?contextType=...&contextId=... 是否已上线全部 contextType 路由
  • 建议判定: 降为 P1(前端代码已修, 后端契约待补)

P1 级(命名/语义混乱, 功能可走通但易踩坑)

问题 P1-1: customer-detail "消费记录"卡片绑定的方法名是 onViewServiceRecords 但实际跳消费记录页 (P1-10 的根因)

  • 源页: customer-detail.wxml L177-181
    <!-- 消费记录 -->
    <view class="card-header" bindtap="onViewServiceRecords">
      <text class="section-title title-orange">消费记录</text>
    </view>
    
  • 处理: onViewServiceRecords 实际跳 customer-records(消费视角), 名字写成"Service"完全是误导.
  • 影响: 看代码读不出真实跳转目标; 改 bug 时容易跳错页面.
  • 期望: 方法名改为 onViewConsumptionRecords / goConsumptionRecords, 与文案"消费记录"一致.
  • 修复方案: 简单重命名(WXML + TS), 不影响功能.
  • 与 P1-10 关系: 04b P1-10 询问"查看消费记录跳哪个目标页", 答案是 customer-records(消费记录页, 2026-03-29 新建), 现状已正确, 但 方法命名误导.

问题 P1-2: task-detail.onLoad fallback 优先级模糊

  • 现状: onLoad({ id?, memberId? }) 同时支持两种语义, 但是当 url 里 同时 出现 ?id=xxx&memberId=yyy 时 优先使用 id 走 loadData, 不走 memberId.
  • 入口分布: 5 个入口都只传一个键, 故无实际冲突, 但接口边界模糊(若未来其他页传两个键, 行为不直观).
  • 期望: 显式声明"id 优先, 仅 id 缺失时才用 memberId", 在文档里写清楚.

问题 P1-3: 字段命名风格不统一 (camelCase vs lowercase)

  • 全局清单(纯 URL key, 不含值):
    • id(单字母 / 没有所属命名空间) → 使用面: 大量(task-list, board-customer, board-coach, coach-service-records, customer-records, customer-service-records 等都用)
    • customerId / coachId / taskId / historyId / memberId / siteCode / employeeNumber / sourcePage / pageFilters / scrollToBottom / phone / role / timeDimension / areaFilter / dimension / typeFilter / projectFilter
  • 风格: 以 camelCase 为主. 问题:
    • id 缺乏所属语义: 同一个 id 在 task-list 是 taskId, 在 board-customer 是 customerId, 在 board-coach 是 coachId. 排查时容易看 url 看错.
    • 混用 idcustomerId: customer-records / customer-service-records / customer-detail 三页的 onLoad 都做了 options?.customerId || options?.id 兼容, 这种"二选一"兼容是历史污渍.
  • 期望: 统一约定"目标页接收明确语义键(taskId / customerId / coachId), 不再接受裸 id"; 兼容期保留 id || customerId 的回退, 但所有 navigateTo 调用方迁移到明确键.

问题 P1-4: 字段类型(string vs number)隐式不一致

  • url 参数本质是 string, 但有些目标页直接 Number() 转换(如 coach-service-records.onLoad), 有些直接用 string(如 customer-records 把 id 写入 setData 用作 string).
  • 现状:
    • coach-service-records: Number(options?.coachId) 后判断 Finite && >0, 否则退回(已正确)
    • customer-detail / customer-records / customer-service-records / coach-detail: 全部用 string, 后端调用时再做转换
    • task-detail.loadByMember: String(detail.id) 显式转换
  • 期望: URL 参数全部按 string 处理, 调后端时转换由 service 层做; 业务侧不要混用.

P2 级(兜底缺失 / 体验问题)

问题 P2-1: 多数目标页缺少必填字段缺失时的 toast / fallback

  • 现状: 仅 coach-service-records 在 coachId 缺失时有 wx.showToast('缺少助教标识') + setTimeout navigateBack 的兜底.
  • 其他页(customer-detail / customer-records / customer-service-records / customer-detail / coach-detail / task-detail / chat)在拿不到必填字段时, 大多数走"setData empty / pageState='empty'"或者直接调后端拿空响应, 不会 toast 提醒.
  • 期望: 关键详情页(customer-detail / coach-detail / task-detail / customer-service-records / coach-service-records / customer-records / chat) 全部加必填字段缺失 toast.
  • chat.ts L552-556: wx.navigateTo({ url: link }) — link 来自 AI 回复消息中的可点链接, 无白名单校验.
  • 风险:
    • link 若指向 tabBar 页面会失败(navigateTo 不能去 tab 页)
    • link 包含恶意构造参数时无防护
  • 期望: 增加白名单(只允许 /pages/... 前缀 + 已知页面路径), navigateTo 失败时降级 switchTab.

问题 P2-3: dev-tools.ts 的 reLaunch 跳"任意页"无白名单校验

  • dev-tools.ts L156-158: const url = "/" + e.currentTarget.dataset.url; wx.reLaunch({ url }) — 来自 dataset, 调试页可接受, 但生产编译要确保 dev-tools 入口被关闭(已有 wx:if="{{false}}" 隐藏 dev-fab).

问题 P2-4: customer-detail 跳 customer-records 时 banner 字段重复加载

  • customer-detail 已有完整客户信息, customer-records.onLoad 只接 customerId, 然后再调 fetchCustomerConsumptionRecords 重新拉 banner.
  • 后果: 多一次接口往返, 但跳转后用户在 customer-records 看到的 banner 数据是新 fetch 的, 与 customer-detail 一致性不强.
  • 期望: 后端响应里 banner 字段(name/avatar/storage)由 customer-records 自己拉(已是现状), 不需要前端透传; 若考虑性能, 可走 globalData 暂存上一页客户对象, 但这是优化项.

角色相关传值问题清单(独立维度)

问题 R-1: 跳转链路中没有携带角色信息

  • 现状: 所有 navigateTo / redirectTo 调用 都不带 role 参数. 目标页通过 checkPageAccess(pageRoute) 在 onShow 调 auth-guard 模块从 globalData(后端 fetchMe 返回)读取角色和权限码.
  • 这是合理设计: URL 不应携带角色, 角色应来自后端权威源.
  • 但意味着: 如果后端 permissions 与页面预期角色不匹配(例如散客访问助教页), 由 auth-guard 拦截并跳 no-permission, 不靠 URL 角色.

问题 R-2: site_id(门店 ID)切换不影响传值

  • site_id 不出现在任何 URL 参数里, 后端通过 JWT + app.current_site_id 会话变量过滤. 这是 RLS 双 schema 设计, 跨店切换由后端处理, 前端 URL 不感知, 正确无问题.

问题 R-3: 散客模式(P1-12)的判断分散

  • 当前 coach-service-recordsNumber(options?.coachId) > 0 判合法, performance.onCustomerTapmid <= 0 判散客拦截.
  • 散客约定不统一(NULL / 0 / -1 / <=0 都有兼容代码), 这是 P1-12 的范畴, 与传值规范同源.
  • 期望: 散客统一约定 + 跳转拦截统一抽到 utils 函数(如 isScattered(memberId)).

三、传值规范建议

3.1 字段命名规范

强制约定:

  • URL 参数键统一使用 camelCase(已是事实标准, 文档化)
  • 禁止使用裸 id, 必须带语义前缀: taskId / customerId / coachId / historyId / memberId / noteId / recordId
  • 兼容期 id || customerId 的双键兼容保留 6 个月, 之后强制只接受语义键

3.2 参数 key 命名约定(全集 + 语义)

key 含义 类型 来源 / 出现页
taskId 任务 id string(数字字符串) task-list / chat / task-detail / performance
customerId 客户(会员) id, 等价 memberId string task-detail / customer-detail / customer-records / customer-service-records / chat
coachId 助教 id string coach-detail / coach-service-records / chat
historyId 对话历史 chatId string chat-history / chat
memberId 会员 id (与 customerId 同义) string(数字字符串) performance / performance-records / task-detail / coach-service-records
siteCode 门店编码(申请预填) string(URI 编码) reviewing → apply / no-permission → apply
employeeNumber 员工号(申请预填) string(URI 编码) 同上
phone 手机号(申请预填) string(URI 编码) 同上
role 角色(申请预填) string(URI 编码) 同上
sourcePage AI 上下文来源页 string(枚举) ai-float-button → chat
pageFilters AI 看板筛选参数集 string(URI + JSON) ai-float-button → chat
scrollToBottom 业绩页滚到底部标记 string('1' / 缺省) task-list → performance
timeDimension 等单键过滤 旧入口兼容 string ai-float-button → chat(回退路径)

统一约定:

  • customerIdmemberId 同义(后端 dim_member.id), 但小程序前端两套用法都存在. 期望: 跨页 URL 统一 customerId, 内部页面 data 里可以叫 memberId(看后端字段名). 迁移历史 url 期 memberId 兼容期 6 个月, 之后只接 customerId.

3.3 目标页 onLoad 必填字段校验模式

推荐模板(以 coach-service-records 为标杆):

onLoad(options: Record<string, string | undefined>) {
  const requiredId = Number(options?.coachId)
  const validId = Number.isFinite(requiredId) && requiredId > 0 ? requiredId : 0
  if (validId === 0) {
    wx.showToast({ title: '缺少助教标识', icon: 'none' })
    setTimeout(() => wx.navigateBack({
      fail: () => wx.switchTab({ url: '/pages/board-finance/board-finance' })
    }), 1000)
    return
  }
  this.setData({ coachId: validId })
  this.loadData(validId)
}

所有详情页应遵循这个模板:

  1. options?.<key> 提取出来做类型/合法性校验
  2. 缺失时明确 toast(中文文案 + icon='none')
  3. setTimeout 后 navigateBack(并提供 fail 兜底, 防止从分享链接首页直入)
  4. 合法时再 setData + 触发数据加载

3.4 跨角色 / 跨店传值约定

  • 角色: 不通过 URL 携带, 由 auth-guard 从 globalData / fetchMe 读取
  • 门店: 不通过 URL 携带, 由 JWT + 后端 RLS 处理
  • 散客判断: 在跳转源头拦截(memberId <= 0 一律不跳, toast"未知客户不提供查看详情"), 等待 P1-12 决策后将判断函数集中到 utils/customer.ts(待新建)

四、修复方案分组

必修(P0): 后端补字段 + 前端去 fallback

模块 改动 工作量
F1 后端 TASK-2 GET /api/xcx/tasks/{id} 响应增加 customerId(JOIN dim_member 由 task.member_id 派生)
F2 前端 task-detail 删除 `customerId = detail?.customerId
F3 后端 chat by-context 验证 GET /api/xcx/chat/messages?contextType=task/customer/coach/general/board-*&contextId= 已支持全部 contextType

应修(P1): 字段命名/类型统一 + 命名重构

模块 改动 工作量
F4 customer-detail.ts + customer-detail.wxml onViewServiceRecords 重命名为 onViewConsumptionRecords, WXML bindtap 同步 极小
F5 board-customer / board-coach 跳 customer-detail / coach-detail 时, 把 ?id= 改为 ?customerId= / ?coachId=(语义化), 目标页保留兼容期
F6 task-list 跳 task-detail 时, ?id= 改为 ?taskId=(目标页兼容期保留 id)
F7 coach-service-records 跳 customer-detail 时, ?id=${memberId} 改为 ?customerId=${memberId} 极小
F8 docs(SPEC) 制定"小程序跨页传值规范"SPEC, 见 §五.建议

可修(P2): 兜底补全 + 安全加固

模块 改动 工作量
F9 customer-detail / coach-detail / task-detail / customer-records / customer-service-records / coach-service-records / chat 必填字段缺失统一加 toast + 退回上一页
F10 chat 消息 link 跳转 增加白名单(/pages/ 前缀 + 已知页面集), 失败降级 switchTab
F11 utils/customer.ts 新建 isScattered(memberId) 函数, 统一散客判断, 等 P1-12 决策后填实现

已确认无需修(误报或已修)

  • performance → task-detail 传 customerName 而非 task_id (P1-4): 已于 2026-03-25 修复, 现 onCustomerTapmemberId, onRecordTap 优先传 taskId fallback memberId. 04b P1-4 描述已过时, 应在 04b 反馈中标注"已修复".
  • chat.loadMessages 仅用 customerId (P1-11): 已于多次迭代修复, 现 chat.onLoad 走 6 分支(historyId / taskId / customerId / coachId / sourcePage / 无参), 04b P1-11 描述已过时, 仅后端契约待核对.

五、给 Neo 的决策清单

决策 D1: 是否同意"必修"清单全部进 Wave 1-3?

子项:

  • D1a: F1 + F2(后端 TASK-2 补 customerId, 前端去 fallback) — 是否进 Wave 1?
  • D1b: F3(后端 chat by-context 全 contextType 验证) — 是否单独立项核对后端实现?

决策 D2: 是否同意"应修"清单的命名重构?

子项:

  • D2a: F4(customer-detail 方法名重命名) — 极小工作量, 建议直接合并到 P0 修复 PR
  • D2b: F5 + F6 + F7(URL 参数从裸 id 迁移到语义键) — 涉及 4 页, 建议在 Wave 2 单独立项, 跨页协调
  • D2c: F8(SPEC 化) — 是否新建 docs/miniprogram-dev/spec/cross-page-params-spec.md?

决策 D3: 是否同意"可修"清单的优先级排序?

子项:

  • D3a: F9(必填字段 toast 兜底) — 7 个页面, 中等工作量, 体验提升明显
  • D3b: F10(chat link 白名单) — 安全加固, 轻量
  • D3c: F11(散客判断集中) — 等 P1-12 决策后再做

决策 D4: P1-4 与 P1-11 在 04b 文档中的状态更新

  • 是否同意将 P1-4 标注"已修复(2026-03-25), 仅文档过时"?
  • 是否同意将 P1-11 标注"前端已修(6 分支), 后端契约待核对"?

决策 D5: 是否制定独立 SPEC

建议新建 docs/miniprogram-dev/spec/cross-page-params-spec.md, 内容包含:

  • §3.1-3.4 的命名规范、key 全集、onLoad 模板、跨角色约定
  • 历史兼容期(双键)的退役时间表
  • 测试矩阵(每个跳转的合法/缺失/类型错路径)

六、调研附录

6.1 调研覆盖度

  • 21 页 100% 覆盖(login / apply / reviewing / no-permission / task-list / board-finance / my-profile / task-detail / notes / performance / performance-records / board-customer / board-coach / customer-detail / customer-service-records / customer-records / coach-detail / coach-service-records / chat / chat-history / dev-tools)
  • 公共组件 ai-float-button / board-tab-bar / dev-fab 100% 覆盖
  • utils/router.ts / utils/auth-guard.ts(getRoleHome / checkPageAccess) 已查
  • 共抓取 53 条跳转(去重前约 70 条), 含组件触发跳转

6.2 调研口径限制

  • 仅调研代码现状, 未跑实际跳转流程验证
  • 未深入后端 API 契约 — F3(chat by-context) 待与后端核对
  • 未涉及 H5 原型 / demo-miniprogram(MOCK 标杆禁改) — 设计参考另议

6.3 与 04b 已知问题对照

04b 问题 调研结论 后续动作
P1-3 (task-detail → chat / customer-service-records 传 detail.id) chat 路径已修, customer-service-records 路径仍是 fallback bug F1+F2 必修
P1-4 (performance → task-detail 传 customerName) 已于 2026-03-25 修, 04b 描述过时 仅更新 04b 状态
P1-10 (customer-detail "查看消费记录"跳哪) 跳 customer-records(消费记录页, 现状正确), 但方法名 onViewServiceRecords 误导 F4 重命名
P1-11 (chat 多入口 / loadMessages 仅用 customerId) 前端已 6 分支, 后端契约待核 F3 待核对
P1-12 (散客 memberId 取值约定) 与 R-3 / F11 同源 等 Neo 决策 + 抽函数

本调研结论与 Neo 反馈的"初步判断不变"一致: 同意必修后端补 task_id / customer_id 字段 + 前端改跳转参数, 且额外发现 P1-1(命名误导)、P1-3(裸 id 不规范)等若干非 P1-3/P1-4 问题, 建议一并制定 SPEC 系统化解决.