feat(pdd-cookie): 持久化保存Cookie校验状态时间并在失效时发送内部告警通知

This commit is contained in:
yml2213
2026-09-12 15:26:40 +08:00
parent ffa3374483
commit c8f7e48746
6 changed files with 241 additions and 48 deletions
@@ -63,6 +63,25 @@ import type {
const { Text, Paragraph } = Typography
/**
* Format ISO date string into readable short format
* 格式化 ISO 时间字符串为月-日 时:分
*/
function formatDisplayTime(dateStr?: string): string {
if (!dateStr) return ''
try {
const d = new Date(dateStr)
if (isNaN(d.getTime())) return String(dateStr)
const month = String(d.getMonth() + 1).padStart(2, '0')
const day = String(d.getDate()).padStart(2, '0')
const hours = String(d.getHours()).padStart(2, '0')
const minutes = String(d.getMinutes()).padStart(2, '0')
return `${month}-${day} ${hours}:${minutes}`
} catch {
return String(dateStr)
}
}
/**
* Extended test result with execution timestamp
* 带时间戳的 CK 校验结果结构
@@ -88,7 +107,7 @@ export function PddPlatformPanel() {
const [syncingShopId, setSyncingShopId] = useState<string | null>(null)
const [togglingShopId, setTogglingShopId] = useState<string | null>(null)
// Test results cache by shopId / 店铺 CK 校验结果缓存
// Test results cache by shopId / 店铺 CK 校验结果缓存 (用于刚点击测试后的即时响应)
const [testResults, setTestResults] = useState<Record<string, ExtendedTestResult>>({})
// Modal State / 弹窗表单状态
@@ -163,6 +182,8 @@ export function PddPlatformPanel() {
} else {
showSuccess('全量店铺同步完成')
}
// Refresh persistent statuses
await loadConfig()
} catch (err) {
showError(err instanceof Error ? err.message : '触发全店铺同步失败')
} finally {
@@ -190,6 +211,8 @@ export function PddPlatformPanel() {
} else {
showSuccess(`店铺【${store.shopName}】同步已触发`)
}
// Refresh persistent store status
await loadConfig()
} catch (err) {
showError(err instanceof Error ? err.message : `店铺【${store.shopName}】同步失败`)
} finally {
@@ -199,7 +222,7 @@ export function PddPlatformPanel() {
/**
* Live test MMS Cookie validity for a store
* 针对指定店铺实时测试 Cookie 有效性
* 针对指定店铺实时测试 Cookie 有效性 (持久化保存结果,失效时向系统自动发送通知)
*/
async function handleTestCookie(store: AdminPddStoreItem) {
setTestingShopId(store.shopId)
@@ -216,12 +239,16 @@ export function PddPlatformPanel() {
...prev,
[store.shopId]: { ...result, testedAt: nowStr },
}))
// Reload persisted state
await loadConfig()
if (result.valid) {
showSuccess(
`【${store.shopName}】Cookie 校验通过,在售/历史订单总数: ${result.totalOrders ?? 0}`,
`【${store.shopName}】Cookie 校验通过,在线在售/历史订单数: ${result.totalOrders ?? 0}`,
)
} else {
showError(`【${store.shopName}】Cookie 校验未通过: ${result.message}`)
showError(
`【${store.shopName}】Cookie 校验未通过: ${result.message}(已触发内部告警通知)`,
)
}
}
} catch (err) {
@@ -361,10 +388,17 @@ export function PddPlatformPanel() {
}
}
// Calculate statistics / 计算统计数据
// Calculate statistics / 计算统计数据 (结合持久化历史状态与即时状态)
const totalStores = config.stores.length
const enabledStores = config.stores.filter((s) => s.enabled).length
const validStores = Object.values(testResults).filter((r) => r.valid).length
const validStores = config.stores.filter((s) => {
const rt = testResults[s.shopId]
return rt ? rt.valid : s.cookieValid === true
}).length
const invalidStores = config.stores.filter((s) => {
const rt = testResults[s.shopId]
return rt ? !rt.valid : s.cookieValid === false
}).length
// Table columns definition / 表格列配置
const columns: TableColumnsType<AdminPddStoreItem> = [
@@ -460,40 +494,49 @@ export function PddPlatformPanel() {
{
title: 'Cookie 校验状态',
key: 'testStatus',
width: 190,
width: 210,
render: (_, record) => {
// Priority: local test cache, fallback to persisted store status
// 优先显示本次测试结果,刷新后自动读取持久化历史状态与时间戳
const testRes = testResults[record.shopId]
if (!testRes) {
return <Badge status="default" text={<Text type="secondary">未校验</Text>} />
}
if (testRes.valid) {
const isValid = testRes ? testRes.valid : record.cookieValid
const message = testRes ? testRes.message : record.cookieCheckMessage
const totalOrders = testRes ? testRes.totalOrders : record.totalOrders
const timeDisplay = testRes?.testedAt || formatDisplayTime(record.lastCheckedAt)
if (isValid === true) {
return (
<Space direction="vertical" size={2}>
<Tag icon={<CheckCircleOutlined />} color="success">
有效 (在售/历史: {testRes.totalOrders ?? 0})
有效 (在售: {totalOrders ?? '-'})
</Tag>
{testRes.testedAt && (
{timeDisplay && (
<Text type="secondary" style={{ fontSize: '11px' }}>
{testRes.testedAt} 测活
{timeDisplay} 校验
</Text>
)}
</Space>
)
}
return (
<Space direction="vertical" size={2}>
<Tooltip title={testRes.message || 'Cookie 失效或风控拦截'}>
<Tag icon={<CloseCircleOutlined />} color="error" style={{ cursor: 'pointer' }}>
失效 (点击查看)
</Tag>
</Tooltip>
{testRes.testedAt && (
<Text type="secondary" style={{ fontSize: '11px' }}>
{testRes.testedAt} 测活
</Text>
)}
</Space>
)
if (isValid === false) {
return (
<Space direction="vertical" size={2}>
<Tooltip title={message || 'Cookie 失效或登录已过期,已发送内部告警通知'}>
<Tag icon={<CloseCircleOutlined />} color="error" style={{ cursor: 'pointer' }}>
失效 (已告警)
</Tag>
</Tooltip>
{timeDisplay && (
<Text type="secondary" style={{ fontSize: '11px' }}>
{timeDisplay} 校验
</Text>
)}
</Space>
)
}
return <Badge status="default" text={<Text type="secondary">未校验</Text>} />
},
},
{
@@ -503,7 +546,7 @@ export function PddPlatformPanel() {
fixed: 'right',
render: (_, record) => (
<Space size={6} wrap={false}>
<Tooltip title="通过 Pure TS 0as 引擎实时测试 MMS 商家 Cookie 有效性">
<Tooltip title="通过 Pure TS 0as 引擎实时测试 MMS 商家 Cookie 有效性并持久化校验状态">
<Button
size="small"
icon={<ThunderboltOutlined />}
@@ -628,17 +671,26 @@ export function PddPlatformPanel() {
display: 'flex',
justifyContent: 'space-between',
alignItems: 'center',
flexWrap: 'wrap',
gap: 4,
}}
>
<Text type="secondary" style={{ fontSize: 12 }}>
已启用 <strong style={{ color: '#52c41a' }}>{enabledStores}</strong> 家 / 待机{' '}
{totalStores - enabledStores} 家
</Text>
{validStores > 0 && (
<Tag color="success" style={{ margin: 0, fontSize: 11 }}>
CK 有效 {validStores}
</Tag>
)}
<Space size={4}>
{validStores > 0 && (
<Tag color="success" style={{ margin: 0, fontSize: 11 }}>
CK有效 {validStores}
</Tag>
)}
{invalidStores > 0 && (
<Tag color="error" style={{ margin: 0, fontSize: 11 }}>
CK失效 {invalidStores}
</Tag>
)}
</Space>
</div>
</Card>
</Col>
@@ -812,10 +864,10 @@ export function PddPlatformPanel() {
message={
<span>
当前拉单规则:默认抓取<strong>【{orderTypeDesc}】</strong>订单,单次拉取最新
<strong>【{config.pageSize || 50}】</strong>单并错峰均摊。
<strong>【{config.pageSize || 50}】</strong>单并持久化记录校验状态。
</span>
}
description="当拼多多买家下单并完成虚拟发货(或服务市场工具发货为已发货)后,系统将自动拉取入库并派发至打手大厅;您也可以随时点击右侧【立即拉单】即时手动触发增量抓取。"
description="系统自动保存每家店铺上次 Cookie 的测活状态与时间戳。若在定时轮询或手动测试中检测到 Cookie 失效(或触发登录过期),系统将自动更新状态并向 Bark / Wpush 发送内部告警通知。"
/>
</Card>
@@ -11,6 +11,10 @@ export interface AdminPddStoreItem {
proxy?: string
etag?: string
enabled: boolean
lastCheckedAt?: string
cookieValid?: boolean
cookieCheckMessage?: string
totalOrders?: number
}
export interface AdminPddConfig {