日期:2026-10-21。证据类型:静态代码、现有纯逻辑测试、从当前源码抽取函数的内存模拟。本报告不代表真实 UI、真实接口、审批写入或微信真机验收通过。
97cbba3b052e346089fe2793ec432f20b5a82021。开始时仅发现本次方案和 docs/testing/ 未跟踪文件;本子任务未改业务源码,未提交 Git,未写数据库,未操作浏览器,未运行 Playwright。graphify-out/wiki/index.md、web-admin/graphify-out/wiki/index.md 均不存在。图谱提示客户/合同详情组件是高连接节点;图谱基线早于当前提交,因此具体结论均回到当前源码核对。主要依据:
“实现可定位”仅表示当前源码有对应入口和处理,不表示已在真实 UI 或服务端验证成功。
| 入口 | 应保留能力 / Web 对照 | 当前实现可定位 | 明确删减或已确认边界 | 本轮判断 |
|---|---|---|---|---|
客户管理 /m/crm/customer |
四视图、关键词/字段筛选/排序、分页;客户增改删、公海;详情资料/跟进/联系人/商机/合同/开票/日志。对照 crm/customer/index.vue、CustomerFormDialog.vue、CustomerDetailDialog.vue |
四视图、远程 facet、分页请求序列保护;全量列表卡字段;增改与证件附件;批量删除/公海;主要联系人/默认开票、商机动作均有代码 | 导出排除;Web 无实际入口的转移/成交不新增;字段显隐已按 10-18 定稿移除;关联商机/合同/日志筛选仅已加载集合是 10-18 明确保留行为 | 输入重建、排序入口差距;其他业务操作待真实回归 |
产品管理 /m/crm/product |
列表/详情/增改/单条上下架/删除/分类维护。对照 crm/product/index.vue、共享产品表单 |
最新列表固定 statusIn=on,分类/型号/价格筛选、扁平卡;详情锚点、分类全路径、品牌/别名/图片;删除创建人限制 |
列表只展示上架、无状态 Tab、成本价不展示均已确认;无导入导出、批量上下架、字段显隐;不把“下架后卡消失”报缺陷 | 输入重建;页面表单仍 Element,作为当前规范差距单列 |
报价管理 /m/crm/quote |
全部/待审批/已审批、详情、增改、复制、删除、单条提交/作废、版本历史。对照 crm/quote/QuoteListPage.vue、QuoteFormPanel.vue、QuoteDetailDialog.vue |
共享移动列表;页面表单 Vant 分支;详情全分区锚点;金额汇总/税费/别名/品牌;审批人有序多选及默认设置预填 | 不要求批量提交/审批、分享、转合同、生成报价单/PDF、导出、统计条、独立审批人设置菜单 | 输入重建;产品分页失败跳页;客户/商机选择上限与即时搜索;金额筛选回显 |
报价审批 /m/crm/quote/approval |
待我审批/已审批;详情、当前步骤通过/驳回 | 列表查询用 pendingApprovalUserId/approvedByUserId;详情要求 status=submitted;复用 findPendingQuoteApproval;管理/审批动作分开 |
仅单条审批;审批页不改单 | 相关纯函数用例通过;真实角色/实际审批未验证 |
合同管理 /m/crm/contract |
列表/详情/增改/复制/删除、提交/作废/恢复、扫描件;批量提交。对照 crm/contract/ContractListPage.vue、ContractFormDialog.vue、ContractDetailDialog.vue |
草稿批量提交并提示跳过;详情按状态动作;附件;详情页面与共享表单 | 调价函管理、执行管理、续签、打印/PDF/Excel、桌面 facet/统计条/审批人设置菜单排除 | 输入重建;锚点高亮错误;详情税费/总计遗漏;金额筛选回显;表单保留桌面形态 |
合同审批 /m/crm/contract/approval |
待我审批/已审批;单条/批量通过/驳回;部分失败反馈 | 列表 canApprove 过滤,驳回理由必填;批量审批 Promise.allSettled 统计成功/失败/跳过;详情有独立审批入口 |
审批页不改单;不能把报价不做批量的边界套到合同 | 详情审批按钮门禁与服务端不同;真实批量部分失败待验证 |
批量补充:客户“全选已加载”文案与 toggleAll() 仅选择当前已加载行一致,不将其误报为全库全选失败。见 客户选择逻辑。合同列表处理批量时清空选择、刷新列表的代码已存在,但没有实际调用审批接口。
detailTabs 却先产品后甲乙方,Tab 顺序。滚动同步 将最后一个 top <= probe 的 Tab 设为当前项,依赖数组与 DOM 同序。probe=104,products.top=100,parties.top=-900,其他后续区块未到达。实际 activeTab=parties,预期 products。mobileProductPage += 1;错误处理 没有回滚页码,也没有保存失败页。[2,3],结果为 p1–p20 + p41–p60,缺 p21–p40。matchProductNo:false、matchModel:true;不能误写成只过滤本地首屏。v-if/v-else 互斥:客户、产品、报价共用列表、合同共用列表。真实 MpBusinessHeader 和更多筛选均在 v-else 内。rows 再 loading=true,300ms 防抖 每次输入触发;因此命中骨架分支,搜索 input 被销毁。产品、报价、合同同样在 reset 清集合后进入 loading。@search,没有输入监听或关键词 watcher,输入后要点键盘搜索才查询,清空也不自动重查。page:1,pageSize:30;商机请求 固定 pageNum:1,pageSize:30。弹层不读取 total,也没有更多页入口。isCurrent;按钮生成 直接使用此结果。status=draft;步骤 1 已 rejected;当前用户步骤 2 pending。结果 canApprove=true,动作 ['approve','reject']。is_current=1 和本轮前置均 approved。按合同审批入口 也查当前节点。/m/crm/contract/:id?from=approve 详情;预期无通过/驳回。需第二个真实账号与隔离流程。status=submitted,并使用具备前置驳回判断的 findPendingQuoteApproval;相关纯逻辑测试本次通过。amountRange='',同时保留 moreDraft 的金额上下限。1-10w,更多内上下限保持 10000/100000,直接确定;实际 minAmount=10000,maxAmount=100000,amountRange=''。空 range 对应快捷栏“全部金额”,但查询继续限制金额;“更多·已筛”虽会出现,快捷栏仍误导。taxAmount;移动产品明细 有税率、含税单价、含税总价,但没有税费行。API 可读字段 taxAmount 已存在。amount + freight + barrelDeposit。移动金额区 仅分别展示三项及 amountWithTax,没有该合计。amountWithTax 是独立接口字段,不能视为前述求和展示的等价替代。sortField/sortOrder;buildQuery 不回传排序。| 检查点 | 静态结果 | 后续验证 |
|---|---|---|
| 客户列表编号/名称等 facet | 服务端 fetchCustomerColumnFacetValues;每次带搜索词,limit=500;保留选中值,具备请求版本保护 |
不能因 limit=500 就说只搜本地首批;需用第 501 个值的唯一关键词验证服务器结果与回显 |
| 产品分类/型号 | 分类取树,列表展示全路径;型号选项 limit=500;更多内可手输型号 | 型号快捷列表超过 500 的覆盖依赖更多输入,需核对用户可发现性 |
| 报价产品 | 服务端即时搜索、滚动分页、主体约束及名称/拼音/型号匹配参数存在 | A02;已选项跨检索/分页保持、不同主体危化限制需真实回归 |
| 报价客户/商机 | 服务端搜索但固定 30,无即时输入事件 | A04 |
| 报价联系人/负责人/主体/审批人 | 联系人由客户拉取;负责人/主体 picker 列表;审批人多选有序,未见人员搜索入口 | 大量人员/联系人下可用性待测,不因缺少搜索直接推断数据丢失 |
| 合同表单选择器 | 页面 variant 继续挂 ProductSelector/CustomerSelector/ContactSelector/QuoteSelector;桌面选择器具备服务端分页 | 不报“只检索首 20/50”;但移动弹层宽度、键盘与滚动须查 |
| 客户关联商机修改 | fetchCustomerOptions({keyword,limit:100}),点击“搜索客户”才查 |
大量匹配项与即时搜索体验候选;不是仅本地过滤 |
| 客户详情关联合同/商机/日志 | 查询分页、关键词/快捷筛选作用已加载集合 | 10-18 专项设计明确允许,未报为新缺陷;界面若未说明“已加载”可做文案改善 |
布局待 CUA 验证项,未宣称视觉失败或通过:
CustomerFields、产品/报价/合同详情多为逐行 KV;合同表单页面样式明确 grid-template-columns:1fr。日期/数量/税率/状态等可作为两列优化候选,但不得把 Web 弹窗“两列”要求机械套成全部移动字段必须两列。需在 375/414 宽长值、空值、错误提示下验证可读性。el-input、el-tree-select;合同 ContractFormDialog.vue 为全屏 el-dialog 并保留桌面选择器 735 行。与当前 H5 补遗的 Vant/底部弹层方向有差距;旧迁移允许复用表单,不把这单独当成真实业务不可用。van-tab 内容,带 swipeable,detail.vue;产品/报价/合同为同页锚点。客户 10-18 专项设计明确按资料/跟进/联系人等业务 Tab 改造,而通用补遗要求详情锚点;这是需结合最新产品意图确认的规范差异,不将业务 Tab 的存在直接判为缺陷。router.replace(listPath);需核验条件、展开项和滚动位置是否合理恢复。未检查 router 缓存全链路前不下丢状态定论。执行前已读脚本和目标模块导入,确认只做纯函数/源码断言:不启动浏览器、不发真实业务请求。test-mp-crm-{customer,product,quote,contract}.mjs 及 *-dom.mjs 含 Playwright,本轮未执行。
在 web-admin/ 执行:
node --import tsx --test src/views/m/crm/customer/model.test.ts src/utils/mp-crm-product-card.test.ts src/utils/mp-crm-product-category-tree.test.ts src/utils/mp-crm-quote-card.test.ts src/utils/mp-crm-contract-card.test.ts src/utils/mp-crm-confirm.test.ts src/utils/mp-crm-product-confirm.test.ts scripts/mp-crm-primitives.test.mjs
Node v24.15.0;退出码 1;结果 52 tests / 51 pass / 1 fail。
| 测试组 | 本次结果 | 能说明什么 |
|---|---|---|
| 客户 model | 9 项通过 | payload 精确 ID、时间、固定卡片字段、响应归一、开票失败后不重复创建客户的替身逻辑 |
| 产品卡片/分类树 | 11 项通过 | 固定只查上架、字段格式化、分类展开纯逻辑 |
| 报价卡片/查询/当前审批人 | 14 项通过 | 查询参数、卡片映射、当前最早步骤及前置驳回保护 |
| 合同卡片/查询 | 9 项通过 | 查询参数/金额格式化;不覆盖详情 pendingApproval 或批量真实接口 |
| 共用确认/产品确认别名 | 5 项通过 | 配置、危险 HTML 转义 |
| primitives 源码契约 | 3 通过、1 失败 | 失败是旧附件类名断言,不能证明像素尺寸或真实点击命中 |
失败详情:scripts/mp-crm-primitives.test.mjs:83 断言 /class="att-grid\b/,当前 MpAttachmentGrid.vue 使用 class="mp-crm-att-grid"。同测试还期待旧 att-doc-thumb 与 att-add mp-wv-touch-target,当前组件/SCSS 已有新结构。将其登记为 测试契约陈旧(P3,CRM-T01);未改测试以制造通过,未据此宣称附件 UI 有缺陷。真实附件大小、删除命中区及长文件名仍待 CUA。
额外内存模拟使用 typescript AST 从当前 .vue 的 <script> 抽取真实函数/变量声明后转译;仅注入 ref/computed、矩形位置和假的 API 返回,无浏览器或业务请求:
CRM-A01 expected="products", actual="parties"
positions: base=-1500, amount=-1200, parties=-900, products=100,
approval=900, attachments=1300; probe=104
CRM-A02 calls=[2,3], pageAfterFailure=2
loaded IDs: p1..p20 + p41..p60; missing p21..p40
CRM-A05 status="draft", canApprove=true, actions=["approve","reject"]
input: step1 rejected; current user step2 pending
CRM-A06 quote: minAmount="10000", maxAmount="100000", amountRange=""
CRM-A06 contract: minAmount="10000", maxAmount="100000", amountRange=""
第一轮抽取脚本在已输出 A01 后因报价 <script> 带 name 属性而解析失败;改为读取任意 <script ...> 标签后,A02 单独执行退出码 0,A05/A06 执行退出码 0。该失败属于临时审计 harness,不属于产品缺陷,未改业务源码。
结论边界:本子任务完成代码对照和上述非浏览器验证;尚未覆盖真实权限隔离、真实保存/上传/审批/删除、微信原生行为、实际像素布局及全字段往返保存。不能据纯函数通过或静态可定位,宣称六入口验收通过。