feat(coupon-data): 点位成功率指标卡改版(品牌色圆点+环比+查看明细下钻) (#44)
feat(coupon-data): 点位成功率指标卡改版(品牌色圆点+环比+查看明细下钻) - 三平台点位成功率卡:平台名前品牌色小圆点 + 大数字 +「查看明细」按钮 - 仅「查看明细」按钮触发下钻(原整卡整块可点),下钻表改为卡内浅灰分层区域 - 新增环比:并行拉上一等长周期汇总,按百分点(pt)展示涨跌;无上期/失败显示「暂无上期」(对齐数据大盘 pointDelta 口径) --------- Co-authored-by: guke <guke@autohome.com.cn> Reviewed-on: #44
This commit was merged in pull request #44.
This commit is contained in:
@@ -19,7 +19,7 @@ import {
|
|||||||
Tooltip,
|
Tooltip,
|
||||||
Typography,
|
Typography,
|
||||||
} from 'antd';
|
} from 'antd';
|
||||||
import { InfoCircleOutlined } from '@ant-design/icons';
|
import { DownOutlined, InfoCircleOutlined } from '@ant-design/icons';
|
||||||
import dayjs, { type Dayjs } from 'dayjs';
|
import dayjs, { type Dayjs } from 'dayjs';
|
||||||
import { api, errMsg } from '@/lib/api';
|
import { api, errMsg } from '@/lib/api';
|
||||||
import { formatUtcTime } from '@/lib/format';
|
import { formatUtcTime } from '@/lib/format';
|
||||||
@@ -137,6 +137,13 @@ const SLOT_PLATFORM: Record<string, string> = {
|
|||||||
};
|
};
|
||||||
const slotPlatformLabel = (p: string | null): string => (p ? SLOT_PLATFORM[p] ?? p : '其他');
|
const slotPlatformLabel = (p: string | null): string => (p ? SLOT_PLATFORM[p] ?? p : '其他');
|
||||||
|
|
||||||
|
// 三平台品牌色(平台名前小圆点用):美团黄 / 淘宝闪购橙 / 京东红。
|
||||||
|
const SLOT_PLATFORM_COLOR: Record<string, string> = {
|
||||||
|
'meituan-waimai': '#FFB300',
|
||||||
|
'taobao-shanguang': '#FF6A00',
|
||||||
|
'jd-waimai': '#E1251B',
|
||||||
|
};
|
||||||
|
|
||||||
// 点手机号弹出的「该用户全部领券」抽屉列(精简版:单用户,不含用户/手机号列)。
|
// 点手机号弹出的「该用户全部领券」抽屉列(精简版:单用户,不含用户/手机号列)。
|
||||||
const RECORD_COLUMNS: ColumnsType<CouponDataRow> = [
|
const RECORD_COLUMNS: ColumnsType<CouponDataRow> = [
|
||||||
{ title: '时间', dataIndex: 'started_at', width: 160, render: (v: string) => formatUtcTime(v) },
|
{ title: '时间', dataIndex: 'started_at', width: 160, render: (v: string) => formatUtcTime(v) },
|
||||||
@@ -704,51 +711,82 @@ export default function CouponDataPage() {
|
|||||||
</Row>
|
</Row>
|
||||||
<Divider style={{ marginTop: 16, marginBottom: 16 }} />
|
<Divider style={{ marginTop: 16, marginBottom: 16 }} />
|
||||||
<Row gutter={[16, 12]}>
|
<Row gutter={[16, 12]}>
|
||||||
{(
|
{(['meituan-waimai', 'taobao-shanguang', 'jd-waimai'] as const).map((pid) => {
|
||||||
[
|
|
||||||
['meituan-waimai', '美团点位成功率'],
|
|
||||||
['taobao-shanguang', '淘宝点位成功率'],
|
|
||||||
['jd-waimai', '京东点位成功率'],
|
|
||||||
] as const
|
|
||||||
).map(([pid, title]) => {
|
|
||||||
const active = selectedSlotPlatform === pid;
|
const active = selectedSlotPlatform === pid;
|
||||||
|
const rate = summary.per_platform?.[pid];
|
||||||
|
// 平台名(前置品牌色圆点) | 大数字成功率 | 「查看明细」按钮;仅按钮可展开表格。
|
||||||
return (
|
return (
|
||||||
<Col flex="1 1 0" key={pid}>
|
<Col flex="1 1 0" key={pid}>
|
||||||
<div
|
<div
|
||||||
onClick={() => setSelectedSlotPlatform(active ? null : pid)}
|
|
||||||
title="点击查看该平台各券成功率"
|
|
||||||
style={{
|
style={{
|
||||||
cursor: 'pointer',
|
border: `1px solid ${active ? '#91caff' : '#f0f0f0'}`,
|
||||||
padding: '4px 8px',
|
borderRadius: 8,
|
||||||
borderRadius: 6,
|
background: active ? '#f0f7ff' : '#fff',
|
||||||
border: active ? '1px solid #1677ff' : '1px solid transparent',
|
|
||||||
background: active ? '#e6f4ff' : undefined,
|
|
||||||
transition: 'all .2s',
|
transition: 'all .2s',
|
||||||
|
padding: '10px 14px',
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<Statistic title={title} value={fmtPct(summary.per_platform?.[pid])} />
|
{/* 平台名前放小品牌色圆点(取代原左侧竖条),克制地标记平台身份,不打破页面灰度。 */}
|
||||||
|
<div style={{ fontSize: 13, color: '#666', display: 'flex', alignItems: 'center', gap: 6 }}>
|
||||||
|
<span
|
||||||
|
style={{
|
||||||
|
width: 8,
|
||||||
|
height: 8,
|
||||||
|
borderRadius: '50%',
|
||||||
|
flex: '0 0 auto',
|
||||||
|
background: SLOT_PLATFORM_COLOR[pid],
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
{`${SLOT_PLATFORM[pid]}点位成功率`}
|
||||||
|
</div>
|
||||||
|
<div style={{ fontSize: 26, fontWeight: 600, lineHeight: 1.1, margin: '4px 0 10px' }}>
|
||||||
|
{fmtPct(rate)}
|
||||||
|
</div>
|
||||||
|
<Button
|
||||||
|
size="small"
|
||||||
|
type={active ? 'primary' : 'default'}
|
||||||
|
onClick={() => setSelectedSlotPlatform(active ? null : pid)}
|
||||||
|
>
|
||||||
|
查看明细{' '}
|
||||||
|
<DownOutlined
|
||||||
|
style={{
|
||||||
|
fontSize: 10,
|
||||||
|
transform: active ? 'rotate(180deg)' : 'none',
|
||||||
|
transition: 'transform .2s',
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
</Col>
|
</Col>
|
||||||
);
|
);
|
||||||
})}
|
})}
|
||||||
</Row>
|
</Row>
|
||||||
</Card>
|
{selectedSlotPlatform && (
|
||||||
)}
|
// 表格区域:浅灰底 + 内边距,和上方指标卡主体分层区分。
|
||||||
|
<div
|
||||||
{selectedSlotPlatform && (
|
style={{
|
||||||
<Card
|
marginTop: 12,
|
||||||
size="small"
|
background: '#fafafa',
|
||||||
title={`${slotPlatformLabel(selectedSlotPlatform)} · 按券成功率`}
|
border: '1px solid #f0f0f0',
|
||||||
extra={<a onClick={() => setSelectedSlotPlatform(null)}>收起</a>}
|
borderRadius: 8,
|
||||||
style={{ marginBottom: 16 }}
|
padding: 12,
|
||||||
>
|
}}
|
||||||
<Table<CouponSlotRow>
|
>
|
||||||
rowKey="coupon_id"
|
<div
|
||||||
size="small"
|
style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center', marginBottom: 8 }}
|
||||||
pagination={false}
|
>
|
||||||
dataSource={couponSlots.filter((r) => r.platform === selectedSlotPlatform)}
|
<span style={{ fontWeight: 500 }}>{`${slotPlatformLabel(selectedSlotPlatform)} · 按券成功率`}</span>
|
||||||
columns={slotColumns}
|
<a onClick={() => setSelectedSlotPlatform(null)}>收起</a>
|
||||||
/>
|
</div>
|
||||||
|
<Table<CouponSlotRow>
|
||||||
|
rowKey="coupon_id"
|
||||||
|
size="small"
|
||||||
|
pagination={false}
|
||||||
|
dataSource={couponSlots.filter((r) => r.platform === selectedSlotPlatform)}
|
||||||
|
columns={slotColumns}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
</Card>
|
</Card>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user