对比区间:
ded04ef(base)→6ba2469(head,v0.1.52) 数据来源:codescan_issues_diff(修复/新增问题,真实数据)+ git diff 精读 + 关键文件人工复核 变更规模:新增 5 个测试文件 + 1 个共享判据模块 + 1 个抽屉组件,改造依赖 mock/order/records/settle/workbench 等核心链路
本版本围绕 D61「拆单 + 服务单状态机 + 建单意向」,交付四块能力:
服务单状态推进(start/finish)
src/pages/shared/orderActions.ts:状态维度(showServiceAdvance / serviceAdvanceStatusReason)+ 权限维度(canOperateService)+ 错误文案(serviceActionErrorText)统一判据,列表行与详情抽屉共用。api/order.ts 新增 startService / finishService 及响应类型;order.mock.ts 补齐同契约 mock(权限 2003、状态 1005 优先序与 server 一致)。OrderRecordDrawer、pos/records/index.tsx 接入按钮、二次确认与灰显 tooltip。员工微信绑定(残留批 2)
api/org.ts 新增 StaffWxBinding / fetchStaffWxBinding / unbindStaffWx,org.mock.ts 补 mock(openid 脱敏、越域 2004、未绑定 1005)。WxBindingDrawer.tsx,org/staffs/index.tsx 行操作「微信绑定」接入;解绑走统一带遮罩 Modal。建单意向「看得见」(D61 §七)
order.ts 详情适配 draftAllocs/draftPayIntent;model.ts 新增 ratioPctText / draftIntentOf。AllocPanel 增加只读意向条;SettleOrderModal 组装意向并在待收款链路透传 pay_intent。测试基建:新增 5 个用例文件(mock 契约、抽屉动作、开单记录推进、意向可读化、微信绑定);testTimeout 20s→60s、asyncUtilTimeout→20s。
总体评价:功能实现规范,边界(权限/状态/错误码)有明确契约且被新用例覆盖,未见影响主流程的功能性缺陷。主要问题集中在新增代码的复杂度膨胀与少量健壮性/分层细节。
均为历史存量质量项在重构中被动消除,主要来自
adaptOrderDetail、OrderRecordDrawer、pos/records、SettleOrderModal的改写。
| 文件 | 类型 | 建议 |
|---|---|---|
| src/api/order.ts:331 | 重复代码块 | 抽取共享函数 |
| src/api/order.ts:424 | 圈复杂度过高 | 拆分小函数 |
| src/api/order.ts:448 | 重复代码块 | 抽取共享函数 |
| src/api/order.ts:576 | 圈复杂度过高 | 拆分小函数 |
| src/components/fund/OrderRecordDrawer.tsx:203 | 行过长 | 换行 |
| src/components/fund/OrderRecordDrawer.tsx:493 | 圈复杂度/嵌套/函数过长(3 条) | 拆分 |
| src/pages/pos/records/index.tsx:25 | 行过长 | 换行 |
| src/pages/pos/records/index.tsx:33 | 圈复杂度/嵌套/函数过长(3 条) | 拆分 |
| src/pages/pos/records/index.tsx:114 | 重复代码块 | 抽取 |
| src/pages/pos/workbench/SettleOrderModal.tsx:270 | 行过长 | 换行 |
说明:其中
OrderRecordDrawer.tsx:493、pos/records/index.tsx:33等为「同函数被改动后行号变化」,与第三节「新增」中同位置的条目互为同一处代码的位置迁移,非功能回归。
| 严重度/类型 | 位置 | 说明 / 建议 |
|---|---|---|
| Medium/Complexity | src/pages/pos/records/index.tsx:56 | PosRecordsPage 337 行、cc=30、扇出 28:推进 mutation + useQueries 权限预取 + 列渲染叠入单一组件,建议把「行操作/推进」抽子组件或自定义 hook |
| Medium/Complexity | src/api/order.ts:464 | adaptOrderDetail 83 行、cc=27:新增 draftAllocs/draftPayIntent/staff_id 映射后进一步膨胀,建议拆分 items/payments/treatment 适配函数 |
| Medium/Complexity | src/pages/org/staffs/WxBindingDrawer.tsx:28 | WxBindingDrawer 120 行、cc=15:可拆「查询+解绑动作」与「展示」 |
| Medium/Complexity | src/components/fund/OrderRecordDrawer.tsx:598 | VoidOrderModal 155 行、cc=18(位置迁移,见下注) |
| Medium/Complexity | src/api/order.mock.ts:487 | cc=11 |
| Medium/Complexity | src/api/order.ts:619 | cc=12 |
| Medium/Complexity | src/pages/pos/pending/index.tsx:24 |
OrderRecordDrawer.tsx:598(VoidOrderModal 圈复杂度/嵌套/函数过长,3 条)↔ base 的 :493,因上方插入 start/finish 代码而下移。SettleOrderModal.tsx:291(行过长)↔ base 的 :270。order.ts:464、records/index.tsx:56 虽亦为位置迁移,但对应函数确有真实增长(新逻辑并入),计入真实新债。orderDrawerActions.test.tsx:99、serviceAdvance.test.tsx:117:重复代码块(测试 setup 重复,可抽 helper)。建议:新增复杂度集中在「列表页推进逻辑」和「详情适配层」,下一迭代优先把
PosRecordsPage的行操作、adaptOrderDetail的子结构适配抽离,可同时消掉多条 Medium。
以下为精读变更代码后识别的问题,按严重度排序;均为新增/改造代码引入。
src/pages/org/staffs/WxBindingDrawer.tsx 渲染分支只以 !binding(data 是否存在)区分,loading 与 error 共用同一 Spin 占位:
{binding ? (…内容…) : (<div style={{padding:60,textAlign:'center'}}><Spin /></div>)}
当 GET /staffs/{id}/wx-binding 失败(网络异常,或 2003/2004/1002 越权/越域),bindingQuery.data 恒为 undefined,抽屉一直停留在 Spin,用户既看不到失败原因也无法重试。
建议:增加 bindingQuery.isError 分支,展示 errorMessage(bindingQuery.error) + 「重试」按钮(复用项目统一错误展示)。
src/api/order.mock.ts 新增 import { useAuthStore } from '@/stores/auth',让 API 层(含 mock)依赖 zustand store,用于在 ensureServiceStaff 中读取当前登录人。
stores/auth → api/auth|api/client|queryClient|menu|storeSelection,当前无循环依赖,运行时不报错。orderServiceFlow.mock.test.ts 等契约测试需先初始化 store 才能跑通,耦合上升。
建议:把「操作人」作为参数显式传入 mock 动作(startService(orderId, operator)),或在更底层注入当前 staff,保持 api 层不感知 store。wxBindings 缺版本迁移,存量会话丢种子绑定态src/api/order.mock.ts 有 MOCK_VERSION 强校验(不足版本重播种),但 src/api/org.mock.ts 的 load() 命中 sessionStorage 即 return JSON.parse(raw),不校验版本、不合并新增字段:
wxBindings,state.wxBindings?.[id] 恒 undefined → 种子已绑定的员工(张小明/周晓芸)显示「未绑定」,unbindStaffWx 直接判定 1005 无需解绑。org.mock 加 MOCK_VERSION(或在 load 中对缺失的 wxBindings 兜底合并 seed() 的默认值)。onOk 返回可能 reject 的链式 Promise,失败后弹窗不关闭 + console 噪音OrderRecordDrawer.confirmFinish/confirmCancel 与 pos/records.runAdvance 的完成分支:
onOk: () => mutation.mutateAsync().then(() => undefined)
失败时 mutateAsync reject,虽 onError 已弹错误文案,但 antd Modal.confirm 会保留弹窗并 console.error,用户可能重复点确认。
建议:onOk 内 try/await/catch 后返回 resolved(失败即由 onError 提示并关闭),或显式 .catch(() => undefined)。
src/pages/pos/workbench/AllocPanel.tsx 的 draftIntentBanner 在销售单分支与常规服务单分支渲染,但服务单「无购买行(全划卡/空行)」的早退分支未渲染,此时收款面板会看不到「下单时已排/支付意向」。属展示一致性问题。
vitest.config.ts 将 testTimeout 由 20s 提到 60s,src/test/setup.ts 将 asyncUtilTimeout 提到 20s。注释称「不改断言口径」,但可用性上是在放大等待上限以吸收大 DOM(PosRecordsPage/OrderRecordDrawer 巨型组件)与 jsdom 可访问名计算开销。这会掩盖页面级性能退化。
建议:结合 3.1 的组件拆分降低单页 DOM 规模,逐步回退超时阈值;而非持续上调。
PosRecordsPage 与 adaptOrderDetail,建议下一迭代优先抽取「行操作 hook」与「详情子结构适配器」,可批量消除复杂度/扇出告警,并配合回退测试超时(4.6)。| src/pages/pos/workbench/SettleOrderModal.tsx:418 | 重复代码块 | 抽取 |
cc=12(settleRow 改造后) |
| Medium/Dependency | src/api/tests/orderServiceFlow.mock.test.ts:1 | 直接依赖 11 函数,超阈值 |
| Low/Dependency | src/pages/pos/records/index.tsx:56 | PosRecordsPage 扇出 28 |
| Low/Dependency | src/components/fund/OrderRecordDrawer.tsx:128 | OrderRecordDrawer 扇出 21 |
| Low/Maintainability | src/api/order.ts:367 / :490 | 重复代码块 |
| Low/Maintainability | src/pages/pos/records/index.tsx:307 | 重复代码块 |
| Low/Maintainability | src/pages/pos/workbench/SettleOrderModal.tsx:439 | 重复代码块 |
| Low/Maintainability | 多文件 | 行过长:OrderRecordDrawer:308、SettleOrderModal:291、orderActions.ts:38、orderActions.test.ts:44、draftIntent.test.tsx:46、records/index.tsx:47 |