diff --git a/apps/backend/src/routes/admin/worker-platform.ts b/apps/backend/src/routes/admin/worker-platform.ts
index d7c40d4c..92ada148 100644
--- a/apps/backend/src/routes/admin/worker-platform.ts
+++ b/apps/backend/src/routes/admin/worker-platform.ts
@@ -325,7 +325,7 @@ router.post(
router.put(
'/worker-platform/orders/:workOrderId',
- requireAdminRoles(['admin', 'operator']),
+ requireAdminRoles(['admin', 'operator', 'support']),
createJsonHandler(
(req) => updateAdminWorkOrder(String(req.params.workOrderId || ''), req.body || {}),
{
diff --git a/apps/backend/src/services/worker-platform/admin-service.ts b/apps/backend/src/services/worker-platform/admin-service.ts
index 0a1f4fdc..2a3175db 100644
--- a/apps/backend/src/services/worker-platform/admin-service.ts
+++ b/apps/backend/src/services/worker-platform/admin-service.ts
@@ -834,6 +834,9 @@ export async function createAdminMockWorkOrder(payload: JsonObject = {}) {
orderAmountFen: paymentFen,
syncSource: 'mock',
mock: true,
+ provider: 'mock',
+ platform: 'mock',
+ shopName: '模拟店铺',
},
}
const workOrder = await createWorkOrder({
diff --git a/apps/frontend/src/pages/admin/panels/WorkOrdersPanel.tsx b/apps/frontend/src/pages/admin/panels/WorkOrdersPanel.tsx
index 1f4b70b5..c1eafcb0 100644
--- a/apps/frontend/src/pages/admin/panels/WorkOrdersPanel.tsx
+++ b/apps/frontend/src/pages/admin/panels/WorkOrdersPanel.tsx
@@ -483,24 +483,38 @@ export default function WorkOrdersPanel() {
{
title: '订单',
minWidth: 300,
- render: (_, row) => (
-
-
openDetailDrawer(row)}>
- {row.productName || row.workOrderNo}
-
-
- {row.categoryName ? {row.categoryName} : null}
- {row.orderId ? (
-
- 源订单 #{row.orderId}
+ render: (_, row) => {
+ const source = asRecord(row.material?.source)
+ const shopName = String(source.shopName || '').trim()
+ const provider = String(source.provider || '').trim()
+ return (
+
+
openDetailDrawer(row)}
+ onSaved={refreshAll}
+ />
+
+ {row.categoryName ? {row.categoryName} : null}
+ {row.orderId ? (
+
+ 源订单 #{row.orderId}
+
+ ) : null}
+
+ {shopName || provider ? (
+
+ {provider ? `来源:${provider}` : ''}
+ {provider && shopName ? ' · ' : ''}
+ {shopName ? `店铺:${shopName}` : ''}
) : null}
-
-
- {row.platformOrderId} · {row.workOrderNo}
-
-
- ),
+
+ {row.platformOrderId} · {row.workOrderNo}
+
+
+ )
+ },
},
{
title: '用户付款金额',
@@ -1438,6 +1452,92 @@ function getUserPaymentFen(order: WorkOrder): number | null {
return Number.isFinite(paymentFen) ? paymentFen : null
}
+/** 商品名:单击看详情,双击原地修改(仅未接走工单) */
+function ProductNameEditableCell({
+ order,
+ onOpenDetail,
+ onSaved,
+}: {
+ order: WorkOrder
+ onOpenDetail: () => void
+ onSaved: () => Promise | void
+}) {
+ const { message } = App.useApp()
+ const [editing, setEditing] = useState(false)
+ const [draft, setDraft] = useState('')
+ const savingRef = useRef(false)
+ const clickTimerRef = useRef(null)
+
+ const editable =
+ ['pending_material', 'unassigned', 'open'].includes(order.status) && !order.worker
+
+ function handleClick() {
+ if (clickTimerRef.current) window.clearTimeout(clickTimerRef.current)
+ clickTimerRef.current = window.setTimeout(() => onOpenDetail(), 260)
+ }
+
+ function handleDoubleClick() {
+ if (clickTimerRef.current) {
+ window.clearTimeout(clickTimerRef.current)
+ clickTimerRef.current = null
+ }
+ if (!editable) return
+ setDraft(order.productName || order.workOrderNo)
+ setEditing(true)
+ }
+
+ async function save() {
+ if (savingRef.current) return
+ const next = draft.trim()
+ if (!next) {
+ message.error('商品名不能为空')
+ return
+ }
+ if (next === order.productName) {
+ setEditing(false)
+ return
+ }
+ savingRef.current = true
+ try {
+ await updateAdminWorkOrder(order.workOrderId, { productName: next })
+ message.success('商品名已更新')
+ setEditing(false)
+ await onSaved()
+ } catch (error) {
+ message.error(error instanceof Error ? error.message : '保存失败')
+ } finally {
+ savingRef.current = false
+ }
+ }
+
+ if (!editing) {
+ return (
+
+ {order.productName || order.workOrderNo}
+
+ )
+ }
+
+ return (
+ setDraft(event.target.value)}
+ onPressEnter={() => void save()}
+ onBlur={() => void save()}
+ onKeyDown={(event) => {
+ if (event.key === 'Escape') setEditing(false)
+ }}
+ />
+ )
+}
+
function AmountEditableCell({
order,
field,