feat(consignment): 新增和平精英寄卖库存管理、定向收集审核与工单智能匹配履约

This commit is contained in:
yml2213
2026-09-14 11:39:15 +08:00
parent 38c0cf1223
commit 1aa6dba931
30 changed files with 6350 additions and 44 deletions
@@ -0,0 +1,947 @@
import {
CheckCircleOutlined,
CloseCircleOutlined,
CopyOutlined,
EyeOutlined,
LinkOutlined,
PlusOutlined,
ReloadOutlined,
} from '@ant-design/icons'
import { useQuery } from '@tanstack/react-query'
import {
Alert,
App,
Badge,
Button,
Card,
Col,
Descriptions,
Form,
Image,
Input,
InputNumber,
Modal,
Radio,
Row,
Select,
Space,
Switch,
Table,
Tabs,
Tag,
Typography,
} from 'antd'
import type { TableColumnsType } from 'antd'
import { useState } from 'react'
import {
approveAdminConsignmentSubmission,
createAdminConsignmentLink,
fetchAdminConsignmentLinks,
fetchAdminConsignmentSubmissions,
rejectAdminConsignmentSubmission,
updateAdminConsignmentLink,
} from '@/services/admin/consignment'
import type { ConsignmentCollectLink, ConsignmentSubmission } from '@/types/consignment'
const { Text } = Typography
export default function ConsignmentSubmissionsPanel() {
const { message } = App.useApp()
const [activeSubTab, setActiveSubTab] = useState<'submissions' | 'links'>('submissions')
// 提报审核状态
const [submissionStatus, setSubmissionStatus] = useState<string>('pending_review')
const [submissionKeyword, setSubmissionKeyword] = useState<string>('')
const [submissionPage, setSubmissionPage] = useState<number>(1)
const [submissionPageSize, setSubmissionPageSize] = useState<number>(20)
// 弹窗状态
const [createLinkModalOpen, setCreateLinkModalOpen] = useState(false)
const [createdLinkUrl, setCreatedLinkUrl] = useState<string>('')
const [approveModalItem, setApproveModalItem] = useState<ConsignmentSubmission | null>(null)
const [rejectModalItem, setRejectModalItem] = useState<ConsignmentSubmission | null>(null)
const [viewingSubmission, setViewingSubmission] = useState<ConsignmentSubmission | null>(null)
const [rejectNote, setRejectNote] = useState('')
const [linkForm] = Form.useForm()
const [approveForm] = Form.useForm()
// 查询提报列表
const submissionsQuery = useQuery({
queryKey: [
'admin-consignment-submissions',
submissionStatus,
submissionKeyword,
submissionPage,
submissionPageSize,
],
queryFn: () =>
fetchAdminConsignmentSubmissions({
status: submissionStatus === 'all' ? undefined : submissionStatus,
keyword: submissionKeyword || undefined,
page: submissionPage,
pageSize: submissionPageSize,
}),
})
// 查询链接列表
const linksQuery = useQuery({
queryKey: ['admin-consignment-links'],
queryFn: () => fetchAdminConsignmentLinks(),
})
const submissions = submissionsQuery.data?.data.items || []
const submissionTotal = submissionsQuery.data?.data.total || 0
const links = Array.isArray(linksQuery.data?.data)
? linksQuery.data?.data
: linksQuery.data?.data?.items || []
// 复制收集公开链接
function copyPublicLink(token: string) {
const origin = window.location.origin
const url = `${origin}/#/consignment-collect/${token}`
navigator.clipboard.writeText(url)
message.success('收集链接已复制到剪贴板,可直接发给客户!')
}
// 切换链接启用/关闭
async function handleToggleLink(record: ConsignmentCollectLink, enabled: boolean) {
try {
await updateAdminConsignmentLink(record.id, { enabled })
message.success(enabled ? '链接已开启' : '链接已关闭')
linksQuery.refetch()
} catch (err: any) {
message.error(err.message || '更新失败')
}
}
// 创建收集链接
async function handleCreateLinkSubmit() {
try {
const values = await linkForm.validateFields()
const presetPriceFen = Math.round(Number(values.presetPrice || 0) * 100)
const briStr = values.brillianceCount > 0 ? `${values.brillianceCount}璀璨` : ''
const defaultTitle = `${values.system}${values.serverZone}${values.series}${values.diamondLevel}钻${briStr} 寄卖征集`
const res = await createAdminConsignmentLink({
title: values.title || defaultTitle,
system: values.system,
serverZone: values.serverZone,
series: values.series,
diamondLevel: Number(values.diamondLevel || 1),
brillianceCount: Number(values.brillianceCount || 0),
presetPriceFen,
buyerName: values.buyerName,
inboundBatch: values.inboundBatch,
isMultiUse: values.isMultiUse !== false,
})
const token = res.data?.token || ''
const url = `${window.location.origin}/#/consignment-collect/${token}`
setCreatedLinkUrl(url)
try {
navigator.clipboard.writeText(url)
} catch {}
message.success('收集链接生成成功!')
setCreateLinkModalOpen(false)
linkForm.resetFields()
await linksQuery.refetch()
} catch (err: any) {
if (err.errorFields) return
message.error(err.message || '创建收集链接失败')
}
}
// 审核通过并入库
async function handleApproveSubmit() {
if (!approveModalItem) return
try {
const values = await approveForm.validateFields()
const costPriceFen = Math.round(Number(values.costPrice || 0) * 100)
await approveAdminConsignmentSubmission(approveModalItem.id, {
costPriceFen,
buyerName: values.buyerName,
shopName: values.shopName,
inboundBatch: values.inboundBatch,
itemName: values.itemName,
system: values.system,
serverZone: values.serverZone,
series: values.series,
diamondLevel: Number(values.diamondLevel || 1),
brillianceCount: Number(values.brillianceCount || 0),
sellerContact: values.sellerContact,
sellerGameId: values.sellerGameId,
sellerPaymentInfo: values.sellerPaymentInfo,
sellerPhone: values.sellerPhone,
reviewNote: values.reviewNote,
})
message.success('审核通过!已正式存入寄售库存待匹配!')
setApproveModalItem(null)
submissionsQuery.refetch()
} catch (err: any) {
if (err.errorFields) return
message.error(err.message || '审核入库失败')
}
}
// 驳回提报
async function handleRejectConfirm() {
if (!rejectModalItem) return
try {
await rejectAdminConsignmentSubmission(rejectModalItem.id, { reviewNote: rejectNote })
message.success('已驳回该提报申请')
setRejectModalItem(null)
setRejectNote('')
submissionsQuery.refetch()
} catch (err: any) {
message.error(err.message || '驳回失败')
}
}
// 提报列表列定义
const submissionColumns: TableColumnsType<ConsignmentSubmission> = [
{
title: '提报单号',
key: 'submissionNo',
width: 170,
render: (_, record) => (
<div>
<Text strong>{record.submissionNo}</Text>
{record.linkTitle ? (
<div style={{ fontSize: 11, color: '#8c8c8c' }}>来自: {record.linkTitle}</div>
) : null}
</div>
),
},
{
title: '提报物品规格',
key: 'specs',
width: 210,
render: (_, record) => (
<Space direction="vertical" size={2}>
<div style={{ fontWeight: 600 }}>{record.itemName}</div>
<Space size={4} wrap>
<Tag color={record.system === '苹果' ? 'geekblue' : 'green'}>{record.system}</Tag>
<Tag color="cyan">{record.serverZone}</Tag>
<Tag color="orange">{record.series}</Tag>
<Tag color="gold">{record.diamondLevel} 钻</Tag>
{record.brillianceCount > 0 ? (
<Tag color="magenta">{record.brillianceCount} 璀璨</Tag>
) : null}
</Space>
</Space>
),
},
{
title: '卖家报价',
key: 'price',
width: 110,
render: (_, record) => (
<Text strong style={{ color: '#cf1322', fontSize: 15 }}>
¥{(record.askingPriceFen / 100).toFixed(2)}
</Text>
),
},
{
title: '卖家联系方式',
key: 'contact',
width: 180,
render: (_, record) => (
<div style={{ fontSize: 12 }}>
<div>联系: {record.contactInfo}</div>
{record.sellerGameId ? <div>游戏ID: {record.sellerGameId}</div> : null}
{record.sellerPhone ? <div>电话: {record.sellerPhone}</div> : null}
</div>
),
},
{
title: '凭据截图',
key: 'screens',
width: 110,
render: (_, record) => {
const screens = Array.isArray(record.screenshotsJson) ? record.screenshotsJson : []
if (screens.length === 0) return <Text type="secondary">无截图</Text>
return (
<Image.PreviewGroup>
<Image
src={screens[0]}
width={48}
height={48}
style={{ objectFit: 'cover', borderRadius: 4 }}
/>
</Image.PreviewGroup>
)
},
},
{
title: '状态',
key: 'status',
width: 100,
render: (_, record) => {
if (record.status === 'pending_review') return <Tag color="gold">待客服审核</Tag>
if (record.status === 'approved') return <Tag color="green">已入库</Tag>
return <Tag color="red">已驳回</Tag>
},
},
{
title: '提报时间',
dataIndex: 'createdAt',
width: 150,
render: (v) => <Text style={{ fontSize: 12 }}>{v}</Text>,
},
{
title: '操作',
key: 'actions',
width: 160,
render: (_, record) => (
<Space size={8}>
<Button
size="small"
type="text"
icon={<EyeOutlined />}
onClick={() => setViewingSubmission(record)}
>
详情
</Button>
{record.status === 'pending_review' ? (
<>
<Button
size="small"
type="primary"
onClick={() => {
setApproveModalItem(record)
approveForm.setFieldsValue({
...record,
costPrice: record.askingPriceFen / 100,
sellerContact: record.contactInfo,
buyerName: '客服',
inboundBatch: new Date().toISOString().slice(0, 7),
})
}}
>
审核入库
</Button>
<Button
size="small"
danger
type="text"
onClick={() => {
setRejectModalItem(record)
setRejectNote('')
}}
>
驳回
</Button>
</>
) : null}
</Space>
),
},
]
// 链接列表列定义
const linkColumns: TableColumnsType<ConsignmentCollectLink> = [
{
title: '收集标题 / 规格',
key: 'title',
width: 280,
render: (_, record) => {
const fullUrl = `${window.location.origin}/#/consignment-collect/${record.token}`
return (
<div>
<div style={{ fontWeight: 600 }}>{record.title}</div>
<Space size={4} wrap style={{ marginTop: 4 }}>
<Tag color={record.system === '苹果' ? 'geekblue' : 'green'}>
{record.system || '通用'}
</Tag>
<Tag color="cyan">{record.serverZone || '全区'}</Tag>
<Tag color="orange">{record.series || '通用'}</Tag>
<Tag color="gold">{record.diamondLevel || 1} 钻</Tag>
{record.brillianceCount > 0 ? (
<Tag color="magenta">{record.brillianceCount} 璀璨</Tag>
) : null}
</Space>
<div style={{ marginTop: 6 }}>
<Text
copyable={{ text: fullUrl }}
style={{ fontSize: 11, color: '#1890ff', wordBreak: 'break-all' }}
>
{fullUrl}
</Text>
</div>
</div>
)
},
},
{
title: '指导参考价',
key: 'price',
width: 110,
render: (_, record) => (
<Text strong style={{ color: '#cf1322' }}>
¥{(record.presetPriceFen / 100).toFixed(2)}
</Text>
),
},
{
title: '创建人/批次',
key: 'creator',
width: 140,
render: (_, record) => (
<div>
<div>{record.createdBy || '-'}</div>
{record.inboundBatch ? (
<div style={{ fontSize: 11, color: '#8c8c8c' }}>批次: {record.inboundBatch}</div>
) : null}
</div>
),
},
{
title: '提报数量',
key: 'count',
width: 100,
render: (_, record) => (
<Badge
count={record.submissionCount || 0}
showZero
style={{ backgroundColor: (record.submissionCount || 0) > 0 ? '#52c41a' : '#d9d9d9' }}
/>
),
},
{
title: '状态开关',
key: 'enabled',
width: 100,
render: (_, record) => (
<Switch
checked={record.enabled}
checkedChildren="开启"
unCheckedChildren="关闭"
onChange={(checked) => handleToggleLink(record, checked)}
/>
),
},
{
title: '操作',
key: 'actions',
width: 180,
render: (_, record) => (
<Space size={8}>
<Button
size="small"
type="primary"
ghost
icon={<CopyOutlined />}
onClick={() => copyPublicLink(record.token)}
>
复制公开链接
</Button>
</Space>
),
},
]
return (
<div style={{ display: 'flex', flexDirection: 'column', gap: 16 }}>
<Tabs
activeKey={activeSubTab}
onChange={(k) => setActiveSubTab(k as any)}
items={[
{
key: 'submissions',
label: (
<span>
玩家提报审核{' '}
{submissions.filter((s) => s.status === 'pending_review').length > 0 ? (
<Badge
count={submissions.filter((s) => s.status === 'pending_review').length}
offset={[6, -2]}
/>
) : null}
</span>
),
children: (
<div style={{ display: 'flex', flexDirection: 'column', gap: 16 }}>
{/* 过滤条 */}
<Card size="small">
<Space wrap size={12}>
<Radio.Group
value={submissionStatus}
onChange={(e) => {
setSubmissionStatus(e.target.value)
setSubmissionPage(1)
}}
buttonStyle="solid"
>
<Radio.Button value="pending_review">待客服审核</Radio.Button>
<Radio.Button value="approved">已审核入库</Radio.Button>
<Radio.Button value="rejected">已驳回</Radio.Button>
<Radio.Button value="all">全部</Radio.Button>
</Radio.Group>
<Input.Search
placeholder="搜索提报单号/微信号/游戏ID"
allowClear
style={{ width: 240 }}
onSearch={(v) => {
setSubmissionKeyword(v)
setSubmissionPage(1)
}}
/>
<Button icon={<ReloadOutlined />} onClick={() => submissionsQuery.refetch()}>
刷新
</Button>
</Space>
</Card>
{/* 提报审核表格 */}
<Card size="small">
<Table
rowKey="id"
columns={submissionColumns}
dataSource={submissions}
loading={submissionsQuery.isLoading}
pagination={{
current: submissionPage,
pageSize: submissionPageSize,
total: submissionTotal,
showSizeChanger: true,
showTotal: (t) => `共 ${t} 条提报记录`,
onChange: (p, ps) => {
setSubmissionPage(p)
setSubmissionPageSize(ps)
},
}}
/>
</Card>
</div>
),
},
{
key: 'links',
label: '收集链接生成与管理',
children: (
<div style={{ display: 'flex', flexDirection: 'column', gap: 16 }}>
<Card size="small">
<Space wrap size={12}>
<Button
type="primary"
icon={<PlusOutlined />}
onClick={() => {
linkForm.resetFields()
linkForm.setFieldsValue({
system: '苹果',
serverZone: '微信区',
series: '暗潮',
diamondLevel: 1,
brillianceCount: 0,
isMultiUse: true,
buyerName: '客服',
})
setCreateLinkModalOpen(true)
}}
>
生成定向收集链接
</Button>
<Button icon={<ReloadOutlined />} onClick={() => linksQuery.refetch()}>
刷新
</Button>
</Space>
</Card>
<Card size="small">
<Table
rowKey="id"
columns={linkColumns}
dataSource={links}
loading={linksQuery.isLoading}
pagination={false}
/>
</Card>
</div>
),
},
]}
/>
{/* 生成收集链接弹窗 */}
<Modal
title="生成寄卖线索收集链接"
open={createLinkModalOpen}
width={600}
onCancel={() => setCreateLinkModalOpen(false)}
onOk={handleCreateLinkSubmit}
destroyOnClose
>
<Form form={linkForm} layout="vertical">
<Row gutter={16}>
<Col span={8}>
<Form.Item name="system" label="指定系统" rules={[{ required: true }]}>
<Select
options={[
{ label: '苹果 (iOS)', value: '苹果' },
{ label: '安卓 (Android)', value: '安卓' },
{ label: '通用', value: '通用' },
]}
/>
</Form.Item>
</Col>
<Col span={8}>
<Form.Item name="serverZone" label="指定区服" rules={[{ required: true }]}>
<Select
options={[
{ label: '微信区', value: '微信区' },
{ label: 'QQ区', value: 'QQ区' },
]}
/>
</Form.Item>
</Col>
<Col span={8}>
<Form.Item name="series" label="枪系/系列" rules={[{ required: true }]}>
<Select
options={[
{ label: '暗潮', value: '暗潮' },
{ label: '怒嚎', value: '怒嚎' },
{ label: '血宴', value: '血宴' },
{ label: '矩阵', value: '矩阵' },
{ label: '其他', value: '其他' },
]}
/>
</Form.Item>
</Col>
</Row>
<Row gutter={16}>
<Col span={8}>
<Form.Item name="diamondLevel" label="钻石等级" rules={[{ required: true }]}>
<Select
options={[
{ label: '1 钻', value: 1 },
{ label: '2 钻', value: 2 },
{ label: '3 钻', value: 3 },
{ label: '4 钻', value: 4 },
{ label: '5 钻', value: 5 },
{ label: '6 钻', value: 6 },
]}
/>
</Form.Item>
</Col>
<Col span={8}>
<Form.Item name="brillianceCount" label="璀璨数">
<InputNumber min={0} max={6} style={{ width: '100%' }} />
</Form.Item>
</Col>
<Col span={8}>
<Form.Item name="presetPrice" label="指导收购价 (元)">
<InputNumber min={0} style={{ width: '100%' }} placeholder="如 80" />
</Form.Item>
</Col>
</Row>
<Form.Item
name="title"
label="链接标题 (留空则根据规格自动生成)"
tooltip="玩家打开链接时看到的标题"
>
<Input placeholder="如:【高价收】苹果微信暗潮1钻 极速审核" />
</Form.Item>
<Row gutter={16}>
<Col span={12}>
<Form.Item name="buyerName" label="默认收购人">
<Input placeholder="客服姓名" />
</Form.Item>
</Col>
<Col span={12}>
<Form.Item name="inboundBatch" label="归属批次">
<Input placeholder="如 202609-01" />
</Form.Item>
</Col>
</Row>
<Form.Item name="isMultiUse" label="允许多次提报" valuePropName="checked">
<Switch defaultChecked checkedChildren="多人可填" unCheckedChildren="单次失效" />
</Form.Item>
</Form>
</Modal>
{/* 审核入库弹窗 */}
<Modal
title="审核寄卖申请并正式入库"
open={Boolean(approveModalItem)}
width={680}
onCancel={() => setApproveModalItem(null)}
onOk={handleApproveSubmit}
okText="审核通过并正式入库"
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>
<Form form={approveForm} layout="vertical">
<Row gutter={16}>
<Col span={14}>
<Form.Item
name="itemName"
label="正式入库物品名"
rules={[{ required: true, message: '请输入入库物品名' }]}
>
<Input />
</Form.Item>
</Col>
<Col span={10}>
<Form.Item
name="costPrice"
label="实际收购成本 (元)"
rules={[{ required: true, message: '请输入实际收购成本' }]}
>
<InputNumber min={0} step={1} style={{ width: '100%' }} />
</Form.Item>
</Col>
</Row>
<Row gutter={16}>
<Col span={6}>
<Form.Item name="system" label="系统">
<Input />
</Form.Item>
</Col>
<Col span={6}>
<Form.Item name="serverZone" label="区服">
<Input />
</Form.Item>
</Col>
<Col span={6}>
<Form.Item name="series" label="系列">
<Input />
</Form.Item>
</Col>
<Col span={6}>
<Form.Item name="diamondLevel" label="钻石等级">
<InputNumber min={1} max={6} style={{ width: '100%' }} />
</Form.Item>
</Col>
</Row>
<Row gutter={16}>
<Col span={8}>
<Form.Item
name="buyerName"
label="收购人 (客服)"
rules={[{ required: true, message: '请填写收购人' }]}
>
<Input />
</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="批次" />
</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>
</Form>
</Modal>
{/* 驳回弹窗 */}
<Modal
title="驳回寄卖提报"
open={Boolean(rejectModalItem)}
onCancel={() => setRejectModalItem(null)}
onOk={handleRejectConfirm}
okText="确认驳回"
okType="danger"
>
<div style={{ marginBottom: 12 }}>
<Text>
确认驳回 <strong>[{rejectModalItem?.submissionNo}]</strong> 的寄卖申请吗?
</Text>
</div>
<Form layout="vertical">
<Form.Item label="驳回原因说明">
<Input.TextArea
rows={3}
value={rejectNote}
onChange={(e) => setRejectNote(e.target.value)}
placeholder="如:要价过高、物品规格不符、账号存在实名绑定限制等"
/>
</Form.Item>
</Form>
</Modal>
{/* 提报详情查看弹窗 */}
<Modal
title={`提报详情 [${viewingSubmission?.submissionNo}]`}
open={Boolean(viewingSubmission)}
width={680}
footer={[
<Button key="close" onClick={() => setViewingSubmission(null)}>
关闭
</Button>,
]}
onCancel={() => setViewingSubmission(null)}
>
{viewingSubmission ? (
<Descriptions bordered size="small" column={2}>
<Descriptions.Item label="提报单号" span={2}>
<Text copyable>{viewingSubmission.submissionNo}</Text>
</Descriptions.Item>
<Descriptions.Item label="物品名称" span={2}>
{viewingSubmission.itemName}
</Descriptions.Item>
<Descriptions.Item label="规格">
{viewingSubmission.system} / {viewingSubmission.serverZone} /{' '}
{viewingSubmission.series} / {viewingSubmission.diamondLevel}钻 (
{viewingSubmission.brillianceCount}璀璨)
</Descriptions.Item>
<Descriptions.Item label="卖家报价">
<Text strong style={{ color: '#cf1322' }}>
¥{(viewingSubmission.askingPriceFen / 100).toFixed(2)}
</Text>
</Descriptions.Item>
<Descriptions.Item label="卖家微信号">
<Text copyable>{viewingSubmission.contactInfo}</Text>
</Descriptions.Item>
<Descriptions.Item label="卖家电话">
<Text copyable>{viewingSubmission.sellerPhone || '-'}</Text>
</Descriptions.Item>
<Descriptions.Item label="卖家游戏ID" span={2}>
<Text copyable>{viewingSubmission.sellerGameId || '-'}</Text>
</Descriptions.Item>
<Descriptions.Item label="卖家收款方式" span={2}>
<Text copyable>{viewingSubmission.sellerPaymentInfo || '-'}</Text>
</Descriptions.Item>
<Descriptions.Item label="凭据截图" span={2}>
{Array.isArray(viewingSubmission.screenshotsJson) &&
viewingSubmission.screenshotsJson.length > 0 ? (
<Image.PreviewGroup>
<Space wrap>
{viewingSubmission.screenshotsJson.map((src, i) => (
<Image
key={i}
src={src}
width={80}
height={80}
style={{ objectFit: 'cover', borderRadius: 4 }}
/>
))}
</Space>
</Image.PreviewGroup>
) : (
<Text type="secondary">无截图</Text>
)}
</Descriptions.Item>
<Descriptions.Item label="审核状态">
{viewingSubmission.status === 'pending_review' ? (
<Tag color="gold">待审核</Tag>
) : viewingSubmission.status === 'approved' ? (
<Tag color="green">已入库</Tag>
) : (
<Tag color="red">已驳回</Tag>
)}
</Descriptions.Item>
<Descriptions.Item label="审核人">
{viewingSubmission.reviewerName || '-'}
</Descriptions.Item>
<Descriptions.Item label="审核备注" span={2}>
{viewingSubmission.reviewNote || '-'}
</Descriptions.Item>
</Descriptions>
) : null}
</Modal>
{/* 链接生成成功提示弹窗 */}
<Modal
title="收集链接生成成功"
open={Boolean(createdLinkUrl)}
onCancel={() => setCreatedLinkUrl('')}
footer={[
<Button
key="copy"
type="primary"
icon={<CopyOutlined />}
onClick={() => {
navigator.clipboard?.writeText(createdLinkUrl)
message.success('链接已复制到剪贴板!')
}}
>
复制公开链接
</Button>,
<Button key="close" onClick={() => setCreatedLinkUrl('')}>
完成
</Button>,
]}
>
<Alert
type="success"
showIcon
message="定向收集链接已就绪"
description="该链接已自动复制到剪贴板。您可以直接发送给玩家卖家,玩家免登录打开即可登记账号与装备信息并上传凭据截图。"
style={{ marginBottom: 16 }}
/>
<div style={{ marginBottom: 8 }}>
<Text strong>公开收集链接:</Text>
</div>
<div
style={{
padding: '12px 16px',
background: '#f6ffed',
border: '1px solid #b7eb8f',
borderRadius: 6,
wordBreak: 'break-all',
}}
>
<Text
copyable={{ text: createdLinkUrl }}
style={{ fontSize: 13, color: '#389e0d', fontWeight: 500 }}
>
{createdLinkUrl}
</Text>
</div>
</Modal>
</div>
)
}