From f950bcd84149a069e6c9e1dd977ed8a7ca2cdbe4 Mon Sep 17 00:00:00 2001 From: zzhyyyyy <2685922758@qq.com> Date: Mon, 6 Jul 2026 22:01:20 +0800 Subject: [PATCH] =?UTF-8?q?feat(marquee):=20=E9=A6=96=E9=A1=B5=E8=BD=AE?= =?UTF-8?q?=E6=92=AD=E7=A7=8D=E5=AD=90=E9=A2=84=E8=A7=88=E6=94=B9=E5=86=85?= =?UTF-8?q?=E8=81=94=E5=B8=B8=E9=A9=BB=E3=80=81=E9=9A=8F=E6=95=B0=E6=8D=AE?= =?UTF-8?q?=E6=BA=90=E6=A8=A1=E5=BC=8F=E5=AE=9E=E6=97=B6=E5=88=B7=E6=96=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 系统配置「首页轮播种子」页:预览从点按钮弹窗改为常驻在「数据源」开关下方, 切换「混播/只真实/只种子」即时重拉、所见即所得。 - 预览请求带上当前选中的 mode(配套 app-server 预览接口的 mode 入参),不依赖 PATCH 落库时序;拨动开关(乐观更新)即刻预览对应模式,切换失败回滚预览也随之回滚。 - 移除原「预览效果」弹窗及相关状态;「只真实」无数据时给空态提示。 Co-Authored-By: Claude Opus 4.8 --- src/app/(main)/config/HomeMarqueeSeeds.tsx | 126 ++++++++++++--------- 1 file changed, 73 insertions(+), 53 deletions(-) diff --git a/src/app/(main)/config/HomeMarqueeSeeds.tsx b/src/app/(main)/config/HomeMarqueeSeeds.tsx index d138052..9155240 100644 --- a/src/app/(main)/config/HomeMarqueeSeeds.tsx +++ b/src/app/(main)/config/HomeMarqueeSeeds.tsx @@ -49,6 +49,7 @@ interface PreviewItem { } const yuan = (cents: number) => (cents / 100).toFixed(2); +const MODE_LABEL: Record = { mixed: '混播', real: '只真实', seed: '只种子' }; /** 首页轮播「种子」管理(真实记录不足时的兜底假数据,现为「生成规则」)。「系统配置 / 首页」里的一个区块。 */ export default function HomeMarqueeSeeds() { @@ -66,7 +67,6 @@ export default function HomeMarqueeSeeds() { const [bulkOpen, setBulkOpen] = useState(false); const [bulkForm] = Form.useForm(); - const [previewOpen, setPreviewOpen] = useState(false); const [previewItems, setPreviewItems] = useState([]); const [previewLoading, setPreviewLoading] = useState(false); @@ -168,11 +168,15 @@ export default function HomeMarqueeSeeds() { } }; - // ===== 预览实际 feed ===== - const fetchPreview = async () => { + // ===== 预览实际 feed(常驻内联,跟随数据源模式实时刷新)===== + // 显式把当前选中的 mode 传给后端预览:不依赖 PATCH 落库时序 —— 拨动开关(乐观更新 mode)即刻预览 + // 对应模式;切换失败回滚 mode 时预览也随之回滚。种子随机抽样,故也可点「换一批」重随机。 + const fetchPreview = async (m: string = mode) => { setPreviewLoading(true); try { - const { data } = await api.get<{ items: PreviewItem[] }>('/admin/api/marquee-seeds/preview?limit=8'); + const { data } = await api.get<{ items: PreviewItem[] }>('/admin/api/marquee-seeds/preview', { + params: { limit: 8, mode: m }, + }); setPreviewItems(data.items); } catch (e) { message.error(errMsg(e)); @@ -180,10 +184,11 @@ export default function HomeMarqueeSeeds() { setPreviewLoading(false); } }; - const openPreview = () => { - setPreviewOpen(true); - fetchPreview(); - }; + // 模式变化(初次拉到持久化模式 / 拨动开关 / 切换失败回滚)→ 重拉预览,保证「所见=当前模式」。 + useEffect(() => { + fetchPreview(mode); + // eslint-disable-next-line react-hooks/exhaustive-deps + }, [mode]); const toggle = async (s: Seed, enabled: boolean) => { try { @@ -300,6 +305,66 @@ export default function HomeMarqueeSeeds() { 混播=真实优先+种子补位;只真实=不掺假数据(真实不足则少显示);只种子=只用下方种子/合成(演示用) + + {/* 预览:常驻内联,跟随上方「数据源」模式实时刷新(所见=客户端实际效果)。 */} +
+
+ + 预览 · {MODE_LABEL[mode] ?? mode} + + 客户端实际会看到的效果,随上方数据源实时刷新;种子随机抽取、金额/用户名每次都不同 + + + +
+ +
+ {previewItems.length === 0 && !previewLoading ? ( +
+ {mode === 'real' + ? '当前无真实比价记录 ——「只真实」模式不补种子,故为空' + : '暂无数据'} +
+ ) : ( + previewItems.map((it, i) => ( +
+ + {it.masked_user} 比价后节省{' '} + {yuan(it.saved_amount_cents)} 元 + + {it.time} +
+ )) + )} +
+
+
+ - - - - } - > -

- 客户端实际会看到的混播结果:真实记录会插队,种子随机抽取、金额/用户名每次都不同。点「换一批」可重新随机。 -

- -
- {previewItems.map((it, i) => ( -
- - {it.masked_user} 比价后节省{' '} - {yuan(it.saved_amount_cents)} 元 - - {it.time} -
- ))} -
-
- ); }