diff --git a/frontend/src/pages/PlatformRock.tsx b/frontend/src/pages/PlatformRock.tsx index d398f77..996108b 100644 --- a/frontend/src/pages/PlatformRock.tsx +++ b/frontend/src/pages/PlatformRock.tsx @@ -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) => ( - #{id} - - {record.redeem_code?.substring(0, 10)}... + #{id} + + {record.redeem_code ? `${record.redeem_code.substring(0, 10)}...` : '-'} ), }, { - title: '颜色与适用范围', + title: '规格与适用范围', dataIndex: 'color', - width: 130, + width: 150, render: (_, record) => ( - 通用黑色 Token + + 通用黑色 Token + - {record.region || 'Q/V可用'} + {record.region || 'Q/V区通用 · 自动分发'} ), }, { - title: '状态', + title: '库存状态', dataIndex: 'status', - width: 120, + width: 140, render: (status) => { switch (status) { case 'available': - return 可用库存 + return ( + + ● 可用库存 + + ) case 'using': - return 使用中 (扫码) + return ( + + ● 扫码使用中 + + ) case 'bound': - return 已绑定授权 + return ( + + ● 已授权绑定 + + ) case 'redeemed': - return 已交付发货 + return ( + + ● 已交付发货 + + ) case 'mismatch': - return 绑定错误 (阻断) + return ( + + ⚠️ 绑定错误 (阻断) + + ) default: return {status} } }, }, { - title: '关联订单', + title: '关联业务工单', dataIndex: 'assigned_order_no', - width: 170, + width: 190, render: (orderNo) => orderNo ? ( - + {orderNo} ) : ( @@ -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 ( - -
- 预期UID: - {record.expected_uid || '-'} +
+
+ 预期 UID: + {record.expected_uid || '-'}
-
- 扫码角色: - +
+ 扫码反查: + {record.actual_role_name ? `${record.actual_role_name} (${record.actual_role_id || '-'})` : '-'}
- {hasMismatch && record.mismatch_reason && ( - - - {record.mismatch_reason} - - + {isMismatch && record.mismatch_reason && ( +
+ + + {record.mismatch_reason} + + +
)} - +
) }, }, { title: '官方发货凭证 (FulfillId)', dataIndex: 'upstream_fulfill_id', - width: 150, + width: 180, render: (fulfillId, record) => fulfillId ? ( - + {fulfillId} - - {record.target_skin || '和平精英道具'} - +
+ + {record.target_skin || '和平精英道具'} + +
) : ( - @@ -305,16 +343,19 @@ export default function PlatformRock() { { title: '操作', key: 'action', - width: 100, + width: 120, + fixed: 'right', render: (_, record) => { if (record.status === 'mismatch') { return ( handleResetToken(record.id)} > - @@ -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 ( -
+
- - {/* 熔断状态警示条 */} - {!autoDelivery && ( - - )} - - {/* 核心指标统计看板 */} - - - - } - suffix="个" - /> -
- - 警戒水位: {config?.token_warning_stock ?? 10} 个 - - {isStockLow && 库存紧缺} -
-
- - - - - 0 ? '#f5222d' : '#8c8c8c', fontWeight: 'bold' }} - prefix={} - suffix="个" - /> -
- - {(stats?.mismatch_stock ?? 0) > 0 ? '存在 UID 校验不匹配的待排查记录' : '当前无绑定异常'} - -
-
- - - - - } - suffix={`(扫码中: ${stats?.using_stock ?? 0})`} - /> -
- - 已完成发货交付总量 - -
-
- - - - - } - suffix="点" - /> -
- - 账号: {stats?.username || '未同步'} - - - 约可采购 {Math.floor((stats?.upstream_points ?? 0) / 21)} 个 - -
-
- -
- - {/* 上游凭据与策略设置 */} - - - 0666.pro 采购凭据与自动发货控制 - - } + subtitle="和平精英「黑色ROCK长袖T恤」与「蓝色运动服上衣」通用库存池、上游采购、UID强一致防错门禁与软熔断机制" extra={ - - + + } - style={{ marginBottom: 24, borderRadius: 8 }} + /> + + {/* 顶部高质感指标卡片 */} + + +
+
+ 可用通用库存 (Available) +
+ +
+
+
+ {availableStock} + 个 +
+
+ 警戒水位: {warningStock} 个 + {isStockLow ? ( + 库存紧缺 + ) : ( + 储备充足 + )} +
+
+ + + +
+
+ 绑定错误阻断 (Mismatch) +
+ +
+
+
+ {stats?.mismatch_stock ?? 0} + 个 +
+
+ {hasMismatch ? 'UID强一致校验拦截保护' : '暂无异常阻断'} + {hasMismatch ? ( + 需核对处理 + ) : ( + 状态正常 + )} +
+
+ + + +
+
+ 已履约交付 (Redeemed) +
+ +
+
+
+ {stats?.redeemed_stock ?? 0} + 个 +
+
+ 当前扫码中 + {stats?.using_stock ?? 0} 个 +
+
+ + + +
+
+ 0666.pro 账号积分 +
+ +
+
+
+ {(stats?.upstream_points ?? 0).toFixed(1)} + 点 +
+
+ 账号: {stats?.username || '未同步'} + 约可采购 {Math.floor((stats?.upstream_points ?? 0) / 21)} 个 +
+
+ +
+ + {/* 核心控制与上游策略看板 */} + + {/* 通道状态与软熔断横幅 */} +
+
+
+ {autoDelivery ? : } +
+
+
+ + {autoDelivery + ? '自动发货通道正常运转 (Active)' + : '自动发货已全局软熔断 (Kill Switch Engaged)'} + + + {autoDelivery ? '反代履约中' : '已转交人工打手'} + +
+
+ {autoDelivery + ? '和平精英「黑色 ROCK 长袖」与「蓝色运动服」开启 0666.pro 全自动反代发货,UID 强一致安全门禁全面守护。' + : '两款商品已彻底切断上游 0666.pro 自动发货通道,所有新订单均保留在待发货状态,由人工接单平台处理。'} +
+
+
+ + + + +
+ + {/* 策略表单 */}
- - - 自动发货总开关 (Kill Switch) - - - - - } + +
- - - - {autoDelivery ? '通道正常,全自动反代履约中' : '已熔断!商品已下线自动通道转交人工处理'} - - - - +
+ + 0666.pro 采购认证凭据 +
- - - - - + + + - - - 上游商户 Bearer Token (yd_token) - - (平台无密码,直接输入从 0666.pro 网页复制的 64 位 Token) - - - } - extra={ -
- - 💡 极简提取指引:登录 0666.pro 网页后,按 F12 打开控制台,在 Console 执行{' '} - localStorage.getItem('yd_token') 即可一键复制。 - -
- } - > - - 测试连通性 - + + 上游商户 Bearer Token (yd_token) + + + + } - /> - + style={{ marginBottom: 12 }} + > + + 测试连通性 + + } + /> +
+ +
+ 💡 极简提取指引:登录 0666.pro 网页后,按 F12 打开控制台,在 Console 执行{' '} + + localStorage.getItem('yd_token') + {' '} + 即可一键复制。 +
+
- - - - - + +
+
+ + 库存风控与自动补货策略 +
- - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + +
- + - - - +
- {/* 本地通用库存池明细 */} + {/* 筛选与搜索工具条(对齐标杆页面) */} - - 通用 Token 库存池与错单审计列表 - - } - extra={ - - setFilterStatus(e.target.value)} buttonStyle="solid"> - 全部 - 可用 - 使用中 - 已绑定 - 已发货 - - - 绑定错误 - - - - - } - style={{ width: 220 }} - onPressEnter={(e) => setSearchKeyword(e.currentTarget.value)} - onChange={(e) => { - if (!e.target.value) setSearchKeyword('') - }} - /> - - - } - style={{ borderRadius: 8 }} + styles={{ body: { padding: '16px 20px' } }} + style={{ marginBottom: 16, borderRadius: 10, border: '1px solid #e2e8f0' }} > - { - setPage(p) - setPageSize(ps) - }, - }} - /> + + + + } + value={searchKeyword} + onChange={(e) => setSearchKeyword(e.target.value)} + onPressEnter={loadTokens} + style={{ width: 280 }} + allowClear + /> + { + setFilterStatus(e.target.value) + setPage(1) + }} + buttonStyle="solid" + > + 全部 + 可用 + 使用中 + 已绑定 + 已发货 + + + 绑定错误 + + + + + + + + + 共检索到 {totalTokens} 条库存记录 + + + + + {/* 主库存与错单审计表格 */} +
`共 ${total} 条库存记录`, + onChange: (p, ps) => { + setPage(p) + setPageSize(ps) + }, + }} + /> ) } +