From ca7c3f27f0919f1d81c190222cd0ef8f204e3b51 Mon Sep 17 00:00:00 2001 From: linkeyu Date: Fri, 31 Jul 2026 17:08:13 +0800 Subject: [PATCH] =?UTF-8?q?=E5=8A=9F=E8=83=BD=EF=BC=9A=E6=96=B0=E5=A2=9E?= =?UTF-8?q?=E7=BB=9F=E4=B8=80=E9=99=90=E5=88=B6=E7=99=BD=E5=90=8D=E5=8D=95?= =?UTF-8?q?=E7=AE=A1=E7=90=86=E9=A1=B5=E9=9D=A2=20(#99)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ## 需求背景 新增统一白名单管理页面,让运营人员能够查看和调整全局限制,并按手机号或设备批量配置临时不限或风险免告警。 ## 主要改动 - 新增白名单导航与完整管理页面 - 全局限制按五类分页展示并支持修改 - 白名单按主体聚合,展示各分类数量及悬浮明细 - 支持手机号与设备搜索、批量多选限制项和统一有效期 - 支持手动筛选、十条分页、主体点击编辑及启用开关 - 风控监控增加快捷加入白名单入口 - 旧引导视频配置页与统一限制入口保持一致 ## 验证 - Next.js 生产构建通过 - TypeScript 类型检查通过 - 共 26 个页面完成静态/动态构建 - 已与后端 PR #207 配套验证 --------- Co-authored-by: linkeyu <798648091@qq.com> Reviewed-on: https://gitea.shaguabijia.com/WonderableAI/shaguabijia-admin-web/pulls/99 Co-authored-by: linkeyu Co-committed-by: linkeyu --- src/app/(main)/config/GuideVideoConfig.tsx | 116 ++- src/app/(main)/layout.tsx | 2 + src/app/(main)/limit-whitelist/page.tsx | 1053 ++++++++++++++++++++ src/app/(main)/risk-monitor/page.tsx | 81 +- src/lib/types.ts | 81 +- src/lib/usePagedList.ts | 9 +- 6 files changed, 1313 insertions(+), 29 deletions(-) create mode 100644 src/app/(main)/limit-whitelist/page.tsx diff --git a/src/app/(main)/config/GuideVideoConfig.tsx b/src/app/(main)/config/GuideVideoConfig.tsx index 706a636..c6cd7d8 100644 --- a/src/app/(main)/config/GuideVideoConfig.tsx +++ b/src/app/(main)/config/GuideVideoConfig.tsx @@ -1,7 +1,18 @@ 'use client'; import { useEffect, useState } from 'react'; -import { Button, Card, InputNumber, Space, Spin, Switch, Tag, Typography, Upload, message } from 'antd'; +import { + Button, + Card, + InputNumber, + Space, + Spin, + Switch, + Tag, + Typography, + Upload, + message, +} from 'antd'; import { DeleteOutlined, UploadOutlined } from '@ant-design/icons'; import { api, errMsg } from '@/lib/api'; import { canDo } from '@/lib/auth'; @@ -38,7 +49,9 @@ function SceneConfig({ scene }: { scene: Scene }) { const load = async () => { setLoading(true); try { - const { data } = await api.get('/admin/api/guide-video', { params: { scene } }); + const { data } = await api.get('/admin/api/guide-video', { + params: { scene }, + }); sync(data); } catch (e) { message.error(errMsg(e)); @@ -56,7 +69,11 @@ function SceneConfig({ scene }: { scene: Scene }) { try { const { data } = await api.patch( '/admin/api/guide-video', - { enabled, max_plays: maxPlays, reward_coin: rewardCoin }, + { + enabled, + reward_coin: rewardCoin, + ...(scene === 'comparison' ? { max_plays: maxPlays } : {}), + }, { params: { scene } }, ); sync(data); @@ -121,11 +138,20 @@ function SceneConfig({ scene }: { scene: Scene }) { size="small" title={meta.title} style={{ marginBottom: 16 }} - extra={cfg?.updated_at ? 更新于 {new Date(cfg.updated_at).toLocaleString('zh-CN')} : null} + extra={ + cfg?.updated_at ? ( + + 更新于 {new Date(cfg.updated_at).toLocaleString('zh-CN')} + + ) : null + } >

- Android 用户点击「{meta.action}」后,前若干次在等候浮层广告位播放本视频并奖励金币。 - 次数按账号、按功能分别计算;开播即计次,播完或中途关闭均发放当次配置的金币。 + Android 用户点击「{meta.action}」后,前 {cfg?.max_plays ?? 3}{' '} + 次在等候浮层广告位播放本视频并奖励金币。次数按账号、按功能分别计算; + 开播即计次,播完或中途关闭均发放当次配置的金币。 + {scene === 'coupon' && + '领券引导视频的播放次数上限请在「监控审计 → 限制策略」中调整。'}

{loading || !cfg ? ( @@ -137,10 +163,24 @@ function SceneConfig({ scene }: { scene: Scene }) {