refactor(hall): 优化投注格子行数与号码输入逻辑
Some checks failed
lotteryfront CI / build (push) Has been cancelled
Some checks failed
lotteryfront CI / build (push) Has been cancelled
- 引入默认草稿行数常量及批量生成草稿行函数
- 根据玩法类别调整号码最大输入长度和清洗规则
- 更新号码输入组件以适应动态最大长度和格式规范
- 修正相关回调依赖,确保玩法类别变更时生效
- 改善行状态、占位符和样式传递,增强代码可读性
feat(results): 添加多提供商开奖结果切换功能
- 新增状态管理并展示多提供商按钮切换激活项
- 根据选中的提供商动态展示对应开奖结果数据
- 细化UI显示,支持多提供商名称并列渲染
feat(results): 在结果列表中显示多提供商名称
- 当存在多个提供商结果时展示其名称或代码
- 改善界面信息丰富度,方便用户辨识来源
feat(wallet): 支持账期还款释额类型的流水显示
- 调整账期流水类型文案,精准反映释额含义
- 引入账期时区参数以支持多时区时间格式化
- 自定义信用盘账期释额流水的颜色和文案显示
- 在流水明细和列表中根据时区格式化展示时间
feat(wallet): 支持钱包账期账单区间时区格式化
- 允许传入账期时区参数格式化账单区间时间
- 在账期账单区间显示组件中显示对应时区格式
- 根据玩家配置自动获取并传递账期时区信息
- 条件渲染中信用盘区块支持账期时区参数传递
chore(i18n): 更新中文钱包模块多处文案
- 新增“释额 {{amount}}”等账期释额相关文案
- 修改“账期收款”为“账期还款释额”以符合业务描述
refactor(types): 扩展开奖结果支持多提供商结构
- 新增DrawResultProviderRow类型定义以描述提供商结果
- 在DrawResultListItem中增加provider_results字段支持多结果
- 在玩家信息类型中新增settlement_timezone字段表示账期时区
This commit is contained in:
@@ -150,6 +150,11 @@ const D4_PLAY_ORDER = [
|
||||
"digit_small",
|
||||
] as const;
|
||||
const MOBILE_QUICK_AMOUNT_PRESETS = ["10", "50", "100"] as const;
|
||||
const DEFAULT_DRAFT_ROW_COUNT = 20;
|
||||
|
||||
function newDraftRows(count = DEFAULT_DRAFT_ROW_COUNT): DraftRow[] {
|
||||
return Array.from({ length: count }, newDraftRow);
|
||||
}
|
||||
|
||||
function newDraftRow(): DraftRow {
|
||||
const id =
|
||||
@@ -215,8 +220,18 @@ function playColumnsForCategory(
|
||||
});
|
||||
}
|
||||
|
||||
function sanitizeNumber(raw: string): string {
|
||||
return raw.replace(/[^0-9Rr]/g, "").toUpperCase().slice(0, 4);
|
||||
function numberMaxCharsForCategory(category: PlayHallCategory): number {
|
||||
return category === "D2" ? 2 : category === "D3" ? 3 : 4;
|
||||
}
|
||||
|
||||
function sanitizeNumber(raw: string, category: PlayHallCategory): string {
|
||||
const normalized =
|
||||
category === "D4"
|
||||
? raw.replace(/[^0-9Rr]/g, "").toUpperCase()
|
||||
: raw.replace(/\D/g, "");
|
||||
const maxChars = numberMaxCharsForCategory(category);
|
||||
|
||||
return category === "D4" ? normalized.slice(0, maxChars) : normalized.slice(-maxChars);
|
||||
}
|
||||
|
||||
function sanitizeAmount(raw: string): string {
|
||||
@@ -439,7 +454,7 @@ export function HallBettingGrid({ drawLive }: { drawLive: HallDrawLiveSnapshot }
|
||||
const creditMode = isCreditFundingPlayer(usePlayerSessionStore((state) => state.profile));
|
||||
const isMobile = useIsMobile();
|
||||
|
||||
const [rows, setRows] = useState<DraftRow[]>(() => Array.from({ length: 20 }, newDraftRow));
|
||||
const [rows, setRows] = useState<DraftRow[]>(() => newDraftRows());
|
||||
const [activeRowId, setActiveRowId] = useState<string | null>(null);
|
||||
const [catalogState, setCatalogState] = useState<
|
||||
| { kind: "loading" }
|
||||
@@ -642,15 +657,16 @@ export function HallBettingGrid({ drawLive }: { drawLive: HallDrawLiveSnapshot }
|
||||
const sealedBetUi = Boolean(display && isHallSealedCountdownUi(display.status));
|
||||
const numberPlaceholder =
|
||||
activeCategory === "D2" ? "00" : activeCategory === "D3" ? "000" : "0000";
|
||||
const numberMaxChars = numberMaxCharsForCategory(activeCategory);
|
||||
|
||||
const updateRowNumber = useCallback((id: string, value: string) => {
|
||||
setRows((current) =>
|
||||
current.map((row) =>
|
||||
row.id === id ? { ...row, number: sanitizeNumber(value) } : row,
|
||||
row.id === id ? { ...row, number: sanitizeNumber(value, activeCategory) } : row,
|
||||
),
|
||||
);
|
||||
setActiveRowId(id);
|
||||
}, []);
|
||||
}, [activeCategory]);
|
||||
|
||||
const updateAmount = useCallback((rowId: string, playCode: string, value: string) => {
|
||||
setRows((current) =>
|
||||
@@ -1151,7 +1167,7 @@ export function HallBettingGrid({ drawLive }: { drawLive: HallDrawLiveSnapshot }
|
||||
setPreviewData(null);
|
||||
setResultData(data);
|
||||
setResultOpen(true);
|
||||
setRows([newDraftRow()]);
|
||||
setRows(newDraftRows());
|
||||
setActiveRowId(null);
|
||||
triggerWalletPollingAfterBet();
|
||||
void refreshWallet();
|
||||
@@ -1752,6 +1768,8 @@ export function HallBettingGrid({ drawLive }: { drawLive: HallDrawLiveSnapshot }
|
||||
rowActive={activeRowId === row.id}
|
||||
tableDisabled={tableDisabled}
|
||||
numberPlaceholder={numberPlaceholder}
|
||||
activeCategory={activeCategory}
|
||||
numberMaxChars={numberMaxChars}
|
||||
playColumns={playColumns}
|
||||
alertRows={alertRows}
|
||||
liveSoldOutNumbers={liveSoldOutNumbers}
|
||||
@@ -1905,6 +1923,8 @@ const DraftRowItem = memo(function DraftRowItem({
|
||||
rowActive,
|
||||
tableDisabled,
|
||||
numberPlaceholder,
|
||||
activeCategory,
|
||||
numberMaxChars,
|
||||
playColumns,
|
||||
alertRows,
|
||||
liveSoldOutNumbers,
|
||||
@@ -1919,16 +1939,18 @@ const DraftRowItem = memo(function DraftRowItem({
|
||||
indexColClass,
|
||||
numberColClass,
|
||||
stickyNumberLeftClass,
|
||||
}: {
|
||||
row: DraftRow;
|
||||
index: number;
|
||||
rowActive: boolean;
|
||||
tableDisabled: boolean;
|
||||
numberPlaceholder: string;
|
||||
playColumns: PlayColumn[];
|
||||
alertRows: DrawCurrentRiskPoolAlert[];
|
||||
liveSoldOutNumbers: Set<string>;
|
||||
liveWarningNumbers: Set<string>;
|
||||
}: {
|
||||
row: DraftRow;
|
||||
index: number;
|
||||
rowActive: boolean;
|
||||
tableDisabled: boolean;
|
||||
numberPlaceholder: string;
|
||||
activeCategory: PlayHallCategory;
|
||||
numberMaxChars: number;
|
||||
playColumns: PlayColumn[];
|
||||
alertRows: DrawCurrentRiskPoolAlert[];
|
||||
liveSoldOutNumbers: Set<string>;
|
||||
liveWarningNumbers: Set<string>;
|
||||
updateRowNumber: (id: string, value: string) => void;
|
||||
updateAmount: (rowId: string, playCode: string, value: string) => void;
|
||||
setActiveRowId: (id: string) => void;
|
||||
@@ -1937,10 +1959,12 @@ const DraftRowItem = memo(function DraftRowItem({
|
||||
isMobile: boolean;
|
||||
removable: boolean;
|
||||
indexColClass: string;
|
||||
numberColClass: string;
|
||||
stickyNumberLeftClass: string;
|
||||
}) {
|
||||
return (
|
||||
numberColClass: string;
|
||||
stickyNumberLeftClass: string;
|
||||
}) {
|
||||
const displayNumber = sanitizeNumber(row.number, activeCategory);
|
||||
|
||||
return (
|
||||
<tr
|
||||
className={cn(
|
||||
"border-b border-[#f0f3f8] last:border-b-0",
|
||||
@@ -1964,13 +1988,14 @@ const DraftRowItem = memo(function DraftRowItem({
|
||||
rowActive ? "bg-[#f5f9ff]" : "bg-white",
|
||||
)}
|
||||
>
|
||||
<Input
|
||||
value={row.number}
|
||||
disabled={tableDisabled}
|
||||
inputMode="numeric"
|
||||
pattern="[0-9Rr]*"
|
||||
autoComplete="off"
|
||||
placeholder={numberPlaceholder}
|
||||
<Input
|
||||
value={displayNumber}
|
||||
disabled={tableDisabled}
|
||||
inputMode="numeric"
|
||||
pattern="[0-9Rr]*"
|
||||
autoComplete="off"
|
||||
placeholder={numberPlaceholder}
|
||||
maxLength={numberMaxChars}
|
||||
onFocus={() => setActiveRowId(row.id)}
|
||||
onClick={() => setActiveRowId(row.id)}
|
||||
onChange={(event) => updateRowNumber(row.id, event.target.value)}
|
||||
|
||||
Reference in New Issue
Block a user