优化:补充半自动履约开发 Mock 与内置 Connector

This commit is contained in:
yml2213
2026-11-09 16:02:52 +08:00
parent cb9538a775
commit b0b8e983ba
12 changed files with 1188 additions and 8 deletions
@@ -8,6 +8,7 @@ import {
Divider,
Form,
Input,
InputNumber,
Result,
Row,
Select,
@@ -23,10 +24,12 @@ import {
buildOpen91QueryDevMock,
createAffiliateDashDevMock,
createKuaishouIndustryVoucherDevMock,
createSemiAutoDevMock,
fetchDevMockStatus,
type DevMockCreateResult,
type DevMockKuaishouIndustryVoucherResult,
type DevMockOpen91QueryResult,
type DevMockSemiAutoResult,
} from '@/services/admin'
export default function AdminDevMockPage() {
@@ -35,6 +38,7 @@ export default function AdminDevMockPage() {
const [lastVoucherCreate, setLastVoucherCreate] =
useState<DevMockKuaishouIndustryVoucherResult | null>(null)
const [lastQuery, setLastQuery] = useState<DevMockOpen91QueryResult | null>(null)
const [lastSemiAuto, setLastSemiAuto] = useState<DevMockSemiAutoResult | null>(null)
const statusQuery = useQuery({
queryKey: ['admin-dev-mock-status'],
@@ -78,6 +82,17 @@ export default function AdminDevMockPage() {
},
})
const semiAutoMutation = useMutation({
mutationFn: createSemiAutoDevMock,
onSuccess: (response) => {
setLastSemiAuto(response.data)
message.success('半自动履约 Mock 已生成')
},
onError: (error) => {
message.error(error instanceof Error ? error.message : '生成失败')
},
})
const defaultOrderNo = useMemo(() => lastCreate?.orderNo || '', [lastCreate?.orderNo])
if (statusQuery.isLoading) {
@@ -134,7 +149,17 @@ export default function AdminDevMockPage() {
</Col>
<Col xs={24} xl={12}>
<Card title="2. 快手电子凭证测试数据" bordered={false}>
<Card title="2. 半自动履约测试单(Mock Connector)" bordered={false}>
<SemiAutoMockForm
loading={semiAutoMutation.isPending}
connectorMode={status?.semiAuto?.connectorMode}
onSubmit={(values) => semiAutoMutation.mutate(values)}
/>
</Card>
</Col>
<Col xs={24} xl={12}>
<Card title="3. 快手电子凭证测试数据" bordered={false}>
<KuaishouIndustryVoucherMockForm
loading={voucherMutation.isPending}
onSubmit={(values) => voucherMutation.mutate(values)}
@@ -143,7 +168,7 @@ export default function AdminDevMockPage() {
</Col>
<Col xs={24}>
<Card title="3. 模拟 91 查单(open-91/query)" bordered={false}>
<Card title="4. 模拟 91 查单(open-91/query)" bordered={false}>
<Form
layout="inline"
initialValues={{ orderNo: defaultOrderNo, execute: '1' }}
@@ -260,6 +285,81 @@ export default function AdminDevMockPage() {
</Card>
) : null}
{lastSemiAuto ? (
<Card
title="最近生成的半自动履约 Mock"
extra={<Link to={lastSemiAuto.adminPath}>打开后台任务</Link>}
>
<Row gutter={[16, 12]}>
<Col xs={24} md={12}>
<Typography.Text type="secondary">订单号</Typography.Text>
<div>
<Typography.Text copyable strong>
{lastSemiAuto.orderNo}
</Typography.Text>
</div>
</Col>
<Col xs={24} md={12}>
<Typography.Text type="secondary">内部 SKU / 任务</Typography.Text>
<div>
{lastSemiAuto.skuKey} · 任务 #{lastSemiAuto.taskId}
</div>
</Col>
<Col span={24}>
<Typography.Text type="secondary">客户履约入口</Typography.Text>
<div>
<Typography.Link
href={`${window.location.origin}${lastSemiAuto.customerPath}`}
target="_blank"
rel="noreferrer"
>
<LinkOutlined /> {window.location.origin}
{lastSemiAuto.customerPath}
</Typography.Link>
</div>
<Space style={{ marginTop: 8 }} wrap>
<Button
icon={<CopyOutlined />}
onClick={async () => {
await navigator.clipboard.writeText(
`${window.location.origin}${lastSemiAuto.customerPath}`,
)
message.success('已复制客户履约链接')
}}
>
复制客户链接
</Button>
<Button
type="primary"
href={`${window.location.origin}${lastSemiAuto.customerPath}`}
target="_blank"
>
打开客户页
</Button>
</Space>
</Col>
<Col span={24}>
<Alert
type={lastSemiAuto.connectorMode === 'mock' ? 'success' : 'warning'}
showIcon
message={
lastSemiAuto.connectorMode === 'mock'
? '当前使用内置 Mock Connector'
: '当前使用外部 Connector'
}
description={
<ul style={{ margin: 0, paddingLeft: 18 }}>
{lastSemiAuto.tips.map((tip) => (
<li key={tip}>{tip}</li>
))}
</ul>
}
/>
</Col>
</Row>
</Card>
) : null}
{lastVoucherCreate ? (
<Card
title="最近生成的电子凭证 Mock"
@@ -400,3 +500,72 @@ function KuaishouIndustryVoucherMockForm({
</Form>
)
}
function SemiAutoMockForm({
loading,
connectorMode,
onSubmit,
}: {
loading: boolean
connectorMode?: 'mock' | 'external'
onSubmit: (values: {
orderNo?: string
skuName?: string
quantity?: number
pageTitle?: string
browserTargetUrl?: string
}) => void
}) {
return (
<Form
layout="vertical"
initialValues={{
quantity: 1,
pageTitle: '虎牙账号授权测试',
browserTargetUrl: 'https://www.huya.com/',
}}
onFinish={onSubmit}
>
<Form.Item
label="内部 SKU 名称(可空)"
name="skuName"
extra="留空自动生成“虎牙半自动测试-时间戳”;必须包含中文。"
>
<Input allowClear placeholder="虎牙半自动测试" />
</Form.Item>
<Form.Item label="订单号 orderNo(可空)" name="orderNo">
<Input allowClear placeholder="留空自动 MOCKSA…" />
</Form.Item>
<Space size={12} style={{ display: 'flex' }}>
<Form.Item label="数量" name="quantity" style={{ flex: 1 }}>
<InputNumber min={1} max={10} style={{ width: '100%' }} />
</Form.Item>
<Form.Item label="客户页标题" name="pageTitle" style={{ flex: 2 }}>
<Input />
</Form.Item>
</Space>
<Form.Item
label="客服浏览器目标页"
name="browserTargetUrl"
extra="客服点击“打开浏览器登录态”时,扩展会注入到此页面。"
>
<Input placeholder="https://www.huya.com/" />
</Form.Item>
<Alert
type={connectorMode === 'mock' ? 'success' : 'warning'}
showIcon
style={{ marginBottom: 12 }}
message={
connectorMode === 'mock'
? '内置 Mock Connector 已启用,登录和绑定会自动推进。'
: connectorMode === 'external'
? '当前配置为外部 Connector,请先确认外部服务已启动。'
: 'Connector 状态未知;生成后可在客户页验证。'
}
/>
<Button type="primary" htmlType="submit" loading={loading} block>
生成半自动履约 Mock
</Button>
</Form>
)
}
@@ -10,6 +10,11 @@ export type DevMockStatus = {
description: string
steps: string[]
}>
semiAuto?: {
connectorMode: 'mock' | 'external'
connectorConfigured: boolean
platform: string
}
}
export type DevMockCreateResult = {
@@ -45,6 +50,21 @@ export type DevMockKuaishouIndustryVoucherResult = {
}>
}
export type DevMockSemiAutoResult = {
platform: 'semi_auto'
orderId: number
orderNo: string
orderItemId: number
fulfillmentId: number
configId: number
taskId: number
skuKey: string
connectorMode: 'mock' | 'external'
customerPath: string
adminPath: string
tips: string[]
}
export function fetchDevMockStatus() {
return apiGet<DevMockStatus>('/api/v1/admin/dev-mock/status')
}
@@ -66,6 +86,17 @@ export function createKuaishouIndustryVoucherDevMock(payload: { sellerId?: strin
)
}
export function createSemiAutoDevMock(payload: {
orderNo?: string
skuName?: string
quantity?: number
pageTitle?: string
pageDescription?: string
browserTargetUrl?: string
}) {
return apiPost<DevMockSemiAutoResult>('/api/v1/admin/dev-mock/semi-auto', payload)
}
export function buildOpen91QueryDevMock(payload: {
orderNo: string
execute?: boolean