Compare commits

..

3 Commits

Author SHA1 Message Date
linkeyu 9f8d9e3dc5 feat(admin): 广告收益增加环境与数据范围筛选 2026-07-21 20:02:24 +08:00
linkeyu 3f5356ad87 feat(admin): 领券完成率和点位成功率展示计算明细 (#53)
## 变更内容
- 将汇总卡“领券成功率”明确为“领券完成率”
- 提示中动态展示完成数、发起数、中途退出数及本期代入计算结果
- 点位成功率提示逐券展示成功数、尝试数、单券成功率和最终等权平均结果
- 展示累计成功/尝试数作为辅助核对,并明确不作为当前加权公式

## 验证
- npx tsc --noEmit
- npm run build

---------

Co-authored-by: linkeyu <798648091@qq.com>
Reviewed-on: #53
Co-authored-by: linkeyu <linkeyu@wonderable.ai>
Co-committed-by: linkeyu <linkeyu@wonderable.ai>
2026-07-21 11:59:50 +08:00
linkeyu c90775d09c fix(admin): 领券广告收益未填充时显示明确文案 (#54)
原 MR #52 已合并到功能分支,无法修改目标分支。本 MR 将同一项“领券广告收益未填充时显示明确文案”修复独立提交到 main,不包含后台看板功能分支的其他提交。

验证:npx tsc --noEmit;npm run build。

Reviewed-on: #54
Co-authored-by: linkeyu <linkeyu@wonderable.ai>
Co-committed-by: linkeyu <linkeyu@wonderable.ai>
2026-07-21 11:59:35 +08:00
2 changed files with 36 additions and 6 deletions
+32 -2
View File
@@ -300,6 +300,8 @@ export default function AdRevenueReportPage() {
const { message } = App.useApp();
const [range, setRange] = useState<[Dayjs, Dayjs]>([dayjs().subtract(1, 'day'), dayjs().subtract(1, 'day')]);
const [userId, setUserId] = useState<number | null>(null);
const [appEnv, setAppEnv] = useState<'prod' | 'test' | 'all'>('prod');
const [revenueScope, setRevenueScope] = useState<'business' | 'all'>('business');
const [adType, setAdType] = useState<string | undefined>();
// 「场景」作为后端全局筛选(feed_scene):同时影响明细 / 合计 / 趋势,与「用户 / 类型」一致,点「查询」生效。
const [scene, setScene] = useState<string | undefined>();
@@ -333,6 +335,8 @@ export default function AdRevenueReportPage() {
date_from: from,
date_to: to,
user_id: userId ?? undefined,
app_env: appEnv === 'all' ? undefined : appEnv,
revenue_scope: revenueScope,
ad_type: adType ?? undefined,
feed_scene: scene ?? undefined,
granularity: gran,
@@ -374,7 +378,7 @@ export default function AdRevenueReportPage() {
setLoading(false);
}
},
[range, userId, adType, scene, granularity, limit, sortBy],
[range, userId, appEnv, revenueScope, adType, scene, granularity, limit, sortBy],
);
useEffect(() => {
@@ -620,7 +624,8 @@ export default function AdRevenueReportPage() {
<br />
<b>穿(T+1)</b>穿 GroMore API(,):
<b>穿</b>= revenue<b>API</b>= ADN 穿//,
<b></b>(//);,
<b></b>(//);穿
+ ;广
</div>
}
>
@@ -655,6 +660,31 @@ export default function AdRevenueReportPage() {
style={{ width: 130 }}
/>
</Space>
<Space size={6}>
<Typography.Text type="secondary"></Typography.Text>
<Select
value={appEnv}
onChange={setAppEnv}
style={{ width: 130 }}
options={[
{ value: 'prod', label: '正式(prod)' },
{ value: 'test', label: '测试(dev)' },
{ value: 'all', label: '全部' },
]}
/>
</Space>
<Space size={6}>
<Typography.Text type="secondary"></Typography.Text>
<Select
value={revenueScope}
onChange={setRevenueScope}
style={{ width: 150 }}
options={[
{ value: 'business', label: '业务代码位' },
{ value: 'all', label: '全部代码位' },
]}
/>
</Space>
<Space size={6}>
<Typography.Text type="secondary"></Typography.Text>
<Select
+4 -4
View File
@@ -73,7 +73,7 @@ interface CouponDataRow {
started_at: string;
claimed_count: number | null;
trace_url: string | null;
ad_revenue_yuan: number; // 本次领券看的信息流广告预估收益(元)
ad_revenue_yuan: number | null; // 本次领券看的信息流广告预估收益(元);未填充为 null
}
interface CouponDataReport {
date_from: string;
@@ -124,9 +124,9 @@ const fmtSec = (ms: number | null | undefined): string =>
const fmtPct = (v: number | null | undefined): string =>
v == null ? '-' : `${(v * 100).toFixed(1)}%`;
// 元(小数)→ "¥0.0050";空值-,真实 0 显示 ¥0.0000,以区分“零收益”和“无数据”
// 元(小数)→ "¥0.0050";空值eCPM 根本未填充,真实 0 显示 ¥0.0000。
const fmtYuan = (v: number | null | undefined): string =>
v == null ? '-' : `¥${v.toFixed(4)}`;
v == null ? '未填充' : `¥${v.toFixed(4)}`;
// 一组按券行的 success_rate 算术平均(每张券等权;空值券跳过);无有效券 → null(显示 -)。
// 汇总卡「分平台/合计点位成功率」据此由按券明细上卷,口径与下方按券表一致。
@@ -512,7 +512,7 @@ export default function CouponDataPage() {
dataIndex: 'ad_revenue_yuan',
width: 100,
align: 'right',
render: (v: number) => fmtYuan(v),
render: (v: number | null) => fmtYuan(v),
},
{
title: '美团耗时',