feat(worker-platform): 接单平台工单详情抽屉支持卖家与买家资料一键复制与单项复制
1. 寄售赠送进度卡片右上角新增【一键复制卖家资料】按钮,一键聚合复制卖家角色昵称、游戏ID、区服、系统、联系方式(微信/QQ/手机)、提报/仓库单号及备注; 2. 资料信息卡片右上角新增【一键复制买家资料】按钮,一键复制买家提交的全部表单字段; 3. 卖家资料与买家资料的各项字段值(角色名、数字ID、区服、系统、联系方式、单号等)右侧均补充内联一键复制小图标,支持快捷单项提取。
This commit is contained in:
@@ -1,5 +1,6 @@
|
||||
import {
|
||||
CheckOutlined,
|
||||
CopyOutlined,
|
||||
DeleteOutlined,
|
||||
EditOutlined,
|
||||
FormOutlined,
|
||||
@@ -1295,6 +1296,63 @@ export default function WorkOrdersPanel() {
|
||||
})
|
||||
}
|
||||
|
||||
function copyBuyerMaterialInfo(order: WorkOrder) {
|
||||
const items = getMaterialDetailItems(order).filter((item) => String(item.value || '').trim())
|
||||
if (items.length === 0) {
|
||||
message.warning('当前工单暂无买家资料')
|
||||
return
|
||||
}
|
||||
const lines = items.map((item) => `${item.label}: ${item.value}`)
|
||||
navigator.clipboard
|
||||
.writeText(lines.join('\n'))
|
||||
.then(() => message.success('买家资料已复制到剪贴板'))
|
||||
.catch(() => message.error('复制失败,请手动复制'))
|
||||
}
|
||||
|
||||
function copyConsignmentSellerInfo(order: WorkOrder) {
|
||||
const consignmentInfo = getConsignmentFulfillment(order)
|
||||
const sellerFields = order.gift?.boosterMaterial?.fields || {}
|
||||
const gameNickname = String(
|
||||
sellerFields.gameNickname || consignmentInfo?.buyerName || '',
|
||||
).trim()
|
||||
const gameId = String(sellerFields.gameId || consignmentInfo?.sellerGameId || '').trim()
|
||||
const serverZone = String(sellerFields.serverZone || consignmentInfo?.serverZone || '').trim()
|
||||
const system = String(sellerFields.system || consignmentInfo?.system || '').trim()
|
||||
const sellerContact = String(
|
||||
sellerFields.sellerContact || consignmentInfo?.sellerContact || '',
|
||||
).trim()
|
||||
const sellerPhone = String(
|
||||
sellerFields.sellerPhone || consignmentInfo?.sellerPhone || '',
|
||||
).trim()
|
||||
const sourceSubmissionNo = String(
|
||||
sellerFields.sourceSubmissionNo || consignmentInfo?.sourceSubmissionNo || '',
|
||||
).trim()
|
||||
const inventoryNo = String(
|
||||
sellerFields.inventoryNo || consignmentInfo?.inventoryNo || '',
|
||||
).trim()
|
||||
const note = String(order.gift?.boosterMaterial?.note || consignmentInfo?.remark || '').trim()
|
||||
|
||||
const lines: string[] = []
|
||||
if (gameNickname) lines.push(`卖家角色昵称: ${gameNickname}`)
|
||||
if (gameId) lines.push(`卖家游戏ID: ${gameId}`)
|
||||
if (serverZone) lines.push(`区服: ${serverZone}`)
|
||||
if (system) lines.push(`系统: ${system}`)
|
||||
if (sellerContact) lines.push(`卖家微信/QQ: ${sellerContact}`)
|
||||
if (sellerPhone) lines.push(`卖家手机: ${sellerPhone}`)
|
||||
if (sourceSubmissionNo) lines.push(`提报单号: ${sourceSubmissionNo}`)
|
||||
if (inventoryNo) lines.push(`仓库单号: ${inventoryNo}`)
|
||||
if (note) lines.push(`卖家备注: ${note}`)
|
||||
|
||||
if (lines.length === 0) {
|
||||
message.warning('当前工单暂无可复制的卖家资料')
|
||||
return
|
||||
}
|
||||
navigator.clipboard
|
||||
.writeText(lines.join('\n'))
|
||||
.then(() => message.success('卖家资料已复制到剪贴板'))
|
||||
.catch(() => message.error('复制失败,请手动复制'))
|
||||
}
|
||||
|
||||
const columns: TableColumnsType<WorkOrder> = [
|
||||
{
|
||||
title: '订单',
|
||||
@@ -2093,7 +2151,19 @@ export default function WorkOrdersPanel() {
|
||||
</Descriptions>
|
||||
</Card>
|
||||
|
||||
<Card title="资料信息" size="small">
|
||||
<Card
|
||||
title="资料信息"
|
||||
size="small"
|
||||
extra={
|
||||
<Button
|
||||
size="small"
|
||||
icon={<CopyOutlined />}
|
||||
onClick={() => copyBuyerMaterialInfo(detailOrder)}
|
||||
>
|
||||
一键复制买家资料
|
||||
</Button>
|
||||
}
|
||||
>
|
||||
{renderDetailFieldValues(getMaterialDetailItems(detailOrder), '当前还没有填写资料')}
|
||||
<div style={{ marginTop: 12 }}>
|
||||
<Typography.Text type="secondary">买家主页截图</Typography.Text>
|
||||
@@ -2109,15 +2179,30 @@ export default function WorkOrdersPanel() {
|
||||
isInternalConsignmentOrder(detailOrder) || isConsignmentOrder(detailOrder)
|
||||
const consignmentInfo = getConsignmentFulfillment(detailOrder)
|
||||
const sellerFields = detailOrder.gift.boosterMaterial?.fields || {}
|
||||
const sellerContact =
|
||||
sellerFields.sellerContact || String(consignmentInfo?.sellerContact || '')
|
||||
const sellerPhone =
|
||||
sellerFields.sellerPhone || String(consignmentInfo?.sellerPhone || '')
|
||||
const inventoryNo =
|
||||
sellerFields.inventoryNo || String(consignmentInfo?.inventoryNo || '')
|
||||
const sourceSubmissionNo =
|
||||
sellerFields.sourceSubmissionNo ||
|
||||
String(consignmentInfo?.sourceSubmissionNo || '')
|
||||
const sellerNickname = String(
|
||||
sellerFields.gameNickname || consignmentInfo?.buyerName || '',
|
||||
).trim()
|
||||
const sellerGameId = String(
|
||||
sellerFields.gameId || consignmentInfo?.sellerGameId || '',
|
||||
).trim()
|
||||
const sellerServerZone = String(
|
||||
sellerFields.serverZone || consignmentInfo?.serverZone || '',
|
||||
).trim()
|
||||
const sellerSystem = String(
|
||||
sellerFields.system || consignmentInfo?.system || '',
|
||||
).trim()
|
||||
const sellerContact = String(
|
||||
sellerFields.sellerContact || consignmentInfo?.sellerContact || '',
|
||||
).trim()
|
||||
const sellerPhone = String(
|
||||
sellerFields.sellerPhone || consignmentInfo?.sellerPhone || '',
|
||||
).trim()
|
||||
const inventoryNo = String(
|
||||
sellerFields.inventoryNo || consignmentInfo?.inventoryNo || '',
|
||||
).trim()
|
||||
const sourceSubmissionNo = String(
|
||||
sellerFields.sourceSubmissionNo || consignmentInfo?.sourceSubmissionNo || '',
|
||||
).trim()
|
||||
const effectiveNote = String(
|
||||
detailOrder.gift?.boosterMaterial?.note || consignmentInfo?.remark || '',
|
||||
).trim()
|
||||
@@ -2127,7 +2212,7 @@ export default function WorkOrdersPanel() {
|
||||
title={isConsignment ? '寄售赠送进度' : '好友赠送进度'}
|
||||
size="small"
|
||||
extra={
|
||||
<Space>
|
||||
<Space wrap>
|
||||
{isInternalConsignmentOrder(detailOrder) ? (
|
||||
<Tag color="cyan">内部寄售匹配</Tag>
|
||||
) : isConsignment ? (
|
||||
@@ -2140,6 +2225,15 @@ export default function WorkOrdersPanel() {
|
||||
<Tag color={resolveGiftPhaseColor(detailOrder.gift.phase)}>
|
||||
{formatGiftPhase(detailOrder.gift.phase, isConsignment)}
|
||||
</Tag>
|
||||
{isConsignment ? (
|
||||
<Button
|
||||
size="small"
|
||||
icon={<CopyOutlined />}
|
||||
onClick={() => copyConsignmentSellerInfo(detailOrder)}
|
||||
>
|
||||
一键复制卖家资料
|
||||
</Button>
|
||||
) : null}
|
||||
{detailOrder.capabilities?.canConfirmFriend && canManageProblem ? (
|
||||
<Button
|
||||
type="primary"
|
||||
@@ -2194,55 +2288,110 @@ export default function WorkOrdersPanel() {
|
||||
</Descriptions>
|
||||
<Descriptions column={{ xs: 1, md: 2 }} bordered size="small">
|
||||
<Descriptions.Item label={isConsignment ? '卖家角色昵称' : '游戏昵称'}>
|
||||
<span className="worker-order-detail-value">
|
||||
{String(
|
||||
sellerFields.gameNickname || consignmentInfo?.buyerName || '',
|
||||
).trim() || '-'}
|
||||
</span>
|
||||
{sellerNickname ? (
|
||||
<Space size={6} align="center">
|
||||
<span className="worker-order-detail-value">{sellerNickname}</span>
|
||||
<Typography.Text
|
||||
copyable={{
|
||||
text: sellerNickname,
|
||||
tooltips: ['复制昵称', '已复制'],
|
||||
}}
|
||||
/>
|
||||
</Space>
|
||||
) : (
|
||||
<span className="worker-order-detail-value">-</span>
|
||||
)}
|
||||
</Descriptions.Item>
|
||||
<Descriptions.Item label={isConsignment ? '卖家游戏ID' : '游戏ID'}>
|
||||
<span className="worker-order-detail-value">
|
||||
{String(
|
||||
sellerFields.gameId || consignmentInfo?.sellerGameId || '',
|
||||
).trim() || '-'}
|
||||
</span>
|
||||
{sellerGameId ? (
|
||||
<Space size={6} align="center">
|
||||
<span className="worker-order-detail-value">{sellerGameId}</span>
|
||||
<Typography.Text
|
||||
copyable={{
|
||||
text: sellerGameId,
|
||||
tooltips: ['复制游戏ID', '已复制'],
|
||||
}}
|
||||
/>
|
||||
</Space>
|
||||
) : (
|
||||
<span className="worker-order-detail-value">-</span>
|
||||
)}
|
||||
</Descriptions.Item>
|
||||
<Descriptions.Item label="区服">
|
||||
<span className="worker-order-detail-value">
|
||||
{String(
|
||||
sellerFields.serverZone || consignmentInfo?.serverZone || '',
|
||||
).trim() || '-'}
|
||||
</span>
|
||||
{sellerServerZone ? (
|
||||
<Space size={6} align="center">
|
||||
<span className="worker-order-detail-value">
|
||||
{sellerServerZone}
|
||||
</span>
|
||||
<Typography.Text
|
||||
copyable={{
|
||||
text: sellerServerZone,
|
||||
tooltips: ['复制区服', '已复制'],
|
||||
}}
|
||||
/>
|
||||
</Space>
|
||||
) : (
|
||||
<span className="worker-order-detail-value">-</span>
|
||||
)}
|
||||
</Descriptions.Item>
|
||||
<Descriptions.Item label="系统">
|
||||
<span className="worker-order-detail-value">
|
||||
{String(
|
||||
sellerFields.system || consignmentInfo?.system || '',
|
||||
).trim() || '-'}
|
||||
</span>
|
||||
{sellerSystem ? (
|
||||
<Space size={6} align="center">
|
||||
<span className="worker-order-detail-value">{sellerSystem}</span>
|
||||
<Typography.Text
|
||||
copyable={{
|
||||
text: sellerSystem,
|
||||
tooltips: ['复制系统', '已复制'],
|
||||
}}
|
||||
/>
|
||||
</Space>
|
||||
) : (
|
||||
<span className="worker-order-detail-value">-</span>
|
||||
)}
|
||||
</Descriptions.Item>
|
||||
{isConsignment && (sellerContact || sellerPhone) ? (
|
||||
<Descriptions.Item label="卖家联系方式" span={2}>
|
||||
<span className="worker-order-detail-value">
|
||||
{[
|
||||
sellerContact ? `微信/QQ: ${sellerContact}` : '',
|
||||
sellerPhone ? `手机: ${sellerPhone}` : '',
|
||||
]
|
||||
.filter(Boolean)
|
||||
.join(' / ')}
|
||||
</span>
|
||||
<Space size={6} align="center" wrap>
|
||||
<span className="worker-order-detail-value">
|
||||
{[
|
||||
sellerContact ? `微信/QQ: ${sellerContact}` : '',
|
||||
sellerPhone ? `手机: ${sellerPhone}` : '',
|
||||
]
|
||||
.filter(Boolean)
|
||||
.join(' / ')}
|
||||
</span>
|
||||
<Typography.Text
|
||||
copyable={{
|
||||
text: [
|
||||
sellerContact ? `微信/QQ: ${sellerContact}` : '',
|
||||
sellerPhone ? `手机: ${sellerPhone}` : '',
|
||||
]
|
||||
.filter(Boolean)
|
||||
.join(' '),
|
||||
tooltips: ['复制联系方式', '已复制'],
|
||||
}}
|
||||
/>
|
||||
</Space>
|
||||
</Descriptions.Item>
|
||||
) : null}
|
||||
{isConsignment && (inventoryNo || sourceSubmissionNo) ? (
|
||||
<Descriptions.Item label="寄售单号" span={2}>
|
||||
<span className="worker-order-detail-value">
|
||||
{[
|
||||
sourceSubmissionNo ? `提报单: ${sourceSubmissionNo}` : '',
|
||||
inventoryNo ? `仓库单: ${inventoryNo}` : '',
|
||||
]
|
||||
.filter(Boolean)
|
||||
.join(' / ')}
|
||||
</span>
|
||||
<Space size={6} align="center" wrap>
|
||||
<span className="worker-order-detail-value">
|
||||
{[
|
||||
sourceSubmissionNo ? `提报单: ${sourceSubmissionNo}` : '',
|
||||
inventoryNo ? `仓库单: ${inventoryNo}` : '',
|
||||
]
|
||||
.filter(Boolean)
|
||||
.join(' / ')}
|
||||
</span>
|
||||
<Typography.Text
|
||||
copyable={{
|
||||
text: sourceSubmissionNo || inventoryNo,
|
||||
tooltips: ['复制单号', '已复制'],
|
||||
}}
|
||||
/>
|
||||
</Space>
|
||||
</Descriptions.Item>
|
||||
) : null}
|
||||
<Descriptions.Item
|
||||
|
||||
@@ -84,21 +84,29 @@ export function renderDetailFieldValues(items: DetailFieldItem[], emptyText: str
|
||||
|
||||
return (
|
||||
<Descriptions column={1} bordered size="small">
|
||||
{items.map((item) => (
|
||||
<Descriptions.Item
|
||||
key={item.key}
|
||||
label={
|
||||
<Space size={6} wrap>
|
||||
<span>{item.label}</span>
|
||||
{item.required ? <Tag color="orange">必填</Tag> : null}
|
||||
</Space>
|
||||
}
|
||||
>
|
||||
<span className="worker-order-detail-value">
|
||||
{String(item.value || '').trim() || '-'}
|
||||
</span>
|
||||
</Descriptions.Item>
|
||||
))}
|
||||
{items.map((item) => {
|
||||
const val = String(item.value || '').trim()
|
||||
return (
|
||||
<Descriptions.Item
|
||||
key={item.key}
|
||||
label={
|
||||
<Space size={6} wrap>
|
||||
<span>{item.label}</span>
|
||||
{item.required ? <Tag color="orange">必填</Tag> : null}
|
||||
</Space>
|
||||
}
|
||||
>
|
||||
{val ? (
|
||||
<Space size={6} align="center">
|
||||
<span className="worker-order-detail-value">{val}</span>
|
||||
<Typography.Text copyable={{ text: val, tooltips: ['复制', '已复制'] }} />
|
||||
</Space>
|
||||
) : (
|
||||
<span className="worker-order-detail-value">-</span>
|
||||
)}
|
||||
</Descriptions.Item>
|
||||
)
|
||||
})}
|
||||
</Descriptions>
|
||||
)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user