实现内置虎牙扫码登录与绑定 Connector

This commit is contained in:
yml2213
2026-11-09 17:11:01 +08:00
parent b0b8e983ba
commit a9937ef8c6
41 changed files with 4246 additions and 152 deletions
@@ -124,7 +124,7 @@ export default function AdminDevMockPage() {
<section className="page-stack">
<PageHeader
title="开发 Mock"
description="一键造单、测领取页与 91 查单,无需真实 91 / affiliate-dash 环境。"
description="一键造单与测试数据;半自动履约可选择只 Mock 订单,登录、绑定走真实 Connector。"
extra={
<Typography.Text type="secondary">NODE_ENV={status?.nodeEnv || '-'}</Typography.Text>
}
@@ -134,8 +134,8 @@ export default function AdminDevMockPage() {
type="info"
showIcon
icon={<BugOutlined />}
message="Mock 会写入开发库真实订单/任务;当前仅保留 affiliate-dash / 电子凭证 / 91 查单。"
description="affiliate-dash 可用默认 UID 测试绑定与提交发货。"
message="Mock 会写入开发库真实订单/任务;除订单外,登录、绑定、票据注入和完成确认都可以走真实流程。"
description="默认使用 order_site 内置真实 Connector,不依赖 live-hub-py;只有显式选择内置 Mock 时才会 Mock 登录和绑定。"
/>
<Row gutter={[16, 16]}>
@@ -149,10 +149,12 @@ export default function AdminDevMockPage() {
</Col>
<Col xs={24} xl={12}>
<Card title="2. 半自动履约测试单(Mock Connector)" bordered={false}>
<Card title="2. 半自动履约测试单(可选 Mock 范围)" bordered={false}>
<SemiAutoMockForm
loading={semiAutoMutation.isPending}
connectorMode={status?.semiAuto?.connectorMode}
defaultConnectorMode={status?.semiAuto?.defaultConnectorMode}
externalConnectorConfigured={status?.semiAuto?.externalConnectorConfigured}
mockConnectorAvailable={status?.semiAuto?.mockConnectorAvailable}
onSubmit={(values) => semiAutoMutation.mutate(values)}
/>
</Card>
@@ -340,12 +342,22 @@ export default function AdminDevMockPage() {
</Col>
<Col span={24}>
<Alert
type={lastSemiAuto.connectorMode === 'mock' ? 'success' : 'warning'}
type={
lastSemiAuto.connectorMode === 'mock'
? 'warning'
: lastSemiAuto.connectorConfigured
? 'success'
: 'error'
}
showIcon
message={
lastSemiAuto.connectorMode === 'mock'
? '当前使用内置 Mock Connector'
: '当前使用外部 Connector'
: lastSemiAuto.connectorConfigured
? lastSemiAuto.connectorMode === 'external'
? '当前使用远程真实 Connector'
: '当前使用 order_site 内置真实 Connector'
: '当前选择远程真实 Connector,但尚未配置'
}
description={
<ul style={{ margin: 0, paddingLeft: 18 }}>
@@ -503,29 +515,70 @@ function KuaishouIndustryVoucherMockForm({
function SemiAutoMockForm({
loading,
connectorMode,
defaultConnectorMode,
externalConnectorConfigured,
mockConnectorAvailable,
onSubmit,
}: {
loading: boolean
connectorMode?: 'mock' | 'external'
defaultConnectorMode?: 'embedded' | 'external' | 'mock'
externalConnectorConfigured?: boolean
mockConnectorAvailable?: boolean
onSubmit: (values: {
orderNo?: string
skuName?: string
quantity?: number
pageTitle?: string
browserTargetUrl?: string
connectorMode?: 'embedded' | 'external' | 'mock'
}) => void
}) {
const [form] = Form.useForm()
const defaultMode =
defaultConnectorMode === 'mock' && mockConnectorAvailable
? 'mock'
: defaultConnectorMode === 'external'
? 'external'
: 'embedded'
const selectedMode =
(Form.useWatch('connectorMode', form) as 'embedded' | 'external' | 'mock' | undefined) ||
defaultMode
return (
<Form
form={form}
layout="vertical"
initialValues={{
quantity: 1,
pageTitle: '虎牙账号授权测试',
browserTargetUrl: 'https://www.huya.com/',
connectorMode: defaultMode,
}}
onFinish={onSubmit}
>
<Form.Item
label="Mock 范围"
name="connectorMode"
extra="只 Mock 订单时,登录、角色绑定和浏览器票据注入可走内置真实 Connector,也可显式使用远程 Connector。"
>
<Select
options={[
{
value: 'embedded',
label: '仅 Mock 订单(内置真实登录 / 绑定 / 注入)',
},
{
value: 'external',
label: '仅 Mock 订单(远程真实 Connector)',
},
{
value: 'mock',
label: '订单 + 登录绑定都 Mock(内置 Connector)',
disabled: mockConnectorAvailable === false,
},
]}
/>
</Form.Item>
<Form.Item
label="内部 SKU 名称(可空)"
name="skuName"
@@ -552,15 +605,23 @@ function SemiAutoMockForm({
<Input placeholder="https://www.huya.com/" />
</Form.Item>
<Alert
type={connectorMode === 'mock' ? 'success' : 'warning'}
type={
selectedMode === 'mock'
? 'warning'
: selectedMode === 'external' && !externalConnectorConfigured
? 'error'
: 'success'
}
showIcon
style={{ marginBottom: 12 }}
message={
connectorMode === 'mock'
? '内置 Mock Connector 已启用,登录和绑定会自动推进。'
: connectorMode === 'external'
? '当前配置为外部 Connector,请先确认外部服务已启动。'
: 'Connector 状态未知;生成后可在客户页验证。'
selectedMode === 'mock'
? '登录和绑定会使用内置 Mock Connector,仅用于联调页面。'
: selectedMode === 'external'
? externalConnectorConfigured
? '远程真实 Connector 已配置;只有订单由 Mock 生成。'
: '远程真实 Connector 未配置:请设置 SEMI_AUTO_CONNECTOR_BASE_URL 和 API_KEY。'
: '使用 order_site 内置真实 Connector;无需启动 live-hub-py,只有订单由 Mock 生成。'
}
/>
<Button type="primary" htmlType="submit" loading={loading} block>
@@ -268,6 +268,16 @@ export default function AdminSemiAutoTasksPage() {
width: 90,
render: (value: string) => <Tag color="purple">{PLATFORM_LABELS[value] || value}</Tag>,
},
{
title: 'Connector',
dataIndex: 'connectorMode',
width: 110,
render: (value: string) => (
<Tag color={value === 'mock' ? 'orange' : 'green'}>
{value === 'mock' ? '内置 Mock' : '真实'}
</Tag>
),
},
{
title: '客户登录',
key: 'login',
@@ -457,6 +467,15 @@ export default function AdminSemiAutoTasksPage() {
<Descriptions.Item label="平台">
{PLATFORM_LABELS[detail.task.platform] || detail.task.platform}
</Descriptions.Item>
<Descriptions.Item label="Connector">
<Tag color={detail.task.connectorMode === 'mock' ? 'orange' : 'green'}>
{detail.task.connectorMode === 'mock'
? '内置 Mock'
: detail.task.connectorMode === 'external'
? '远程真实'
: '内置真实'}
</Tag>
</Descriptions.Item>
<Descriptions.Item label="当前状态">
<Tag color={STATUS_COLORS[detail.task.displayStatus.key] || 'default'}>
{detail.task.displayStatus.label}
@@ -100,6 +100,10 @@ export default function CustomerFulfillmentPage() {
}, [orderNo, selectedTask?.id])
useEffect(() => {
if (loginInfo?.qrImage) {
setLoginQrImage(loginInfo.qrImage)
return
}
if (!loginInfo?.qrContent) {
setLoginQrImage('')
return
@@ -109,7 +113,7 @@ export default function CustomerFulfillmentPage() {
margin: 2,
color: { dark: '#111827', light: '#ffffff' },
}).then(setLoginQrImage)
}, [loginInfo?.qrContent])
}, [loginInfo?.qrContent, loginInfo?.qrImage])
useEffect(() => {
if (!selectedTask || !orderNo) return
+6 -3
View File
@@ -11,8 +11,9 @@ export type DevMockStatus = {
steps: string[]
}>
semiAuto?: {
connectorMode: 'mock' | 'external'
connectorConfigured: boolean
defaultConnectorMode: 'embedded' | 'external' | 'mock'
externalConnectorConfigured: boolean
mockConnectorAvailable: boolean
platform: string
}
}
@@ -59,7 +60,8 @@ export type DevMockSemiAutoResult = {
configId: number
taskId: number
skuKey: string
connectorMode: 'mock' | 'external'
connectorMode: 'embedded' | 'external' | 'mock'
connectorConfigured: boolean
customerPath: string
adminPath: string
tips: string[]
@@ -93,6 +95,7 @@ export function createSemiAutoDevMock(payload: {
pageTitle?: string
pageDescription?: string
browserTargetUrl?: string
connectorMode?: 'embedded' | 'external' | 'mock'
}) {
return apiPost<DevMockSemiAutoResult>('/api/v1/admin/dev-mock/semi-auto', payload)
}
@@ -15,6 +15,7 @@ export type SemiAutoTask = {
loginStatus: string
bindingStatus: string
executionStatus: string
connectorMode: 'embedded' | 'external' | 'mock'
displayStatus: SemiAutoDisplayStatus
connectorReady: boolean
huyaUid: string
@@ -29,6 +29,7 @@ export type CustomerSemiAutoTask = {
export type CustomerLoginInfo = {
status: string
qrContent: string
qrImage?: string
expiresAt: string
message: string
}