feat: enhance wallet functionality and improve error handling

- Updated .env.example to include optional player site code configuration.
- Modified error messages in hall-bet-errors for better clarity.
- Improved the betting grid logic to handle invalid draw IDs and reload draws when necessary.
- Adjusted wallet components to differentiate between credit and main wallet balances, including new translations for credit-related terms.
- Enhanced wallet logs to support credit activity tracking and improved UI for displaying credit information.
This commit is contained in:
2026-06-05 18:01:11 +08:00
parent 3cd87ce014
commit 36adf8699d
21 changed files with 496 additions and 80 deletions

View File

@@ -28,7 +28,7 @@ export function mapTicketBetError(
"玩法参数不完整(如单双大小需选择位数与维度)。",
);
case 2006:
return msg("hall.ticketError.2006", "当前期号不可下注。");
return msg("hall.ticketError.2006", "期号无效或已切换,请刷新大厅后重试。");
case 2007:
return msg("hall.ticketError.2007", "该玩法暂不支持或缺少赔率配置。");
case 2008:

View File

@@ -75,7 +75,8 @@ function SubmittingPanel() {
alt=""
width={150}
height={119}
className="mx-auto h-[118px] w-[150px] object-contain"
style={{ width: "auto", height: "auto" }}
className="mx-auto max-h-[118px] w-[150px] object-contain"
priority
aria-hidden
/>

View File

@@ -978,6 +978,9 @@ export function HallBettingGrid({ drawLive }: { drawLive: HallDrawLiveSnapshot }
setPreviewData(null);
clearPlaceTraceId();
}
if (e instanceof LotteryApiBizError && (code === 2001 || code === 2006)) {
void reloadDraw();
}
toast.error(mapTicketBetError(code, msg, t));
} finally {
setPreviewLoading(false);
@@ -1009,10 +1012,17 @@ export function HallBettingGrid({ drawLive }: { drawLive: HallDrawLiveSnapshot }
const traceId = placeTraceIdRef.current ?? newPlaceTraceId();
placeTraceIdRef.current = traceId;
const drawIdForBet =
previewData.draw.draw_id.trim() || display.draw_no.trim();
if (drawIdForBet === "") {
toast.error(t("hall.notBettable"));
return;
}
setPlaceLoading(true);
try {
const data = await postTicketPlace({
draw_id: display.draw_no,
draw_id: drawIdForBet,
currency_code: currencyCode,
client_trace_id: traceId,
lines,
@@ -1067,6 +1077,9 @@ export function HallBettingGrid({ drawLive }: { drawLive: HallDrawLiveSnapshot }
setPreviewData(null);
clearPlaceTraceId();
}
if (e instanceof LotteryApiBizError && (code === 2001 || code === 2006)) {
void reloadDraw();
}
toast.error(mapTicketBetError(code, msg, t));
} finally {
setPlaceLoading(false);

View File

@@ -84,6 +84,8 @@ export function HallWalletStrip() {
}, [mode, refresh]);
const availableMinor = Number(balance?.available_balance ?? balance?.balance ?? 0);
const isCreditPlayer =
balance?.credit_line_mode === true || balance?.funding_mode === "credit";
const mainMinor =
balance?.main_balance === null || balance?.main_balance === undefined
? null
@@ -108,7 +110,11 @@ export function HallWalletStrip() {
<Wallet className="size-7" aria-hidden />
</div>
<div className="min-w-0 flex-1">
<p className="text-sm font-semibold text-white/90">{t("wallet.balance")}</p>
<p className="text-sm font-semibold text-white/90">
{balance?.credit_line_mode
? t("wallet.creditAvailable", { defaultValue: "可用信用" })
: t("wallet.balance")}
</p>
{loading ? (
<Skeleton className="mt-2 h-8 w-44 rounded-md bg-white/25" />
) : (
@@ -120,27 +126,29 @@ export function HallWalletStrip() {
</div>
</div>
<div className="grid grid-cols-2 gap-2.5">
<TransferInDialog
idPrefix="hall-"
triggerVariant="hall"
triggerLabel={t("wallet.transferIn")}
triggerClassName="h-12 rounded-lg text-base font-bold"
currency={currency}
lotteryMinor={availableMinor}
mainMinor={mainMinor}
onSuccess={refresh}
/>
<TransferOutDialog
idPrefix="hall-"
triggerVariant="hall"
triggerLabel={t("wallet.transferOut")}
triggerClassName="h-12 rounded-lg text-base font-bold"
currency={currency}
availableMinor={availableMinor}
onSuccess={refresh}
/>
</div>
{isCreditPlayer ? null : (
<div className="grid grid-cols-2 gap-2.5">
<TransferInDialog
idPrefix="hall-"
triggerVariant="hall"
triggerLabel={t("wallet.transferIn")}
triggerClassName="h-12 rounded-lg text-base font-bold"
currency={currency}
lotteryMinor={availableMinor}
mainMinor={mainMinor}
onSuccess={refresh}
/>
<TransferOutDialog
idPrefix="hall-"
triggerVariant="hall"
triggerLabel={t("wallet.transferOut")}
triggerClassName="h-12 rounded-lg text-base font-bold"
currency={currency}
availableMinor={availableMinor}
onSuccess={refresh}
/>
</div>
)}
</section>
);
}