feat(hall): 优化桌面端投注表格布局与国际化文本支持
Some checks failed
lotteryfront CI / build (push) Has been cancelled
Some checks failed
lotteryfront CI / build (push) Has been cancelled
This commit is contained in:
@@ -1628,14 +1628,15 @@ export function HallBettingGrid({ drawLive }: { drawLive: HallDrawLiveSnapshot }
|
||||
</div>
|
||||
) : null}
|
||||
|
||||
<div
|
||||
className={cn(
|
||||
"overflow-hidden border border-[#e6edf8] bg-white transition-opacity",
|
||||
isMobile ? "rounded-lg" : "rounded-xl shadow-[0_8px_24px_rgba(15,23,42,0.05)]",
|
||||
tableDisabled && "opacity-55",
|
||||
showWideTableHint && "player-table-scroll-wrap",
|
||||
)}
|
||||
>
|
||||
<div className={cn("min-w-0", !isMobile && "flex items-start gap-3")}>
|
||||
<div
|
||||
className={cn(
|
||||
"min-w-0 flex-1 overflow-hidden border border-[#e6edf8] bg-white transition-opacity",
|
||||
isMobile ? "rounded-lg" : "rounded-xl shadow-[0_8px_24px_rgba(15,23,42,0.05)]",
|
||||
tableDisabled && "opacity-55",
|
||||
showWideTableHint && "player-table-scroll-wrap",
|
||||
)}
|
||||
>
|
||||
<div className="mb-3 overflow-x-auto rounded border border-[#dae3f3] shadow-sm">
|
||||
<table className="w-full border-collapse text-center text-[11px] tabular-nums">
|
||||
<thead>
|
||||
@@ -1727,8 +1728,12 @@ export function HallBettingGrid({ drawLive }: { drawLive: HallDrawLiveSnapshot }
|
||||
...current,
|
||||
[column.key]: checked === true,
|
||||
}))}
|
||||
aria-label={`${playColumnHeaderLabel(column.play, playCategory(column.play.play_code), column.digitSlot, t)} 同步本列金额`}
|
||||
title="同步本列金额"
|
||||
aria-label={t("hall.table.syncColumnAmount", {
|
||||
column: playColumnHeaderLabel(column.play, playCategory(column.play.play_code), column.digitSlot, t),
|
||||
})}
|
||||
title={t("hall.table.syncColumnAmount", {
|
||||
column: playColumnHeaderLabel(column.play, playCategory(column.play.play_code), column.digitSlot, t),
|
||||
})}
|
||||
className="mx-auto mt-1 size-3.5"
|
||||
/>
|
||||
</th>
|
||||
@@ -1745,15 +1750,15 @@ export function HallBettingGrid({ drawLive }: { drawLive: HallDrawLiveSnapshot }
|
||||
event.currentTarget.value = "";
|
||||
}}
|
||||
className="mx-auto mt-1 h-5 w-full rounded border border-[#d7e1f3] bg-white px-0.5 text-[10px] font-semibold text-[#304f86]"
|
||||
aria-label="全选种类"
|
||||
title="统一设置所有行的种类"
|
||||
aria-label={t("hall.table.selectAllTypes")}
|
||||
title={t("hall.table.setAllTypes")}
|
||||
>
|
||||
<option value="">全选</option>
|
||||
<option value="straight">正字</option>
|
||||
<option value="reverse">来回</option>
|
||||
<option value="full_cover">全保</option>
|
||||
<option value="full_play">全打</option>
|
||||
{activeCategory === "D4" ? <option value="half_play">半打</option> : null}
|
||||
<option value="">{t("hall.table.selectAll")}</option>
|
||||
<option value="straight">{t("hall.table.selectionTypes.straight")}</option>
|
||||
<option value="reverse">{t("hall.table.selectionTypes.reverse")}</option>
|
||||
<option value="full_cover">{t("hall.table.selectionTypes.full_cover")}</option>
|
||||
<option value="full_play">{t("hall.table.selectionTypes.full_play")}</option>
|
||||
{activeCategory === "D4" ? <option value="half_play">{t("hall.table.selectionTypes.half_play")}</option> : null}
|
||||
</select>
|
||||
</th>
|
||||
) : null}
|
||||
@@ -1770,7 +1775,7 @@ export function HallBettingGrid({ drawLive }: { drawLive: HallDrawLiveSnapshot }
|
||||
checked={checked}
|
||||
disabled={tableDisabled}
|
||||
onCheckedChange={(next) => toggleProviderColumn(provider.code, next === true)}
|
||||
aria-label={`全选 ${provider.name}`}
|
||||
aria-label={t("hall.table.selectAllProvider", { provider: provider.name })}
|
||||
className="mx-auto mt-1 border-slate-500 bg-white data-checked:border-slate-800 data-checked:bg-slate-800"
|
||||
/>
|
||||
</th>
|
||||
@@ -1816,74 +1821,63 @@ export function HallBettingGrid({ drawLive }: { drawLive: HallDrawLiveSnapshot }
|
||||
))}
|
||||
</tbody>
|
||||
</table>
|
||||
{!isMobile ? (
|
||||
<aside className="min-w-[12rem] flex-1 border-l border-[#e6edf8] bg-[#f8fbff] px-4 py-4 text-[#304f86]">
|
||||
<p className="text-xs font-black">{t("hall.table.orderSummary", { defaultValue: "Order summary" })}</p>
|
||||
<dl className="mt-5 space-y-4">
|
||||
<div className="flex items-center justify-between gap-3">
|
||||
<dt className="text-xs text-slate-500">{t("hall.table.lineCount", { defaultValue: "Lines" })}</dt>
|
||||
<dd className="font-mono text-base font-black tabular-nums">{draftEntries.length}</dd>
|
||||
</div>
|
||||
<div className="flex items-center justify-between gap-3">
|
||||
<dt className="text-xs text-slate-500">{t("hall.table.providerCount", { defaultValue: "Providers" })}</dt>
|
||||
<dd className="font-mono text-base font-black tabular-nums">{selectedProviderCount}</dd>
|
||||
</div>
|
||||
<div className="border-t border-[#dce6f5] pt-4">
|
||||
<dt className="text-xs text-slate-500">{t("hall.table.actualTotal")}</dt>
|
||||
<dd className="mt-1 text-lg font-black tabular-nums text-[#0b3f96]">
|
||||
{formatMinorAsCurrency(submitActualMinor, currencyCode)}
|
||||
</dd>
|
||||
</div>
|
||||
</dl>
|
||||
</aside>
|
||||
) : null}
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
{!isMobile ? (
|
||||
<aside className="sticky top-3 z-20 w-64 shrink-0 self-start rounded-xl border border-[#e6edf8] bg-[#f8fbff] px-4 py-4 text-[#304f86] shadow-[0_8px_24px_rgba(15,23,42,0.05)]">
|
||||
<p className="text-xs font-black">{t("hall.table.orderSummary", { defaultValue: "Order summary" })}</p>
|
||||
<dl className="mt-5 space-y-4">
|
||||
<div className="flex items-center justify-between gap-3">
|
||||
<dt className="text-xs text-slate-500">{t("hall.table.lineCount", { defaultValue: "Lines" })}</dt>
|
||||
<dd className="font-mono text-base font-black tabular-nums">{draftEntries.length}</dd>
|
||||
</div>
|
||||
<div className="flex items-center justify-between gap-3">
|
||||
<dt className="text-xs text-slate-500">{t("hall.table.providerCount", { defaultValue: "Providers" })}</dt>
|
||||
<dd className="font-mono text-base font-black tabular-nums">{selectedProviderCount}</dd>
|
||||
</div>
|
||||
<div className="border-t border-[#dce6f5] pt-4">
|
||||
<dt className="text-xs text-slate-500">{t("hall.table.actualTotal")}</dt>
|
||||
<dd className="mt-1 text-lg font-black tabular-nums text-[#0b3f96]">
|
||||
{formatMinorAsCurrency(submitActualMinor, currencyCode)}
|
||||
</dd>
|
||||
</div>
|
||||
</dl>
|
||||
<Button
|
||||
type="button"
|
||||
disabled={!canSubmit || previewLoading}
|
||||
onClick={() => void handlePreview()}
|
||||
className={cn(
|
||||
"mt-6 h-11 w-full gap-2 rounded-lg border-0 text-sm font-bold text-white",
|
||||
!isBettable
|
||||
? "bg-slate-500 shadow-none hover:bg-slate-500 disabled:opacity-100"
|
||||
: "bg-[#e5002c] shadow-[0_8px_20px_rgba(229,0,44,0.26)] hover:bg-[#d10028]",
|
||||
)}
|
||||
>
|
||||
{!isBettable ? (
|
||||
<Lock className="size-4 shrink-0" aria-hidden />
|
||||
) : (
|
||||
<Ticket className="size-4 shrink-0" aria-hidden />
|
||||
)}
|
||||
{previewLoading
|
||||
? t("hall.table.previewing")
|
||||
: !isBettable
|
||||
? t("hall.closed.title")
|
||||
: availableMinor < submitActualMinor
|
||||
? t("hall.table.insufficientBalance")
|
||||
: t("hall.table.submitBet")}
|
||||
</Button>
|
||||
</aside>
|
||||
) : null}
|
||||
</div>
|
||||
|
||||
{!isMobile ? (
|
||||
<div className="flex items-center justify-between rounded-xl border border-[#e9eef7] bg-[#f8fbff] px-3 py-2.5 text-sm shadow-[0_6px_20px_rgba(15,23,42,0.04)]">
|
||||
<span className="text-xs font-medium text-slate-500">
|
||||
{t("hall.table.draftTotal")}
|
||||
</span>
|
||||
<span className="text-base font-black tabular-nums text-[#0b3f96]">
|
||||
{formatMinorAsCurrency(debouncedSummary.actual, currencyCode)}
|
||||
</span>
|
||||
</div>
|
||||
) : null}
|
||||
|
||||
{sealedBetUi ? (
|
||||
<p className="rounded-lg border border-red-200 bg-red-50 px-3 py-2 text-xs text-red-600">
|
||||
{t("hall.table.sealedHint")}
|
||||
</p>
|
||||
) : null}
|
||||
|
||||
{!isMobile ? (
|
||||
<Button
|
||||
type="button"
|
||||
disabled={!canSubmit || previewLoading}
|
||||
onClick={() => void handlePreview()}
|
||||
className={cn(
|
||||
"h-12 w-full gap-2 rounded-xl border-0 text-base font-bold text-white",
|
||||
!isBettable
|
||||
? "bg-slate-500 shadow-none hover:bg-slate-500 disabled:opacity-100"
|
||||
: "bg-[#e5002c] shadow-[0_8px_20px_rgba(229,0,44,0.26)] hover:bg-[#d10028]",
|
||||
)}
|
||||
>
|
||||
{!isBettable ? (
|
||||
<Lock className="size-5 shrink-0" aria-hidden />
|
||||
) : (
|
||||
<Ticket className="size-5 shrink-0" aria-hidden />
|
||||
)}
|
||||
{previewLoading
|
||||
? t("hall.table.previewing")
|
||||
: !isBettable
|
||||
? t("hall.closed.title")
|
||||
: availableMinor < submitActualMinor
|
||||
? t("hall.table.insufficientBalance")
|
||||
: t("hall.table.submitBet")}
|
||||
</Button>
|
||||
) : null}
|
||||
</section>
|
||||
|
||||
{isMobile ? (
|
||||
@@ -2140,13 +2134,13 @@ const DraftRowItem = memo(function DraftRowItem({
|
||||
disabled={tableDisabled}
|
||||
onChange={(event) => updateRowSelectionType(row.id, event.target.value as DraftRow["selectionType"])}
|
||||
className="h-8 w-full rounded-md border border-[#e1e8f3] bg-white px-1 text-[10px] font-semibold text-[#304f86]"
|
||||
aria-label={`第 ${index + 1} 行种类`}
|
||||
aria-label={t("hall.table.selectionTypeForRow", { row: index + 1 })}
|
||||
>
|
||||
<option value="straight">正字</option>
|
||||
<option value="reverse">来回</option>
|
||||
<option value="full_cover">全保</option>
|
||||
<option value="full_play">全打</option>
|
||||
{activeCategory === "D4" ? <option value="half_play">半打</option> : null}
|
||||
<option value="straight">{t("hall.table.selectionTypes.straight")}</option>
|
||||
<option value="reverse">{t("hall.table.selectionTypes.reverse")}</option>
|
||||
<option value="full_cover">{t("hall.table.selectionTypes.full_cover")}</option>
|
||||
<option value="full_play">{t("hall.table.selectionTypes.full_play")}</option>
|
||||
{activeCategory === "D4" ? <option value="half_play">{t("hall.table.selectionTypes.half_play")}</option> : null}
|
||||
</select>
|
||||
</td>
|
||||
) : null}
|
||||
|
||||
Reference in New Issue
Block a user