diff --git a/apps/frontend/src/pages/admin/panels/WorkOrdersPanel.tsx b/apps/frontend/src/pages/admin/panels/WorkOrdersPanel.tsx index e9a03322..a2a5c07b 100644 --- a/apps/frontend/src/pages/admin/panels/WorkOrdersPanel.tsx +++ b/apps/frontend/src/pages/admin/panels/WorkOrdersPanel.tsx @@ -780,20 +780,61 @@ export default function WorkOrdersPanel() { } /** 非精确匹配(订单规格信息不全 / 高配充低配)必须人工确认,后端也会二次拦截 */ - function confirmPartialMatch(matchType: string | undefined, onOk: () => void) { - if (matchType !== 'exact') { - modal.confirm({ - title: '该现货不是精确匹配,确认继续?', - content: - '订单规格信息不全或这件现货高于订单要求(高配充低配)。继续履约后无法自动回退,请确认商品与买家订单一致。', - okText: '确认履约', - okButtonProps: { danger: true }, - cancelText: '再想想', - onOk, - }) - return - } - onOk() + /** + * 匹配弹窗里的两个动作**都会立刻占用现货**,点错就得走「撤销寄售履约」才能退回来, + * 而且两个按钮挨在一起很容易点错,所以一律二次确认,并把后果写清楚: + * 用哪个号占用、给谁、要不要冻结押金、能不能回退。 + */ + function confirmConsignmentMatchAction(input: { + kind: 'assign_worker' | 'internal_stock' + matchType?: string + consignmentNo: string + workerName?: string + depositFen?: number | null + onOk: () => void + }) { + const isPartial = input.matchType !== 'exact' + const isAssignWorker = input.kind === 'assign_worker' + const depositText = + input.depositFen != null ? `履约押金 ¥${(input.depositFen / 100).toFixed(2)}` : '履约押金' + + modal.confirm({ + title: isAssignWorker ? '确认走接单平台指派打手?' : '确认用内部现货履约?', + width: 460, + content: ( +
+
+ 寄卖单号: + + {input.consignmentNo} + +
+
+ {isAssignWorker + ? `动作:把订单指派给供货打手${input.workerName ? `「${input.workerName}」` : ''}接单,需冻结${depositText}` + : '动作:不向外部打手派单,直接用这件现货履约'} +
+
+ {isAssignWorker + ? '结果:立刻占用该现货,订单转入打手履约,其它订单不能再匹配它。' + : '结果:立刻占用该现货,跳过「待打手提交资料」直接进入赠送冷却期,其它订单不能再匹配它。'} +
+
+ 退回需要走「撤销寄售履约」,请先核对商品与买家订单一致。 +
+ {isPartial ? ( +
+ 注意:这不是精确匹配(规格信息不全,或这件现货高于订单要求=高配充低配), + 履约后无法自动回退。 +
+ ) : null} +
+ ), + okText: isAssignWorker ? '确认指派打手' : '确认占用并履约', + okButtonProps: isPartial ? { danger: true } : undefined, + cancelText: '再想想', + onOk: input.onOk, + }) } async function handleFulfillWithConsignment(inventoryId: number, allowPartial = false) { @@ -3074,34 +3115,72 @@ export default function WorkOrdersPanel() { -
- +
+
+
+ 选择履约方式(都会立刻占用该现货) +
{inv.workerId ? ( - + <> + +
+ 由该供货打手接单,需冻结履约押金 +
+ ) : null} - +
+ 不外派打手,直接用库存账号赠送 +
+
diff --git a/docs/寄卖系统优化方案.md b/docs/寄卖系统优化方案.md index 7c68eb1b..562e66da 100644 --- a/docs/寄卖系统优化方案.md +++ b/docs/寄卖系统优化方案.md @@ -21,6 +21,7 @@ | `632dddc4` | 上一轮:H5 渠道整体下线 + 凭据字段修复 + 状态机封闭(撤销守卫 / 库存绑定唯一性 / 生命周期解绑)+ 押金归属取台账 | 迁移 `079`、`consignment-*` 五个文件、`work-order-*` 三个仓库、两个前端面板 | | `5d11bf20` | 批次 C+D:指派部分成功补偿、凭证核销如实反馈、空规格不放行 + 履约/指派服务端规格复检 | `consignment-fulfillment-service.ts`、`consignment-matching-service.ts`、`consignment-repo.ts`、履约路由、`WorkOrdersPanel.tsx` | | `d6f6219f` | 批次 F1:内部现货履约停在「待加好友」,客服确认后才进赠送冷却 + 备注快捷项 | `work-order-gift-repo.ts`、履约服务、`WorkOrdersPanel.tsx`、`utils/gift-phase.ts` | +| 本批提交(批次 L,同一提交内含本文档,故不写自身 hash) | 批次 L:匹配弹窗两个动作一律二次确认 + 按钮分区/图标/后果说明,防点错 | `WorkOrdersPanel.tsx` | | 本批提交(批次 K,同一提交内含本文档,故不写自身 hash) | 批次 K:匹配弹窗改用寄卖单号(候选查询补 join),客服界面不再展示内部仓库号 | `consignment-repo.ts`、`WorkOrdersPanel.tsx`、`ConsignmentInventoryPanel.tsx` | | 本批提交(批次 J,同一提交内含本文档,故不写自身 hash) | 批次 J:凭证链可视化(提报凭证 + 赠送凭证),客服审核/仓库面板统一展示 | `consignment-admin-service.ts`、`consignment-repo.ts`、`ConsignmentSubmissionsPanel.tsx`、`ConsignmentInventoryPanel.tsx` | | 本批提交(批次 I,同一提交内含本文档,故不写自身 hash) | 批次 I:提报单号为唯一寄卖单号(一件货一行)+ 统一状态机 + 卖家确认加好友/提交赠送截图 | `consignment-item-stage.ts`、`consignment-worker-service.ts`、`routes/worker/consignment.ts`、`ConsignmentInventoryPanel.tsx`、`WorkerConsignmentPage.tsx` | @@ -281,6 +282,22 @@ 前端在"部分匹配"候选上先 `modal.confirm` 危险确认,再带 `allowPartial: true` 重试,高配充低配的合法玩法保留但不可误触。 3. ⏳ 匹配下推 SQL + 批量匹配接口 + 工单列表角标(P2-8)未做:当前仍是"取全量在库 → 内存比对"。 +### 批次 L · 匹配弹窗防点错(本轮) + +**问题**:匹配弹窗里「走接单平台指派打手(冻结押金交付)」与「内部现货履约」两个按钮 +上下紧挨、样式相近,而且**只有"部分匹配"才弹确认**——精确匹配时两个按钮点下去都立刻执行, +点错就要走「撤销寄售履约」才能退回来。 + +**改法**: + +1. ✅ 两个动作**一律二次确认**(不再只有部分匹配才确认),确认框把后果写清楚: + 寄卖单号(可复制)、动作(给谁/要不要冻结押金)、结果(立刻占用现货、其它订单不能再匹配它、 + 内部履约还会跳过「待打手提交资料」直接进冷却)、以及"退回要走撤销寄售履约"; + 部分匹配时额外红字提示"不是精确匹配、无法自动回退",并把确认按钮降为 danger。 +2. ✅ 按钮区做成独立分区的「选择履约方式」小卡片:两个按钮各占一行、`block` 铺满(点击目标更大、 + 不再是小按钮挨着)、间距拉开到 14px、各加图标(打手=TeamOutlined,库存=PushpinOutlined), + 每个按钮下方一句后果说明("由该供货打手接单,需冻结履约押金" / "不外派打手,直接用库存账号赠送")。 + ### 批次 K · 匹配弹窗也改用寄卖单号,内部仓库号只留内部(本轮) **问题**:内部寄售库存匹配弹窗(发单时拦一下"有现货可直接履约"那个)显示的是