feat(integration): 新增 site_code 支持并增强玩家与注单管理界面
在后台玩家与注单相关 API 中新增 site_code 参数,支持按站点筛选数据。 更新 PlayersConsole 与 PlayerTicketsConsole UI 组件,新增站点选择筛选功能。 增强国际化支持,在英文与中文语言包中新增站点相关文案。 优化配置中心页面,新增跳转至集成站点管理的入口,提升后台导航体验。
This commit is contained in:
@@ -5,6 +5,7 @@ import { useExportLabels } from "@/hooks/use-export-labels";
|
||||
import { useTranslation } from "react-i18next";
|
||||
|
||||
import { getAdminTicketItems } from "@/api/admin-tickets";
|
||||
import { useAdminSiteCodeOptions } from "@/hooks/use-admin-site-code-options";
|
||||
import { AdminDateRangeField } from "@/components/admin/admin-date-range-field";
|
||||
import { AdminListPaginationFooter } from "@/components/admin/admin-list-pagination-footer";
|
||||
import { AdminTableExportButton } from "@/components/admin/admin-table-export-button";
|
||||
@@ -19,6 +20,13 @@ import {
|
||||
} from "@/components/ui/dropdown-menu";
|
||||
import { Input } from "@/components/ui/input";
|
||||
import { Label } from "@/components/ui/label";
|
||||
import {
|
||||
Select,
|
||||
SelectContent,
|
||||
SelectItem,
|
||||
SelectTrigger,
|
||||
SelectValue,
|
||||
} from "@/components/ui/select";
|
||||
import {
|
||||
Table,
|
||||
TableBody,
|
||||
@@ -48,6 +56,7 @@ const TICKET_STATUS_OPTIONS = [
|
||||
] as const;
|
||||
|
||||
type TicketFilters = {
|
||||
siteCode: string;
|
||||
playerQuery: string;
|
||||
drawNo: string;
|
||||
numberKeyword: string;
|
||||
@@ -57,6 +66,7 @@ type TicketFilters = {
|
||||
};
|
||||
|
||||
const emptyTicketFilters: TicketFilters = {
|
||||
siteCode: "",
|
||||
playerQuery: "",
|
||||
drawNo: "",
|
||||
numberKeyword: "",
|
||||
@@ -90,6 +100,7 @@ function ticketStatusSummary(statuses: string[], t: TicketTranslateFn): string {
|
||||
|
||||
export function PlayerTicketsConsole(): React.ReactElement {
|
||||
const { t } = useTranslation(["tickets", "common"]);
|
||||
const { sites: siteOptions, canChooseSite } = useAdminSiteCodeOptions();
|
||||
const playCodeLabel = useAdminPlayCodeLabel();
|
||||
const exportLabels = useExportLabels("tickets");
|
||||
const formatTs = useAdminDateTimeFormatter();
|
||||
@@ -118,6 +129,7 @@ export function PlayerTicketsConsole(): React.ReactElement {
|
||||
page,
|
||||
per_page: perPage,
|
||||
...query,
|
||||
site_code: applied.siteCode.trim() || undefined,
|
||||
draw_no: applied.drawNo.trim() || undefined,
|
||||
status: applied.statuses.length > 0 ? applied.statuses : undefined,
|
||||
number: applied.numberKeyword.trim() || undefined,
|
||||
@@ -143,6 +155,7 @@ export function PlayerTicketsConsole(): React.ReactElement {
|
||||
setErr(null);
|
||||
setApplied({
|
||||
...draft,
|
||||
siteCode: draft.siteCode.trim(),
|
||||
playerQuery: draft.playerQuery.trim(),
|
||||
drawNo: draft.drawNo.trim(),
|
||||
numberKeyword: draft.numberKeyword.trim(),
|
||||
@@ -173,6 +186,32 @@ export function PlayerTicketsConsole(): React.ReactElement {
|
||||
</CardHeader>
|
||||
<CardContent className="admin-list-content">
|
||||
<div className="admin-list-toolbar">
|
||||
{canChooseSite ? (
|
||||
<div className="admin-list-field">
|
||||
<Label className="sm:shrink-0">{t("filterSite")}</Label>
|
||||
<Select
|
||||
value={draft.siteCode || "__all__"}
|
||||
onValueChange={(v) =>
|
||||
setDraft((current) => ({
|
||||
...current,
|
||||
siteCode: 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 min-w-[12rem] flex-1 sm:max-w-md">
|
||||
<Label htmlFor="pt-player" className="sm:shrink-0">
|
||||
{t("playerId")}
|
||||
|
||||
Reference in New Issue
Block a user