Files
affiliate_dash/frontend/src/App.tsx
T
yml2213 ef7f67dd0c feat(fulfillment): 接入Rock发货平台(0666.pro)代理履约、通用库存池与UID强一致风控
1. 数据库新增 012_rock_fulfillment 迁移,创建 rock_configs 配置表与 rock_tokens 通用库存表,补齐黑色ROCK长袖T恤与蓝色运动服上衣商品目录;
2. 封装 RockClient 与 RockService,实现 0666.pro 平台 Bearer Token 极简连通校验、批量采购50个入库、水位监控巡检与自动补货;
3. 新增 RockProvider 实现标准履约路由,引入 Anti-Ghost 旧绑定基线比对与 UID 强一致门禁,扫错号硬阻断并记录为 mismatch 状态;
4. 针对黑色ROCK与蓝色运动服实现动态发货(绑定后发货前动态选择 skin),并提取腾讯官方发货流水号 fulfillId 对账;
5. 新增全局自动发货总开关(Kill Switch),支持一键软熔断降级转人工接单处理;
6. 前端新增 PlatformRock 管理大屏,提供总开关切换、Token配置与连通测试、库存监控、一键补货及错单解冻重置。
2026-10-05 14:56:11 +08:00

168 lines
6.1 KiB
TypeScript

import { BrowserRouter, Navigate, Route, Routes, useLocation } from 'react-router-dom'
import { ConfigProvider, App as AntdApp, Spin } from 'antd'
import zhCN from 'antd/locale/zh_CN'
import { AuthProvider, useAuth } from './store/auth'
import MainLayout from './layouts/MainLayout'
import Login from './pages/Login'
import Dashboard from './pages/Dashboard'
import OpenApiDocs from './pages/OpenApiDocs'
import ApiDebugger from './pages/ApiDebugger'
import Delivery from './pages/Delivery'
import MerchantCenter from './pages/MerchantCenter'
import MerchantRecharge from './pages/MerchantRecharge'
import AlertSettings from './pages/AlertSettings'
import PlatformMerchants from './pages/PlatformMerchants'
import PlatformProducts from './pages/PlatformProducts'
import PlatformUsers from './pages/PlatformUsers'
import PlatformRock from './pages/PlatformRock'
import type { ReactNode } from 'react'
function PrivateRoute({ children }: { children: ReactNode }) {
const { token } = useAuth()
if (!token) return <Navigate to="/login" replace />
return <>{children}</>
}
function AdminRoute({ children }: { children: ReactNode }) {
const { isAdmin } = useAuth()
if (!isAdmin) return <Navigate to="/" replace />
return <>{children}</>
}
const tabPermissions: Record<string, string> = {
products: 'products:manage',
orders: 'orders:manage',
wallet: 'wallet:ledger',
api: 'api:manage',
callbacks: 'callbacks:manage',
members: 'members:manage',
}
function MerchantPermissionRoute({ permission, children }: { permission?: string; children: ReactNode }) {
const { isAdmin, merchantLoading, merchantPermissions } = useAuth()
if (isAdmin || !permission) return <>{children}</>
if (merchantLoading) {
return <div style={{ textAlign: 'center', padding: '100px 0' }}><Spin size="large" /></div>
}
return merchantPermissions.includes(permission) ? <>{children}</> : <Navigate to="/" replace />
}
function MerchantCenterRoute() {
const location = useLocation()
const requestedTab = new URLSearchParams(location.search).get('tab') || 'products'
const tab = requestedTab in tabPermissions ? requestedTab : 'products'
return (
<MerchantPermissionRoute permission={tabPermissions[tab]}>
<MerchantCenter />
</MerchantPermissionRoute>
)
}
function AppRoutes() {
return (
<Routes>
<Route path="/login" element={<Login />} />
<Route path="/delivery/:channel/:orderNo" element={<Delivery />} />
<Route
path="/"
element={
<PrivateRoute>
<MainLayout />
</PrivateRoute>
}
>
<Route index element={<Dashboard />} />
<Route path="merchant-center" element={<MerchantCenterRoute />} />
<Route path="merchant-products" element={<MerchantPermissionRoute permission="products:manage"><MerchantCenter fixedTab="products" title="商品列表" /></MerchantPermissionRoute>} />
<Route path="merchant-orders" element={<MerchantPermissionRoute permission="orders:manage"><MerchantCenter fixedTab="orders" title="发货订单" /></MerchantPermissionRoute>} />
<Route path="merchant-wallet" element={<MerchantPermissionRoute permission="wallet:ledger"><MerchantCenter fixedTab="wallet" title="积分明细" /></MerchantPermissionRoute>} />
<Route path="merchant-recharge" element={<MerchantPermissionRoute permission="wallet:view"><MerchantRecharge /></MerchantPermissionRoute>} />
<Route path="merchant-alert-settings" element={<MerchantPermissionRoute permission="recharge:manage"><AlertSettings /></MerchantPermissionRoute>} />
<Route path="merchant-members" element={<MerchantPermissionRoute permission="members:manage"><MerchantCenter fixedTab="members" title="成员" /></MerchantPermissionRoute>} />
<Route path="merchant-callbacks" element={<MerchantPermissionRoute permission="callbacks:manage"><MerchantCenter fixedTab="callbacks" title="回调" /></MerchantPermissionRoute>} />
<Route path="merchant-api-keys" element={<MerchantPermissionRoute permission="api:manage"><MerchantCenter fixedTab="api" title="API 密钥" /></MerchantPermissionRoute>} />
<Route
path="platform-merchants"
element={
<AdminRoute>
<PlatformMerchants />
</AdminRoute>
}
/>
<Route
path="platform-products"
element={
<AdminRoute>
<PlatformProducts />
</AdminRoute>
}
/>
<Route
path="platform-rock"
element={
<AdminRoute>
<PlatformRock />
</AdminRoute>
}
/>
<Route path="platform-users" element={<AdminRoute><PlatformUsers /></AdminRoute>} />
<Route path="open-api" element={<MerchantPermissionRoute permission="api:manage"><OpenApiDocs /></MerchantPermissionRoute>} />
<Route
path="api-debug"
element={
<AdminRoute>
<ApiDebugger />
</AdminRoute>
}
/>
</Route>
<Route path="*" element={<Navigate to="/" replace />} />
</Routes>
)
}
export default function App() {
return (
<ConfigProvider
locale={zhCN}
theme={{
token: {
colorPrimary: '#2563eb',
colorInfo: '#2563eb',
colorSuccess: '#16a34a',
colorWarning: '#d97706',
colorError: '#dc2626',
borderRadius: 8,
fontFamily: `-apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif`,
},
components: {
Card: {
paddingLG: 20,
borderRadiusLG: 10,
},
Table: {
headerBg: '#f8fafc',
headerColor: '#475569',
headerSplitColor: 'transparent',
rowHoverBg: '#f1f5f9',
},
Button: {
fontWeight: 600,
borderRadius: 6,
},
Tag: {
borderRadiusSM: 4,
},
},
}}
>
<AntdApp>
<AuthProvider>
<BrowserRouter>
<AppRoutes />
</BrowserRouter>
</AuthProvider>
</AntdApp>
</ConfigProvider>
)
}