feat:寄卖增加对接客服,db脚本迁移修复

This commit is contained in:
2026-10-27 13:39:48 +08:00
parent 0de0fd7b58
commit 622bd779dd
25 changed files with 1515 additions and 106 deletions
@@ -29,6 +29,7 @@ import { useState } from 'react'
import ConsignmentEvidenceGallery from '@/components/admin/ConsignmentEvidenceGallery'
import {
archiveAdminConsignmentInventory,
fetchAdminConsignmentContacts,
fetchAdminConsignmentInventories,
fetchAdminConsignmentStats,
returnAdminConsignmentInventory,
@@ -40,6 +41,7 @@ import ConsignmentManualMatchModal from '@/components/admin/ConsignmentManualMat
import type { ConsignmentInventory, GiftEvidenceReviewStatus } from '@/types/consignment'
import { fetchAdminSession } from '@/services/admin/auth'
import { resolveAdminPermission } from '@/utils/admin-auth'
import { formatConsignmentContactSupporter } from '@/utils/consignment-contact'
import { describeGiftEvidence, resolveGiftEvidenceBadge } from '@/utils/consignment-evidence'
import { CONSIGNMENT_SYSTEM_OPTIONS, CONSIGNMENT_ZONE_OPTIONS } from '@/utils/consignment-spec'
import { formatDateTime } from '@/utils/date-time'
@@ -174,6 +176,18 @@ export default function ConsignmentInventoryPanel() {
name: w.displayName || w.username,
}))
// 对接客服名单:编辑现货时可改派对接人(含已禁用项,历史数据需要能显示原值)
const contactsQuery = useQuery({
queryKey: ['admin-consignment-contacts'],
queryFn: () => fetchAdminConsignmentContacts(),
})
const contactSupporterOptions = (contactsQuery.data?.data.items || []).map((item) => ({
label: `${item.name}${item.enabled ? '' : '(已禁用)'}${
item.phone ? ` · ${item.phone}` : item.wechat ? ` · ${item.wechat}` : ''
}`,
value: item.id,
}))
// 数据查询
const inventoriesQuery = useQuery({
queryKey: [
@@ -255,6 +269,7 @@ export default function ConsignmentInventoryPanel() {
workerId: values.workerId || undefined,
workerName: selectedWorker?.name || editingItem.workerName || undefined,
workerPhone: selectedWorker?.phone || editingItem.workerPhone || undefined,
contactSupporterId: values.contactSupporterId ?? null,
remark: values.remark,
allowMatching: values.allowMatching !== false,
})
@@ -456,6 +471,22 @@ export default function ConsignmentInventoryPanel() {
</div>
),
},
{
title: '对接客服',
key: 'contactSupporter',
width: 150,
render: (_, record) => {
const contact = formatConsignmentContactSupporter(record)
return (
<div style={{ fontSize: 12 }}>
<div style={{ fontWeight: 600 }}>{contact.name || contact.text}</div>
{contact.contact ? (
<div style={{ color: '#8c8c8c', marginTop: 2 }}>{contact.contact}</div>
) : null}
</div>
)
},
},
{
title: '凭证',
key: 'evidence',
@@ -990,6 +1021,24 @@ export default function ConsignmentInventoryPanel() {
</Col>
</Row>
<Row gutter={16}>
<Col span={14}>
<Form.Item
name="contactSupporterId"
label="对接客服"
tooltip="用于提成归属与联系;发布寄卖时由卖家必选"
>
<Select
allowClear
showSearch
optionFilterProp="label"
placeholder="选择对接客服(选填)"
options={contactSupporterOptions}
/>
</Form.Item>
</Col>
</Row>
<Form.Item name="sellerPaymentInfo" label="卖家收款信息">
<Input />
</Form.Item>
@@ -1082,6 +1131,23 @@ export default function ConsignmentInventoryPanel() {
<Text type="secondary">内部自营现货</Text>
)}
</Descriptions.Item>
<Descriptions.Item label="对接客服">
{(() => {
const contact = formatConsignmentContactSupporter(viewingItem)
return contact.name ? (
<Space direction="vertical" size={2}>
<Text strong>{contact.name}</Text>
{contact.contact ? (
<Text type="secondary" style={{ fontSize: 12 }}>
{contact.contact}
</Text>
) : null}
</Space>
) : (
<Text type="secondary">未指定</Text>
)
})()}
</Descriptions.Item>
<Descriptions.Item label="履约押金要求">
{viewingItem.depositAmountFen ? (
<Tag color="gold">¥{(viewingItem.depositAmountFen / 100).toFixed(0)}</Tag>
@@ -40,6 +40,7 @@ import { fetchAdminSession } from '@/services/admin/auth'
import { fetchAdminWorkerUsers } from '@/services/admin/worker-platform'
import type { ConsignmentSubmission, GiftEvidenceReviewStatus } from '@/types/consignment'
import { resolveAdminPermission } from '@/utils/admin-auth'
import { formatConsignmentContactSupporter } from '@/utils/consignment-contact'
import { describeGiftEvidence, resolveGiftEvidenceBadge } from '@/utils/consignment-evidence'
import { CONSIGNMENT_SYSTEM_OPTIONS, CONSIGNMENT_ZONE_OPTIONS } from '@/utils/consignment-spec'
import { formatDateTime } from '@/utils/date-time'
@@ -271,6 +272,22 @@ export default function ConsignmentSubmissionsPanel() {
</div>
),
},
{
title: '对接客服',
key: 'contactSupporter',
width: 150,
render: (_, record) => {
const contact = formatConsignmentContactSupporter(record)
return (
<div style={{ fontSize: 12 }}>
<div style={{ fontWeight: 600 }}>{contact.name || contact.text}</div>
{contact.contact ? (
<div style={{ color: '#8c8c8c', marginTop: 2 }}>{contact.contact}</div>
) : null}
</div>
)
},
},
{
title: '提报凭证(游戏主页截图)',
key: 'submissionScreenshots',
@@ -536,6 +553,10 @@ export default function ConsignmentSubmissionsPanel() {
<span>
联系方式:<Text strong>{approveModalItem?.contactInfo || '-'}</Text>
</span>
<span>
对接客服:
<Text strong>{formatConsignmentContactSupporter(approveModalItem).text}</Text>
</span>
<span>
游戏ID:<Text strong>{approveModalItem?.sellerGameId || '-'}</Text>
</span>
@@ -852,6 +873,23 @@ export default function ConsignmentSubmissionsPanel() {
<Text type="secondary">未关联打手账号</Text>
)}
</Descriptions.Item>
<Descriptions.Item label="对接客服">
{(() => {
const contact = formatConsignmentContactSupporter(viewingSubmission)
return contact.name ? (
<Space direction="vertical" size={2}>
<Text strong>{contact.name}</Text>
{contact.contact ? (
<Text type="secondary" style={{ fontSize: 12 }}>
{contact.contact}
</Text>
) : null}
</Space>
) : (
<Text type="secondary">未指定</Text>
)
})()}
</Descriptions.Item>
<Descriptions.Item label="履约押金要求">
{viewingSubmission.depositAmountFen ? (
<Tag color="gold">¥{(viewingSubmission.depositAmountFen / 100).toFixed(0)}</Tag>
@@ -92,6 +92,7 @@ import { notifyVoucherConsume } from '@/utils/voucher-consume'
import type { ConsignmentFulfillmentInfo, WorkOrderInventoryMatchCheck } from '@/types/consignment'
import type { UploadedFile, WorkOrder, WorkOrderShare } from '@/types/worker-platform'
import { canManuallyMatchConsignmentOrder } from '@/utils/consignment-manual-match'
import { formatConsignmentContactSupporter } from '@/utils/consignment-contact'
import {
isConsignmentOrder,
isInternalConsignmentOrder,
@@ -1644,10 +1645,15 @@ export default function WorkOrdersPanel() {
</Typography.Text>
) : null}
{consignment ? (
<Tag color="purple" style={{ marginTop: 2, width: 'fit-content' }}>
寄卖单号: {resolveConsignmentNo(consignment) || '-'} (成本: ¥
{((Number(consignment.costPriceFen) || 0) / 100).toFixed(2)})
</Tag>
<Space size={[4, 4]} wrap>
<Tag color="purple" style={{ marginTop: 2, width: 'fit-content' }}>
寄卖单号: {resolveConsignmentNo(consignment) || '-'} (成本: ¥
{((Number(consignment.costPriceFen) || 0) / 100).toFixed(2)})
</Tag>
<Tag color="cyan" style={{ marginTop: 2, width: 'fit-content' }}>
对接客服: {formatConsignmentContactSupporter(consignment).text}
</Tag>
</Space>
) : null}
</div>
)
@@ -2317,6 +2323,11 @@ export default function WorkOrdersPanel() {
</Typography.Text>
</Descriptions.Item>
) : null}
{detailConsignment ? (
<Descriptions.Item label="对接客服">
{formatConsignmentContactSupporter(detailConsignment).text}
</Descriptions.Item>
) : null}
<Descriptions.Item label="状态">
<Tag color={resolveStatusColor(detailOrder.status)}>
{formatStatus(detailOrder.status)}
@@ -2655,6 +2666,13 @@ export default function WorkOrdersPanel() {
</Space>
</Descriptions.Item>
) : null}
{isConsignment ? (
<Descriptions.Item label="对接客服" span={2}>
<span className="worker-order-detail-value">
{formatConsignmentContactSupporter(consignmentInfo).text}
</span>
</Descriptions.Item>
) : null}
<Descriptions.Item
label={isConsignment ? '卖家备注' : '打手备注'}
span={2}
@@ -4095,6 +4113,9 @@ export default function WorkOrdersPanel() {
供货打手: {inv.workerName} ({inv.workerPhone || '无手机号'})
</Tag>
) : null}
<Tag color="cyan">
对接客服: {formatConsignmentContactSupporter(inv).text}
</Tag>
{inv.depositAmountFen != null ? (
<Tag color="warning">
履约押金: ¥{(inv.depositAmountFen / 100).toFixed(2)}