feat(consignment): 客服手动指定现货匹配的界面入口

后端批次已提供判定/差异/强制留痕与双向读取接口,这里补界面,让客服真的能用上。

- 新增共享弹窗 ConsignmentManualMatchModal:订单侧(匹配弹窗「手动指定现货匹配」)与
  库存侧(寄售仓库行内「手动匹配订单」)共用同一套交互与落地逻辑,避免两套 UI 漂移
- 交互:搜索 → 选中(精确/非精确/规格冲突三档标签 + 字段级差异说明)→ 选交付方式
  (内部现货履约 / 指派供货打手)→ 非精确需勾选确认、冲突需勾选「确认规格不一致」并必填原因
  → 落地;并在落地前提示"现货立刻被占用、点错需撤销寄售履约"
- 判定规则收敛成纯函数 consignment-manual-match.ts(需不需要确认/填原因、能否提交、
  关键词过滤、标签文案)并加 4 例单测
- 服务与类型补齐:fetchWorkOrderConsignmentMatchOptions / fetchInventoryMatchableOrders,
  fulfill/assign 入参增加 allowSpecMismatch 与 matchNote
- 凭证核销失败的提示沿用既有规则(核销失败不能报成功)

验证:前端 typecheck/lint/format/44 例测试/build 全过;两个新接口未登录访问均 401
(路由已挂载、权限位生效)。
This commit is contained in:
yml2213
2026-09-17 12:23:30 +08:00
parent 94328ac643
commit a7a55d6c16
8 changed files with 771 additions and 0 deletions
@@ -3,7 +3,9 @@ import type {
ConsignmentInventory,
ConsignmentStatsSummary,
ConsignmentSubmission,
InventoryMatchableOrders,
WorkOrderInventoryMatchCheck,
WorkOrderInventoryMatchOptions,
} from '@/types/consignment'
// --- 库存管理 ---
@@ -97,6 +99,27 @@ export function checkWorkOrderConsignmentMatches(workOrderId: number | string) {
)
}
/**
* 手动指定现货:该订单的**全部**在库现货(含不符合规格的),逐件带匹配判定与差异说明。
* 与 checkWorkOrderConsignmentMatches 的区别:后者只给系统候选,这里给"人工拍板"的全量视图。
*/
export function fetchWorkOrderConsignmentMatchOptions(workOrderId: number | string) {
return apiGet<WorkOrderInventoryMatchOptions>(
`/api/v1/admin/worker-platform/consignment/matches/${workOrderId}/options`,
)
}
/** 手动匹配:从现货出发,列出可以匹配的待指派/待补资料订单(逐单带规格判定) */
export function fetchInventoryMatchableOrders(
inventoryId: number | string,
params?: { keyword?: string },
) {
return apiGet<InventoryMatchableOrders>(
`/api/v1/admin/worker-platform/consignment/inventories/${inventoryId}/match-orders`,
params,
)
}
/** 履约/指派返回的电子凭证核销结果:ok=false 时必须提示运营人工核销,不能报成功 */
export type WorkOrderVoucherConsumeResult = {
ok: boolean
@@ -113,6 +136,10 @@ export function fulfillWorkOrderWithConsignment(payload: {
inventoryId: number | string
/** 订单规格信息不全或高配充低配时,必须显式确认才放行(后端会二次校验) */
allowPartial?: boolean
/** 规格真冲突(系统/区服/系列/钻级不符)也放行,必须同时给 matchNote */
allowSpecMismatch?: boolean
/** 手动指定现货的原因(强制匹配必填,后端会留痕) */
matchNote?: string
}) {
return apiPost<{
workOrder: unknown
@@ -127,6 +154,10 @@ export function assignWorkOrderWithConsignmentWorker(payload: {
workerId?: number | null
/** 订单规格信息不全或高配充低配时,必须显式确认才放行(后端会二次校验) */
allowPartial?: boolean
/** 规格真冲突(系统/区服/系列/钻级不符)也放行,必须同时给 matchNote */
allowSpecMismatch?: boolean
/** 手动指定现货的原因(强制匹配必填,后端会留痕) */
matchNote?: string
}) {
return apiPost<{
workOrder: unknown