feat: 增强 iframe 通信机制与通知处理功能
实现 resolvePostMessageTargetOrigin,优化 iframe 消息通信中的目标来源(origin)解析与校验。 更新 IframeBridge:支持定期刷新允许的来源列表,并优化消息事件管理机制。 重构 usePendingWalletReconcile:优化待对账通知的获取与缓存逻辑,提升性能与用户体验。 增强 NotificationsScreen:新增待对账通知内容,并优化界面展示效果。 更新英文、尼泊尔语与中文语言包,新增待对账通知相关翻译文案。
This commit is contained in:
@@ -166,14 +166,6 @@ export function useHallDrawLive(): HallDrawLiveSnapshot {
|
||||
return () => window.removeEventListener(PLAYER_CURRENCY_CHANGE_EVENT, onCurrencyChange);
|
||||
}, [load]);
|
||||
|
||||
// 初始加载
|
||||
useEffect(() => {
|
||||
const timer = window.setTimeout(() => {
|
||||
void load();
|
||||
}, 0);
|
||||
return () => window.clearTimeout(timer);
|
||||
}, [load]);
|
||||
|
||||
// 爆池等场景:刷新大厅快照(含奖池余额)
|
||||
useEffect(() => {
|
||||
const onHallRefresh = () => {
|
||||
|
||||
@@ -4,6 +4,7 @@ import { useEffect } from "react";
|
||||
|
||||
import { getPublicCurrencies } from "@/api/currency";
|
||||
import { getPlayerMe } from "@/api/player";
|
||||
import { loadCurrencyDisplayFormat } from "@/lib/currency-display-settings";
|
||||
import { usePlayerSessionStore } from "@/stores/player-session-store";
|
||||
|
||||
/**
|
||||
@@ -19,6 +20,11 @@ export function HydratePlayerAuth(): null {
|
||||
|
||||
useEffect(() => {
|
||||
usePlayerSessionStore.getState().reconcileSelectedCurrency();
|
||||
void loadCurrencyDisplayFormat();
|
||||
const refreshFormat = setInterval(() => {
|
||||
void loadCurrencyDisplayFormat(true);
|
||||
}, 60_000);
|
||||
|
||||
const token = restoreBearerToken();
|
||||
void (async () => {
|
||||
try {
|
||||
@@ -40,6 +46,10 @@ export function HydratePlayerAuth(): null {
|
||||
/* 401 由 lottery-http 拦截跳转 */
|
||||
}
|
||||
})();
|
||||
|
||||
return () => {
|
||||
clearInterval(refreshFormat);
|
||||
};
|
||||
}, [restoreBearerToken, setCurrencies, setProfile]);
|
||||
|
||||
return null;
|
||||
|
||||
@@ -6,10 +6,13 @@ import { useTranslation } from "react-i18next";
|
||||
|
||||
import { Button } from "@/components/ui/button";
|
||||
import { PlayerPanel } from "@/components/layout/player-panel";
|
||||
import { logTypeLabel } from "@/features/wallet/wallet-logs-block";
|
||||
import { usePendingWalletReconcile } from "@/hooks/use-pending-wallet-reconcile";
|
||||
import { formatLocalDateTime } from "@/lib/format-local-datetime";
|
||||
import { formatMinorAsCurrency } from "@/lib/money";
|
||||
import {
|
||||
pendingReconcileDescriptionKey,
|
||||
pendingReconcileTitleKey,
|
||||
} from "@/lib/pending-reconcile-notification";
|
||||
import { cn } from "@/lib/utils";
|
||||
|
||||
export function NotificationsScreen() {
|
||||
@@ -21,6 +24,10 @@ export function NotificationsScreen() {
|
||||
return (
|
||||
<PlayerPanel title={t("notifications.title")} backHref="/hall">
|
||||
<div className="space-y-3">
|
||||
<p className="rounded-xl border border-amber-200 bg-amber-50/90 px-3 py-2.5 text-xs leading-relaxed text-amber-900">
|
||||
{t("notifications.subtitle")}
|
||||
</p>
|
||||
|
||||
<div className="flex items-center justify-between rounded-xl border border-[#dce7f7] bg-[#f8fbff] px-3 py-2.5">
|
||||
<p className="text-sm font-semibold text-[#0b3f96]">
|
||||
{t("notifications.unreadCount", { count: unreadCount })}
|
||||
@@ -67,26 +74,36 @@ export function NotificationsScreen() {
|
||||
>
|
||||
<div className="flex items-start justify-between gap-2">
|
||||
<div className="min-w-0">
|
||||
<p className="text-sm font-bold text-[#0b3f96]">
|
||||
{logTypeLabel(item.type, t)}
|
||||
<p className="text-sm font-bold text-amber-900">
|
||||
{t(pendingReconcileTitleKey(item.type))}
|
||||
</p>
|
||||
<p className="mt-0.5 text-xs text-slate-500">
|
||||
{formatLocalDateTime(item.created_at)}
|
||||
</p>
|
||||
</div>
|
||||
<span
|
||||
className={cn(
|
||||
"shrink-0 rounded-full px-2 py-0.5 text-[11px] font-bold",
|
||||
cardRead
|
||||
? "bg-slate-100 text-slate-500"
|
||||
: "bg-amber-100 text-amber-700",
|
||||
)}
|
||||
>
|
||||
{cardRead ? t("notifications.read") : t("notifications.unread")}
|
||||
</span>
|
||||
<div className="flex shrink-0 flex-col items-end gap-1">
|
||||
<span className="rounded-full bg-amber-100 px-2 py-0.5 text-[11px] font-bold text-amber-800">
|
||||
{t("notifications.pendingBadge")}
|
||||
</span>
|
||||
<span
|
||||
className={cn(
|
||||
"text-[10px] font-semibold",
|
||||
cardRead ? "text-slate-400" : "text-amber-700",
|
||||
)}
|
||||
>
|
||||
{cardRead ? t("notifications.read") : t("notifications.unread")}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<p className="mt-2 text-xs leading-relaxed text-amber-950/85">
|
||||
{t(pendingReconcileDescriptionKey(item.type))}
|
||||
</p>
|
||||
|
||||
<p className="mt-2 text-sm text-slate-700">
|
||||
<span className="text-xs font-medium text-slate-500">
|
||||
{t("notifications.amountLabel")}{" "}
|
||||
</span>
|
||||
{formatMinorAsCurrency(item.amount, item.currency_code)}
|
||||
</p>
|
||||
|
||||
@@ -105,7 +122,7 @@ export function NotificationsScreen() {
|
||||
className="inline-flex h-8 items-center rounded-full bg-[#07459f] px-3 text-xs font-semibold text-white hover:bg-[#063b88]"
|
||||
onClick={() => markAsRead(item.transfer_no)}
|
||||
>
|
||||
{t("notifications.open")}
|
||||
{t("notifications.viewLogs")}
|
||||
</Link>
|
||||
</div>
|
||||
</li>
|
||||
|
||||
Reference in New Issue
Block a user