diff --git a/src/app/(main)/ad-revenue-report/UserAdRevenueDrawer.tsx b/src/app/(main)/ad-revenue-report/UserAdRevenueDrawer.tsx index 9c16731..c3153b4 100644 --- a/src/app/(main)/ad-revenue-report/UserAdRevenueDrawer.tsx +++ b/src/app/(main)/ad-revenue-report/UserAdRevenueDrawer.tsx @@ -32,9 +32,24 @@ interface Props { onClose: () => void; userId: number | null; phone: string | null; // 报表行已有的手机号:概览拉取失败时兜底展示 + dateFrom: string | null; + dateTo: string | null; + appEnv?: 'prod' | 'test'; + revenueScope: 'business' | 'all'; + feedScene?: 'comparison' | 'coupon' | 'welfare'; } -export default function UserAdRevenueDrawer({ open, onClose, userId, phone }: Props) { +export default function UserAdRevenueDrawer({ + open, + onClose, + userId, + phone, + dateFrom, + dateTo, + appEnv, + revenueScope, + feedScene, +}: Props) { // UserRewardPanel 的 user 快照:它只读 phone/nickname/wechat_nickname/created_at,其余按 snapshot 形状补齐。 const [user, setUser] = useState(null); @@ -82,7 +97,19 @@ export default function UserAdRevenueDrawer({ open, onClose, userId, phone }: Pr > {/* userId 就绪即渲染;UserRewardPanel 内部按 userId 自行拉统计与金币记录,user 基本信息随后补上。 statsVariant="ad":统计区只显示 6 项看广告统计(累计提现/现金余额/激励视频观看数+eCPM/draw观看数+eCPM) */} - {userId != null && } + {userId != null && ( + + )} ); } diff --git a/src/app/(main)/ad-revenue-report/page.tsx b/src/app/(main)/ad-revenue-report/page.tsx index e798ad6..1c4109e 100644 --- a/src/app/(main)/ad-revenue-report/page.tsx +++ b/src/app/(main)/ad-revenue-report/page.tsx @@ -470,7 +470,27 @@ export default function AdRevenueReportPage() { const [loading, setLoading] = useState(false); const [formulaOpen, setFormulaOpen] = useState(false); // 点用户手机号弹出的「用户广告收益详情」半屏抽屉(userId + 手机号;null=关闭) - const [userDrawer, setUserDrawer] = useState<{ userId: number; phone: string | null } | null>(null); + const [userDrawer, setUserDrawer] = useState<{ + userId: number; + phone: string | null; + dateFrom: string; + dateTo: string; + appEnv?: 'prod' | 'test'; + revenueScope: 'business' | 'all'; + feedScene?: 'comparison' | 'coupon' | 'welfare'; + } | null>(null); + const [queriedDetailFilters, setQueriedDetailFilters] = useState<{ + dateFrom: string; + dateTo: string; + appEnv?: 'prod' | 'test'; + revenueScope: 'business' | 'all'; + feedScene?: 'comparison' | 'coupon' | 'welfare'; + }>({ + dateFrom: range[0].format('YYYY-MM-DD'), + dateTo: range[1].format('YYYY-MM-DD'), + appEnv: 'prod', + revenueScope: 'business', + }); // 当前选择是否跨多天:跨多天时「按小时」无意义,粒度强制按天 const rangeMultiDay = range[0].format('YYYY-MM-DD') !== range[1].format('YYYY-MM-DD'); @@ -503,6 +523,13 @@ export default function AdRevenueReportPage() { }, }); setData(res.data); + setQueriedDetailFilters({ + dateFrom: from, + dateTo: to, + appEnv: appEnv === 'all' ? undefined : appEnv, + revenueScope, + feedScene: scene as 'comparison' | 'coupon' | 'welfare' | undefined, + }); setPage(targetPage); setQueriedLimit(targetLimit); setQueriedGranularity(gran); @@ -551,7 +578,7 @@ export default function AdRevenueReportPage() { width: 150, render: (phone: string | null, r: AdRevenueRow) => ( // 点手机号/用户 → 打开该用户「广告收益详情」半屏抽屉(统计卡 + 金币记录) - setUserDrawer({ userId: r.user_id, phone })}> + setUserDrawer({ userId: r.user_id, phone, ...queriedDetailFilters })}> {phone ? ( {phone} @@ -1284,6 +1311,11 @@ export default function AdRevenueReportPage() { open={!!userDrawer} userId={userDrawer?.userId ?? null} phone={userDrawer?.phone ?? null} + dateFrom={userDrawer?.dateFrom ?? null} + dateTo={userDrawer?.dateTo ?? null} + appEnv={userDrawer?.appEnv} + revenueScope={userDrawer?.revenueScope ?? 'all'} + feedScene={userDrawer?.feedScene} onClose={() => setUserDrawer(null)} /> diff --git a/src/app/(main)/withdraws/UserRewardPanel.tsx b/src/app/(main)/withdraws/UserRewardPanel.tsx index dc5c4f2..5281026 100644 --- a/src/app/(main)/withdraws/UserRewardPanel.tsx +++ b/src/app/(main)/withdraws/UserRewardPanel.tsx @@ -44,6 +44,11 @@ interface Props { withdrawSource?: 'coin_cash' | 'invite_cash'; // 统计区字段集:withdraw(默认,提现详情:含提现细分) / ad(广告收益详情:只看看广告观看统计,对齐参考图 6 项) statsVariant?: 'withdraw' | 'ad'; + initialDateFrom?: string; + initialDateTo?: string; + appEnv?: 'prod' | 'test'; + revenueScope?: 'business' | 'all'; + feedScene?: 'comparison' | 'coupon' | 'welfare'; } /** 用户看广告/提现详情:基本信息 + 互斥时间筛选 + 统计区(按 statsVariant 取字段集)+ 金币发放记录表。 */ @@ -52,9 +57,17 @@ export default function UserRewardPanel({ user, withdrawSource, statsVariant = 'withdraw', + initialDateFrom, + initialDateTo, + appEnv, + revenueScope = 'all', + feedScene, }: Props) { - const [mode, setMode] = useState<'all' | 'range'>('all'); // all=注册至今 / range=自定义区间 - const [range, setRange] = useState<[Dayjs, Dayjs] | null>(null); + const hasInitialRange = Boolean(initialDateFrom && initialDateTo); + const [mode, setMode] = useState<'all' | 'range'>(hasInitialRange ? 'range' : 'all'); + const [range, setRange] = useState<[Dayjs, Dayjs] | null>(() => + hasInitialRange ? [dayjs(initialDateFrom), dayjs(initialDateTo)] : null, + ); const [stats, setStats] = useState(null); const [statsLoading, setStatsLoading] = useState(false); @@ -80,6 +93,9 @@ export default function UserRewardPanel({ params: { ...JSON.parse(paramsKey), ...(withdrawSource ? { withdraw_source: withdrawSource } : {}), + ...(appEnv ? { app_env: appEnv } : {}), + revenue_scope: revenueScope, + ...(feedScene ? { feed_scene: feedScene } : {}), }, }); setStats(data); @@ -88,7 +104,7 @@ export default function UserRewardPanel({ } finally { setStatsLoading(false); } - }, [userId, paramsKey, withdrawSource]); + }, [userId, paramsKey, withdrawSource, appEnv, revenueScope, feedScene]); const loadRecords = useCallback( async (p: number) => { @@ -236,7 +252,7 @@ export default function UserRewardPanel({ {statsVariant === 'ad' - ? '统计随上方时间筛选(现金余额除外,为当前快照);次数仅统计成功发奖记录,信息流按奖励份数统计;eCPM 为预估值。' + ? '统计继承广告收益页已查询的日期、环境、业务代码位和场景;次数仅统计成功发奖记录,信息流按奖励份数统计;Draw eCPM 按全部实际展示统计(含未发奖)。' : '统计随上方时间筛选(现金余额除外,为当前快照);提现按申请提交时间统计;累计收益为已发金币按当前汇率折算,不代表实际已提现金额;eCPM 为预估值。'} diff --git a/src/lib/types.ts b/src/lib/types.ts index 6444a9e..69d329e 100644 --- a/src/lib/types.ts +++ b/src/lib/types.ts @@ -233,7 +233,7 @@ export interface UserRewardStats { reward_video_avg_ecpm: number; // 平均激励视频 eCPM(分/千次) reward_video_cash_cents: number; // 激励视频提现 feed_count: number; // 累计信息流广告数(份) - feed_avg_ecpm: number; // 平均信息流广告 eCPM(分/千次) + feed_avg_ecpm: number; // 全部 Draw/feed 实际展示的平均 eCPM(分/千次,含未发奖展示) feed_cash_cents: number; // 信息流广告提现 }