feat(admin): 仪表盘重构、代理线路修复与后台体验优化
Some checks failed
lotteryadmin CI / build (push) Has been cancelled
Some checks failed
lotteryadmin CI / build (push) Has been cancelled
- 各角色仪表盘:KPI 可点击跳转、快捷入口、去重冗余区块,代理/站点降级 analytics - 代理线路:创建玩家权限、侧栏搜索、深链 URL、档案保存与删除预检等修复 - 统一密码最短 6 位;代理模块表格/侧栏背景色一致(admin-table-inset) - 报表、钱包、对账、开奖、结算、配置等模块结构与 i18n 同步更新
This commit is contained in:
@@ -1,24 +1,5 @@
|
||||
import type { Metadata } from "next";
|
||||
import { redirect } from "next/navigation";
|
||||
|
||||
import { ModuleScaffold } from "@/components/admin/module-scaffold";
|
||||
import { AdminPermissionGate } from "@/components/admin/admin-permission-gate";
|
||||
import { AgentsDirectoryConsole } from "@/modules/agents/agents-directory-console";
|
||||
import {
|
||||
PRD_AGENT_LINE_PROVISION_ACCESS_ANY,
|
||||
PRD_AGENTS_ACCESS_ANY,
|
||||
} from "@/lib/admin-prd";
|
||||
import { buildPageMetadata } from "@/lib/page-metadata";
|
||||
|
||||
export const metadata: Metadata = buildPageMetadata("agents", "listTitle");
|
||||
|
||||
export default function AgentsListPage() {
|
||||
return (
|
||||
<ModuleScaffold embedded>
|
||||
<AdminPermissionGate
|
||||
requiredAny={[...PRD_AGENTS_ACCESS_ANY, ...PRD_AGENT_LINE_PROVISION_ACCESS_ANY]}
|
||||
>
|
||||
<AgentsDirectoryConsole />
|
||||
</AdminPermissionGate>
|
||||
</ModuleScaffold>
|
||||
);
|
||||
}
|
||||
export default function AgentsListRedirectPage() {
|
||||
redirect("/admin/agents?view=list");
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
import { ModuleScaffold } from "@/components/admin/module-scaffold";
|
||||
import { AdminPermissionGate } from "@/components/admin/admin-permission-gate";
|
||||
import { AgentsConsole } from "@/modules/agents/agents-console";
|
||||
import { AgentsManagementScreen } from "@/modules/agents/agents-management-screen";
|
||||
import {
|
||||
PRD_AGENT_LINE_PROVISION_ACCESS_ANY,
|
||||
PRD_AGENTS_ACCESS_ANY,
|
||||
@@ -16,8 +16,8 @@ export default function AgentsPage() {
|
||||
<AdminPermissionGate
|
||||
requiredAny={[...PRD_AGENTS_ACCESS_ANY, ...PRD_AGENT_LINE_PROVISION_ACCESS_ANY]}
|
||||
>
|
||||
<AgentsConsole />
|
||||
<AgentsManagementScreen />
|
||||
</AdminPermissionGate>
|
||||
</ModuleScaffold>
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -15,4 +15,4 @@ export default function AdminAuditLogsPage() {
|
||||
</AdminPermissionGate>
|
||||
</ModuleScaffold>
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
import { ModuleScaffold } from "@/components/admin/module-scaffold";
|
||||
import { DrawSubnav } from "@/modules/draws/draw-subnav";
|
||||
import { DrawDetailShell } from "@/modules/draws/draw-detail-shell";
|
||||
|
||||
export default async function AdminDrawSegmentLayout(props: {
|
||||
children: React.ReactNode;
|
||||
@@ -9,8 +9,7 @@ export default async function AdminDrawSegmentLayout(props: {
|
||||
|
||||
return (
|
||||
<ModuleScaffold>
|
||||
<DrawSubnav drawId={drawId} />
|
||||
{props.children}
|
||||
<DrawDetailShell drawId={drawId}>{props.children}</DrawDetailShell>
|
||||
</ModuleScaffold>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1,17 +1,33 @@
|
||||
import { notFound, redirect } from "next/navigation";
|
||||
import { buildPageMetadata } from "@/lib/page-metadata";
|
||||
import { notFound } from "next/navigation";
|
||||
import { Suspense } from "react";
|
||||
import type { Metadata } from "next";
|
||||
|
||||
import { AdminPermissionGate } from "@/components/admin/admin-permission-gate";
|
||||
import { AdminLoadingState } from "@/components/admin/admin-loading-state";
|
||||
import { PRD_REPORTS_PAGE_ACCESS_ANY } from "@/lib/admin-prd";
|
||||
import { buildPageMetadata } from "@/lib/page-metadata";
|
||||
import { ReportsConsole } from "@/modules/reports/reports-console";
|
||||
import type { ReportCategory } from "@/modules/reports/reports-definitions";
|
||||
|
||||
export const metadata: Metadata = buildPageMetadata("reports", "title");
|
||||
|
||||
const VALID_CATEGORIES = new Set<ReportCategory>(["profit", "wallet", "risk", "audit"]);
|
||||
|
||||
export default async function AdminReportsCategoryPage({
|
||||
params,
|
||||
}: {
|
||||
params: Promise<{ category: string }>;
|
||||
}) {
|
||||
const { category } = await params;
|
||||
if (!["profit", "wallet", "risk", "audit"].includes(category)) {
|
||||
if (!VALID_CATEGORIES.has(category as ReportCategory)) {
|
||||
notFound();
|
||||
}
|
||||
redirect("/admin/reports");
|
||||
}
|
||||
|
||||
return (
|
||||
<AdminPermissionGate requiredAny={PRD_REPORTS_PAGE_ACCESS_ANY}>
|
||||
<Suspense fallback={<AdminLoadingState minHeight="12rem" />}>
|
||||
<ReportsConsole initialCategory={category as ReportCategory} />
|
||||
</Suspense>
|
||||
</AdminPermissionGate>
|
||||
);
|
||||
}
|
||||
@@ -1,15 +1,5 @@
|
||||
import { AdminPermissionGate } from "@/components/admin/admin-permission-gate";
|
||||
import { AdminLoadingState } from "@/components/admin/admin-loading-state";
|
||||
import { PRD_REPORTS_VIEW_ACCESS_ANY } from "@/lib/admin-prd";
|
||||
import { ReportsConsole } from "@/modules/reports/reports-console";
|
||||
import { Suspense } from "react";
|
||||
import { redirect } from "next/navigation";
|
||||
|
||||
export default function AdminReportsPage() {
|
||||
return (
|
||||
<AdminPermissionGate requiredAny={PRD_REPORTS_VIEW_ACCESS_ANY}>
|
||||
<Suspense fallback={<AdminLoadingState minHeight="12rem" />}>
|
||||
<ReportsConsole />
|
||||
</Suspense>
|
||||
</AdminPermissionGate>
|
||||
);
|
||||
}
|
||||
redirect("/admin/reports/profit");
|
||||
}
|
||||
@@ -1,14 +1,12 @@
|
||||
import type { ReactNode } from "react";
|
||||
|
||||
import { WalletScopeHint } from "@/modules/wallet/wallet-scope-hint";
|
||||
import { WalletSubnav } from "@/modules/wallet/wallet-subnav";
|
||||
|
||||
export default function AdminWalletLayout({ children }: { children: ReactNode }) {
|
||||
return (
|
||||
<div className="mx-auto flex w-full max-w-[1680px] min-w-0 flex-col gap-6 px-4 py-5 sm:px-6 lg:px-8 lg:py-6">
|
||||
<div className="sticky top-14 z-20 space-y-2 bg-background/95 pb-2 backdrop-blur supports-[backdrop-filter]:bg-background/80">
|
||||
<div className="sticky top-14 z-20 bg-background/95 pb-2 backdrop-blur supports-[backdrop-filter]:bg-background/80">
|
||||
<WalletSubnav />
|
||||
<WalletScopeHint />
|
||||
</div>
|
||||
{children}
|
||||
</div>
|
||||
|
||||
@@ -168,6 +168,24 @@
|
||||
@apply overflow-x-auto rounded-2xl border border-border/80 bg-card shadow-sm;
|
||||
}
|
||||
|
||||
/* Flat table inside an existing card — same white surface, no nested panel or blue header tint */
|
||||
.admin-table-inset {
|
||||
@apply overflow-x-auto rounded-xl border border-border/80;
|
||||
}
|
||||
|
||||
.admin-table-inset [data-slot="table-header"] {
|
||||
@apply bg-card;
|
||||
}
|
||||
|
||||
.admin-table-inset [data-slot="table-head"][class*="sticky"],
|
||||
.admin-table-inset [data-slot="table-cell"][class*="sticky"] {
|
||||
background-color: var(--card);
|
||||
}
|
||||
|
||||
.admin-table-inset [data-slot="table-row"]:hover > [data-slot="table-cell"][class*="sticky"] {
|
||||
@apply bg-muted/20;
|
||||
}
|
||||
|
||||
/* Sticky columns need an opaque background so scrolled cells/headers do not show through */
|
||||
[data-slot="table-head"][class*="sticky"] {
|
||||
@apply bg-muted;
|
||||
|
||||
Reference in New Issue
Block a user