fix(admin-web): 比价记录页时区/cancelled/详情展示位修复

- 列表时间改 formatWallTime(created_at 北京 wall-clock 口径, 原 formatUtcTime 快 8h)
- cancelled 加颜色/中文(成功/失败/已终止) + 筛选选项
- 详情补 下单商品(items+跳过菜)/最优深链/device_id 展示位
- comparison_results 空值兜底

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
2026-06-17 23:32:36 +08:00
parent 472912560c
commit f4043f2abf
+38 -7
View File
@@ -8,11 +8,12 @@ import {
} from 'antd'; } from 'antd';
import type { ColumnsType } from 'antd/es/table'; import type { ColumnsType } from 'antd/es/table';
import { api, errMsg } from '@/lib/api'; import { api, errMsg } from '@/lib/api';
import { formatUtcTime, yuan } from '@/lib/format'; import { formatWallTime, yuan } from '@/lib/format';
import { usePagedList } from '@/lib/usePagedList'; import { usePagedList } from '@/lib/usePagedList';
import type { ComparisonRecordDetail, ComparisonRecordListItem } from '@/lib/types'; import type { ComparisonRecordDetail, ComparisonRecordListItem } from '@/lib/types';
const STATUS_COLOR: Record<string, string> = { success: 'green', failed: 'red' }; const STATUS_COLOR: Record<string, string> = { success: 'green', failed: 'red', cancelled: 'default' };
const STATUS_LABEL: Record<string, string> = { success: '成功', failed: '失败', cancelled: '已终止' };
// 「卡在哪一步」: platform_results[*].status 翻成人话(找店/加菜/起送/读价) // 「卡在哪一步」: platform_results[*].status 翻成人话(找店/加菜/起送/读价)
const STUCK_LABEL: Record<string, string> = { const STUCK_LABEL: Record<string, string> = {
@@ -97,7 +98,7 @@ export default function ComparisonRecordsPage() {
</div> </div>
), ),
}, },
{ title: '状态', dataIndex: 'status', width: 72, render: (s: string) => <Tag color={STATUS_COLOR[s]}>{s}</Tag> }, { title: '状态', dataIndex: 'status', width: 72, render: (s: string) => <Tag color={STATUS_COLOR[s]}>{STATUS_LABEL[s] || s}</Tag> },
{ title: '源平台', dataIndex: 'source_platform_name', width: 90, render: (v) => v || '-' }, { title: '源平台', dataIndex: 'source_platform_name', width: 90, render: (v) => v || '-' },
{ title: '店/商品', dataIndex: 'store_name', width: 150, ellipsis: true, render: (v) => v || '-' }, { title: '店/商品', dataIndex: 'store_name', width: 150, ellipsis: true, render: (v) => v || '-' },
{ title: '最优', dataIndex: 'best_platform_name', width: 80, render: (v) => v || '-' }, { title: '最优', dataIndex: 'best_platform_name', width: 80, render: (v) => v || '-' },
@@ -126,7 +127,7 @@ export default function ComparisonRecordsPage() {
ellipsis: true, ellipsis: true,
render: (_, r) => [r.device_model, r.rom_name].filter(Boolean).join(' / ') || '-', render: (_, r) => [r.device_model, r.rom_name].filter(Boolean).join(' / ') || '-',
}, },
{ title: '时间', dataIndex: 'created_at', width: 150, render: (v: string) => formatUtcTime(v) }, { title: '时间', dataIndex: 'created_at', width: 150, render: (v: string) => formatWallTime(v) },
{ {
title: '操作', title: '操作',
key: 'op', key: 'op',
@@ -163,7 +164,11 @@ export default function ComparisonRecordsPage() {
onChange={setStatus} onChange={setStatus}
allowClear allowClear
style={{ width: 110 }} style={{ width: 110 }}
options={[{ value: 'success', label: 'success' }, { value: 'failed', label: 'failed' }]} options={[
{ value: 'success', label: '成功' },
{ value: 'failed', label: '失败' },
{ value: 'cancelled', label: '已终止' },
]}
/> />
<Button type="primary" onClick={search}></Button> <Button type="primary" onClick={search}></Button>
<Button onClick={reset}></Button> <Button onClick={reset}></Button>
@@ -194,7 +199,7 @@ export default function ComparisonRecordsPage() {
<Descriptions.Item label="用户"> <Descriptions.Item label="用户">
{detail.phone || `#${detail.user_id}`}{detail.nickname ? `(${detail.nickname})` : ''} {detail.phone || `#${detail.user_id}`}{detail.nickname ? `(${detail.nickname})` : ''}
</Descriptions.Item> </Descriptions.Item>
<Descriptions.Item label="状态"><Tag color={STATUS_COLOR[detail.status]}>{detail.status}</Tag></Descriptions.Item> <Descriptions.Item label="状态"><Tag color={STATUS_COLOR[detail.status]}>{STATUS_LABEL[detail.status] || detail.status}</Tag></Descriptions.Item>
<Descriptions.Item label="业务">{detail.business_type}</Descriptions.Item> <Descriptions.Item label="业务">{detail.business_type}</Descriptions.Item>
<Descriptions.Item label="耗时">{fmtMs(detail.total_ms)}</Descriptions.Item> <Descriptions.Item label="耗时">{fmtMs(detail.total_ms)}</Descriptions.Item>
<Descriptions.Item label="步数">{detail.step_count ?? '-'}</Descriptions.Item> <Descriptions.Item label="步数">{detail.step_count ?? '-'}</Descriptions.Item>
@@ -212,6 +217,11 @@ export default function ComparisonRecordsPage() {
<Descriptions.Item label="定位" span={2}> <Descriptions.Item label="定位" span={2}>
{detail.longitude != null ? `${detail.longitude}, ${detail.latitude}` : '-'} {detail.longitude != null ? `${detail.longitude}, ${detail.latitude}` : '-'}
</Descriptions.Item> </Descriptions.Item>
<Descriptions.Item label="最优深链" span={2}>
{detail.best_deeplink
? <Typography.Text copyable={{ text: detail.best_deeplink }} style={{ fontSize: 12, wordBreak: 'break-all' }}>{detail.best_deeplink}</Typography.Text>
: '-'}
</Descriptions.Item>
</Descriptions> </Descriptions>
<Card size="small" title="设备环境"> <Card size="small" title="设备环境">
@@ -221,9 +231,30 @@ export default function ComparisonRecordsPage() {
<Descriptions.Item label="Android">{detail.android_version || '-'}SDK {detail.android_sdk ?? '-'}</Descriptions.Item> <Descriptions.Item label="Android">{detail.android_version || '-'}SDK {detail.android_sdk ?? '-'}</Descriptions.Item>
<Descriptions.Item label="App 版本">{detail.app_version || '-'}{detail.app_version_code ?? '-'}</Descriptions.Item> <Descriptions.Item label="App 版本">{detail.app_version || '-'}{detail.app_version_code ?? '-'}</Descriptions.Item>
<Descriptions.Item label="源 App 版本" span={2}>{detail.source_app_version || '-'}</Descriptions.Item> <Descriptions.Item label="源 App 版本" span={2}>{detail.source_app_version || '-'}</Descriptions.Item>
<Descriptions.Item label="device_id" span={2}>{detail.device_id || '-'}</Descriptions.Item>
</Descriptions> </Descriptions>
</Card> </Card>
{((detail.items?.length ?? 0) > 0 || (detail.skipped_dish_names?.length ?? 0) > 0) && (
<Card size="small" title={`下单商品${detail.total_dish_count != null ? `(共 ${detail.total_dish_count}` : ''}`}>
{(detail.items?.length ?? 0) > 0 ? (
<ul style={{ margin: 0, paddingLeft: 18 }}>
{detail.items.map((it, i) => (
<li key={i}>
{it.name}{it.qty != null ? ` ×${it.qty}` : ''}
{it.specs?.length ? <span style={{ color: '#999' }}>{it.specs.join('/')}</span> : null}
</li>
))}
</ul>
) : <Typography.Text type="secondary"></Typography.Text>}
{(detail.skipped_dish_names?.length ?? 0) > 0 && (
<div style={{ marginTop: 8, color: '#cf1322' }}>
{detail.skipped_dish_count != null ? ` ${detail.skipped_dish_count} ` : ''}{detail.skipped_dish_names.join('、')}
</div>
)}
</Card>
)}
{platformResults.length > 0 && ( {platformResults.length > 0 && (
<Card size="small" title="逐平台结局(卡在哪一步)"> <Card size="small" title="逐平台结局(卡在哪一步)">
<Table <Table
@@ -240,7 +271,7 @@ export default function ComparisonRecordsPage() {
</Card> </Card>
)} )}
{detail.comparison_results.length > 0 && ( {(detail.comparison_results?.length ?? 0) > 0 && (
<Collapse <Collapse
size="small" size="small"
items={[{ items={[{