From 1922a29f49796120d50ce2143997d57b8bd8f66c Mon Sep 17 00:00:00 2001 From: kang Date: Mon, 11 May 2026 14:00:51 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E5=A2=9E=E5=BC=BA=E5=B0=81=E7=9B=98?= =?UTF-8?q?=E7=8A=B6=E6=80=81=E5=A4=84=E7=90=86=E4=B8=8E=E7=94=A8=E6=88=B7?= =?UTF-8?q?=E7=95=8C=E9=9D=A2=E5=8F=8D=E9=A6=88?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 在 draw-status-meta.ts 中新增 isHallSealedCountdownUi 函数以判断封盘状态 - 在 hall-bet-preview-dialog.tsx 中添加 allowSubmit 属性,控制提交按钮状态 - 更新 hall-betting-grid.tsx 以显示封盘提示与禁用下注功能 - 在 hall-draw-panel.tsx 中优化封盘状态的视觉反馈 - 修改 hall-screen.tsx 的注释以反映封盘相关的界面变化 --- src/features/draw/draw-status-meta.ts | 8 +++++ src/features/hall/hall-bet-preview-dialog.tsx | 16 +++++++-- src/features/hall/hall-betting-grid.tsx | 32 ++++++++++++++--- src/features/hall/hall-draw-panel.tsx | 34 ++++++++++++++----- src/features/hall/hall-screen.tsx | 2 +- 5 files changed, 75 insertions(+), 17 deletions(-) diff --git a/src/features/draw/draw-status-meta.ts b/src/features/draw/draw-status-meta.ts index 507f2c8..bd35a80 100644 --- a/src/features/draw/draw-status-meta.ts +++ b/src/features/draw/draw-status-meta.ts @@ -6,6 +6,14 @@ export type DrawStatusHud = { countdownKind: "close" | "draw" | "cooldown" | "none"; }; +/** + * 界面文档 §4.2「封盘」展示:`closing`(封盘中)与 `closed`(待开奖)—— + * 倒计时区域使用错误色 #ff4d4f,并提示「请选择下一期」。 + */ +export function isHallSealedCountdownUi(status: string): boolean { + return status === "closing" || status === "closed"; +} + /** 对齐界面文档 §4.2 状态文案与 PRD 期号状态 */ export function drawStatusHud(status: string): DrawStatusHud { switch (status) { diff --git a/src/features/hall/hall-bet-preview-dialog.tsx b/src/features/hall/hall-bet-preview-dialog.tsx index c5200c2..4f5c36f 100644 --- a/src/features/hall/hall-bet-preview-dialog.tsx +++ b/src/features/hall/hall-bet-preview-dialog.tsx @@ -22,6 +22,8 @@ type HallBetPreviewDialogProps = { currencyCode: string; data: TicketPreviewData | null; placing: boolean; + /** 界面 §4.2:封盘后禁止提交,主按钮文案为「已封盘」 */ + allowSubmit?: boolean; onConfirmPlace: () => void; }; @@ -56,6 +58,7 @@ export function HallBetPreviewDialog({ currencyCode, data, placing, + allowSubmit = true, onConfirmPlace, }: HallBetPreviewDialogProps) { const summary = data?.summary; @@ -71,6 +74,15 @@ export function HallBetPreviewDialog({ 请核对号码、玩法与实扣金额;确认后将扣减彩票钱包且不可撤单(产品文档 §6.3)。 + {!allowSubmit ? ( + + + 已封盘 + + 当前期已停止接收注单,无法提交。请选择下一期(界面文档 §4.2)。 + + + ) : null} @@ -160,8 +172,8 @@ export function HallBetPreviewDialog({ - diff --git a/src/features/hall/hall-betting-grid.tsx b/src/features/hall/hall-betting-grid.tsx index 7a69b2b..82f8908 100644 --- a/src/features/hall/hall-betting-grid.tsx +++ b/src/features/hall/hall-betting-grid.tsx @@ -18,6 +18,7 @@ import { mapTicketBetError } from "@/features/hall/hall-bet-errors"; import { HallBetAmountInput } from "@/features/hall/hall-bet-amount-input"; import { HallBetPreviewDialog } from "@/features/hall/hall-bet-preview-dialog"; import { HallBetNumberInput } from "@/features/hall/hall-bet-number-input"; +import { isHallSealedCountdownUi } from "@/features/draw/draw-status-meta"; import { playNeedsDigitSlot, playNeedsDimension, @@ -195,6 +196,7 @@ export function HallBettingGrid() { const maxBet = selectedRow?.config?.max_bet_amount ?? 999_999_999; const tableDisabled = !isBettable || catalogState.kind !== "ok"; + const sealedBetUi = Boolean(display && isHallSealedCountdownUi(display.status)); const [previewOpen, setPreviewOpen] = useState(false); const [previewData, setPreviewData] = useState(null); @@ -271,6 +273,10 @@ export function HallBettingGrid() { const handlePlace = async () => { if (!display || !previewData) return; + if (!isBettable) { + toast.error("已封盘,无法提交。"); + return; + } const line = buildLine(); if (!line) { toast.error("提交前数据已变化,请关闭预览后重试。"); @@ -328,13 +334,23 @@ export function HallBettingGrid() {
{!isBettable && display ? ( -

- 已封盘:本期状态为「{display.status}」,不可下注。按钮已锁定为「已封盘」(产品文档 §6.3、界面 §4.2)。 -

+ sealedBetUi ? ( +
+

+ 已封盘:表格置灰且不可编辑;倒计时区域见上方期号卡片(界面文档 §4.2)。 +

+

请选择下一期。

+
+ ) : ( +

+ 当前期不可下注(状态「{display.status}」)。提交入口已禁用。 +

+ ) ) : null} - + 下注 @@ -456,6 +477,7 @@ export function HallBettingGrid() { currencyCode={currencyCode} data={previewData} placing={placeLoading} + allowSubmit={isBettable} onConfirmPlace={() => void handlePlace()} /> diff --git a/src/features/hall/hall-draw-panel.tsx b/src/features/hall/hall-draw-panel.tsx index 2d65948..1e1cc27 100644 --- a/src/features/hall/hall-draw-panel.tsx +++ b/src/features/hall/hall-draw-panel.tsx @@ -11,13 +11,16 @@ import { CardTitle, } from "@/components/ui/card"; import { Skeleton } from "@/components/ui/skeleton"; -import { drawStatusHud } from "@/features/draw/draw-status-meta"; +import { drawStatusHud, isHallSealedCountdownUi } from "@/features/draw/draw-status-meta"; import { useHallDrawLive } from "@/features/hall/use-hall-draw-live"; import { formatSecondsClock } from "@/lib/format-gmt"; import { formatLotteryInstant } from "@/lib/player-datetime"; import { cn } from "@/lib/utils"; import type { DrawCurrentPayload } from "@/types/api/draw-current"; +/** 界面文档 §1.4:错误/封盘 #ff4d4f */ +const UI_DOC_ERROR = "text-[#ff4d4f]"; + function CountdownStrip({ hud, payload, @@ -25,6 +28,8 @@ function CountdownStrip({ hud: ReturnType; payload: DrawCurrentPayload; }) { + const sealedCountdown = isHallSealedCountdownUi(payload.status); + if (hud.countdownKind === "close" && payload.seconds_to_close > 0) { return (

@@ -37,12 +42,17 @@ function CountdownStrip({ } if (hud.countdownKind === "draw" && payload.seconds_to_draw > 0) { return ( -

+

距离开奖:{" "} {formatSecondsClock(payload.seconds_to_draw)} @@ -112,9 +122,12 @@ export function HallDrawPanel() { } const hud = drawStatusHud(display.status); + const sealedUi = isHallSealedCountdownUi(display.status); return ( - +

@@ -143,11 +156,14 @@ export function HallDrawPanel() { - {(display.status === "closing" || display.status === "closed") && ( -

- 已封盘:下注区已锁定,提交按钮显示「已封盘」。详见产品文档 §6.3、实施计划 §13.3。 -

- )} + {sealedUi ? ( +
+

+ 已封盘:期号状态已标记「已封盘」,下注表格置灰且不可编辑;提交入口为「已封盘」。 +

+

请选择下一期。

+
+ ) : null} {Array.isArray(display.result_items) && display.result_items.length > 0 ? (
本期号码已发布,完整 23 组展示见{" "} diff --git a/src/features/hall/hall-screen.tsx b/src/features/hall/hall-screen.tsx index bf8f196..b843af3 100644 --- a/src/features/hall/hall-screen.tsx +++ b/src/features/hall/hall-screen.tsx @@ -6,7 +6,7 @@ import { HallPlayCatalogPanel } from "@/features/hall/hall-play-catalog-panel"; import { HallWalletStrip } from "@/features/hall/hall-wallet-strip"; /** - * 下注大厅:钱包条 §4 + 当期期号 §4.2;玩法目录阶段 4(§12.3);下注表格阶段 5(§13.3)。 + * 下注大厅:钱包条 §4 + 当期期号 §4.2(封盘置灰 / 倒计时错误色 / WS+轮询);玩法目录 §12.3;下注表格 §13.3。 */ export function HallScreen() { return (