Files
order_site/apps/frontend/tests/consignment-template-proposal.test.ts
zhaoxing 787b8e2771 feat(consignment): 接单模板反推规格字段,打手端大批量选项改下拉
- 新增 consignment-template-spec-service:按「分类 + 子树」解析接单模板商品名,
  全部可拆成统一维度且无组合碰撞时生成多字段矩阵,否则整类降级为商品名下拉;
  选项只存 ruleKey,取价时实时回查模板,模板停用/删除即无价(missingPricePolicy=block)。
- 匹配引擎:模板驱动配置强制使用 profile specs(不再回退库存旧快照),订单侧按
  product_rule_id 反解规格;解析失败按 unknown 处理,不参与自动匹配。
- 管理端:寄卖配置新增「从接单模板生成」,弹窗给出推荐模式(规格字段 / 商品名下拉)、
  降级原因与组合→模板价覆盖矩阵。
- 打手端:选项超过 8 个改用带搜索的下拉(地铁逃生 100 个商品),规格网格按字段数
  自适应铺满;物品名改用商品名,去掉硬编码「苏尔南」后缀。
- 迁移重编号:合并 main 后寄卖线顺延为 147–151,migrate.ts 保留 legacy→new 幂等映射。
- 同工作区的拼单份额报酬口径、超时重匹配兜底、整单/拼单匹配弹窗调整一并提交。

验证:前端 254/254、后端寄卖相关 41/41、双端 tsc 通过;开发库已实跑
发布→审核入库→自动匹配(模板价 1200 → 匹配报酬 1200)。
2026-11-07 12:26:10 +08:00

66 lines
2.5 KiB
TypeScript

import assert from 'node:assert/strict'
import { readFileSync } from 'node:fs'
import { fileURLToPath } from 'node:url'
import test from 'node:test'
function readPanelSource() {
return readFileSync(
fileURLToPath(new URL('../src/pages/admin/panels/ConsignmentConfigPanel.tsx', import.meta.url)),
'utf8',
).replace(/\r\n/g, '\n')
}
test('从接单模板生成:factor 模式必须显式推荐「规格字段(多字段矩阵)」', () => {
const source = readPanelSource()
assert.ok(
source.includes('推荐使用:规格字段(多字段矩阵)'),
'factor 模式必须给出推荐文案,运营才知道该用多字段矩阵',
)
assert.ok(
source.includes("proposal.mode === 'factor' ? ("),
'推荐文案必须按 proposal.mode 分支渲染',
)
})
test('从接单模板生成:product 模式必须显式推荐「商品名下拉」并解释原因', () => {
const source = readPanelSource()
assert.ok(source.includes('推荐使用:商品名下拉'), '降级为商品下拉时必须说明推荐该模式')
assert.ok(source.includes('拆不成同一组维度'), '必须解释为什么不能拆成多字段矩阵')
assert.ok(
source.includes('无法纳入统一维度的模板(前 5 条)'),
'必须列出拆不动的模板示例,便于运营判断是否改名',
)
})
test('从接单模板生成:无模板时必须给配置引导,而不是只显示一句报错', () => {
const source = readPanelSource()
assert.ok(
source.includes('请先在「接单模板」里为该分类配置至少 1 条启用模板'),
'空状态必须引导去接单模板配置',
)
assert.ok(
source.includes('该分类的启用模板都没有报酬或单价'),
'有模板但无价时必须区分提示,避免误以为没有模板',
)
assert.ok(
source.includes('推荐规则:商品名能拆成同一组维度时'),
'空状态也要说明两种模式的推荐规则',
)
assert.ok(
!source.includes('该分类没有启用且有价的接单模板,无法生成规格字段'),
'旧的死板提示必须被 Empty 引导替换',
)
})
test('从接单模板生成:应用按钮按「有价组合数」禁用,空提案不能被应用', () => {
const source = readPanelSource()
assert.ok(
source.includes('templateProposalQuery.data.data.matrix.length === 0'),
'应用按钮必须在没有组合价时禁用',
)
assert.ok(
source.includes('proposal.matrix.length === 0 || proposal.fields.length === 0'),
'应用动作本身也要兜底拦截空提案',
)
})