Some checks failed
lotteryadmin CI / build (push) Has been cancelled
- 各角色仪表盘:KPI 可点击跳转、快捷入口、去重冗余区块,代理/站点降级 analytics - 代理线路:创建玩家权限、侧栏搜索、深链 URL、档案保存与删除预检等修复 - 统一密码最短 6 位;代理模块表格/侧栏背景色一致(admin-table-inset) - 报表、钱包、对账、开奖、结算、配置等模块结构与 i18n 同步更新
176 lines
7.2 KiB
TypeScript
176 lines
7.2 KiB
TypeScript
"use client";
|
|
|
|
import { Eye, Lock } from "lucide-react";
|
|
import { useTranslation } from "react-i18next";
|
|
|
|
import type { SettlementPeriodRow } from "@/api/admin-agent-settlement";
|
|
import { AdminTableNoResourceRow } from "@/components/admin/admin-no-resource-state";
|
|
import { AdminTableLoadingRow } from "@/components/admin/admin-loading-state";
|
|
import { AdminRowActionsMenu } from "@/components/admin/admin-row-actions-menu";
|
|
import { AdminStatusBadge } from "@/components/admin/admin-status-badge";
|
|
import { formatSettlementPeriodSpan } from "@/lib/agent-settlement-period-range";
|
|
import { cn } from "@/lib/utils";
|
|
import { formatDashboardMoneyMinor } from "@/modules/dashboard/use-dashboard-analytics";
|
|
import { signedSettlementMoneyClass } from "@/modules/settlement/settlement-signed-money";
|
|
import { settlementPeriodStatusLabel } from "@/modules/settlement/settlement-status-label";
|
|
import {
|
|
Table,
|
|
TableBody,
|
|
TableCell,
|
|
TableHead,
|
|
TableHeader,
|
|
TableRow,
|
|
} from "@/components/ui/table";
|
|
|
|
const COL_SPAN = 9;
|
|
|
|
type SettlementPeriodsTableProps = {
|
|
periods: SettlementPeriodRow[];
|
|
loading?: boolean;
|
|
canManage: boolean;
|
|
busy?: boolean;
|
|
currencyCode?: string;
|
|
emptyMessage?: string;
|
|
onViewDetail: (periodId: number) => void;
|
|
onRequestClose: (row: SettlementPeriodRow) => void;
|
|
};
|
|
|
|
export function SettlementPeriodsTable({
|
|
periods,
|
|
loading = false,
|
|
canManage,
|
|
busy = false,
|
|
currencyCode = "NPR",
|
|
emptyMessage,
|
|
onViewDetail,
|
|
onRequestClose,
|
|
}: SettlementPeriodsTableProps): React.ReactElement {
|
|
const { t } = useTranslation(["settlementCenter", "agents", "common"]);
|
|
|
|
const billCount = (row: SettlementPeriodRow): number =>
|
|
(row.summary?.player_bills ?? 0)
|
|
+ (row.summary?.agent_bills ?? 0)
|
|
+ (row.summary?.adjustment_bills ?? 0);
|
|
|
|
const winLossScope = periods.find((row) => row.pipeline?.win_loss_scope)?.pipeline?.win_loss_scope
|
|
?? "platform";
|
|
const winLossLabel =
|
|
winLossScope === "agent"
|
|
? t("periodTable.agentWinLoss", { defaultValue: "代理输赢" })
|
|
: t("periodTable.platformWinLoss", { defaultValue: "平台输赢" });
|
|
|
|
return (
|
|
<div className="admin-table-shell overflow-x-auto">
|
|
<Table>
|
|
<TableHeader>
|
|
<TableRow>
|
|
<TableHead>{t("periodTable.range", { defaultValue: "账期" })}</TableHead>
|
|
<TableHead>{t("columns.status", { defaultValue: "状态" })}</TableHead>
|
|
<TableHead className="text-right">
|
|
{t("periodTable.shareLedger", { defaultValue: "占成流水" })}
|
|
</TableHead>
|
|
<TableHead className="text-right">{winLossLabel}</TableHead>
|
|
<TableHead className="text-right">
|
|
{t("agents:settlementReports.summary.billCount", { defaultValue: "账单数" })}
|
|
</TableHead>
|
|
<TableHead className="text-right">
|
|
{t("periodTable.pending", { defaultValue: "待确认" })}
|
|
</TableHead>
|
|
<TableHead className="text-right">
|
|
{t("periodTable.awaiting", { defaultValue: "待收付" })}
|
|
</TableHead>
|
|
<TableHead className="text-right">
|
|
{t("agents:settlementReports.summary.totalUnpaid", { defaultValue: "未结合计" })}
|
|
</TableHead>
|
|
<TableHead className="sticky right-0 z-10 w-36 bg-muted text-center shadow-[-1px_0_0_rgba(203,213,225,0.7)]">
|
|
{t("common:table.actions", { defaultValue: "操作" })}
|
|
</TableHead>
|
|
</TableRow>
|
|
</TableHeader>
|
|
<TableBody>
|
|
{loading ? (
|
|
<AdminTableLoadingRow colSpan={COL_SPAN} />
|
|
) : periods.length === 0 ? (
|
|
<AdminTableNoResourceRow colSpan={COL_SPAN} message={emptyMessage} />
|
|
) : (
|
|
periods.map((row) => {
|
|
const canCloseRow = canManage && row.status === "open";
|
|
const todoCount =
|
|
(row.summary?.pending_confirm ?? 0) + (row.summary?.awaiting_payment ?? 0);
|
|
const detailLabel =
|
|
todoCount > 0
|
|
? t("periodTable.processBills", { defaultValue: "处理账单" })
|
|
: t("periodTable.viewDetail", { defaultValue: "查看详情" });
|
|
|
|
return (
|
|
<TableRow key={row.id}>
|
|
<TableCell className="font-medium whitespace-nowrap">
|
|
{formatSettlementPeriodSpan(row.period_start, row.period_end)}
|
|
</TableCell>
|
|
<TableCell>
|
|
<AdminStatusBadge status={row.status}>
|
|
{settlementPeriodStatusLabel(row.status, t)}
|
|
</AdminStatusBadge>
|
|
</TableCell>
|
|
<TableCell className="text-right tabular-nums">
|
|
{row.pipeline?.share_ledger_count ?? "—"}
|
|
</TableCell>
|
|
<TableCell
|
|
className={cn(
|
|
"text-right tabular-nums whitespace-nowrap",
|
|
row.pipeline?.game_win_loss_total != null
|
|
? signedSettlementMoneyClass(row.pipeline.game_win_loss_total, true)
|
|
: undefined,
|
|
)}
|
|
>
|
|
{row.pipeline?.game_win_loss_total != null
|
|
? formatDashboardMoneyMinor(row.pipeline.game_win_loss_total, currencyCode)
|
|
: "—"}
|
|
</TableCell>
|
|
<TableCell className="text-right tabular-nums">
|
|
{billCount(row) > 0 ? billCount(row) : "—"}
|
|
</TableCell>
|
|
<TableCell className="text-right tabular-nums">
|
|
{row.summary?.pending_confirm ?? "—"}
|
|
</TableCell>
|
|
<TableCell className="text-right tabular-nums">
|
|
{row.summary?.awaiting_payment ?? "—"}
|
|
</TableCell>
|
|
<TableCell className="text-right tabular-nums whitespace-nowrap">
|
|
{(row.summary?.total_unpaid ?? 0) > 0
|
|
? formatDashboardMoneyMinor(row.summary?.total_unpaid ?? 0, currencyCode)
|
|
: "—"}
|
|
</TableCell>
|
|
<TableCell
|
|
className="sticky right-0 z-10 bg-card text-center shadow-[-1px_0_0_rgba(203,213,225,0.7)]"
|
|
onClick={(e) => e.stopPropagation()}
|
|
>
|
|
<AdminRowActionsMenu
|
|
busy={busy}
|
|
actions={[
|
|
{
|
|
key: "detail",
|
|
label: detailLabel,
|
|
icon: Eye,
|
|
onClick: () => onViewDetail(row.id),
|
|
},
|
|
{
|
|
key: "close",
|
|
label: t("periodTable.close", { defaultValue: "关账" }),
|
|
icon: Lock,
|
|
hidden: !canCloseRow,
|
|
onClick: () => onRequestClose(row),
|
|
},
|
|
]}
|
|
/>
|
|
</TableCell>
|
|
</TableRow>
|
|
);
|
|
})
|
|
)}
|
|
</TableBody>
|
|
</Table>
|
|
</div>
|
|
);
|
|
}
|