feat: 增强开奖 API 的币种支持并优化钱包处理逻辑
更新 getDrawCurrent、getDrawResults 与 getDrawResultByNo 方法,新增币种参数支持,以适配玩家币种偏好。 优化 HallBettingGrid 及相关组件:支持币种切换时自动刷新钱包数据。 重构钱包处理逻辑,简化余额更新流程并提升用户体验。 新增会话过期相关多语言提示文案,并优化现有翻译内容,提升多语言环境下的提示清晰度。
This commit is contained in:
@@ -68,6 +68,15 @@ function initialSteps(): EntryStep[] {
|
||||
];
|
||||
}
|
||||
|
||||
function stripSearchParamFromBrowserUrl(name: string): void {
|
||||
if (typeof window === "undefined") return;
|
||||
const url = new URL(window.location.href);
|
||||
if (!url.searchParams.has(name)) return;
|
||||
url.searchParams.delete(name);
|
||||
const next = `${url.pathname}${url.search}${url.hash}`;
|
||||
window.history.replaceState(null, "", next);
|
||||
}
|
||||
|
||||
function shouldRetryEntryRequest(error: unknown): boolean {
|
||||
if (error instanceof LotteryApiBizError) {
|
||||
return false;
|
||||
@@ -93,12 +102,22 @@ export function EntryGate() {
|
||||
const { t: tc } = useTranslation("common");
|
||||
|
||||
const tokenFromUrl = searchParams.get("token") ?? "";
|
||||
const sessionExpired = searchParams.get("session") === "expired";
|
||||
|
||||
const { bearerToken, setBearerToken, setProfile, setCurrencies, clearBearerToken } =
|
||||
usePlayerSessionStore();
|
||||
|
||||
const [phase, setPhase] = useState<Phase>("loading");
|
||||
const [failureDetails, setFailureDetails] = useState<FailureRow[]>([]);
|
||||
const [phase, setPhase] = useState<Phase>(sessionExpired ? "failed" : "loading");
|
||||
const [failureDetails, setFailureDetails] = useState<FailureRow[]>(() =>
|
||||
sessionExpired
|
||||
? [
|
||||
{
|
||||
code: "SESSION_EXPIRED",
|
||||
detailKey: "errors.sessionExpiredDetail",
|
||||
},
|
||||
]
|
||||
: [],
|
||||
);
|
||||
const [steps, setSteps] = useState<EntryStep[]>(initialSteps());
|
||||
|
||||
const effectiveToken = tokenFromUrl || bearerToken;
|
||||
@@ -113,12 +132,6 @@ export function EntryGate() {
|
||||
return Math.round(((doneCount + inProgressCount * 0.5) / steps.length) * 100);
|
||||
}, [steps]);
|
||||
|
||||
const handleRetry = useCallback(() => {
|
||||
setPhase("loading");
|
||||
setFailureDetails([]);
|
||||
setSteps(initialSteps());
|
||||
}, []);
|
||||
|
||||
const doEntry = useCallback(async () => {
|
||||
if (!effectiveToken) {
|
||||
setPhase("failed");
|
||||
@@ -128,6 +141,7 @@ export function EntryGate() {
|
||||
|
||||
if (tokenFromUrl) {
|
||||
setBearerToken(tokenFromUrl);
|
||||
stripSearchParamFromBrowserUrl("token");
|
||||
}
|
||||
|
||||
setSteps((prev) =>
|
||||
@@ -231,12 +245,26 @@ export function EntryGate() {
|
||||
t,
|
||||
]);
|
||||
|
||||
const handleRetry = useCallback(() => {
|
||||
setPhase("loading");
|
||||
setFailureDetails([]);
|
||||
setSteps(initialSteps());
|
||||
void doEntry();
|
||||
}, [doEntry]);
|
||||
|
||||
useEffect(() => {
|
||||
if (!sessionExpired) return;
|
||||
clearBearerToken();
|
||||
stripSearchParamFromBrowserUrl("session");
|
||||
}, [sessionExpired, clearBearerToken]);
|
||||
|
||||
useEffect(() => {
|
||||
if (sessionExpired) return;
|
||||
const tmr = window.setTimeout(() => {
|
||||
void doEntry();
|
||||
}, 300);
|
||||
return () => window.clearTimeout(tmr);
|
||||
}, [doEntry]);
|
||||
}, [doEntry, sessionExpired]);
|
||||
|
||||
return (
|
||||
<div className="relative flex min-h-dvh flex-col bg-white">
|
||||
|
||||
Reference in New Issue
Block a user