fix(worker-platform): 优化工单号精准检索与跨状态流转展示,修复状态更新后工单消失问题
1. 后端查询重构:新增 isWorkOrderNoLookupKeyword 工单号前缀与忽略大小写精准索引匹配,优化后端 work-order-query-repo 的工单号检索路径; 2. 前端单号智能穿透:管理员输入 WO... 等精准单号查询时,自动放宽细粒度排他状态/阶段过滤,避免加好友/验收等状态流转后工单因旧状态筛选脱靶消失; 3. 搜索栏交互升级:输入框清空即时重置关键词与页码,支持回车/按钮/清除全方位无缝触发; 4. 详情抽屉与多面板联动:增加 ordersQuery 数据更新对 detailOrder 的自动同步,并将 refreshAll 广播范围覆盖至寄售仓库与统计指标。
This commit is contained in:
@@ -41,6 +41,8 @@ export type ConsignmentInventoryRow = {
|
||||
gift_evidence_json?: string | Record<string, unknown> | null
|
||||
gift_work_order_no?: string | null
|
||||
gift_work_order_status?: string | null
|
||||
gift_phase?: string | null
|
||||
gift_friend_added_at?: string | null
|
||||
bound_work_order_material_json?: string | Record<string, unknown> | null
|
||||
bound_work_order_requirement_json?: string | Record<string, unknown> | null
|
||||
worker_id?: string | number | null
|
||||
@@ -197,6 +199,8 @@ export async function listConsignmentInventories(filters: {
|
||||
wo.acceptance_json AS gift_evidence_json,
|
||||
wo.work_order_no AS gift_work_order_no,
|
||||
wo.status AS gift_work_order_status,
|
||||
wo.gift_phase AS gift_phase,
|
||||
wo.friend_added_at AS gift_friend_added_at,
|
||||
wo.material_json AS bound_work_order_material_json,
|
||||
wo.requirement_json AS bound_work_order_requirement_json
|
||||
FROM consignment_inventories ci
|
||||
@@ -314,6 +318,8 @@ export async function getConsignmentInventoryById(
|
||||
wo.acceptance_json AS gift_evidence_json,
|
||||
wo.work_order_no AS gift_work_order_no,
|
||||
wo.status AS gift_work_order_status,
|
||||
wo.gift_phase AS gift_phase,
|
||||
wo.friend_added_at AS gift_friend_added_at,
|
||||
wo.material_json AS bound_work_order_material_json,
|
||||
wo.requirement_json AS bound_work_order_requirement_json
|
||||
FROM consignment_inventories ci
|
||||
|
||||
@@ -3,9 +3,14 @@ import type { ListInput, WorkOrderRow, WorkOrderStatistics } from './types.js'
|
||||
import type { PoolClient } from 'pg'
|
||||
import {
|
||||
normalizeWorkOrderAcceptanceMode,
|
||||
WORK_ORDER_ACCEPTANCE_MODE,
|
||||
WORK_ORDER_GIFT_PHASE,
|
||||
} from '../../domain/work-order-acceptance-mode.js'
|
||||
import { isPlatformOrderIdLookupKeyword } from '../../utils/platform-order-id.js'
|
||||
import {
|
||||
isPlatformOrderIdLookupKeyword,
|
||||
isWorkOrderNoLookupKeyword,
|
||||
} from '../../utils/platform-order-id.js'
|
||||
|
||||
export const WORK_ORDER_SELECT = `
|
||||
SELECT
|
||||
wo.*,
|
||||
@@ -843,6 +848,12 @@ export function buildWorkOrderWhere({
|
||||
filters.push(
|
||||
`(wo.platform_order_id = ${paramIndex} OR wo.platform_order_id LIKE ${paramIndex} || '%')`,
|
||||
)
|
||||
} else if (isWorkOrderNoLookupKeyword(normalizedKeyword)) {
|
||||
params.push(normalizedKeyword)
|
||||
const paramIndex = `$${params.length}`
|
||||
filters.push(
|
||||
`(wo.work_order_no = ${paramIndex} OR wo.work_order_no ILIKE ${paramIndex} || '%' OR LOWER(wo.work_order_no) = LOWER(${paramIndex}))`,
|
||||
)
|
||||
} else {
|
||||
params.push(`%${normalizedKeyword}%`)
|
||||
filters.push(`${workOrderSearchExpression()} LIKE LOWER($${params.length})`)
|
||||
@@ -887,11 +898,37 @@ export function buildWorkOrderWhere({
|
||||
)
|
||||
}
|
||||
if (acceptanceMode) {
|
||||
params.push(normalizeWorkOrderAcceptanceMode(acceptanceMode))
|
||||
filters.push(`wo.acceptance_mode = $${params.length}`)
|
||||
const rawMode = String(acceptanceMode).trim()
|
||||
if (rawMode === 'internal_consignment') {
|
||||
filters.push(`(
|
||||
wo.material_json->'consignment'->>'inventoryId' IS NOT NULL
|
||||
AND (wo.material_json->'consignment'->>'fulfillmentType' IS NULL OR wo.material_json->'consignment'->>'fulfillmentType' != 'worker_deposit')
|
||||
AND (wo.material_json->'consignment'->>'workerId' IS NULL OR wo.material_json->'consignment'->>'workerId' = '0')
|
||||
AND (wo.assigned_worker_id IS NULL OR wo.assigned_worker_id = 0)
|
||||
)`)
|
||||
} else if (rawMode === WORK_ORDER_ACCEPTANCE_MODE.FRIEND_GIFT) {
|
||||
filters.push(`(
|
||||
wo.acceptance_mode = 'friend_gift'
|
||||
AND NOT (
|
||||
wo.material_json->'consignment'->>'inventoryId' IS NOT NULL
|
||||
AND (wo.material_json->'consignment'->>'fulfillmentType' IS NULL OR wo.material_json->'consignment'->>'fulfillmentType' != 'worker_deposit')
|
||||
AND (wo.material_json->'consignment'->>'workerId' IS NULL OR wo.material_json->'consignment'->>'workerId' = '0')
|
||||
AND (wo.assigned_worker_id IS NULL OR wo.assigned_worker_id = 0)
|
||||
)
|
||||
)`)
|
||||
} else if (rawMode === WORK_ORDER_ACCEPTANCE_MODE.STANDARD) {
|
||||
filters.push(`(
|
||||
wo.acceptance_mode = 'standard'
|
||||
AND wo.material_json->'consignment'->>'inventoryId' IS NULL
|
||||
)`)
|
||||
} else {
|
||||
params.push(normalizeWorkOrderAcceptanceMode(acceptanceMode))
|
||||
filters.push(`wo.acceptance_mode = $${params.length}`)
|
||||
}
|
||||
}
|
||||
if (giftPhase) {
|
||||
const normalizedGiftPhase = String(giftPhase).trim()
|
||||
const activeGiftStatusSql = `wo.status NOT IN ('accepted', 'cancelled')`
|
||||
if (normalizedGiftPhase === WORK_ORDER_GIFT_PHASE.GIFT_READY) {
|
||||
// gift_ready 是冷却到点后的实时阶段,由时间条件计算而不是落库状态。
|
||||
filters.push(`(
|
||||
@@ -899,10 +936,18 @@ export function buildWorkOrderWhere({
|
||||
AND wo.gift_phase = 'friend_countdown'
|
||||
AND wo.gift_available_at IS NOT NULL
|
||||
AND wo.gift_available_at <= NOW()
|
||||
AND ${activeGiftStatusSql}
|
||||
)`)
|
||||
} else if (normalizedGiftPhase === WORK_ORDER_GIFT_PHASE.FRIEND_COUNTDOWN) {
|
||||
filters.push(`(
|
||||
wo.acceptance_mode = 'friend_gift'
|
||||
AND wo.gift_phase = 'friend_countdown'
|
||||
AND (wo.gift_available_at IS NULL OR wo.gift_available_at > NOW())
|
||||
AND ${activeGiftStatusSql}
|
||||
)`)
|
||||
} else if (Object.values(WORK_ORDER_GIFT_PHASE).includes(normalizedGiftPhase as never)) {
|
||||
params.push(normalizedGiftPhase)
|
||||
const giftPhaseFilter = `wo.acceptance_mode = 'friend_gift' AND wo.gift_phase = $${params.length}`
|
||||
const giftPhaseFilter = `wo.acceptance_mode = 'friend_gift' AND wo.gift_phase = $${params.length} AND ${activeGiftStatusSql}`
|
||||
// 待打手提交资料仅代表已接单后的赠送流程;待抢单/未分配模板单不应混入该筛选。
|
||||
filters.push(
|
||||
normalizedGiftPhase === WORK_ORDER_GIFT_PHASE.MATERIAL_REQUIRED
|
||||
|
||||
@@ -110,6 +110,8 @@ function mapConsignmentEvidence(source: {
|
||||
gift_evidence_json?: string | Record<string, unknown> | null
|
||||
gift_work_order_no?: string | null
|
||||
gift_work_order_status?: string | null
|
||||
gift_phase?: string | null
|
||||
gift_friend_added_at?: string | null
|
||||
}) {
|
||||
const acceptance = toRecord(source.gift_evidence_json)
|
||||
const files = Array.isArray(acceptance?.files) ? (acceptance.files as unknown[]) : []
|
||||
@@ -146,6 +148,8 @@ function mapConsignmentEvidence(source: {
|
||||
giftEvidenceSubmittedAt: String(acceptance?.submittedAt || ''),
|
||||
giftWorkOrderNo: source.gift_work_order_no || '',
|
||||
giftWorkOrderStatus: workOrderStatus,
|
||||
giftPhase: source.gift_phase || '',
|
||||
giftFriendAddedAt: source.gift_friend_added_at || '',
|
||||
/** none=还没交 / pending=交了待客服验收 / accepted=客服已验收 / submitted=其他在途状态 */
|
||||
giftEvidenceReviewStatus: reviewStatus,
|
||||
}
|
||||
|
||||
@@ -1635,6 +1635,25 @@ test('好友赠送待打手提交资料筛选排除待抢单订单', () => {
|
||||
assert.match(whereClause, /wo\.status IN \('in_progress', 'problem'\)/)
|
||||
})
|
||||
|
||||
test('工单筛选支持内部寄售匹配与打手好友赠送隔离,且赠送冷却中排除已验收已取消工单', () => {
|
||||
const internalQuery = buildWorkOrderWhere({ acceptanceMode: 'internal_consignment' })
|
||||
assert.match(internalQuery.whereClause, /wo\.material_json->'consignment'->>'inventoryId' IS NOT NULL/)
|
||||
assert.match(internalQuery.whereClause, /wo\.assigned_worker_id IS NULL OR wo\.assigned_worker_id = 0/)
|
||||
|
||||
const friendGiftQuery = buildWorkOrderWhere({ acceptanceMode: 'friend_gift' })
|
||||
assert.match(friendGiftQuery.whereClause, /wo\.acceptance_mode = 'friend_gift'/)
|
||||
assert.match(friendGiftQuery.whereClause, /NOT \(/)
|
||||
|
||||
const countdownQuery = buildWorkOrderWhere({ giftPhase: 'friend_countdown' })
|
||||
assert.match(countdownQuery.whereClause, /wo\.gift_phase = 'friend_countdown'/)
|
||||
assert.match(countdownQuery.whereClause, /wo\.gift_available_at > NOW\(\)/)
|
||||
assert.match(countdownQuery.whereClause, /wo\.status NOT IN \('accepted', 'cancelled'\)/)
|
||||
|
||||
const readyQuery = buildWorkOrderWhere({ giftPhase: 'gift_ready' })
|
||||
assert.match(readyQuery.whereClause, /wo\.gift_available_at <= NOW\(\)/)
|
||||
assert.match(readyQuery.whereClause, /wo\.status NOT IN \('accepted', 'cancelled'\)/)
|
||||
})
|
||||
|
||||
test('好友赠送冷却中才允许客服手动结束冷却', () => {
|
||||
const cooling = mapWorkOrderAdmin(
|
||||
buildWorkOrderRow({
|
||||
|
||||
@@ -1,7 +1,10 @@
|
||||
import assert from 'node:assert/strict'
|
||||
import test from 'node:test'
|
||||
|
||||
import { isPlatformOrderIdLookupKeyword } from './platform-order-id.js'
|
||||
import {
|
||||
isPlatformOrderIdLookupKeyword,
|
||||
isWorkOrderNoLookupKeyword,
|
||||
} from './platform-order-id.js'
|
||||
|
||||
test('识别纯数字平台订单号', () => {
|
||||
assert.equal(isPlatformOrderIdLookupKeyword('20247230034021572'), true)
|
||||
@@ -14,9 +17,19 @@ test('识别拼多多带连字符的 order_sn', () => {
|
||||
assert.equal(isPlatformOrderIdLookupKeyword('260912-123456789012345'), true)
|
||||
})
|
||||
|
||||
test('识别统一内部工单号 (WO...)', () => {
|
||||
assert.equal(isWorkOrderNoLookupKeyword('WOb320ee0b39b9'), true)
|
||||
assert.equal(isWorkOrderNoLookupKeyword('wob320ee0b39b9'), true)
|
||||
assert.equal(isWorkOrderNoLookupKeyword('WO26091216358821'), true)
|
||||
assert.equal(isWorkOrderNoLookupKeyword('WO12'), false)
|
||||
assert.equal(isWorkOrderNoLookupKeyword('20247230034021572'), false)
|
||||
})
|
||||
|
||||
test('拒绝普通关键词', () => {
|
||||
assert.equal(isPlatformOrderIdLookupKeyword('皮肤店'), false)
|
||||
assert.equal(isPlatformOrderIdLookupKeyword('安卓怒嚎3钻'), false)
|
||||
assert.equal(isPlatformOrderIdLookupKeyword('DT881aa66294cc'), false)
|
||||
assert.equal(isPlatformOrderIdLookupKeyword(''), false)
|
||||
assert.equal(isWorkOrderNoLookupKeyword('皮肤店'), false)
|
||||
})
|
||||
|
||||
|
||||
@@ -6,3 +6,12 @@ export function isPlatformOrderIdLookupKeyword(value: unknown): boolean {
|
||||
const trimmed = String(value || '').trim()
|
||||
return /^\d{6,}(-\d{6,})?$/.test(trimmed)
|
||||
}
|
||||
|
||||
/**
|
||||
* 识别内部统一工单号 (以 WO 开头且至少 4 位字符,如 WOb320ee0b39b9、WO26091216358821)。
|
||||
*/
|
||||
export function isWorkOrderNoLookupKeyword(value: unknown): boolean {
|
||||
const trimmed = String(value || '').trim()
|
||||
return /^WO[0-9a-zA-Z]{4,}$/i.test(trimmed)
|
||||
}
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { useQuery } from '@tanstack/react-query'
|
||||
import { useQuery, useQueryClient } from '@tanstack/react-query'
|
||||
import { Card, Space, Tabs } from 'antd'
|
||||
import { useEffect, useRef, useState } from 'react'
|
||||
import { useLocation, useSearchParams } from 'react-router'
|
||||
@@ -27,7 +27,30 @@ type AfterSalesLocationState = {
|
||||
createOrder?: WorkOrder
|
||||
}
|
||||
|
||||
const TAB_QUERY_KEYS: Record<string, string[][]> = {
|
||||
'consignment-inventory': [['admin-consignment-inventories'], ['admin-consignment-stats']],
|
||||
'consignment-submissions': [
|
||||
['admin-consignment-submissions'],
|
||||
['admin-consignment-submissions-pending-total'],
|
||||
],
|
||||
orders: [['admin-work-orders'], ['admin-work-orders-stats']],
|
||||
'cancel-requests': [['admin-work-order-cancel-requests']],
|
||||
'after-sales': [['admin-after-sales-orders'], ['admin-after-sales-stats']],
|
||||
feedbacks: [['admin-feedbacks']],
|
||||
rules: [['admin-product-rules']],
|
||||
'product-match': [['admin-product-match']],
|
||||
categories: [['admin-categories']],
|
||||
workers: [['admin-workers'], ['admin-worker-users']],
|
||||
leaderboard: [['admin-leaderboard']],
|
||||
finance: [['admin-finance-settlements'], ['admin-finance-withdrawals']],
|
||||
levels: [['admin-worker-levels']],
|
||||
notifications: [['admin-notifications']],
|
||||
announcement: [['admin-announcements']],
|
||||
'hall-config': [['admin-hall-config']],
|
||||
}
|
||||
|
||||
export default function AdminWorkerPlatformPage() {
|
||||
const queryClient = useQueryClient()
|
||||
const [searchParams, setSearchParams] = useSearchParams()
|
||||
const location = useLocation()
|
||||
const [activeTab, setActiveTab] = useState(() => loadActiveTab(searchParams.get('tab')))
|
||||
@@ -49,6 +72,18 @@ export default function AdminWorkerPlatformPage() {
|
||||
? 'orders'
|
||||
: activeTab
|
||||
|
||||
// 切换标签页时自动刷新对应标签页的查询数据,确保切入即为最新状态
|
||||
useEffect(() => {
|
||||
if (!visibleActiveTab) return
|
||||
const queries = TAB_QUERY_KEYS[visibleActiveTab]
|
||||
if (queries) {
|
||||
queries.forEach((queryKey) => {
|
||||
void queryClient.invalidateQueries({ queryKey })
|
||||
})
|
||||
}
|
||||
void queryClient.invalidateQueries({ queryKey: ['admin-worker-platform-summary'] })
|
||||
}, [visibleActiveTab, queryClient])
|
||||
|
||||
useEffect(() => {
|
||||
const tab = searchParams.get('tab')
|
||||
if (isWorkerPlatformTab(tab)) {
|
||||
|
||||
@@ -331,6 +331,31 @@ export default function ConsignmentInventoryPanel() {
|
||||
{resolveConsignmentNo(record)}
|
||||
</Text>
|
||||
</Space>
|
||||
{record.giftWorkOrderNo ? (
|
||||
<div style={{ marginTop: 2 }}>
|
||||
<Space size={4} align="center" wrap>
|
||||
<Text type="secondary" style={{ fontSize: 12 }}>
|
||||
关联工单
|
||||
</Text>
|
||||
<Text copyable style={{ fontSize: 12, fontWeight: 600, color: '#1677ff' }}>
|
||||
{record.giftWorkOrderNo}
|
||||
</Text>
|
||||
{record.giftWorkOrderStatus ? (
|
||||
<Tag
|
||||
color="cyan"
|
||||
style={{
|
||||
fontSize: 10,
|
||||
lineHeight: '16px',
|
||||
padding: '0 4px',
|
||||
marginInlineEnd: 0,
|
||||
}}
|
||||
>
|
||||
{formatGiftWorkOrderStatus(record.giftWorkOrderStatus)}
|
||||
</Tag>
|
||||
) : null}
|
||||
</Space>
|
||||
</div>
|
||||
) : null}
|
||||
<div style={{ marginTop: 2 }}>
|
||||
{record.sourceType === 'worker_portal' ? (
|
||||
<Tag color="purple" style={{ fontSize: 11, padding: '0 4px' }}>
|
||||
@@ -510,8 +535,18 @@ export default function ConsignmentInventoryPanel() {
|
||||
return (
|
||||
<Space direction="vertical" size={2}>
|
||||
<Badge status="success" text="已履约出库" />
|
||||
{record.giftWorkOrderNo ? (
|
||||
<Space size={2} align="center">
|
||||
<Text type="secondary" style={{ fontSize: 11 }}>
|
||||
工单:
|
||||
</Text>
|
||||
<Text copyable style={{ fontSize: 11, color: '#1677ff', fontWeight: 600 }}>
|
||||
{record.giftWorkOrderNo}
|
||||
</Text>
|
||||
</Space>
|
||||
) : null}
|
||||
{record.boundPlatformOrderId ? (
|
||||
<Text copyable style={{ fontSize: 11, color: '#1890ff' }}>
|
||||
<Text copyable style={{ fontSize: 11, color: '#8c8c8c' }}>
|
||||
{record.boundPlatformOrderId}
|
||||
</Text>
|
||||
) : null}
|
||||
@@ -601,6 +636,8 @@ export default function ConsignmentInventoryPanel() {
|
||||
) : null}
|
||||
{record.status === 'consumed' &&
|
||||
canManageConsignment &&
|
||||
!record.giftFriendAddedAt &&
|
||||
(!record.giftPhase || record.giftPhase === 'material_required') &&
|
||||
record.giftEvidenceReviewStatus !== 'accepted' &&
|
||||
record.giftWorkOrderStatus !== 'accepted' ? (
|
||||
<Button
|
||||
|
||||
@@ -30,6 +30,7 @@ import type { TableColumnsType } from 'antd'
|
||||
import { useState } from 'react'
|
||||
|
||||
import ConsignmentEvidenceGallery from '@/components/admin/ConsignmentEvidenceGallery'
|
||||
import ImagePreviewList from '@/components/files/ImagePreviewList'
|
||||
import {
|
||||
approveAdminConsignmentSubmission,
|
||||
fetchAdminConsignmentSubmissions,
|
||||
@@ -468,9 +469,16 @@ export default function ConsignmentSubmissionsPanel() {
|
||||
</Card>
|
||||
|
||||
<Modal
|
||||
title="审核寄卖申请并正式入库"
|
||||
title={
|
||||
<div style={{ display: 'flex', alignItems: 'center', gap: 8 }}>
|
||||
<CheckCircleOutlined style={{ color: '#52c41a' }} />
|
||||
<span>审核寄卖申请并正式入库</span>
|
||||
</div>
|
||||
}
|
||||
open={Boolean(approveModalItem)}
|
||||
width={680}
|
||||
width={760}
|
||||
style={{ top: 24 }}
|
||||
bodyStyle={{ maxHeight: 'calc(86vh - 120px)', overflowY: 'auto', paddingRight: 8 }}
|
||||
onCancel={() => setApproveModalItem(null)}
|
||||
onOk={handleApproveSubmit}
|
||||
confirmLoading={approving}
|
||||
@@ -478,73 +486,186 @@ export default function ConsignmentSubmissionsPanel() {
|
||||
okType="primary"
|
||||
destroyOnClose
|
||||
>
|
||||
<div style={{ marginBottom: 16 }}>
|
||||
<Text type="secondary">
|
||||
提报人联系方式:<strong>{approveModalItem?.contactInfo}</strong> | 游戏ID:
|
||||
<strong>{approveModalItem?.sellerGameId || '-'}</strong> | 卖家要价:
|
||||
<strong style={{ color: '#cf1322' }}>
|
||||
¥{((approveModalItem?.askingPriceFen || 0) / 100).toFixed(2)}
|
||||
</strong>
|
||||
</Text>
|
||||
{/* 顶部提报概览卡片 */}
|
||||
<div
|
||||
style={{
|
||||
background: 'linear-gradient(135deg, #f8fafc 0%, #f1f5f9 100%)',
|
||||
border: '1px solid #e2e8f0',
|
||||
borderRadius: 8,
|
||||
padding: '12px 16px',
|
||||
marginBottom: 16,
|
||||
}}
|
||||
>
|
||||
<div
|
||||
style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'flex-start' }}
|
||||
>
|
||||
<div>
|
||||
<Space wrap size={8} style={{ marginBottom: 6 }}>
|
||||
<Text strong style={{ fontSize: 14 }}>
|
||||
单号:{approveModalItem?.submissionNo}
|
||||
</Text>
|
||||
{approveModalItem?.workerName ? (
|
||||
<Tag color="cyan">打手提报: {approveModalItem.workerName}</Tag>
|
||||
) : (
|
||||
<Tag color="purple">卖家自主提报</Tag>
|
||||
)}
|
||||
{approveModalItem?.createdAt ? (
|
||||
<Text type="secondary" style={{ fontSize: 12 }}>
|
||||
提报于 {formatDateTime(approveModalItem.createdAt)}
|
||||
</Text>
|
||||
) : null}
|
||||
</Space>
|
||||
<div
|
||||
style={{
|
||||
fontSize: 12,
|
||||
color: '#475569',
|
||||
display: 'flex',
|
||||
flexWrap: 'wrap',
|
||||
gap: '12px 20px',
|
||||
}}
|
||||
>
|
||||
<span>
|
||||
联系方式:<Text strong>{approveModalItem?.contactInfo || '-'}</Text>
|
||||
</span>
|
||||
<span>
|
||||
游戏ID:<Text strong>{approveModalItem?.sellerGameId || '-'}</Text>
|
||||
</span>
|
||||
{approveModalItem?.sellerPaymentInfo ? (
|
||||
<span>
|
||||
提报收款:<Text strong>{approveModalItem.sellerPaymentInfo}</Text>
|
||||
</span>
|
||||
) : null}
|
||||
</div>
|
||||
</div>
|
||||
<div style={{ textAlign: 'right', flexShrink: 0, paddingLeft: 16 }}>
|
||||
<div style={{ fontSize: 12, color: '#64748b' }}>卖家提报要价</div>
|
||||
<div style={{ fontSize: 22, fontWeight: 700, color: '#f5222d', lineHeight: 1.2 }}>
|
||||
¥{((approveModalItem?.askingPriceFen || 0) / 100).toFixed(2)}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* 提报截图快速直览 */}
|
||||
{approveModalItem?.screenshotsJson && approveModalItem.screenshotsJson.length > 0 ? (
|
||||
<div
|
||||
style={{
|
||||
marginTop: 10,
|
||||
paddingTop: 8,
|
||||
borderTop: '1px dashed #cbd5e1',
|
||||
display: 'flex',
|
||||
alignItems: 'center',
|
||||
gap: 12,
|
||||
}}
|
||||
>
|
||||
<Text type="secondary" style={{ fontSize: 12, flexShrink: 0 }}>
|
||||
商品截图 ({approveModalItem.screenshotsJson.length}张):
|
||||
</Text>
|
||||
<ImagePreviewList
|
||||
imageUrls={approveModalItem.screenshotsJson}
|
||||
size={38}
|
||||
maxVisible={6}
|
||||
/>
|
||||
</div>
|
||||
) : null}
|
||||
</div>
|
||||
|
||||
<Form form={approveForm} layout="vertical">
|
||||
<Row gutter={16}>
|
||||
<Col span={14}>
|
||||
{/* 分组一:物品与规格 */}
|
||||
<div
|
||||
style={{
|
||||
display: 'flex',
|
||||
alignItems: 'center',
|
||||
gap: 8,
|
||||
marginBottom: 10,
|
||||
fontWeight: 600,
|
||||
fontSize: 13,
|
||||
color: '#1e293b',
|
||||
}}
|
||||
>
|
||||
<div style={{ width: 3, height: 14, background: '#1677ff', borderRadius: 2 }} />
|
||||
物品属性与收购成本
|
||||
</div>
|
||||
|
||||
<Row gutter={12}>
|
||||
<Col span={15}>
|
||||
<Form.Item
|
||||
name="itemName"
|
||||
label="正式入库物品名"
|
||||
rules={[{ required: true, message: '请输入入库物品名' }]}
|
||||
style={{ marginBottom: 12 }}
|
||||
>
|
||||
<Input />
|
||||
<Input placeholder="如:安卓暗潮1钻1璀璨 苏尔南" />
|
||||
</Form.Item>
|
||||
</Col>
|
||||
<Col span={10}>
|
||||
<Col span={9}>
|
||||
<Form.Item
|
||||
name="costPrice"
|
||||
label="实际收购成本 (元)"
|
||||
label="实际收购成本"
|
||||
rules={[{ required: true, message: '请输入实际收购成本' }]}
|
||||
style={{ marginBottom: 12 }}
|
||||
>
|
||||
<InputNumber min={0} step={1} style={{ width: '100%' }} />
|
||||
<InputNumber
|
||||
min={0}
|
||||
step={1}
|
||||
prefix="¥"
|
||||
addonAfter="元"
|
||||
style={{ width: '100%' }}
|
||||
/>
|
||||
</Form.Item>
|
||||
</Col>
|
||||
</Row>
|
||||
|
||||
<Row gutter={16}>
|
||||
<Row gutter={12}>
|
||||
<Col span={5}>
|
||||
<Form.Item name="system" label="系统">
|
||||
{/* 审核可修正规格:与打手端发布同一套选项(苹果/安卓;微信/QQ/互通) */}
|
||||
<Form.Item name="system" label="系统" style={{ marginBottom: 16 }}>
|
||||
<Select options={[...CONSIGNMENT_SYSTEM_OPTIONS]} />
|
||||
</Form.Item>
|
||||
</Col>
|
||||
<Col span={5}>
|
||||
<Form.Item name="serverZone" label="区服">
|
||||
<Form.Item name="serverZone" label="区服" style={{ marginBottom: 16 }}>
|
||||
<Select options={[...CONSIGNMENT_ZONE_OPTIONS]} />
|
||||
</Form.Item>
|
||||
</Col>
|
||||
<Col span={5}>
|
||||
<Form.Item name="series" label="系列">
|
||||
<Input />
|
||||
</Form.Item>
|
||||
</Col>
|
||||
<Col span={5}>
|
||||
<Form.Item name="diamondLevel" label="钻石等级 (1-7)">
|
||||
<InputNumber min={1} max={7} style={{ width: '100%' }} />
|
||||
<Form.Item name="series" label="系列" style={{ marginBottom: 16 }}>
|
||||
<Input placeholder="如 暗潮" />
|
||||
</Form.Item>
|
||||
</Col>
|
||||
<Col span={4}>
|
||||
<Form.Item name="brillianceCount" label="璀璨数 (0-7)">
|
||||
<Form.Item name="diamondLevel" label="钻石等级" style={{ marginBottom: 16 }}>
|
||||
<InputNumber min={1} max={7} style={{ width: '100%' }} />
|
||||
</Form.Item>
|
||||
</Col>
|
||||
<Col span={5}>
|
||||
<Form.Item name="brillianceCount" label="璀璨数" style={{ marginBottom: 16 }}>
|
||||
<InputNumber min={0} max={7} style={{ width: '100%' }} />
|
||||
</Form.Item>
|
||||
</Col>
|
||||
</Row>
|
||||
|
||||
<Row gutter={16}>
|
||||
{/* 分组二:履约与打手 */}
|
||||
<div
|
||||
style={{
|
||||
display: 'flex',
|
||||
alignItems: 'center',
|
||||
gap: 8,
|
||||
marginBottom: 10,
|
||||
fontWeight: 600,
|
||||
fontSize: 13,
|
||||
color: '#1e293b',
|
||||
}}
|
||||
>
|
||||
<div style={{ width: 3, height: 14, background: '#52c41a', borderRadius: 2 }} />
|
||||
履约模式与打手关联 (选填)
|
||||
</div>
|
||||
|
||||
<Row gutter={12}>
|
||||
<Col span={14}>
|
||||
<Form.Item
|
||||
name="workerId"
|
||||
label="走打手接单平台 (关联履约打手)"
|
||||
tooltip="指派该打手接单丢枪交货时,接单平台将自动冻结其押金并担保交付"
|
||||
tooltip="指派该打手接单丢枪交货时,接单平台将自动冻结其押金并担保交付;不选则为客服/内部匹配"
|
||||
style={{ marginBottom: 16 }}
|
||||
>
|
||||
<Select
|
||||
allowClear
|
||||
@@ -554,7 +675,7 @@ export default function ConsignmentSubmissionsPanel() {
|
||||
.toLowerCase()
|
||||
.includes(input.toLowerCase())
|
||||
}
|
||||
placeholder="可选择关联的接单打手 (选填)"
|
||||
placeholder="未选择则为客服直接入库/内部现货匹配"
|
||||
options={workerOptions}
|
||||
/>
|
||||
</Form.Item>
|
||||
@@ -562,13 +683,15 @@ export default function ConsignmentSubmissionsPanel() {
|
||||
<Col span={10}>
|
||||
<Form.Item
|
||||
name="depositAmount"
|
||||
label="履约押金金额 (元)"
|
||||
label="履约押金金额"
|
||||
tooltip="指派该打手交枪履约时,系统冻结的押金金额"
|
||||
style={{ marginBottom: 16 }}
|
||||
>
|
||||
<InputNumber
|
||||
min={0}
|
||||
step={10}
|
||||
addonBefore="¥"
|
||||
prefix="¥"
|
||||
addonAfter="元"
|
||||
style={{ width: '100%' }}
|
||||
placeholder="如 100"
|
||||
/>
|
||||
@@ -576,52 +699,69 @@ export default function ConsignmentSubmissionsPanel() {
|
||||
</Col>
|
||||
</Row>
|
||||
|
||||
<Row gutter={16}>
|
||||
{/* 分组三:卖家信息与入库登记 */}
|
||||
<div
|
||||
style={{
|
||||
display: 'flex',
|
||||
alignItems: 'center',
|
||||
gap: 8,
|
||||
marginBottom: 10,
|
||||
fontWeight: 600,
|
||||
fontSize: 13,
|
||||
color: '#1e293b',
|
||||
}}
|
||||
>
|
||||
<div style={{ width: 3, height: 14, background: '#722ed1', borderRadius: 2 }} />
|
||||
卖家联络与入库登记
|
||||
</div>
|
||||
|
||||
<Row gutter={12}>
|
||||
<Col span={8}>
|
||||
<Form.Item name="sellerContact" label="卖家微信号" style={{ marginBottom: 12 }}>
|
||||
<Input placeholder="微信号" />
|
||||
</Form.Item>
|
||||
</Col>
|
||||
<Col span={8}>
|
||||
<Form.Item name="sellerPhone" label="卖家手机" style={{ marginBottom: 12 }}>
|
||||
<Input placeholder="手机号" />
|
||||
</Form.Item>
|
||||
</Col>
|
||||
<Col span={8}>
|
||||
<Form.Item name="sellerGameId" label="卖家游戏ID" style={{ marginBottom: 12 }}>
|
||||
<Input placeholder="游戏昵称/ID" />
|
||||
</Form.Item>
|
||||
</Col>
|
||||
</Row>
|
||||
|
||||
<Row gutter={12}>
|
||||
<Col span={10}>
|
||||
<Form.Item name="sellerPaymentInfo" label="卖家收款信息" style={{ marginBottom: 12 }}>
|
||||
<Input placeholder="如 走打手接单平台钱包 或 支付宝账号" />
|
||||
</Form.Item>
|
||||
</Col>
|
||||
<Col span={7}>
|
||||
<Form.Item
|
||||
name="buyerName"
|
||||
label="收购人 (客服)"
|
||||
rules={[{ required: true, message: '请填写收购人' }]}
|
||||
style={{ marginBottom: 12 }}
|
||||
>
|
||||
<Input />
|
||||
<Input placeholder="如 客服" />
|
||||
</Form.Item>
|
||||
</Col>
|
||||
<Col span={8}>
|
||||
<Form.Item name="shopName" label="关联店铺">
|
||||
<Input placeholder="店铺名" />
|
||||
</Form.Item>
|
||||
</Col>
|
||||
<Col span={8}>
|
||||
<Form.Item name="inboundBatch" label="收购批次">
|
||||
<Input placeholder="批次" />
|
||||
<Col span={7}>
|
||||
<Form.Item name="inboundBatch" label="收购批次" style={{ marginBottom: 12 }}>
|
||||
<Input placeholder="如 2026-09" />
|
||||
</Form.Item>
|
||||
</Col>
|
||||
</Row>
|
||||
|
||||
<Row gutter={16}>
|
||||
<Col span={8}>
|
||||
<Form.Item name="sellerContact" label="卖家微信号">
|
||||
<Input />
|
||||
</Form.Item>
|
||||
</Col>
|
||||
<Col span={8}>
|
||||
<Form.Item name="sellerPhone" label="卖家手机">
|
||||
<Input />
|
||||
</Form.Item>
|
||||
</Col>
|
||||
<Col span={8}>
|
||||
<Form.Item name="sellerGameId" label="卖家游戏ID">
|
||||
<Input />
|
||||
</Form.Item>
|
||||
</Col>
|
||||
</Row>
|
||||
|
||||
<Form.Item name="sellerPaymentInfo" label="卖家收款信息">
|
||||
<Input />
|
||||
</Form.Item>
|
||||
|
||||
<Form.Item name="reviewNote" label="审核备注">
|
||||
<Input.TextArea rows={2} placeholder="审核核准说明" />
|
||||
{/* 分组四:审核备注 */}
|
||||
<Form.Item name="reviewNote" label="审核备注" style={{ marginTop: 4, marginBottom: 0 }}>
|
||||
<Input.TextArea
|
||||
rows={2}
|
||||
placeholder="可选填写核准或沟通说明(如:已与打手核对主页截图无误)"
|
||||
/>
|
||||
</Form.Item>
|
||||
</Form>
|
||||
</Modal>
|
||||
|
||||
@@ -415,6 +415,17 @@ export default function WorkOrdersPanel() {
|
||||
}),
|
||||
})
|
||||
const ordersPagination = ordersQuery.data?.data.pagination
|
||||
|
||||
// 当列表重新拉取最新数据后,若详情抽屉正处于打开状态,自动用最新状态同步更新 detailOrder
|
||||
useEffect(() => {
|
||||
if (!detailOrder) return
|
||||
const items = ordersQuery.data?.data.items || []
|
||||
const updated = items.find((item) => item.workOrderId === detailOrder.workOrderId)
|
||||
if (updated) {
|
||||
setDetailOrder(updated)
|
||||
}
|
||||
}, [ordersQuery.data])
|
||||
|
||||
const categoriesQuery = useQuery({
|
||||
queryKey: ['admin-worker-platform-categories'],
|
||||
queryFn: () => fetchAdminWorkCategories(),
|
||||
@@ -518,7 +529,9 @@ export default function WorkOrdersPanel() {
|
||||
}, [showWorkerLevelFilter])
|
||||
|
||||
useEffect(() => {
|
||||
if (acceptanceMode !== 'friend_gift') setGiftPhase(undefined)
|
||||
if (acceptanceMode !== 'friend_gift' && acceptanceMode !== 'internal_consignment') {
|
||||
setGiftPhase(undefined)
|
||||
}
|
||||
}, [acceptanceMode])
|
||||
|
||||
function openAssignModal(row: WorkOrder) {
|
||||
@@ -680,6 +693,12 @@ export default function WorkOrdersPanel() {
|
||||
queryClient.invalidateQueries({
|
||||
queryKey: ['admin-worker-platform-summary'],
|
||||
}),
|
||||
queryClient.invalidateQueries({
|
||||
queryKey: ['admin-consignment-inventories'],
|
||||
}),
|
||||
queryClient.invalidateQueries({
|
||||
queryKey: ['admin-consignment-stats'],
|
||||
}),
|
||||
])
|
||||
}
|
||||
|
||||
@@ -1008,9 +1027,26 @@ export default function WorkOrdersPanel() {
|
||||
setMaterialScreenshots([])
|
||||
}
|
||||
|
||||
function isExplicitOrderNoSearch(text: string) {
|
||||
const trimmed = text.trim()
|
||||
if (!trimmed) return false
|
||||
return (
|
||||
/^WO[0-9a-zA-Z]{4,}$/i.test(trimmed) ||
|
||||
/^\d{6,}(-\d{6,})?$/.test(trimmed) ||
|
||||
/^OD[0-9a-zA-Z]{4,}$/i.test(trimmed)
|
||||
)
|
||||
}
|
||||
|
||||
function searchOrders() {
|
||||
setKeyword(keywordInput.trim())
|
||||
const trimmed = keywordInput.trim()
|
||||
setKeyword(trimmed)
|
||||
setPage(1)
|
||||
// 管理员精准搜索工单号/平台单号时,自动清除排他的状态与阶段限制,避免状态流转后工单从视野中消失
|
||||
if (isExplicitOrderNoSearch(trimmed)) {
|
||||
if (giftPhase) setGiftPhase(undefined)
|
||||
if (statuses.length > 0) setStatuses([])
|
||||
if (acceptanceMode) setAcceptanceMode(undefined)
|
||||
}
|
||||
}
|
||||
|
||||
function clearOrderFilters() {
|
||||
@@ -1395,8 +1431,14 @@ export default function WorkOrdersPanel() {
|
||||
置顶
|
||||
</Tag>
|
||||
) : null}
|
||||
{row.acceptanceMode === 'friend_gift' ? <Tag color="purple">好友赠送</Tag> : null}
|
||||
{row.acceptanceMode === 'friend_gift' &&
|
||||
{isInternalConsignmentOrder(row) ? (
|
||||
<Tag color="cyan">内部匹配</Tag>
|
||||
) : row.acceptanceMode === 'friend_gift' ? (
|
||||
<Tag color="purple">好友赠送</Tag>
|
||||
) : null}
|
||||
{row.status !== 'accepted' &&
|
||||
row.status !== 'cancelled' &&
|
||||
row.acceptanceMode === 'friend_gift' &&
|
||||
row.gift &&
|
||||
(!['pending_material', 'unassigned', 'open'].includes(row.rawStatus || row.status) ||
|
||||
isInternalConsignmentOrder(row)) ? (
|
||||
@@ -1682,9 +1724,16 @@ export default function WorkOrdersPanel() {
|
||||
<Input
|
||||
allowClear
|
||||
value={keywordInput}
|
||||
placeholder="订单号 / 商品名 / 游戏ID / 游戏昵称"
|
||||
placeholder="工单号 / 平台单号 / 商品名 / 游戏ID / 游戏昵称"
|
||||
style={{ width: 280 }}
|
||||
onChange={(event) => setKeywordInput(event.target.value)}
|
||||
onChange={(event) => {
|
||||
const nextVal = event.target.value
|
||||
setKeywordInput(nextVal)
|
||||
if (!nextVal.trim()) {
|
||||
setKeyword('')
|
||||
setPage(1)
|
||||
}
|
||||
}}
|
||||
onPressEnter={searchOrders}
|
||||
/>
|
||||
<Select
|
||||
@@ -1763,17 +1812,18 @@ export default function WorkOrdersPanel() {
|
||||
allowClear
|
||||
value={acceptanceMode}
|
||||
placeholder="全部验收模式"
|
||||
style={{ width: 150 }}
|
||||
style={{ width: 160 }}
|
||||
options={[
|
||||
{ value: 'standard', label: '标准验收' },
|
||||
{ value: 'friend_gift', label: '好友赠送' },
|
||||
{ value: 'friend_gift', label: '打手好友赠送' },
|
||||
{ value: 'internal_consignment', label: '内部寄售匹配' },
|
||||
]}
|
||||
onChange={(nextMode) => {
|
||||
setAcceptanceMode(nextMode)
|
||||
setPage(1)
|
||||
}}
|
||||
/>
|
||||
{acceptanceMode === 'friend_gift' ? (
|
||||
{acceptanceMode === 'friend_gift' || acceptanceMode === 'internal_consignment' ? (
|
||||
<Select
|
||||
allowClear
|
||||
value={giftPhase}
|
||||
@@ -1781,7 +1831,11 @@ export default function WorkOrdersPanel() {
|
||||
style={{ width: 170 }}
|
||||
options={GIFT_PHASE_FILTER_OPTIONS.map((phase) => ({
|
||||
value: phase,
|
||||
label: <Tag color={resolveGiftPhaseColor(phase)}>{formatGiftPhase(phase)}</Tag>,
|
||||
label: (
|
||||
<Tag color={resolveGiftPhaseColor(phase)}>
|
||||
{formatGiftPhase(phase, acceptanceMode === 'internal_consignment')}
|
||||
</Tag>
|
||||
),
|
||||
}))}
|
||||
onChange={(nextPhase) => {
|
||||
setGiftPhase(nextPhase)
|
||||
@@ -2041,11 +2095,17 @@ export default function WorkOrdersPanel() {
|
||||
|
||||
{detailOrder.acceptanceMode === 'friend_gift' && detailOrder.gift ? (
|
||||
<Card
|
||||
title="好友赠送进度"
|
||||
title={
|
||||
isInternalConsignmentOrder(detailOrder) ? '内部寄售赠送进度' : '好友赠送进度'
|
||||
}
|
||||
size="small"
|
||||
extra={
|
||||
<Space>
|
||||
<Tag color="purple">{formatAcceptanceMode(detailOrder.acceptanceMode)}</Tag>
|
||||
{isInternalConsignmentOrder(detailOrder) ? (
|
||||
<Tag color="cyan">内部寄售匹配</Tag>
|
||||
) : (
|
||||
<Tag color="purple">{formatAcceptanceMode(detailOrder.acceptanceMode)}</Tag>
|
||||
)}
|
||||
<Tag color={resolveGiftPhaseColor(detailOrder.gift.phase)}>
|
||||
{formatGiftPhase(
|
||||
detailOrder.gift.phase,
|
||||
|
||||
@@ -12,7 +12,7 @@ import {
|
||||
SafetyCertificateOutlined,
|
||||
UserOutlined,
|
||||
} from '@ant-design/icons'
|
||||
import { useQuery } from '@tanstack/react-query'
|
||||
import { useQuery, useQueryClient } from '@tanstack/react-query'
|
||||
import {
|
||||
Alert,
|
||||
App,
|
||||
@@ -101,6 +101,8 @@ export default function WorkerConsignmentPage() {
|
||||
const priceFetchTimer = useRef<ReturnType<typeof setTimeout> | null>(null)
|
||||
const lastPriceQueryKeyRef = useRef('')
|
||||
|
||||
const queryClient = useQueryClient()
|
||||
|
||||
const profileQuery = useQuery({
|
||||
queryKey: ['worker-profile'],
|
||||
queryFn: () => fetchWorkerProfile(),
|
||||
@@ -114,6 +116,14 @@ export default function WorkerConsignmentPage() {
|
||||
queryFn: () => fetchWorkerConsignments(),
|
||||
})
|
||||
|
||||
// 切换标签页时自动刷新最新数据
|
||||
useEffect(() => {
|
||||
if (activeTab === 'records') {
|
||||
void queryClient.invalidateQueries({ queryKey: ['worker-my-consignments'] })
|
||||
}
|
||||
void queryClient.invalidateQueries({ queryKey: ['worker-profile'] })
|
||||
}, [activeTab, queryClient])
|
||||
|
||||
// 后端已按「一件货一行」聚合,前端不再合并提报单与库存
|
||||
const records = myConsignmentsQuery.data?.data.items || []
|
||||
const stageCounts = myConsignmentsQuery.data?.data.stageCounts || {}
|
||||
@@ -1104,10 +1114,37 @@ function ConsignmentRecordCard({
|
||||
</Space>
|
||||
) : null}
|
||||
{shots.length > 0 || giftShots.length > 0 ? (
|
||||
<div style={{ display: 'flex', flexWrap: 'wrap', gap: 10, marginTop: 8, alignItems: 'center' }}>
|
||||
<div
|
||||
style={{
|
||||
display: 'flex',
|
||||
flexWrap: 'wrap',
|
||||
gap: 10,
|
||||
marginTop: 8,
|
||||
alignItems: 'center',
|
||||
}}
|
||||
>
|
||||
{shots.length > 0 ? (
|
||||
<div style={{ display: 'inline-flex', alignItems: 'center', gap: 8, background: '#f8fafc', padding: '4px 10px', borderRadius: 6, border: '1px solid #e2e8f0' }}>
|
||||
<Typography.Text type="secondary" style={{ fontSize: 12, display: 'flex', alignItems: 'center', gap: 4, whiteSpace: 'nowrap' }}>
|
||||
<div
|
||||
style={{
|
||||
display: 'inline-flex',
|
||||
alignItems: 'center',
|
||||
gap: 8,
|
||||
background: '#f8fafc',
|
||||
padding: '4px 10px',
|
||||
borderRadius: 6,
|
||||
border: '1px solid #e2e8f0',
|
||||
}}
|
||||
>
|
||||
<Typography.Text
|
||||
type="secondary"
|
||||
style={{
|
||||
fontSize: 12,
|
||||
display: 'flex',
|
||||
alignItems: 'center',
|
||||
gap: 4,
|
||||
whiteSpace: 'nowrap',
|
||||
}}
|
||||
>
|
||||
<PictureOutlined />
|
||||
商品截图({shots.length})
|
||||
</Typography.Text>
|
||||
@@ -1127,8 +1164,28 @@ function ConsignmentRecordCard({
|
||||
</div>
|
||||
) : null}
|
||||
{giftShots.length > 0 ? (
|
||||
<div style={{ display: 'inline-flex', alignItems: 'center', gap: 8, background: '#f0fdf4', padding: '4px 10px', borderRadius: 6, border: '1px solid #bbf7d0' }}>
|
||||
<Typography.Text strong style={{ fontSize: 12, color: '#15803d', display: 'flex', alignItems: 'center', gap: 4, whiteSpace: 'nowrap' }}>
|
||||
<div
|
||||
style={{
|
||||
display: 'inline-flex',
|
||||
alignItems: 'center',
|
||||
gap: 8,
|
||||
background: '#f0fdf4',
|
||||
padding: '4px 10px',
|
||||
borderRadius: 6,
|
||||
border: '1px solid #bbf7d0',
|
||||
}}
|
||||
>
|
||||
<Typography.Text
|
||||
strong
|
||||
style={{
|
||||
fontSize: 12,
|
||||
color: '#15803d',
|
||||
display: 'flex',
|
||||
alignItems: 'center',
|
||||
gap: 4,
|
||||
whiteSpace: 'nowrap',
|
||||
}}
|
||||
>
|
||||
<CheckCircleOutlined />
|
||||
赠送凭证({giftShots.length})
|
||||
</Typography.Text>
|
||||
@@ -1146,7 +1203,11 @@ function ConsignmentRecordCard({
|
||||
</Space>
|
||||
</Image.PreviewGroup>
|
||||
{record.giftEvidenceNote ? (
|
||||
<Typography.Text type="secondary" style={{ fontSize: 11, color: '#4b5563', maxWidth: 160 }} ellipsis={{ tooltip: record.giftEvidenceNote }}>
|
||||
<Typography.Text
|
||||
type="secondary"
|
||||
style={{ fontSize: 11, color: '#4b5563', maxWidth: 160 }}
|
||||
ellipsis={{ tooltip: record.giftEvidenceNote }}
|
||||
>
|
||||
{record.giftEvidenceNote}
|
||||
</Typography.Text>
|
||||
) : null}
|
||||
|
||||
@@ -26,6 +26,10 @@ export type ConsignmentEvidenceFields = {
|
||||
giftWorkOrderNo?: string
|
||||
/** 关联工单状态:in_progress / pending_acceptance / accepted 等 */
|
||||
giftWorkOrderStatus?: string
|
||||
/** 关联工单赠送阶段:material_required / material_submitted / friend_countdown / gift_ready 等 */
|
||||
giftPhase?: string
|
||||
/** 关联工单确认加好友时间(ISO 字符串,为空代表尚未确认加好友) */
|
||||
giftFriendAddedAt?: string
|
||||
/** 赠送凭证的客服验收状态 */
|
||||
giftEvidenceReviewStatus?: GiftEvidenceReviewStatus
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user