refactor(collect): 移除旧补资料链接 token 体系
- 删除管理端生成补资料链接接口、链接仓储读写与 TTL 配置服务 - 删除补资料链接配置面板及前端相关服务、类型 - 新增迁移 113:删除 work_order_material_links 表与 work_order_material_link 配置 - 「复制补资料链接」改为本地复制 /supplement/<平台订单号>,不再请求后端
This commit is contained in:
@@ -127,7 +127,7 @@ export default function App() {
|
||||
return <RedeemApplication />
|
||||
}
|
||||
|
||||
// 一次性补资料链接(`/supplement`):路径式公开页,先于站点判断,
|
||||
// 补资料页(`/supplement`):路径式公开页,先于站点判断,
|
||||
// 保证在后台域名和打手端域名下都能打开。带订单号直接进补资料页,不带订单号进输入页。
|
||||
if (isCollectMaterialLinkPath(window.location.pathname)) {
|
||||
return <CollectMaterialLinkApplication />
|
||||
@@ -238,11 +238,11 @@ function ClaimApplication() {
|
||||
}
|
||||
|
||||
/**
|
||||
* 一次性补资料链接(`/supplement`)的独立路由树。
|
||||
* 补资料页(`/supplement`)的独立路由树。
|
||||
*
|
||||
* - `/supplement`:输入平台订单号;
|
||||
* - `/supplement/<订单号>`:直接打开对应订单的补资料页;
|
||||
* - 其余子路径:交给补资料页展示「链接无效」。
|
||||
* - 其余子路径:交给补资料页展示「订单号无效」。
|
||||
*
|
||||
* 路径式公开页,不带 hash;不依赖后台会话。
|
||||
*/
|
||||
|
||||
@@ -32,7 +32,6 @@ import type { WorkerAnnouncementConfig } from '@/types/worker-platform'
|
||||
import { formatAdminDateTime } from '@/utils/admin-time'
|
||||
|
||||
import HallConfigPanel from './HallConfigPanel'
|
||||
import MaterialLinkConfigPanel from './MaterialLinkConfigPanel'
|
||||
|
||||
function isDepositUnfreezeJob(job: AdminScheduledJobItem) {
|
||||
return job.type === 'deposit_unfreeze' || job.id === 'deposit-unfreeze'
|
||||
@@ -45,7 +44,6 @@ export default function AnnouncementPanel() {
|
||||
<DepositUnfreezeCard />
|
||||
<MockCustomShopsCard />
|
||||
<HallConfigPanel />
|
||||
<MaterialLinkConfigPanel />
|
||||
</Space>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -1,74 +0,0 @@
|
||||
import { useQuery, useQueryClient } from '@tanstack/react-query'
|
||||
import { App, Button, Card, Form, InputNumber, Space, Typography } from 'antd'
|
||||
import { useEffect, useState } from 'react'
|
||||
|
||||
import {
|
||||
fetchAdminWorkerMaterialLinkConfig,
|
||||
saveAdminWorkerMaterialLinkConfig,
|
||||
} from '@/services/admin'
|
||||
import type { WorkerMaterialLinkConfig } from '@/types/worker-platform'
|
||||
|
||||
export default function MaterialLinkConfigPanel() {
|
||||
const { message } = App.useApp()
|
||||
const queryClient = useQueryClient()
|
||||
const [form] = Form.useForm<WorkerMaterialLinkConfig>()
|
||||
const [saving, setSaving] = useState(false)
|
||||
|
||||
const configQuery = useQuery({
|
||||
queryKey: ['admin-worker-material-link-config'],
|
||||
queryFn: fetchAdminWorkerMaterialLinkConfig,
|
||||
})
|
||||
const config = configQuery.data?.data
|
||||
|
||||
useEffect(() => {
|
||||
if (config) {
|
||||
form.setFieldsValue({ ttlMinutes: config.ttlMinutes })
|
||||
}
|
||||
}, [config, form])
|
||||
|
||||
async function saveConfig(values: WorkerMaterialLinkConfig) {
|
||||
setSaving(true)
|
||||
try {
|
||||
await saveAdminWorkerMaterialLinkConfig({ ttlMinutes: Number(values.ttlMinutes) })
|
||||
await queryClient.invalidateQueries({ queryKey: ['admin-worker-material-link-config'] })
|
||||
message.success('补资料链接配置已保存')
|
||||
} catch (error) {
|
||||
message.error(error instanceof Error ? error.message : '保存补资料链接配置失败')
|
||||
} finally {
|
||||
setSaving(false)
|
||||
}
|
||||
}
|
||||
|
||||
return (
|
||||
<Card title="补资料链接" bordered={false} loading={configQuery.isLoading}>
|
||||
<Space direction="vertical" size="middle" style={{ width: '100%', maxWidth: 700 }}>
|
||||
<Typography.Paragraph type="secondary" style={{ marginBottom: 0 }}>
|
||||
客服在「接单工单」复制的一次性补资料链接,客户只能修改补资料内容;提交成功后工单转为「未分配」,
|
||||
链接立即失效,需要重新发送。修改有效期只影响新生成的链接。
|
||||
</Typography.Paragraph>
|
||||
<Form form={form} layout="vertical" onFinish={saveConfig}>
|
||||
<Form.Item
|
||||
name="ttlMinutes"
|
||||
label="链接有效期(分钟)"
|
||||
extra="默认 30 分钟,可设置 1 - 10080 分钟(7 天)。"
|
||||
rules={[{ required: true, message: '请输入链接有效期' }]}
|
||||
style={{ marginBottom: 12 }}
|
||||
>
|
||||
<InputNumber
|
||||
min={1}
|
||||
max={10080}
|
||||
precision={0}
|
||||
style={{ width: 220 }}
|
||||
addonAfter="分钟"
|
||||
/>
|
||||
</Form.Item>
|
||||
<Form.Item style={{ marginBottom: 0 }}>
|
||||
<Button type="primary" htmlType="submit" loading={saving}>
|
||||
保存配置
|
||||
</Button>
|
||||
</Form.Item>
|
||||
</Form>
|
||||
</Space>
|
||||
</Card>
|
||||
)
|
||||
}
|
||||
@@ -60,7 +60,6 @@ import {
|
||||
cancelAdminWorkOrderSharingPart,
|
||||
completeAdminWorkOrderGiftCooldown,
|
||||
confirmAdminWorkOrderFriend,
|
||||
createAdminWorkOrderMaterialLink,
|
||||
deductAdminWorkOrderPendingDeposit,
|
||||
deleteAdminWorkOrder,
|
||||
disposeAdminWorkOrderShareProblem,
|
||||
@@ -205,7 +204,7 @@ function getConsignmentFulfillment(row: WorkOrder): ConsignmentFulfillmentInfo |
|
||||
return Object.keys(consignment).length > 0 ? (consignment as ConsignmentFulfillmentInfo) : null
|
||||
}
|
||||
|
||||
/** 公开补资料链接只在「待完善 / 待分配」且有平台订单号时生成;已进大厅或已接单不允许客户改资料。 */
|
||||
/** 补资料链接按平台订单号打开;只有待完善 / 待分配且存在平台订单号时才展示复制入口。 */
|
||||
function canCopyMaterialLink(order: WorkOrder): boolean {
|
||||
const status = String(order.rawStatus || order.status || '')
|
||||
const platformOrderId = String(order.platformOrderId || '').trim()
|
||||
@@ -354,11 +353,7 @@ export default function WorkOrdersPanel() {
|
||||
const [materialOrder, setMaterialOrder] = useState<WorkOrder | null>(null)
|
||||
const [materialScreenshots, setMaterialScreenshots] = useState<UploadedFile[]>([])
|
||||
const [materialPasteText, setMaterialPasteText] = useState('')
|
||||
const [materialLinkLoadingId, setMaterialLinkLoadingId] = useState<number | null>(null)
|
||||
const [materialLinkFallback, setMaterialLinkFallback] = useState<{
|
||||
url: string
|
||||
expiresAt: string
|
||||
} | null>(null)
|
||||
const [materialLinkFallback, setMaterialLinkFallback] = useState<{ url: string } | null>(null)
|
||||
const [sharingOrder, setSharingOrder] = useState<WorkOrder | null>(null)
|
||||
const [cancelShare, setCancelShare] = useState<WorkOrderShare | null>(null)
|
||||
const [reduceShare, setReduceShare] = useState<WorkOrderShare | null>(null)
|
||||
@@ -1654,36 +1649,23 @@ export default function WorkOrdersPanel() {
|
||||
}
|
||||
|
||||
async function copyMaterialLink(order: WorkOrder) {
|
||||
setMaterialLinkLoadingId(order.workOrderId)
|
||||
try {
|
||||
const response = await createAdminWorkOrderMaterialLink(order.workOrderId)
|
||||
// 新后端返回 platformOrderId;旧后端缺失时回退 token,仅用于前后端滚动发布。
|
||||
const platformOrderId = String(
|
||||
response.data.platformOrderId || response.data.token || '',
|
||||
).trim()
|
||||
if (!platformOrderId) {
|
||||
message.error('生成补资料链接失败:缺少平台订单号')
|
||||
return
|
||||
}
|
||||
const url = buildCollectMaterialLinkUrl(window.location.origin, platformOrderId)
|
||||
if (!url) {
|
||||
message.error('生成补资料链接失败:链接地址为空')
|
||||
return
|
||||
}
|
||||
const copied = await copyTextToClipboard(url)
|
||||
const expiresText = formatAdminDateTime(response.data.expiresAt)
|
||||
if (copied) {
|
||||
message.success(
|
||||
`${response.data.reused ? '已复制现有链接' : '已生成并复制链接'}(订单号 ${platformOrderId}),${expiresText} 前有效;该订单号下已生成链接的待补商品会一起显示`,
|
||||
)
|
||||
} else {
|
||||
setMaterialLinkFallback({ url, expiresAt: response.data.expiresAt })
|
||||
}
|
||||
} catch (error) {
|
||||
message.error(error instanceof Error ? error.message : '生成补资料链接失败')
|
||||
} finally {
|
||||
setMaterialLinkLoadingId(null)
|
||||
const platformOrderId = String(order.platformOrderId || '').trim()
|
||||
if (!platformOrderId) {
|
||||
message.error('复制补资料链接失败:缺少平台订单号')
|
||||
return
|
||||
}
|
||||
const url = buildCollectMaterialLinkUrl(window.location.origin, platformOrderId)
|
||||
if (!url) {
|
||||
message.error('复制补资料链接失败:链接地址为空')
|
||||
return
|
||||
}
|
||||
const copied = await copyTextToClipboard(url)
|
||||
if (copied) {
|
||||
message.success(`补资料链接已复制(订单号 ${platformOrderId})`)
|
||||
return
|
||||
}
|
||||
// 剪贴板 API 不可用时退回弹窗,让客服手动复制。
|
||||
setMaterialLinkFallback({ url })
|
||||
}
|
||||
|
||||
const columns: TableColumnsType<WorkOrder> = [
|
||||
@@ -1998,9 +1980,8 @@ export default function WorkOrdersPanel() {
|
||||
{row.capabilities?.canUpdateMaterial && canUpdateMaterial && canCopyMaterialLink(row) ? (
|
||||
<Button
|
||||
icon={<LinkOutlined />}
|
||||
loading={materialLinkLoadingId === row.workOrderId}
|
||||
onClick={() => void copyMaterialLink(row)}
|
||||
title="生成一次性补资料链接(按平台订单号打开;有效期内每个工单仅可提交一次)"
|
||||
title="复制补资料链接(按平台订单号打开)"
|
||||
>
|
||||
复制补资料链接
|
||||
</Button>
|
||||
@@ -3291,8 +3272,7 @@ export default function WorkOrdersPanel() {
|
||||
{materialLinkFallback ? (
|
||||
<Space direction="vertical" size={10} style={{ width: '100%' }}>
|
||||
<Typography.Text type="secondary">
|
||||
同一订单号下已生成链接的多个待补工单会显示在同一个页面,每个工单各自仅可提交一次;
|
||||
{formatAdminDateTime(materialLinkFallback.expiresAt)} 前有效。
|
||||
该链接按平台订单号打开,可查看该订单号下全部工单的补资料状态;每个工单仅可提交一次。
|
||||
</Typography.Text>
|
||||
<Input.TextArea
|
||||
value={materialLinkFallback.url}
|
||||
|
||||
@@ -15,7 +15,6 @@ import type {
|
||||
WorkerDepositUnfreeze,
|
||||
WorkerFinanceConfig,
|
||||
WorkerHallConfig,
|
||||
WorkerMaterialLinkConfig,
|
||||
WorkerRiskConfig,
|
||||
WorkerRiskOverview,
|
||||
WorkerRiskEventList,
|
||||
@@ -102,17 +101,6 @@ export function saveAdminWorkerHallConfig(
|
||||
return apiPost<WorkerHallConfig>('/api/v1/admin/worker-platform/hall-config', payload)
|
||||
}
|
||||
|
||||
export function fetchAdminWorkerMaterialLinkConfig() {
|
||||
return apiGet<WorkerMaterialLinkConfig>('/api/v1/admin/worker-platform/material-link-config')
|
||||
}
|
||||
|
||||
export function saveAdminWorkerMaterialLinkConfig(payload: WorkerMaterialLinkConfig) {
|
||||
return apiPost<WorkerMaterialLinkConfig>(
|
||||
'/api/v1/admin/worker-platform/material-link-config',
|
||||
payload,
|
||||
)
|
||||
}
|
||||
|
||||
export function fetchAdminWorkerAnnouncement() {
|
||||
return apiGet<WorkerAnnouncementConfig>('/api/v1/admin/worker-platform/announcement')
|
||||
}
|
||||
@@ -769,16 +757,6 @@ export function submitAdminWorkOrderMaterial(
|
||||
)
|
||||
}
|
||||
|
||||
export function createAdminWorkOrderMaterialLink(workOrderId: number) {
|
||||
return apiPost<{
|
||||
token: string
|
||||
/** 公开 URL 使用的平台订单号;旧后端可能没有该字段,前端仅用于滚动发布兜底。 */
|
||||
platformOrderId?: string
|
||||
expiresAt: string
|
||||
reused: boolean
|
||||
}>(`/api/v1/admin/worker-platform/orders/${workOrderId}/material-link`)
|
||||
}
|
||||
|
||||
/** 客服重置补资料:仅「待分配 + 未指派 + 无份额 + 未发布」可重置回待完善。 */
|
||||
export function resetAdminWorkOrderMaterialStatus(workOrderId: number) {
|
||||
return apiPost<{ order: WorkOrder }>(
|
||||
|
||||
@@ -334,11 +334,6 @@ export type WorkerHallConfig = {
|
||||
queuedOrderCount: number
|
||||
}
|
||||
|
||||
/** 一次性补资料链接配置:有效期只影响新生成的链接。 */
|
||||
export type WorkerMaterialLinkConfig = {
|
||||
ttlMinutes: number
|
||||
}
|
||||
|
||||
export type WorkerWithdrawalAccount = {
|
||||
accountChannel: string
|
||||
accountName: string
|
||||
|
||||
Reference in New Issue
Block a user