import { useCallback, useEffect, useMemo, useRef, useState } from 'react'; import { Button, Card, Col, DatePicker, Form, Input, InputNumber, message, Modal, QRCode, Row, Select, Space, Table, Tabs, Tag, Tooltip, Typography, theme, } from 'antd'; import type { TableProps } from 'antd'; import type { Dayjs } from 'dayjs'; import { AppstoreOutlined, CheckCircleOutlined, CreditCardOutlined, FieldTimeOutlined, LinkOutlined, PlayCircleOutlined, QrcodeOutlined, ReloadOutlined, SearchOutlined, SettingOutlined, ShoppingOutlined, } from '@ant-design/icons'; import { huyaApi, type HuyaAccountItem, type HuyaConfig, type HuyaGoodsItem, type HuyaRechargeGoodsItem, type HuyaTaskItem, } from '../api/modules'; import RealtimeLogPanel from '../components/RealtimeLogPanel'; import { usePermissions } from '../hooks/usePermissions'; import { useWebSocketLogs } from '../hooks/useWebSocketLogs'; import { formatTime } from '../utils/time'; import { getErrorMessage } from '../utils/error'; const { Text } = Typography; const FALLBACK_TASK_TYPES: Record = { get_bind_qr: '获取绑定二维码', confirm_bind: '确认绑定', query_points: '一键查询积分', query_game_name: '一键查询游戏名', query_exchange_records: '一键查询兑换记录', refresh_goods: '刷新商品列表', refresh_recharge_goods: '刷新充值商品列表', exchange_goods: '兑换商品', create_recharge_order: '生成支付二维码', }; const QUICK_ACTIONS = [ { key: 'get_bind_qr', icon: }, { key: 'confirm_bind', icon: }, { key: 'query_points', icon: }, { key: 'query_game_name', icon: }, { key: 'query_exchange_records', icon: }, { key: 'refresh_goods', icon: }, { key: 'refresh_recharge_goods', icon: }, { key: 'exchange_goods', icon: }, { key: 'create_recharge_order', icon: }, ]; const STATUS_COLORS: Record = { planned: 'default', pending: 'default', running: 'processing', success: 'success', failed: 'error', error: 'error', }; const STATUS_LABELS: Record = { planned: '已计划', pending: '等待中', running: '执行中', success: '成功', failed: '失败', error: '异常', }; function accountLabel(account: HuyaAccountItem): string { const name = account.nickname || account.username || account.uid || `#${account.id}`; const tag = account.tag ? ` [${account.tag}]` : ''; const phone = account.game_phone ? ` / ${account.game_phone}` : ''; return `${name}${tag}${phone}`; } function resultText(result: Record | null | undefined, key: string): string { const value = result?.[key]; return typeof value === 'string' ? value : ''; } function resultObject(result: Record | null | undefined, key: string): Record | null { const value = result?.[key]; if (!value || typeof value !== 'object' || Array.isArray(value)) return null; return value as Record; } function resultProfileNick(result: Record | null | undefined): string { const profile = result?.profile; if (!profile || typeof profile !== 'object' || Array.isArray(profile)) return ''; const nick = (profile as Record).nick; return typeof nick === 'string' ? nick : ''; } function goodsRawString(item: HuyaGoodsItem, key: string): string { const value = item.raw?.[key]; if (typeof value === 'string') return value; if (typeof value === 'number') return String(value); return ''; } function goodsRawNumber(item: HuyaGoodsItem, key: string): number { const value = item.raw?.[key]; if (typeof value === 'number') return value; if (typeof value === 'string' && value.trim()) return Number(value) || 0; return 0; } function goodsCategoryKey(item: HuyaGoodsItem): string { return goodsRawString(item, 'category_id') || goodsRawString(item, 'category_name') || 'uncategorized'; } function goodsCategoryLabel(item: HuyaGoodsItem): string { return goodsRawString(item, 'category_name') || goodsRawString(item, 'category_id') || '未分类'; } function formatRemainText(value: string): string { const text = String(value || '').trim(); if (!text || text.endsWith('%')) return text; return /^-?\d+(\.\d+)?$/.test(text) ? `${text}%` : text; } function formatPriceText(value: number | null | undefined): string { if (!value) return ''; return `¥${(value / 100).toFixed(2)}`; } function hasMiniQrcode(task: HuyaTaskItem): boolean { return task.task_type === 'get_bind_qr' && Boolean(resultText(task.result, 'mini_qrcode_image')); } function hasPaymentQrcode(task: HuyaTaskItem): boolean { return task.task_type === 'create_recharge_order' && Boolean(resultText(task.result, 'pay_url')); } export default function HuyaTasksPage() { const { token } = theme.useToken(); const [form] = Form.useForm(); const [accounts, setAccounts] = useState([]); const [tasks, setTasks] = useState([]); const [goods, setGoods] = useState([]); const [rechargeGoods, setRechargeGoods] = useState([]); const [taskTypes, setTaskTypes] = useState>(FALLBACK_TASK_TYPES); const [selectedIds, setSelectedIds] = useState([]); const [selectedTaskType, setSelectedTaskType] = useState('query_points'); const [selectedGoodsCategory, setSelectedGoodsCategory] = useState(''); const [selectedExchangeGoodsId, setSelectedExchangeGoodsId] = useState(''); const [exchangeAt, setExchangeAt] = useState(null); const [selectedRechargeGoodsId, setSelectedRechargeGoodsId] = useState(''); const [rechargeCount, setRechargeCount] = useState(1); const [rechargePayChannel, setRechargePayChannel] = useState('Weixin'); const [concurrency, setConcurrency] = useState(() => { const v = localStorage.getItem('huya_task_concurrency'); return v ? Math.max(1, Math.min(10, Number(v) || 3)) : 3; }); const [loading, setLoading] = useState(false); const [starting, setStarting] = useState(false); const [savingConfig, setSavingConfig] = useState(false); const [batchId, setBatchId] = useState(null); const [qrTask, setQrTask] = useState(null); const [payTask, setPayTask] = useState(null); const [exchangeRecordsTask, setExchangeRecordsTask] = useState(null); const autoOpenedQrTaskIds = useRef>(new Set()); const autoOpenQrReady = useRef(false); const autoOpenedPayTaskIds = useRef>(new Set()); const autoOpenPayReady = useRef(false); const { logs, connected: wsConnected, connect: connectLogs } = useWebSocketLogs(); const { can } = usePermissions(); const canTask = can('huya:task'); const canConfig = can('huya:config'); useEffect(() => { localStorage.setItem('huya_task_concurrency', String(concurrency)); }, [concurrency]); const rememberExistingQrcodes = useCallback((items: HuyaTaskItem[]) => { if (autoOpenQrReady.current) return; items.filter(hasMiniQrcode).forEach((task) => autoOpenedQrTaskIds.current.add(task.id)); autoOpenQrReady.current = true; }, []); const rememberExistingPaymentQrcodes = useCallback((items: HuyaTaskItem[]) => { if (autoOpenPayReady.current) return; items.filter(hasPaymentQrcode).forEach((task) => autoOpenedPayTaskIds.current.add(task.id)); autoOpenPayReady.current = true; }, []); const openQrTask = useCallback((task: HuyaTaskItem) => { autoOpenedQrTaskIds.current.add(task.id); setQrTask(task); }, []); const openPayTask = useCallback((task: HuyaTaskItem) => { autoOpenedPayTaskIds.current.add(task.id); setPayTask(task); }, []); const loadAll = useCallback(async () => { setLoading(true); try { const [accountResult, taskResult, goodsResult, rechargeGoodsResult, configResult, taskTypeResult] = await Promise.allSettled([ huyaApi.listAccounts(), huyaApi.listTasks(), huyaApi.listGoods(), huyaApi.listRechargeGoods(), canConfig ? huyaApi.getConfig() : Promise.resolve(null), huyaApi.taskTypes(), ]); if (accountResult.status === 'fulfilled') setAccounts(accountResult.value); if (taskResult.status === 'fulfilled') { rememberExistingQrcodes(taskResult.value); rememberExistingPaymentQrcodes(taskResult.value); setTasks(taskResult.value); } if (goodsResult.status === 'fulfilled') setGoods(goodsResult.value); if (rechargeGoodsResult.status === 'fulfilled') setRechargeGoods(rechargeGoodsResult.value); if (configResult.status === 'fulfilled' && configResult.value) form.setFieldsValue(configResult.value); if (taskTypeResult.status === 'fulfilled') setTaskTypes({ ...FALLBACK_TASK_TYPES, ...taskTypeResult.value }); const failedLabels = [ accountResult.status === 'rejected' ? `CK 列表: ${getErrorMessage(accountResult.reason)}` : '', taskResult.status === 'rejected' ? `任务记录: ${getErrorMessage(taskResult.reason)}` : '', goodsResult.status === 'rejected' ? `兑换商品: ${getErrorMessage(goodsResult.reason)}` : '', rechargeGoodsResult.status === 'rejected' ? `充值商品: ${getErrorMessage(rechargeGoodsResult.reason)}` : '', configResult.status === 'rejected' ? `虎牙配置: ${getErrorMessage(configResult.reason)}` : '', taskTypeResult.status === 'rejected' ? `任务类型: ${getErrorMessage(taskTypeResult.reason)}` : '', ].filter(Boolean); if (failedLabels.length > 0) { message.warning(`部分数据加载失败:${failedLabels.join(';')}`); } } finally { setLoading(false); } }, [canConfig, form, rememberExistingPaymentQrcodes, rememberExistingQrcodes]); const loadTasks = useCallback(async () => { try { const data = await huyaApi.listTasks(); rememberExistingQrcodes(data); rememberExistingPaymentQrcodes(data); setTasks(data); } catch { // 轮询失败不打扰操作,下一轮继续刷新。 } }, [rememberExistingPaymentQrcodes, rememberExistingQrcodes]); useEffect(() => { loadAll(); }, [loadAll]); useEffect(() => { const timer = setInterval(loadTasks, 3000); return () => clearInterval(timer); }, [loadTasks]); useEffect(() => { if (!autoOpenQrReady.current || qrTask) return; const nextQrTask = tasks .filter((task) => hasMiniQrcode(task) && !autoOpenedQrTaskIds.current.has(task.id)) .sort((a, b) => b.id - a.id)[0]; if (nextQrTask) openQrTask(nextQrTask); }, [openQrTask, qrTask, tasks]); useEffect(() => { if (!autoOpenPayReady.current || payTask) return; const nextPayTask = tasks .filter((task) => hasPaymentQrcode(task) && !autoOpenedPayTaskIds.current.has(task.id)) .sort((a, b) => b.id - a.id)[0]; if (nextPayTask) openPayTask(nextPayTask); }, [openPayTask, payTask, tasks]); const accountOptions = useMemo(() => { return accounts.map((account) => ({ value: account.id, label: accountLabel(account) })); }, [accounts]); const sortedGoods = useMemo(() => { return [...goods].sort((a, b) => ( goodsRawNumber(a, 'category_sort') - goodsRawNumber(b, 'category_sort') || goodsRawNumber(a, 'raw_order') - goodsRawNumber(b, 'raw_order') || a.id - b.id )); }, [goods]); const sortedRechargeGoods = useMemo(() => { return [...rechargeGoods].sort((a, b) => { const aOrder = goodsRawNumber({ raw: a.raw } as HuyaGoodsItem, 'raw_order'); const bOrder = goodsRawNumber({ raw: b.raw } as HuyaGoodsItem, 'raw_order'); return aOrder - bOrder || a.id - b.id; }); }, [rechargeGoods]); const rechargeGoodsOptions = useMemo(() => { return sortedRechargeGoods.map((item) => ({ value: item.spu_id, label: `${item.name || item.spu_id}${item.price ? ` / ${formatPriceText(item.price)}` : ''}`, })); }, [sortedRechargeGoods]); const selectedRechargeGoods = useMemo(() => { return sortedRechargeGoods.find((item) => item.spu_id === selectedRechargeGoodsId) || null; }, [sortedRechargeGoods, selectedRechargeGoodsId]); useEffect(() => { if (sortedRechargeGoods.length === 0) { if (selectedRechargeGoodsId) setSelectedRechargeGoodsId(''); return; } if (!sortedRechargeGoods.some((item) => item.spu_id === selectedRechargeGoodsId)) { setSelectedRechargeGoodsId(sortedRechargeGoods[0].spu_id); } }, [selectedRechargeGoodsId, sortedRechargeGoods]); const goodsCategories = useMemo(() => { const map = new Map(); sortedGoods.forEach((item) => { const key = goodsCategoryKey(item); const current = map.get(key); if (current) { current.count += 1; return; } map.set(key, { key, label: goodsCategoryLabel(item), sort: goodsRawNumber(item, 'category_sort'), count: 1, }); }); return Array.from(map.values()).sort((a, b) => a.sort - b.sort || a.label.localeCompare(b.label)); }, [sortedGoods]); useEffect(() => { if (goodsCategories.length === 0) { if (selectedGoodsCategory) setSelectedGoodsCategory(''); return; } if (!goodsCategories.some((item) => item.key === selectedGoodsCategory)) { setSelectedGoodsCategory(goodsCategories[0].key); } }, [goodsCategories, selectedGoodsCategory]); const filteredGoods = useMemo(() => { if (!selectedGoodsCategory) return sortedGoods; return sortedGoods.filter((item) => goodsCategoryKey(item) === selectedGoodsCategory); }, [sortedGoods, selectedGoodsCategory]); const goodsOptions = useMemo(() => { return sortedGoods.map((item) => ({ value: item.product_id, label: `${item.name || item.product_id}${item.price ? ` / ${item.price}积分` : ''}`, })); }, [sortedGoods]); const selectedExchangeGoods = useMemo(() => { return sortedGoods.find((item) => item.product_id === selectedExchangeGoodsId) || null; }, [selectedExchangeGoodsId, sortedGoods]); useEffect(() => { if (sortedGoods.length === 0) { if (selectedExchangeGoodsId) setSelectedExchangeGoodsId(''); return; } if (!sortedGoods.some((item) => item.product_id === selectedExchangeGoodsId)) { setSelectedExchangeGoodsId(sortedGoods[0].product_id); } }, [selectedExchangeGoodsId, sortedGoods]); const createPayload = (taskType: string) => { if (taskType === 'exchange_goods') { return { product_id: selectedExchangeGoods?.product_id || selectedExchangeGoodsId, product_name: selectedExchangeGoods?.name || '', scheduled_at: exchangeAt ? exchangeAt.toISOString() : '', }; } if (taskType !== 'create_recharge_order') return {}; return { spu_id: selectedRechargeGoods?.spu_id || selectedRechargeGoodsId, sku_id: selectedRechargeGoods?.sku_id || '', product_name: selectedRechargeGoods?.name || '', count: rechargeCount, pay_channel: rechargePayChannel, }; }; const startTask = async (taskType = selectedTaskType) => { if (selectedIds.length === 0) { message.warning('请先选择虎牙 CK'); return; } if (taskType === 'create_recharge_order' && !selectedRechargeGoodsId) { message.warning('请先选择充值商品'); return; } if (taskType === 'exchange_goods' && !selectedExchangeGoodsId) { message.warning('请先选择兑换商品'); return; } setStarting(true); try { const result = await huyaApi.createTasks({ account_ids: selectedIds, task_type: taskType, concurrency, payload: createPayload(taskType), }); const finishTask = () => { setBatchId(null); setStarting(false); if (taskType === 'refresh_goods' || taskType === 'refresh_recharge_goods') { void loadAll(); } else { void loadTasks(); } }; setBatchId(result.batch_id); message.success(`已创建 ${taskTypes[taskType] || taskType},共 ${result.count} 个账号`); await loadTasks(); connectLogs(`/api/huya/ws/${result.batch_id}`, { onClose: finishTask, onResult: finishTask, onError: finishTask, }); } catch (e: unknown) { message.error(getErrorMessage(e)); setStarting(false); } }; const saveConfig = async () => { setSavingConfig(true); try { const values = await form.validateFields(); const result = await huyaApi.updateConfig(values); form.setFieldsValue(result); message.success('虎牙配置已保存'); } catch (e: unknown) { message.error(getErrorMessage(e)); } finally { setSavingConfig(false); } }; const successCount = tasks.filter((task) => task.status === 'success').length; const plannedCount = tasks.filter((task) => task.status === 'planned').length; const failedCount = tasks.filter((task) => ['failed', 'error'].includes(task.status)).length; const qrResult = qrTask?.result || null; const qrImage = resultText(qrResult, 'mini_qrcode_image'); const qrAccountName = qrTask ? resultProfileNick(qrResult) || qrTask.account_nickname || qrTask.account_uid || `#${qrTask.account_id}` : ''; const payResult = payTask?.result || null; const payUrl = resultText(payResult, 'pay_url'); const payProductName = resultText(payResult, 'product_name'); const payAmountText = resultText(payResult, 'amount_text'); const payChannelLabel = resultText(payResult, 'pay_channel_label'); const payOrderId = payResult?.order_id; const payAccountName = payTask ? payTask.account_nickname || payTask.account_uid || `#${payTask.account_id}` : ''; const exchangeRecordsResult = exchangeRecordsTask?.result || null; const exchangeRecordsRaw = exchangeRecordsResult?.records; const exchangeRecords = Array.isArray(exchangeRecordsRaw) ? exchangeRecordsRaw.filter((item) => item && typeof item === 'object') as Record[] : []; const exchangeRecordsAccountName = exchangeRecordsTask ? exchangeRecordsTask.account_nickname || exchangeRecordsTask.account_uid || `#${exchangeRecordsTask.account_id}` : ''; const renderTaskResult = (value: Record | null, record: HuyaTaskItem) => { const bindQrImage = resultText(value, 'mini_qrcode_image'); if (bindQrImage) { return ( ); } if (record.task_type === 'get_bind_qr') { if (value?.can_change_bind === false) { const changeAt = resultText(value, 'change_available_at'); return ( 不可更换 {changeAt ? {changeAt} : null} ); } return -; } if (record.task_type === 'confirm_bind') { if (value?.bind_confirmed === true) { const gameRole = resultObject(value, 'game_role'); const roleName = typeof gameRole?.role_name === 'string' ? gameRole.role_name : ''; return ( 已绑定 {roleName ? {roleName} : null} ); } return -; } if (record.task_type === 'query_game_name') { const roleName = resultText(value, 'role_name'); if (roleName) return {roleName}; if (value?.is_bound === false) return 未绑定; return -; } if (record.task_type === 'query_exchange_records') { const recordCount = value?.record_count; if (typeof recordCount === 'number' && recordCount > 0) { return ( ); } if (typeof recordCount === 'number') return 记录 {recordCount} 条; return -; } if (record.task_type === 'refresh_goods') { const goodsCount = value?.goods_count; if (typeof goodsCount === 'number') return 商品 {goodsCount} 个; return -; } if (record.task_type === 'exchange_goods') { const productName = resultText(value, 'product_name'); const orderId = resultText(value, 'order_id'); if (record.status !== 'success') { return productName ? {productName} : -; } return ( 已兑换 {productName ? {productName} : null} {orderId ? {orderId} : null} ); } if (record.task_type === 'refresh_recharge_goods') { const goodsCount = value?.goods_count; const failedCount = value?.failed_count; if (typeof goodsCount === 'number') { return ( 充值商品 {goodsCount} 个 {typeof failedCount === 'number' && failedCount > 0 ? 失败 {failedCount} : null} ); } return -; } if (record.task_type === 'create_recharge_order') { if (resultText(value, 'pay_url')) { return ( ); } return -; } const availableScore = value?.available_score; if (typeof availableScore === 'number') { return 可用积分 {availableScore}; } return value ? {JSON.stringify(value)} : -; }; const taskColumns: TableProps['columns'] = [ { title: 'ID', dataIndex: 'id', width: 70, align: 'center' }, { title: '任务', dataIndex: 'task_type', width: 150, render: (value: string) => taskTypes[value] || value, }, { title: '账号', width: 160, render: (_: unknown, record) => record.account_nickname || record.account_uid || record.account_id, }, { title: '状态', dataIndex: 'status', width: 100, align: 'center', render: (status: string) => ( {STATUS_LABELS[status] || status} ), }, { title: '消息', dataIndex: 'message', ellipsis: true }, { title: '结果', dataIndex: 'result', width: 210, ellipsis: true, render: renderTaskResult, }, { title: '时间', dataIndex: 'created_at', width: 170, render: (value: string | null) => value ? formatTime(value) : -, }, ]; const goodsColumns: TableProps['columns'] = [ { title: '商品ID', dataIndex: 'product_id', width: 88, ellipsis: true }, { title: '名称', dataIndex: 'name', width: 230, render: (value: string) => ( {value || '-'} ), }, { title: '分类', width: 96, render: (_: unknown, record) => { const label = goodsCategoryLabel(record); return label ? {label} : -; }, }, { title: '价格', dataIndex: 'price', width: 78, align: 'center', render: (value: number | null) => value ?? -, }, { title: '库存', dataIndex: 'remain_text', width: 72, render: (value: string) => formatRemainText(value) || -, }, { title: '更新时间', dataIndex: 'updated_at', width: 154, render: (value: string | null) => value ? formatTime(value) : -, }, ]; const rechargeGoodsColumns: TableProps['columns'] = [ { title: 'SPU', dataIndex: 'spu_id', width: 120, ellipsis: true }, { title: 'SKU', dataIndex: 'sku_id', width: 100, ellipsis: true }, { title: '名称', dataIndex: 'name', ellipsis: true }, { title: '单价', dataIndex: 'price', width: 90, align: 'center', render: (value: number | null) => formatPriceText(value) || -, }, { title: '库存', dataIndex: 'stock', width: 90, align: 'center', render: (value: number | null) => value ?? -, }, { title: '来源', dataIndex: 'task_name', width: 140, ellipsis: true, render: (value: string) => value || 商品详情, }, { title: '更新时间', dataIndex: 'updated_at', width: 160, render: (value: string | null) => value ? formatTime(value) : -, }, ]; const exchangeRecordColumns: TableProps>['columns'] = [ { title: '序号', width: 70, align: 'center', render: (_: unknown, record, index) => String(record.index || index + 1), }, { title: '消耗', width: 110, render: (_: unknown, record) => { const scoreText = record.score_text; if (typeof scoreText === 'string' && scoreText) return scoreText; const score = record.score; return typeof score === 'number' ? `${score}积分` : -; }, }, { title: '奖品名称', dataIndex: 'prize_name', ellipsis: true, render: (value: unknown) => typeof value === 'string' && value ? value : -, }, { title: '兑换状态', width: 110, align: 'center', render: (_: unknown, record) => { const label = typeof record.status_label === 'string' ? record.status_label : ''; const color = label === '已发放' ? 'green' : 'orange'; return label ? {label} : -; }, }, { title: '兑换时间', width: 170, render: (_: unknown, record) => { const text = record.exchange_time_text; return typeof text === 'string' && text ? text : -; }, }, ]; return (

虎牙兑换与充值

{batchId && 批次 {batchId}}
虎牙配置} extra={canConfig && ( )} style={{ marginBottom: 12 }} >
setSelectedExchangeGoodsId(value || '')} options={goodsOptions} style={{ minWidth: 220 }} filterOption={(input, option) => String(option?.label || '').toLowerCase().includes(input.toLowerCase())} /> {goodsCategories.length > 0 && ( ({ key: item.key, label: `${item.label} (${item.count})`, })) } /> )} ({ onClick: () => setSelectedExchangeGoodsId(record.product_id), })} rowClassName={(record) => record.product_id === selectedExchangeGoodsId ? 'ant-table-row-selected' : ''} /> 充值商品列表} extra={( )} style={{ marginBottom: 12 }} >
({ onClick: () => setSelectedRechargeGoodsId(record.spu_id), })} rowClassName={(record) => record.spu_id === selectedRechargeGoodsId ? 'ant-table-row-selected' : ''} />
({ value, label }))} style={{ flex: '1 1 220px', minWidth: 180 }} /> setConcurrency(value || 1)} addonBefore="并发" style={{ width: 130, flexShrink: 0 }} />
{QUICK_ACTIONS.map((item) => ( ))}
当前已接入查询积分、绑定、兑换记录、兑换商品列表、商品兑换、充值商品列表和扫码支付。
{tasks.length} 个任务 已计划 {plannedCount} 成功 {successCount} 失败 {failedCount}
`共 ${total} 条` }} scroll={{ x: 920 }} /> setExchangeRecordsTask(null)} footer={null} width={760} > {exchangeRecordsAccountName}{exchangeRecordsResult?.sid ? ` / SID ${String(exchangeRecordsResult.sid)}` : ''}
String(record.record_id || record.order_id || record.index)} size="small" pagination={false} scroll={{ y: 360 }} locale={{ emptyText: '暂无兑换记录' }} /> setQrTask(null)} footer={null} width={360} > {qrTask && (
{qrAccountName} {qrImage ? (
绑定小程序码
) : ( 暂无二维码 )}
)}
setPayTask(null)} footer={null} width={380} > {payTask && (
{payProductName || '充值商品'} {payChannelLabel || '支付'}{payAmountText ? ` / ${payAmountText}` : ''}{payAccountName ? ` / ${payAccountName}` : ''} {typeof payOrderId === 'number' || typeof payOrderId === 'string' ? ( 订单号 {String(payOrderId)} ) : null} {payUrl ? (
) : ( 暂无支付二维码 )}
)}
); }