优化操作区域

This commit is contained in:
yml2213
2026-07-23 11:44:36 +08:00
parent d7f9918d06
commit 66ef033b47
2 changed files with 364 additions and 96 deletions
@@ -120,6 +120,8 @@ export default function AdminKuaishouIndustryPage() {
const [actionLoading, setActionLoading] = useState('')
const [consumingVoucherId, setConsumingVoucherId] = useState<number | null>(null)
const [vouchers, setVouchers] = useState<AdminKuaishouIndustryVoucher[]>([])
const [selectedVoucher, setSelectedVoucher] =
useState<AdminKuaishouIndustryVoucher | null>(null)
const [voucherTotal, setVoucherTotal] = useState(0)
const [voucherFilters, setVoucherFilters] = useState<VoucherFilterState>({
oid: '',
@@ -341,15 +343,21 @@ export default function AdminKuaishouIndustryPage() {
)
}
const isSelected = selectedVoucher?.id === row.id
return (
<Button size="small" type="primary" ghost onClick={() => selectVoucher(row)}>
<Button
size="small"
type="primary"
ghost={!isSelected}
onClick={() => selectVoucher(row)}
>
{isSelected ? '已选' : '选择'}
</Button>
)
},
},
],
[consumingVoucherId, isSupportOnly, shopNameBySellerId],
[consumingVoucherId, isSupportOnly, selectedVoucher?.id, shopNameBySellerId],
)
const refundColumns = useMemo<TableColumnsType<Record<string, unknown>>>(
@@ -425,7 +433,14 @@ export default function AdminKuaishouIndustryPage() {
page: filters.page,
pageSize: filters.pageSize,
})
setVouchers(response.data.items)
const items = response.data.items
setVouchers(items)
setSelectedVoucher((current) => {
if (!current) {
return null
}
return items.find((item) => item.id === current.id) || current
})
setVoucherTotal(response.data.pagination.total)
} catch (error) {
showError(error instanceof Error ? error.message : '查询电子凭证失败')
@@ -435,18 +450,8 @@ export default function AdminKuaishouIndustryPage() {
}
function selectVoucher(row: AdminKuaishouIndustryVoucher) {
setToolForm((current) => ({
...current,
sellerId: row.sellerId,
oid: row.oid,
orderId: row.oid,
taskId: row.taskId || '',
voucherCode: row.voucherCode,
eticketType: row.eticketType || current.eticketType || '',
serialNum: row.consumeSerialNum || current.serialNum,
reason: current.reason || 'USER_APPLY_REFUND',
}))
showSuccess('已填入券码操作区')
setSelectedVoucher(row)
showSuccess(`已选择券码 ${row.voucherCode}`)
}
async function runCheckAvailable() {
@@ -688,9 +693,17 @@ export default function AdminKuaishouIndustryPage() {
}
function buildVoucherToolPayload(): AdminKuaishouIndustryVoucherToolPayload {
const voucherCode = String(toolForm.voucherCode || '').trim()
const voucherCode = String(selectedVoucher?.voucherCode || toolForm.voucherCode || '').trim()
const oid = String(selectedVoucher?.oid || toolForm.oid || toolForm.orderId || '').trim()
return {
...toolForm,
sellerId: selectedVoucher?.sellerId || toolForm.sellerId,
oid,
orderId: oid,
taskId: selectedVoucher?.taskId || toolForm.taskId,
voucherCode,
eticketType: selectedVoucher?.eticketType || toolForm.eticketType,
serialNum: toolForm.serialNum || selectedVoucher?.consumeSerialNum,
etickets: voucherCode ? [{ id: voucherCode, code: voucherCode, num: 1 }] : undefined,
}
}
@@ -878,6 +891,9 @@ export default function AdminKuaishouIndustryPage() {
columns={columns}
dataSource={vouchers}
loading={voucherLoading}
rowClassName={(row) =>
selectedVoucher?.id === row.id ? 'kuaishou-industry-row-selected' : ''
}
// 列已压缩;仅在极窄容器时横向滚动
scroll={{ x: scrollX || 1064 }}
pagination={buildAdminTablePagination({
@@ -900,6 +916,18 @@ export default function AdminKuaishouIndustryPage() {
}
function renderVoucherTab() {
const hasVoucherTarget = Boolean(
selectedVoucher ||
String(toolForm.voucherCode || '').trim() ||
String(toolForm.taskId || '').trim() ||
String(toolForm.oid || toolForm.orderId || '').trim(),
)
const selectedShopName = selectedVoucher
? selectedVoucher.shopName ||
shopNameBySellerId.get(String(selectedVoucher.sellerId || '').trim()) ||
'未命名店铺'
: ''
return (
<div className="page-stack">
{renderVoucherFilters()}
@@ -909,84 +937,200 @@ export default function AdminKuaishouIndustryPage() {
{renderVoucherTable(1064)}
</Card>
<Card title="接口操作">
<div className="kuaishou-industry-tool-grid">
<Input
placeholder="店铺 ID"
value={toolForm.sellerId}
onChange={(event) => updateToolForm({ sellerId: event.target.value })}
/>
<Input
placeholder="订单号 oid"
value={toolForm.oid}
onChange={(event) =>
updateToolForm({
oid: event.target.value,
orderId: event.target.value,
})
}
/>
<Input
placeholder="任务 ID"
value={String(toolForm.taskId || '')}
onChange={(event) => updateToolForm({ taskId: event.target.value })}
/>
<Input
placeholder="券码"
value={toolForm.voucherCode}
onChange={(event) => updateToolForm({ voucherCode: event.target.value })}
/>
<Input
placeholder="电子凭证类型(选中券码自动填入)"
value={toolForm.eticketType}
onChange={(event) => updateToolForm({ eticketType: event.target.value })}
/>
<Input
placeholder="核销序列号"
value={toolForm.serialNum}
onChange={(event) => updateToolForm({ serialNum: event.target.value })}
/>
<Input
placeholder="核销类型"
value={toolForm.consumeType}
onChange={(event) => updateToolForm({ consumeType: event.target.value })}
/>
<Select
allowClear
placeholder="销毁/冲正原因"
value={toolForm.reason || undefined}
onChange={(value) => updateToolForm({ reason: value || '' })}
options={[
{ label: 'USER_APPLY_REFUND(用户退款)', value: 'USER_APPLY_REFUND' },
{ label: 'SYS_ADMIN_DESTROY(后台作废)', value: 'SYS_ADMIN_DESTROY' },
{ label: 'SUPPLY_DESTROY(供应商作废)', value: 'SUPPLY_DESTROY' },
{ label: 'ETICKET_EXPIRED(凭证过期)', value: 'ETICKET_EXPIRED' },
]}
style={{ minWidth: 220 }}
/>
<Input
placeholder="门店名称"
value={toolForm.storeName}
onChange={(event) => updateToolForm({ storeName: event.target.value })}
/>
<Input
placeholder="门店地址"
value={toolForm.storeAddress}
onChange={(event) => updateToolForm({ storeAddress: event.target.value })}
/>
<Card title="券码操作" className="kuaishou-industry-tool-card">
<div className="kuaishou-industry-tool-section">
<div className="kuaishou-industry-tool-section-title"></div>
{selectedVoucher ? (
<div className="kuaishou-industry-selected-voucher">
<div className="kuaishou-industry-selected-header">
<Typography.Text
strong
copyable={{ text: selectedVoucher.voucherCode }}
className="kuaishou-industry-selected-code"
>
{selectedVoucher.voucherCode}
</Typography.Text>
<Space size={4}>
<Tag color={getVoucherStatusColor(selectedVoucher.status)}>
{getVoucherStatusLabel(selectedVoucher.status)}
</Tag>
<Button type="link" size="small" onClick={() => setSelectedVoucher(null)}>
</Button>
</Space>
</div>
<div className="kuaishou-industry-selected-meta">
<div>
<span></span>
<Typography.Text copyable={{ text: selectedVoucher.oid }}>
{selectedVoucher.oid || '-'}
</Typography.Text>
</div>
<div>
<span></span>
<strong>{selectedVoucher.taskNo || selectedVoucher.taskId || '-'}</strong>
</div>
<div>
<span></span>
<strong>{selectedShopName}</strong>
<small>{selectedVoucher.sellerId || '-'}</small>
</div>
<div>
<span></span>
<strong title={selectedVoucher.eticketType || undefined}>
{selectedVoucher.eticketType || '-'}
</strong>
</div>
</div>
</div>
) : (
<div className="kuaishou-industry-selected-empty">
<strong></strong>
<span></span>
</div>
)}
</div>
<Space wrap className="kuaishou-industry-actions">
<div className="kuaishou-industry-tool-section">
<div className="kuaishou-industry-tool-section-title"></div>
<div className="kuaishou-industry-tool-grid">
<label className="kuaishou-industry-tool-field">
<span></span>
<Input
placeholder="consume"
value={toolForm.consumeType}
onChange={(event) => updateToolForm({ consumeType: event.target.value })}
/>
</label>
<label className="kuaishou-industry-tool-field">
<span></span>
<Input
placeholder={selectedVoucher?.consumeSerialNum || '默认使用卡券记录'}
value={toolForm.serialNum}
onChange={(event) => updateToolForm({ serialNum: event.target.value })}
/>
</label>
<label className="kuaishou-industry-tool-field kuaishou-industry-tool-field-wide">
<span></span>
<Select
value={toolForm.reason || undefined}
onChange={(value) => updateToolForm({ reason: value || '' })}
options={[
{ label: '用户申请退款', value: 'USER_APPLY_REFUND' },
{ label: '后台作废', value: 'SYS_ADMIN_DESTROY' },
{ label: '供应商作废', value: 'SUPPLY_DESTROY' },
{ label: '凭证过期', value: 'ETICKET_EXPIRED' },
]}
/>
</label>
<label className="kuaishou-industry-tool-field">
<span></span>
<Input
placeholder="用于核销明细"
value={toolForm.storeName}
onChange={(event) => updateToolForm({ storeName: event.target.value })}
/>
</label>
<label className="kuaishou-industry-tool-field">
<span></span>
<Input
placeholder="用于核销明细"
value={toolForm.storeAddress}
onChange={(event) => updateToolForm({ storeAddress: event.target.value })}
/>
</label>
</div>
</div>
<Collapse
ghost
size="small"
className="kuaishou-industry-manual-target"
items={[
{
key: 'manual-target',
label: selectedVoucher
? '手动指定卡券(清除当前选择后可用)'
: '手动指定卡券',
children: (
<div className="kuaishou-industry-tool-grid">
<label className="kuaishou-industry-tool-field">
<span> ID</span>
<Input
disabled={Boolean(selectedVoucher)}
value={toolForm.sellerId}
onChange={(event) => updateToolForm({ sellerId: event.target.value })}
/>
</label>
<label className="kuaishou-industry-tool-field">
<span> oid</span>
<Input
disabled={Boolean(selectedVoucher)}
value={toolForm.oid}
onChange={(event) =>
updateToolForm({
oid: event.target.value,
orderId: event.target.value,
})
}
/>
</label>
<label className="kuaishou-industry-tool-field">
<span> ID</span>
<Input
disabled={Boolean(selectedVoucher)}
value={String(toolForm.taskId || '')}
onChange={(event) => updateToolForm({ taskId: event.target.value })}
/>
</label>
<label className="kuaishou-industry-tool-field">
<span></span>
<Input
disabled={Boolean(selectedVoucher)}
value={toolForm.voucherCode}
onChange={(event) =>
updateToolForm({ voucherCode: event.target.value })
}
/>
</label>
<label className="kuaishou-industry-tool-field kuaishou-industry-tool-field-wide">
<span></span>
<Input
disabled={Boolean(selectedVoucher)}
value={toolForm.eticketType}
onChange={(event) =>
updateToolForm({ eticketType: event.target.value })
}
/>
</label>
</div>
),
},
]}
/>
<div className="kuaishou-industry-actions">
<Button
icon={<SyncOutlined />}
loading={actionLoading === 'check'}
disabled={!hasVoucherTarget}
onClick={runCheckAvailable}
>
</Button>
<Button
icon={<SendOutlined />}
loading={actionLoading === 'resend'}
disabled={!hasVoucherTarget}
onClick={runResendCode}
>
</Button>
<Button
type="primary"
icon={<CheckCircleOutlined />}
loading={actionLoading === 'consume'}
disabled={!hasVoucherTarget}
onClick={runConsume}
>
@@ -995,6 +1139,7 @@ export default function AdminKuaishouIndustryPage() {
danger
icon={<RollbackOutlined />}
loading={actionLoading === 'reverse'}
disabled={!hasVoucherTarget}
onClick={runReverse}
>
@@ -1004,6 +1149,7 @@ export default function AdminKuaishouIndustryPage() {
description="将向快手发起销毁回调,并关闭关联任务。已销毁券会重试回调。"
okText="销毁"
cancelText="取消"
disabled={!canManageRefund || !hasVoucherTarget}
onConfirm={() => runDestroy()}
>
<Button
@@ -1011,19 +1157,12 @@ export default function AdminKuaishouIndustryPage() {
type="primary"
icon={<DeleteOutlined />}
loading={actionLoading === 'destroy'}
disabled={!canManageRefund}
disabled={!canManageRefund || !hasVoucherTarget}
>
</Button>
</Popconfirm>
<Button
icon={<SendOutlined />}
loading={actionLoading === 'resend'}
onClick={runResendCode}
>
</Button>
</Space>
</div>
{renderInlineActionResult('vouchers')}
</Card>
</div>