Compare commits

..

2 Commits

Author SHA1 Message Date
guke 4bf24cb6fd Merge branch 'main' into codex/hide-withdraw-reason-column 2026-07-28 10:04:14 +08:00
linkeyu c30a5cabb7 优化:隐藏到账和打款中无关原因列 2026-07-27 19:13:34 +08:00
3 changed files with 12 additions and 24 deletions
+10 -10
View File
@@ -30,7 +30,7 @@ import {
} from '@ant-design/icons';
import dayjs, { type Dayjs } from 'dayjs';
import { api, errMsg } from '@/lib/api';
import { formatUtcTime, nearestRankPercentile } from '@/lib/format';
import { formatUtcTime, percentile } from '@/lib/format';
import type {
AdRevenueDaily,
AdRevenueHourly,
@@ -758,9 +758,9 @@ export default function AdRevenueReportPage() {
.filter((item) => item.feed_scene === sceneName)
.map((item) => item.sub_count ?? 1);
return {
p5: nearestRankPercentile(counts, 0.05),
p50: nearestRankPercentile(counts, 0.5),
p95: nearestRankPercentile(counts, 0.95),
p5: percentile(counts, 0.05, false),
p50: percentile(counts, 0.5, false),
p95: percentile(counts, 0.95, false),
};
};
return { coupon: summarize('coupon'), comparison: summarize('comparison') };
@@ -1083,12 +1083,12 @@ export default function AdRevenueReportPage() {
</Typography.Text>
</Divider>
<Row gutter={[16, 12]}>
<Col span={4}><Statistic title="单次领券广告数 P5" value={sessionAdCounts.coupon.p5 ?? '-'} precision={0} /></Col>
<Col span={4}><Statistic title="单次领券广告数 P50" value={sessionAdCounts.coupon.p50 ?? '-'} precision={0} /></Col>
<Col span={4}><Statistic title="单次领券广告数 P95" value={sessionAdCounts.coupon.p95 ?? '-'} precision={0} /></Col>
<Col span={4}><Statistic title="单次比价广告数 P5" value={sessionAdCounts.comparison.p5 ?? '-'} precision={0} /></Col>
<Col span={4}><Statistic title="单次比价广告数 P50" value={sessionAdCounts.comparison.p50 ?? '-'} precision={0} /></Col>
<Col span={4}><Statistic title="单次比价广告数 P95" value={sessionAdCounts.comparison.p95 ?? '-'} precision={0} /></Col>
<Col span={4}><Statistic title="单次领券广告数 P5" value={sessionAdCounts.coupon.p5 ?? '-'} precision={1} /></Col>
<Col span={4}><Statistic title="单次领券广告数 P50" value={sessionAdCounts.coupon.p50 ?? '-'} precision={1} /></Col>
<Col span={4}><Statistic title="单次领券广告数 P95" value={sessionAdCounts.coupon.p95 ?? '-'} precision={1} /></Col>
<Col span={4}><Statistic title="单次比价广告数 P5" value={sessionAdCounts.comparison.p5 ?? '-'} precision={1} /></Col>
<Col span={4}><Statistic title="单次比价广告数 P50" value={sessionAdCounts.comparison.p50 ?? '-'} precision={1} /></Col>
<Col span={4}><Statistic title="单次比价广告数 P95" value={sessionAdCounts.comparison.p95 ?? '-'} precision={1} /></Col>
</Row>
</Card>
)}
+2 -2
View File
@@ -710,7 +710,7 @@ export default function DashboardPage() {
<div>
<h1></h1>
<p>
{updatedAt ?? '--'} · · 00:00
{updatedAt ?? '--'} · · 00:00
</p>
</div>
<div className="controls">
@@ -734,7 +734,7 @@ export default function DashboardPage() {
format="YYYY-MM-DD"
allowClear={false}
open={datePickerOpen}
disabledDate={(date) => date.isAfter(dayjs(), 'day')}
disabledDate={(date) => date.isAfter(dayjs().subtract(1, 'day'), 'day')}
suffixIcon={<CalendarOutlined />}
onClick={() => setDatePickerOpen(true)}
onOpenChange={setDatePickerOpen}
-12
View File
@@ -37,18 +37,6 @@ export function percentile(values: readonly number[], q: number, round = true):
return round ? Math.round(result) : result;
}
/**
* 离散计数分位数(nearest-rank)。
* 广告条数等不可拆分的计数不做线性插值,结果始终取自真实样本。
*/
export function nearestRankPercentile(values: readonly number[], q: number): number | null {
if (!values.length) return null;
const sorted = [...values].sort((a, b) => a - b);
const quantile = Math.min(1, Math.max(0, q));
const rank = Math.max(1, Math.ceil(quantile * sorted.length));
return sorted[rank - 1];
}
const hasTz = (v: string) => /(?:Z|[+-]\d{2}:?\d{2})$/i.test(v);
/** 把 UTC 口径字符串解析为带时区的 dayjs(无时区后缀的补 Z 当 UTC)。 */