feat(integration): 新增 site_code 支持并增强玩家与注单管理界面
在后台玩家与注单相关 API 中新增 site_code 参数,支持按站点筛选数据。 更新 PlayersConsole 与 PlayerTicketsConsole UI 组件,新增站点选择筛选功能。 增强国际化支持,在英文与中文语言包中新增站点相关文案。 优化配置中心页面,新增跳转至集成站点管理的入口,提升后台导航体验。
This commit is contained in:
@@ -50,6 +50,7 @@ import {
|
||||
TableRow,
|
||||
} from "@/components/ui/table";
|
||||
import { useAdminCurrencyCatalog } from "@/hooks/use-admin-currency-catalog";
|
||||
import { useAdminSiteCodeOptions } from "@/hooks/use-admin-site-code-options";
|
||||
import { formatAdminMinorUnits } from "@/lib/money";
|
||||
import { LotteryApiBizError } from "@/types/api/errors";
|
||||
import type { AdminPlayerRow, AdminPlayerWalletRow } from "@/types/api/admin-player";
|
||||
@@ -87,8 +88,11 @@ export function PlayersConsole(): React.ReactElement {
|
||||
const canFreezePlayers = adminHasAnyPermission(profile?.permissions, [PRD_PLAYER_FREEZE_MANAGE]);
|
||||
const [page, setPage] = useState(1);
|
||||
const [perPage, setPerPage] = useState(10);
|
||||
const { sites: siteOptions, canChooseSite } = useAdminSiteCodeOptions();
|
||||
const [keyword, setKeyword] = useState("");
|
||||
const [query, setQuery] = useState("");
|
||||
const [siteCode, setSiteCode] = useState("");
|
||||
const [appliedSiteCode, setAppliedSiteCode] = useState("");
|
||||
|
||||
const [items, setItems] = useState<AdminPlayerRow[]>([]);
|
||||
const [total, setTotal] = useState(0);
|
||||
@@ -124,6 +128,7 @@ export function PlayersConsole(): React.ReactElement {
|
||||
page,
|
||||
per_page: perPage,
|
||||
keyword: query.trim() || undefined,
|
||||
site_code: appliedSiteCode.trim() || undefined,
|
||||
});
|
||||
setItems(data.items);
|
||||
setTotal(data.meta.total);
|
||||
@@ -137,7 +142,7 @@ export function PlayersConsole(): React.ReactElement {
|
||||
} finally {
|
||||
setLoading(false);
|
||||
}
|
||||
}, [page, perPage, query, t]);
|
||||
}, [page, perPage, query, appliedSiteCode, t]);
|
||||
|
||||
useEffect(() => {
|
||||
queueMicrotask(() => {
|
||||
@@ -297,6 +302,24 @@ export function PlayersConsole(): React.ReactElement {
|
||||
) : null}
|
||||
</div>
|
||||
<div className="admin-list-toolbar">
|
||||
{canChooseSite ? (
|
||||
<div className="admin-list-field">
|
||||
<Label className="sm:w-20 sm:shrink-0">{t("filterSite")}</Label>
|
||||
<Select value={siteCode || "__all__"} onValueChange={(v) => setSiteCode(v === "__all__" ? "" : v)}>
|
||||
<SelectTrigger className="w-full sm:w-[12rem]">
|
||||
<SelectValue placeholder={t("filterAllSites")} />
|
||||
</SelectTrigger>
|
||||
<SelectContent>
|
||||
<SelectItem value="__all__">{t("filterAllSites")}</SelectItem>
|
||||
{siteOptions.map((site) => (
|
||||
<SelectItem key={site.code} value={site.code}>
|
||||
{site.code} — {site.name}
|
||||
</SelectItem>
|
||||
))}
|
||||
</SelectContent>
|
||||
</Select>
|
||||
</div>
|
||||
) : null}
|
||||
<div className="admin-list-field xl:min-w-0">
|
||||
<Label htmlFor="player-search" className="sm:w-20 sm:shrink-0">
|
||||
{t("search")}
|
||||
@@ -311,6 +334,7 @@ export function PlayersConsole(): React.ReactElement {
|
||||
if (e.key === "Enter") {
|
||||
setPage(1);
|
||||
setQuery(keyword.trim());
|
||||
setAppliedSiteCode(siteCode.trim());
|
||||
}
|
||||
}}
|
||||
/>
|
||||
@@ -326,6 +350,7 @@ export function PlayersConsole(): React.ReactElement {
|
||||
onClick={() => {
|
||||
setPage(1);
|
||||
setQuery(keyword.trim());
|
||||
setAppliedSiteCode(siteCode.trim());
|
||||
}}
|
||||
>
|
||||
{t("search")}
|
||||
|
||||
Reference in New Issue
Block a user