refactor(coupon-data): 去掉点位成功率卡环比涨跌(暂无数据源)
- 移除环比徽标、上一周期并行查询及 prevPerPlatform 状态 - 指标卡保留:品牌色小圆点 + 大数字成功率 + 「查看明细」按钮下钻 Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -19,12 +19,7 @@ import {
|
||||
Tooltip,
|
||||
Typography,
|
||||
} from 'antd';
|
||||
import {
|
||||
CaretDownOutlined,
|
||||
CaretUpOutlined,
|
||||
DownOutlined,
|
||||
InfoCircleOutlined,
|
||||
} from '@ant-design/icons';
|
||||
import { DownOutlined, InfoCircleOutlined } from '@ant-design/icons';
|
||||
import dayjs, { type Dayjs } from 'dayjs';
|
||||
import { api, errMsg } from '@/lib/api';
|
||||
import { formatUtcTime } from '@/lib/format';
|
||||
@@ -142,31 +137,13 @@ const SLOT_PLATFORM: Record<string, string> = {
|
||||
};
|
||||
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',
|
||||
};
|
||||
|
||||
// 点位成功率「环比上一等长周期」徽标:绿↑/红↓/灰持平/灰暂无上期。
|
||||
// 口径对齐数据大盘 pointDelta:成功率为 0..1,差值换算成百分点(pt)。
|
||||
function SlotRateDelta({ rate, prev }: { rate: number | null | undefined; prev: number | null | undefined }) {
|
||||
if (rate == null || prev == null)
|
||||
return <span style={{ fontSize: 12, color: '#bfbfbf' }}>暂无上期</span>;
|
||||
const diffPt = (rate - prev) * 100;
|
||||
if (Math.abs(diffPt) < 0.05) return <span style={{ fontSize: 12, color: '#8c8c8c' }}>持平</span>;
|
||||
const up = diffPt > 0;
|
||||
return (
|
||||
<span
|
||||
style={{ fontSize: 12, color: up ? '#3f8600' : '#cf1322', display: 'inline-flex', alignItems: 'center', gap: 2 }}
|
||||
>
|
||||
{up ? <CaretUpOutlined /> : <CaretDownOutlined />}
|
||||
{Math.abs(diffPt).toFixed(1)}pt
|
||||
</span>
|
||||
);
|
||||
}
|
||||
|
||||
// 点手机号弹出的「该用户全部领券」抽屉列(精简版:单用户,不含用户/手机号列)。
|
||||
const RECORD_COLUMNS: ColumnsType<CouponDataRow> = [
|
||||
{ title: '时间', dataIndex: 'started_at', width: 160, render: (v: string) => formatUtcTime(v) },
|
||||
@@ -370,8 +347,6 @@ export default function CouponDataPage() {
|
||||
const [couponSlots, setCouponSlots] = useState<CouponSlotRow[]>([]);
|
||||
// 按券表:默认隐藏,点某平台点位成功率卡 → 展开该平台的券表(null=隐藏)。
|
||||
const [selectedSlotPlatform, setSelectedSlotPlatform] = useState<string | null>(null);
|
||||
// 上一等长周期各平台点位成功率(算环比涨跌;拉取失败为 null → 显示「暂无上期」)。
|
||||
const [prevPerPlatform, setPrevPerPlatform] = useState<Record<string, number | null> | null>(null);
|
||||
const [loading, setLoading] = useState(false);
|
||||
// 点手机号:抽屉看该用户全部领券(总次数 + 记录)
|
||||
const [recordsUser, setRecordsUser] = useState<{ userId: number; phone: string | null } | null>(null);
|
||||
@@ -388,10 +363,6 @@ export default function CouponDataPage() {
|
||||
const to = range[1].format('YYYY-MM-DD');
|
||||
const multiDay = from !== to;
|
||||
const gran = multiDay ? 'day' : granularity;
|
||||
// 环比:上一个等长周期(对齐数据大盘「环比上周期」口径)。
|
||||
const spanDays = range[1].diff(range[0], 'day') + 1;
|
||||
const prevTo = range[0].subtract(1, 'day');
|
||||
const prevFrom = prevTo.subtract(spanDays - 1, 'day');
|
||||
setLoading(true);
|
||||
try {
|
||||
const res = await api.get<CouponDataReport>('/admin/api/coupon-data', {
|
||||
@@ -417,23 +388,6 @@ export default function CouponDataPage() {
|
||||
})
|
||||
.then((r) => setCouponSlots(r.data.items))
|
||||
.catch(() => setCouponSlots([]));
|
||||
// 并行拉「上一周期」汇总算环比(同筛选条件、上一等长周期);只用 summary,limit=1 省流量,失败按「暂无上期」。
|
||||
api
|
||||
.get<CouponDataReport>('/admin/api/coupon-data', {
|
||||
params: {
|
||||
date_from: prevFrom.format('YYYY-MM-DD'),
|
||||
date_to: prevTo.format('YYYY-MM-DD'),
|
||||
user: user.trim() || undefined,
|
||||
app_env: appEnv,
|
||||
status: statuses,
|
||||
granularity: 'day',
|
||||
limit: 1,
|
||||
offset: 0,
|
||||
},
|
||||
paramsSerializer: { indexes: null },
|
||||
})
|
||||
.then((r) => setPrevPerPlatform(r.data.summary?.per_platform ?? null))
|
||||
.catch(() => setPrevPerPlatform(null));
|
||||
setPage(targetPage);
|
||||
setQueriedLimit(targetLimit);
|
||||
setQueriedGranularity(gran);
|
||||
@@ -760,7 +714,7 @@ export default function CouponDataPage() {
|
||||
{(['meituan-waimai', 'taobao-shanguang', 'jd-waimai'] as const).map((pid) => {
|
||||
const active = selectedSlotPlatform === pid;
|
||||
const rate = summary.per_platform?.[pid];
|
||||
// 左侧品牌色块 | 中间大数字+环比 | 底部「查看明细」按钮;仅按钮可展开表格。
|
||||
// 平台名(前置品牌色圆点) | 大数字成功率 | 「查看明细」按钮;仅按钮可展开表格。
|
||||
return (
|
||||
<Col flex="1 1 0" key={pid}>
|
||||
<div
|
||||
@@ -785,9 +739,8 @@ export default function CouponDataPage() {
|
||||
/>
|
||||
{`${SLOT_PLATFORM[pid]}点位成功率`}
|
||||
</div>
|
||||
<div style={{ display: 'flex', alignItems: 'baseline', gap: 8, margin: '4px 0 10px' }}>
|
||||
<span style={{ fontSize: 26, fontWeight: 600, lineHeight: 1.1 }}>{fmtPct(rate)}</span>
|
||||
<SlotRateDelta rate={rate} prev={prevPerPlatform?.[pid]} />
|
||||
<div style={{ fontSize: 26, fontWeight: 600, lineHeight: 1.1, margin: '4px 0 10px' }}>
|
||||
{fmtPct(rate)}
|
||||
</div>
|
||||
<Button
|
||||
size="small"
|
||||
|
||||
Reference in New Issue
Block a user