style(platform-rock): 深度重构 Rock 管理大屏 UI,全面对齐平台设计规范

1. 页面容器对标 PlatformProducts 规范,移除内层冗余白底外壳,优化整体边距与排版;
2. 废弃原生低质感 Statistic 标签,全面改用 metric-card 高质感统计看板(可用库存、错单阻断、交付总量、上游积分);
3. 重构通道控制与 0666.pro 凭据面板,增加通道呼吸状态条与软熔断一键切换 Banner,表单分栏结构化展示;
4. 筛选工具栏与库存审计表格全面升级,增加 UID 强一致校验高亮对比与错单解冻重置操作。
This commit is contained in:
yml2213
2026-10-05 15:36:45 +08:00
parent 611c658a8a
commit 80554555d3
+453 -295
View File
@@ -1,6 +1,5 @@
import { useCallback, useEffect, useState } from 'react'
import {
Alert,
Badge,
Button,
Card,
@@ -14,7 +13,6 @@ import {
Row,
Radio,
Space,
Statistic,
Switch,
Table,
Tag,
@@ -24,11 +22,12 @@ import {
} from 'antd'
import {
CheckCircleOutlined,
ControlOutlined,
ExclamationCircleOutlined,
FireOutlined,
KeyOutlined,
PlusCircleOutlined,
ReloadOutlined,
SafetyCertificateOutlined,
SearchOutlined,
ShoppingCartOutlined,
ThunderboltOutlined,
@@ -113,16 +112,18 @@ export default function PlatformRock() {
Modal.confirm({
title: checked ? '确认开启 Rock 自动发货通道?' : '确认一键关闭 Rock 自动发货通道(软熔断)?',
content: checked
? '开启后,黑色 ROCK 与蓝色运动服两款商品将恢复全自动反向代理发货。'
: '关闭后,两款商品将彻底脱离自动发货流程,订单将转交人工打手或客服处理,避免错单穿透。',
okText: '确认更改',
? '开启后,黑色 ROCK 与蓝色运动服两款商品将恢复 0666.pro 全自动反代发货。'
: '关闭后,两款商品将脱离自动发货通道,进单将转交人工打手大厅处理,防止错单穿透。',
okText: checked ? '确认开启' : '立即熔断关闭',
cancelText: '取消',
okType: checked ? 'primary' : 'danger',
okButtonProps: {
danger: !checked,
},
onOk: async () => {
try {
const updated = await rockApi.updateConfig({ auto_delivery_enabled: checked })
setConfig(updated)
message.success(checked ? '自动发货已开启' : '自动发货已成功熔断关闭')
message.success(checked ? '自动发货通道已开启' : '自动发货通道已成功熔断关闭')
loadData()
} catch (e) {
message.error('更新总开关失败: ' + (e instanceof Error ? e.message : '未知错误'))
@@ -141,7 +142,7 @@ export default function PlatformRock() {
setTestingConn(true)
try {
const res = await rockApi.testConnection(bearerToken)
message.success(`连通成功!采购商户:${res.user?.username || '正常'},可用积分:${res.user?.points || 0}`)
message.success(`连通成功!商户:${res.user?.username || '正常'},可用积分:${res.user?.points || 0}`)
loadData()
} catch (e) {
message.error('连通性测试失败:' + (e instanceof Error ? e.message : '未知错误'))
@@ -157,7 +158,7 @@ export default function PlatformRock() {
setSavingConfig(true)
const updated = await rockApi.updateConfig(values)
setConfig(updated)
message.success('配置已保存生效')
message.success('配置已成功保存生效')
loadData()
} catch (e) {
if (e instanceof Error) {
@@ -187,7 +188,7 @@ export default function PlatformRock() {
const handleResetToken = async (id: number) => {
try {
await rockApi.resetToken(id)
message.success('已解冻重置为可用库存')
message.success('已解除绑定异常,重置为可用库存')
loadData()
loadTokens()
} catch (e) {
@@ -199,57 +200,83 @@ export default function PlatformRock() {
{
title: 'ID / 提取码',
dataIndex: 'id',
width: 140,
width: 170,
render: (id, record) => (
<Space direction="vertical" size={2}>
<Text strong>#{id}</Text>
<Text copyable={{ text: record.redeem_code }} type="secondary" style={{ fontSize: 12 }}>
{record.redeem_code?.substring(0, 10)}...
<Text code style={{ fontWeight: 600 }}>#{id}</Text>
<Text
copyable={{ text: record.redeem_code }}
type="secondary"
style={{ fontSize: 12, fontFamily: 'monospace' }}
>
{record.redeem_code ? `${record.redeem_code.substring(0, 10)}...` : '-'}
</Text>
</Space>
),
},
{
title: '颜色与适用范围',
title: '规格与适用范围',
dataIndex: 'color',
width: 130,
width: 150,
render: (_, record) => (
<Space direction="vertical" size={2}>
<Tag color="purple">通用黑色 Token</Tag>
<Tag color="geekblue" style={{ borderRadius: 4, fontWeight: 500 }}>
通用黑色 Token
</Tag>
<Text type="secondary" style={{ fontSize: 12 }}>
{record.region || 'Q/V可用'}
{record.region || 'Q/V区通用 · 自动分发'}
</Text>
</Space>
),
},
{
title: '状态',
title: '库存状态',
dataIndex: 'status',
width: 120,
width: 140,
render: (status) => {
switch (status) {
case 'available':
return <Tag color="green">可用库存</Tag>
return (
<Tag color="success" style={{ fontWeight: 600, padding: '2px 8px' }}>
● 可用库存
</Tag>
)
case 'using':
return <Tag color="blue">使用中 (扫码)</Tag>
return (
<Tag color="processing" style={{ fontWeight: 600, padding: '2px 8px' }}>
● 扫码使用中
</Tag>
)
case 'bound':
return <Tag color="cyan">已绑定授权</Tag>
return (
<Tag color="cyan" style={{ fontWeight: 600, padding: '2px 8px' }}>
● 已授权绑定
</Tag>
)
case 'redeemed':
return <Tag color="purple">已交付发货</Tag>
return (
<Tag color="purple" style={{ fontWeight: 600, padding: '2px 8px' }}>
● 已交付发货
</Tag>
)
case 'mismatch':
return <Tag color="red">绑定错误 (阻断)</Tag>
return (
<Tag color="error" style={{ fontWeight: 600, padding: '2px 8px', border: '1px solid #ff4d4f' }}>
⚠️ 绑定错误 (阻断)
</Tag>
)
default:
return <Tag>{status}</Tag>
}
},
},
{
title: '关联订单',
title: '关联业务工单',
dataIndex: 'assigned_order_no',
width: 170,
width: 190,
render: (orderNo) =>
orderNo ? (
<Text copyable style={{ fontSize: 12 }}>
<Text code copyable={{ text: orderNo }} style={{ fontWeight: 600, color: '#1d4ed8' }}>
{orderNo}
</Text>
) : (
@@ -257,46 +284,57 @@ export default function PlatformRock() {
),
},
{
title: '预期 UID vs 扫码角色',
width: 220,
title: '预期 UID vs 扫码角色 (风控门禁)',
width: 250,
render: (_, record) => {
const hasMismatch = record.status === 'mismatch'
const isMismatch = record.status === 'mismatch'
return (
<Space direction="vertical" size={2} style={{ width: '100%' }}>
<div>
<Text type="secondary" style={{ fontSize: 12 }}>预期UID: </Text>
<Text strong>{record.expected_uid || '-'}</Text>
<div
style={{
padding: isMismatch ? '6px 10px' : '0',
background: isMismatch ? '#fff1f0' : 'transparent',
borderRadius: isMismatch ? 6 : 0,
border: isMismatch ? '1px dashed #ffa39e' : 'none',
}}
>
<div style={{ display: 'flex', alignItems: 'center', gap: 6, fontSize: 12 }}>
<span style={{ color: '#64748b' }}>预期 UID:</span>
<Text strong style={{ color: '#0f172a' }}>{record.expected_uid || '-'}</Text>
</div>
<div>
<Text type="secondary" style={{ fontSize: 12 }}>扫码角色: </Text>
<Text type={hasMismatch ? 'danger' : undefined}>
<div style={{ display: 'flex', alignItems: 'center', gap: 6, fontSize: 12, marginTop: 2 }}>
<span style={{ color: '#64748b' }}>扫码反查:</span>
<Text type={isMismatch ? 'danger' : undefined} strong={isMismatch}>
{record.actual_role_name ? `${record.actual_role_name} (${record.actual_role_id || '-'})` : '-'}
</Text>
</div>
{hasMismatch && record.mismatch_reason && (
<Tooltip title={record.mismatch_reason}>
<Tag color="error" style={{ fontSize: 11, maxWidth: 200, overflow: 'hidden', textOverflow: 'ellipsis' }}>
{record.mismatch_reason}
</Tag>
</Tooltip>
{isMismatch && record.mismatch_reason && (
<div style={{ marginTop: 4 }}>
<Tooltip title={record.mismatch_reason}>
<Tag color="error" style={{ fontSize: 11, margin: 0, maxWidth: 220, overflow: 'hidden', textOverflow: 'ellipsis' }}>
{record.mismatch_reason}
</Tag>
</Tooltip>
</div>
)}
</Space>
</div>
)
},
},
{
title: '官方发货凭证 (FulfillId)',
dataIndex: 'upstream_fulfill_id',
width: 150,
width: 180,
render: (fulfillId, record) =>
fulfillId ? (
<Space direction="vertical" size={2}>
<Text copyable strong style={{ color: '#52c41a' }}>
<Text code copyable strong style={{ color: '#059669', fontSize: 12 }}>
{fulfillId}
</Text>
<Text type="secondary" style={{ fontSize: 12 }}>
{record.target_skin || '和平精英道具'}
</Text>
<div>
<Tag color="default" style={{ fontSize: 11 }}>
{record.target_skin || '和平精英道具'}
</Tag>
</div>
</Space>
) : (
<Text type="secondary">-</Text>
@@ -305,16 +343,19 @@ export default function PlatformRock() {
{
title: '操作',
key: 'action',
width: 100,
width: 120,
fixed: 'right',
render: (_, record) => {
if (record.status === 'mismatch') {
return (
<Popconfirm
title="确定解冻重置该 Token?"
description="重置后将清除订单关联并重新释放为可用库存。"
description="重置后将清除原订单绑定与错误标记,重新释放为可用通用库存。"
okText="确认解冻"
cancelText="取消"
onConfirm={() => handleResetToken(record.id)}
>
<Button size="small" type="link" danger icon={<UndoOutlined />}>
<Button size="small" type="primary" danger ghost icon={<UndoOutlined />}>
解冻重置
</Button>
</Popconfirm>
@@ -327,283 +368,400 @@ export default function PlatformRock() {
const autoDelivery = config?.auto_delivery_enabled ?? true
const availableStock = stats?.available_stock ?? 0
const isStockLow = availableStock <= (config?.token_warning_stock ?? 10)
const warningStock = config?.token_warning_stock ?? 10
const isStockLow = availableStock <= warningStock
const hasMismatch = (stats?.mismatch_stock ?? 0) > 0
return (
<div style={{ padding: 24, maxWidth: 1400, margin: '0 auto' }}>
<div style={{ padding: '0 4px' }}>
<PageHeader
title="Rock 发货平台 (0666.pro) 自动发货与库存风控"
subtitle="管理和平精英「黑色ROCK长袖T恤」与「蓝色运动服上衣」通用库存池、采购策略、UID强一致防错门禁与软熔断机制"
/>
{/* 熔断状态警示条 */}
{!autoDelivery && (
<Alert
type="error"
showIcon
style={{ marginBottom: 20 }}
message="【注意】Rock 自动发货全局总开关已关闭(已软熔断)"
description="当前黑色 ROCK 和蓝色运动服两款商品已停止调用 0666.pro 自动发货,订单保留在待发货状态,将由人工打手在接单平台处理。"
/>
)}
{/* 核心指标统计看板 */}
<Row gutter={[16, 16]} style={{ marginBottom: 24 }}>
<Col xs={24} sm={12} md={6}>
<Card bordered={false} style={{ background: '#fff', borderRadius: 8, boxShadow: '0 2px 8px rgba(0,0,0,0.06)' }}>
<Statistic
title="可用通用库存 (Available)"
value={availableStock}
valueStyle={{ color: isStockLow ? '#cf1322' : '#3f8600', fontWeight: 'bold' }}
prefix={<ShoppingCartOutlined />}
suffix="个"
/>
<div style={{ marginTop: 8, display: 'flex', justifyContent: 'space-between', alignItems: 'center' }}>
<Text type="secondary" style={{ fontSize: 12 }}>
警戒水位: {config?.token_warning_stock ?? 10} 个
</Text>
{isStockLow && <Tag color="error">库存紧缺</Tag>}
</div>
</Card>
</Col>
<Col xs={24} sm={12} md={6}>
<Card bordered={false} style={{ background: '#fff', borderRadius: 8, boxShadow: '0 2px 8px rgba(0,0,0,0.06)' }}>
<Statistic
title="绑定错误阻断 (Mismatch)"
value={stats?.mismatch_stock ?? 0}
valueStyle={{ color: (stats?.mismatch_stock ?? 0) > 0 ? '#f5222d' : '#8c8c8c', fontWeight: 'bold' }}
prefix={<ExclamationCircleOutlined />}
suffix="个"
/>
<div style={{ marginTop: 8 }}>
<Text type="secondary" style={{ fontSize: 12 }}>
{(stats?.mismatch_stock ?? 0) > 0 ? '存在 UID 校验不匹配的待排查记录' : '当前无绑定异常'}
</Text>
</div>
</Card>
</Col>
<Col xs={24} sm={12} md={6}>
<Card bordered={false} style={{ background: '#fff', borderRadius: 8, boxShadow: '0 2px 8px rgba(0,0,0,0.06)' }}>
<Statistic
title="履约中 / 已交付"
value={stats?.redeemed_stock ?? 0}
valueStyle={{ color: '#1677ff', fontWeight: 'bold' }}
prefix={<CheckCircleOutlined />}
suffix={`(扫码中: ${stats?.using_stock ?? 0})`}
/>
<div style={{ marginTop: 8 }}>
<Text type="secondary" style={{ fontSize: 12 }}>
已完成发货交付总量
</Text>
</div>
</Card>
</Col>
<Col xs={24} sm={12} md={6}>
<Card bordered={false} style={{ background: '#fff', borderRadius: 8, boxShadow: '0 2px 8px rgba(0,0,0,0.06)' }}>
<Statistic
title="0666 账号积分余额"
value={stats?.upstream_points ?? 0}
precision={1}
valueStyle={{ color: (stats?.upstream_points ?? 0) < (config?.min_points_warning ?? 1050) ? '#faad14' : '#722ed1', fontWeight: 'bold' }}
prefix={<FireOutlined />}
suffix="点"
/>
<div style={{ marginTop: 8, display: 'flex', justifyContent: 'space-between' }}>
<Text type="secondary" style={{ fontSize: 12 }}>
账号: {stats?.username || '未同步'}
</Text>
<Text type="secondary" style={{ fontSize: 12 }}>
约可采购 {Math.floor((stats?.upstream_points ?? 0) / 21)} 个
</Text>
</div>
</Card>
</Col>
</Row>
{/* 上游凭据与策略设置 */}
<Card
title={
<Space>
<KeyOutlined />
<span>0666.pro 采购凭据与自动发货控制</span>
</Space>
}
subtitle="和平精英「黑色ROCK长袖T恤」与「蓝色运动服上衣」通用库存池、上游采购、UID强一致防错门禁与软熔断机制"
extra={
<Space>
<Button icon={<ReloadOutlined />} onClick={loadData} loading={loadingStats}>
刷新状态
</Button>
<Space size="middle">
<Button
type="primary"
icon={<PlusCircleOutlined />}
icon={<ShoppingCartOutlined />}
onClick={() => handlePurchase(50)}
loading={purchasing}
style={{
background: 'linear-gradient(135deg, #2563eb 0%, #1d4ed8 100%)',
boxShadow: '0 2px 4px rgba(37,99,235,0.2)',
}}
>
一键采购 50 个通用 Token
</Button>
<Button icon={<ReloadOutlined />} onClick={loadData} loading={loadingStats}>
刷新状态
</Button>
</Space>
}
style={{ marginBottom: 24, borderRadius: 8 }}
/>
{/* 顶部高质感指标卡片 */}
<Row gutter={[16, 16]} style={{ marginBottom: 20 }}>
<Col xs={24} sm={12} lg={6}>
<div className="metric-card-box">
<div className="metric-card-header">
<span className="metric-card-title">可用通用库存 (Available)</span>
<div className={`metric-card-icon ${isStockLow ? 'metric-card-icon--rose' : ''}`}>
<ShoppingCartOutlined />
</div>
</div>
<div className="metric-card-value" style={{ color: isStockLow ? '#e11d48' : '#0f172a' }}>
{availableStock}
<span style={{ fontSize: 13, fontWeight: 500, marginLeft: 4, color: '#64748b' }}>个</span>
</div>
<div className="metric-card-footer">
<span>警戒水位: {warningStock} 个</span>
{isStockLow ? (
<Tag color="error" style={{ margin: 0, borderRadius: 4 }}>库存紧缺</Tag>
) : (
<span style={{ color: '#10b981', fontWeight: 600 }}>储备充足</span>
)}
</div>
</div>
</Col>
<Col xs={24} sm={12} lg={6}>
<div className="metric-card-box">
<div className="metric-card-header">
<span className="metric-card-title">绑定错误阻断 (Mismatch)</span>
<div className={`metric-card-icon ${hasMismatch ? 'metric-card-icon--rose' : ''}`}>
<ExclamationCircleOutlined />
</div>
</div>
<div className="metric-card-value" style={{ color: hasMismatch ? '#e11d48' : '#0f172a' }}>
{stats?.mismatch_stock ?? 0}
<span style={{ fontSize: 13, fontWeight: 500, marginLeft: 4, color: '#64748b' }}>个</span>
</div>
<div className="metric-card-footer">
<span>{hasMismatch ? 'UID强一致校验拦截保护' : '暂无异常阻断'}</span>
{hasMismatch ? (
<Tag color="error" style={{ margin: 0, borderRadius: 4 }}>需核对处理</Tag>
) : (
<span style={{ color: '#10b981', fontWeight: 600 }}>状态正常</span>
)}
</div>
</div>
</Col>
<Col xs={24} sm={12} lg={6}>
<div className="metric-card-box">
<div className="metric-card-header">
<span className="metric-card-title">已履约交付 (Redeemed)</span>
<div className="metric-card-icon metric-card-icon--emerald">
<CheckCircleOutlined />
</div>
</div>
<div className="metric-card-value">
{stats?.redeemed_stock ?? 0}
<span style={{ fontSize: 13, fontWeight: 500, marginLeft: 4, color: '#64748b' }}>个</span>
</div>
<div className="metric-card-footer">
<span>当前扫码中</span>
<span style={{ fontWeight: 600, color: '#2563eb' }}>{stats?.using_stock ?? 0} 个</span>
</div>
</div>
</Col>
<Col xs={24} sm={12} lg={6}>
<div className="metric-card-box">
<div className="metric-card-header">
<span className="metric-card-title">0666.pro 账号积分</span>
<div className="metric-card-icon metric-card-icon--purple">
<FireOutlined />
</div>
</div>
<div className="metric-card-value" style={{ color: '#7c3aed' }}>
{(stats?.upstream_points ?? 0).toFixed(1)}
<span style={{ fontSize: 13, fontWeight: 500, marginLeft: 4, color: '#64748b' }}>点</span>
</div>
<div className="metric-card-footer">
<span>账号: {stats?.username || '未同步'}</span>
<span>约可采购 <strong style={{ color: '#0f172a' }}>{Math.floor((stats?.upstream_points ?? 0) / 21)}</strong> 个</span>
</div>
</div>
</Col>
</Row>
{/* 核心控制与上游策略看板 */}
<Card
style={{
marginBottom: 20,
borderRadius: 12,
border: '1px solid #e2e8f0',
boxShadow: 'var(--shadow-sm)',
}}
styles={{ body: { padding: '20px 24px' } }}
>
{/* 通道状态与软熔断横幅 */}
<div
style={{
display: 'flex',
alignItems: 'center',
justifyContent: 'space-between',
padding: '14px 18px',
borderRadius: 8,
marginBottom: 20,
background: autoDelivery ? '#f0fdf4' : '#fef2f2',
border: autoDelivery ? '1px solid #bbf7d0' : '1px solid #fecaca',
transition: 'all 0.3s ease',
}}
>
<div style={{ display: 'flex', alignItems: 'center', gap: 12 }}>
<div
style={{
width: 38,
height: 38,
borderRadius: 8,
display: 'flex',
alignItems: 'center',
justifyContent: 'center',
fontSize: 18,
background: autoDelivery ? '#dcfce7' : '#fee2e2',
color: autoDelivery ? '#16a34a' : '#dc2626',
}}
>
{autoDelivery ? <SafetyCertificateOutlined /> : <ControlOutlined />}
</div>
<div>
<div style={{ display: 'flex', alignItems: 'center', gap: 8 }}>
<strong style={{ fontSize: 14, color: autoDelivery ? '#166534' : '#991b1b' }}>
{autoDelivery
? '自动发货通道正常运转 (Active)'
: '自动发货已全局软熔断 (Kill Switch Engaged)'}
</strong>
<Tag color={autoDelivery ? 'success' : 'error'} style={{ borderRadius: 10 }}>
{autoDelivery ? '反代履约中' : '已转交人工打手'}
</Tag>
</div>
<div style={{ fontSize: 12, color: autoDelivery ? '#15803d' : '#b91c1c', marginTop: 2 }}>
{autoDelivery
? '和平精英「黑色 ROCK 长袖」与「蓝色运动服」开启 0666.pro 全自动反代发货,UID 强一致安全门禁全面守护。'
: '两款商品已彻底切断上游 0666.pro 自动发货通道,所有新订单均保留在待发货状态,由人工接单平台处理。'}
</div>
</div>
</div>
<Space size="middle">
<Switch
checked={autoDelivery}
onChange={handleToggleAutoDelivery}
checkedChildren="开启"
unCheckedChildren="熔断"
style={{
backgroundColor: autoDelivery ? '#16a34a' : '#dc2626',
}}
/>
<Button
size="small"
danger={autoDelivery}
type={autoDelivery ? 'default' : 'primary'}
onClick={() => handleToggleAutoDelivery(!autoDelivery)}
>
{autoDelivery ? '一键紧急熔断' : '恢复自动发货'}
</Button>
</Space>
</div>
{/* 策略表单 */}
<Form form={form} layout="vertical">
<Row gutter={24}>
<Col xs={24} md={12}>
<Form.Item
label={
<Space>
<Text strong>自动发货总开关 (Kill Switch)</Text>
<Tooltip title="关闭后黑色 ROCK 与蓝色运动服两款商品停走自动发货通道,平滑转人工打手接单">
<ExclamationCircleOutlined />
</Tooltip>
</Space>
}
<Col xs={24} lg={12}>
<div
style={{
background: '#f8fafc',
padding: '16px 18px',
borderRadius: 10,
border: '1px solid #f1f5f9',
height: '100%',
}}
>
<Space size="middle">
<Switch
checked={autoDelivery}
onChange={handleToggleAutoDelivery}
checkedChildren="自动发货中"
unCheckedChildren="已熔断转人工"
/>
<Text type={autoDelivery ? 'success' : 'danger'}>
{autoDelivery ? '通道正常,全自动反代履约中' : '已熔断!商品已下线自动通道转交人工处理'}
</Text>
</Space>
</Form.Item>
</Col>
<div style={{ display: 'flex', alignItems: 'center', gap: 8, marginBottom: 16 }}>
<KeyOutlined style={{ color: '#2563eb', fontSize: 16 }} />
<strong style={{ fontSize: 14, color: '#0f172a' }}>0666.pro 采购认证凭据</strong>
</div>
<Col xs={24} md={12}>
<Form.Item name="base_url" label="上游平台接口地址 (Base URL)">
<Input placeholder="https://0666.pro" />
</Form.Item>
</Col>
<Form.Item name="base_url" label="上游平台接口地址 (Base URL)" style={{ marginBottom: 14 }}>
<Input placeholder="https://0666.pro" />
</Form.Item>
<Col xs={24}>
<Form.Item
name="bearer_token"
label={
<Space>
<Text strong>上游商户 Bearer Token (yd_token)</Text>
<Text type="secondary" style={{ fontSize: 12 }}>
(平台无密码,直接输入从 0666.pro 网页复制的 64 位 Token)
</Text>
</Space>
}
extra={
<div style={{ marginTop: 4 }}>
<Text type="secondary" style={{ fontSize: 12 }}>
💡 极简提取指引:登录 0666.pro 网页后,按 F12 打开控制台,在 Console 执行{' '}
<code>localStorage.getItem('yd_token')</code> 即可一键复制。
</Text>
</div>
}
>
<Input.Password
placeholder="粘贴 64 位十六进制 Bearer Token"
addonAfter={
<Button type="link" size="small" onClick={handleTestConnection} loading={testingConn}>
测试连通性
</Button>
<Form.Item
name="bearer_token"
label={
<Space>
<span>上游商户 Bearer Token (yd_token)</span>
<Tooltip title="0666.pro 采用无密码架构,直接从网页 localStorage 提取 64 位十六进制 Token 即可">
<ExclamationCircleOutlined style={{ color: '#94a3b8' }} />
</Tooltip>
</Space>
}
/>
</Form.Item>
style={{ marginBottom: 12 }}
>
<Input.Password
placeholder="粘贴 64 位十六进制 Bearer Token"
addonAfter={
<Button
type="link"
size="small"
onClick={handleTestConnection}
loading={testingConn}
style={{ padding: '0 4px', height: 'auto' }}
>
测试连通性
</Button>
}
/>
</Form.Item>
<div
style={{
background: '#eff6ff',
border: '1px dashed #bfdbfe',
borderRadius: 6,
padding: '8px 12px',
fontSize: 12,
color: '#1e40af',
}}
>
💡 <strong>极简提取指引:</strong>登录 0666.pro 网页后,按 F12 打开控制台,在 Console 执行{' '}
<Text code copyable={{ text: "localStorage.getItem('yd_token')" }}>
localStorage.getItem('yd_token')
</Text>{' '}
即可一键复制。
</div>
</div>
</Col>
<Col xs={24} sm={12} md={6}>
<Form.Item name="token_warning_stock" label="库存告警安全水位">
<InputNumber min={1} max={500} style={{ width: '100%' }} addonAfter="个" />
</Form.Item>
</Col>
<Col xs={24} lg={12}>
<div
style={{
background: '#f8fafc',
padding: '16px 18px',
borderRadius: 10,
border: '1px solid #f1f5f9',
height: '100%',
}}
>
<div style={{ display: 'flex', alignItems: 'center', gap: 8, marginBottom: 16 }}>
<ThunderboltOutlined style={{ color: '#7c3aed', fontSize: 16 }} />
<strong style={{ fontSize: 14, color: '#0f172a' }}>库存风控与自动补货策略</strong>
</div>
<Col xs={24} sm={12} md={6}>
<Form.Item name="auto_purchase_enabled" label="自动补货触发开关" valuePropName="checked">
<Switch checkedChildren="开启自动采购" unCheckedChildren="关闭" />
</Form.Item>
</Col>
<Col xs={24} sm={12} md={6}>
<Form.Item name="auto_purchase_count" label="单次自动补货数量">
<InputNumber min={5} max={200} style={{ width: '100%' }} addonAfter="个" />
</Form.Item>
</Col>
<Col xs={24} sm={12} md={6}>
<Form.Item name="purchase_cooldown_minutes" label="补货防抖冷却时间">
<InputNumber min={1} max={60} style={{ width: '100%' }} addonAfter="分钟" />
</Form.Item>
<Row gutter={16}>
<Col span={12}>
<Form.Item name="token_warning_stock" label="库存告警安全水位">
<InputNumber min={1} max={500} style={{ width: '100%' }} addonAfter="个" />
</Form.Item>
</Col>
<Col span={12}>
<Form.Item name="auto_purchase_enabled" label="自动补货触发开关" valuePropName="checked">
<Switch checkedChildren="开启自动补货" unCheckedChildren="关闭" />
</Form.Item>
</Col>
<Col span={12}>
<Form.Item name="auto_purchase_count" label="单次自动补货数量">
<InputNumber min={5} max={200} style={{ width: '100%' }} addonAfter="个" />
</Form.Item>
</Col>
<Col span={12}>
<Form.Item name="purchase_cooldown_minutes" label="补货防抖冷却时间">
<InputNumber min={1} max={60} style={{ width: '100%' }} addonAfter="分钟" />
</Form.Item>
</Col>
</Row>
</div>
</Col>
</Row>
<Divider style={{ margin: '12px 0 20px 0' }} />
<Divider style={{ margin: '18px 0 16px 0' }} />
<Space>
<Button type="primary" onClick={handleSaveConfig} loading={savingConfig}>
<div style={{ display: 'flex', justifyContent: 'flex-end' }}>
<Button
type="primary"
onClick={handleSaveConfig}
loading={savingConfig}
style={{
background: 'linear-gradient(135deg, #2563eb 0%, #1d4ed8 100%)',
minWidth: 130,
}}
>
保存策略配置
</Button>
</Space>
</div>
</Form>
</Card>
{/* 本地通用库存池明细 */}
{/* 筛选与搜索工具条(对齐标杆页面) */}
<Card
title={
<Space>
<ThunderboltOutlined />
<span>通用 Token 库存池与错单审计列表</span>
</Space>
}
extra={
<Space>
<Radio.Group value={filterStatus} onChange={(e) => setFilterStatus(e.target.value)} buttonStyle="solid">
<Radio.Button value="all">全部</Radio.Button>
<Radio.Button value="available">可用</Radio.Button>
<Radio.Button value="using">使用中</Radio.Button>
<Radio.Button value="bound">已绑定</Radio.Button>
<Radio.Button value="redeemed">已发货</Radio.Button>
<Radio.Button value="mismatch">
<Badge count={stats?.mismatch_stock ?? 0} offset={[8, -2]}>
<span>绑定错误</span>
</Badge>
</Radio.Button>
</Radio.Group>
<Input
placeholder="搜索订单号 / UID / 角色名"
allowClear
prefix={<SearchOutlined />}
style={{ width: 220 }}
onPressEnter={(e) => setSearchKeyword(e.currentTarget.value)}
onChange={(e) => {
if (!e.target.value) setSearchKeyword('')
}}
/>
<Button icon={<ReloadOutlined />} onClick={loadTokens} loading={loadingTokens}>
刷新
</Button>
</Space>
}
style={{ borderRadius: 8 }}
styles={{ body: { padding: '16px 20px' } }}
style={{ marginBottom: 16, borderRadius: 10, border: '1px solid #e2e8f0' }}
>
<Table
rowKey="id"
columns={columns}
dataSource={tokens}
loading={loadingTokens}
pagination={{
current: page,
pageSize,
total: totalTokens,
showSizeChanger: true,
onChange: (p, ps) => {
setPage(p)
setPageSize(ps)
},
}}
/>
<Row gutter={[16, 12]} align="middle" justify="space-between">
<Col xs={24} md={16}>
<Space size="middle" wrap>
<Input
placeholder="搜索订单号 / UID / 角色名 / 提取码"
prefix={<SearchOutlined style={{ color: '#94a3b8' }} />}
value={searchKeyword}
onChange={(e) => setSearchKeyword(e.target.value)}
onPressEnter={loadTokens}
style={{ width: 280 }}
allowClear
/>
<Radio.Group
value={filterStatus}
onChange={(e) => {
setFilterStatus(e.target.value)
setPage(1)
}}
buttonStyle="solid"
>
<Radio.Button value="all">全部</Radio.Button>
<Radio.Button value="available">可用</Radio.Button>
<Radio.Button value="using">使用中</Radio.Button>
<Radio.Button value="bound">已绑定</Radio.Button>
<Radio.Button value="redeemed">已发货</Radio.Button>
<Radio.Button value="mismatch">
<Badge count={stats?.mismatch_stock ?? 0} offset={[6, -2]} size="small">
<span>绑定错误</span>
</Badge>
</Radio.Button>
</Radio.Group>
<Button icon={<ReloadOutlined />} onClick={loadTokens} loading={loadingTokens}>
刷新
</Button>
</Space>
</Col>
<Col xs={24} md={8} style={{ textAlign: 'right' }}>
<Text type="secondary" style={{ fontSize: 13 }}>
共检索到 <strong style={{ color: '#0f172a' }}>{totalTokens}</strong> 条库存记录
</Text>
</Col>
</Row>
</Card>
{/* 主库存与错单审计表格 */}
<Table
rowKey="id"
columns={columns}
dataSource={tokens}
loading={loadingTokens}
scroll={{ x: 1100 }}
pagination={{
current: page,
pageSize,
total: totalTokens,
showSizeChanger: true,
pageSizeOptions: ['10', '20', '50', '100'],
showTotal: (total) => `共 ${total} 条库存记录`,
onChange: (p, ps) => {
setPage(p)
setPageSize(ps)
},
}}
/>
</div>
)
}