feat: 添加货币管理功能,更新国际化支持,移除报表相关代码

This commit is contained in:
2026-05-21 16:24:56 +08:00
parent 6ecbaf5fb4
commit 055c613a6d
87 changed files with 1615 additions and 1319 deletions

View File

@@ -26,6 +26,7 @@ const NAV_TRANSLATION_KEYS: Record<string, string> = {
admin_users: "admin_users",
admin_roles: "admin_roles",
players: "players",
currencies: "currencies",
wallet: "wallet",
draws: "draws",
config: "config",
@@ -33,11 +34,14 @@ const NAV_TRANSLATION_KEYS: Record<string, string> = {
settlement: "settlement",
reconcile: "reconcile",
tickets: "tickets",
reports: "reports",
audit: "audit",
settings: "settings",
};
const SETTINGS_ROUTE_LABELS: Record<string, string> = {
currencies: "currencies.title",
};
function titleCase(value: string): string {
return value
.split("-")
@@ -52,7 +56,7 @@ type BreadcrumbCrumb = {
};
export function AdminBreadcrumb() {
const { t } = useTranslation(["common", "dashboard", "reports", "audit", "config", "draws"]);
const { t } = useTranslation(["common", "dashboard", "audit", "config", "draws"]);
const pathname = usePathname();
const profile = useAdminProfile();
const navItems = profile?.navigation ?? [];
@@ -105,6 +109,11 @@ export function AdminBreadcrumb() {
let subLabel = "";
if (businessSegment === "config" && subSegment) {
subLabel = t(`nav.items.${subSegment}`, { ns: "config", defaultValue: titleCase(subSegment) });
} else if (businessSegment === "settings" && subSegment) {
subLabel = t(SETTINGS_ROUTE_LABELS[subSegment] ?? `settings.${subSegment}`, {
ns: "config",
defaultValue: titleCase(subSegment),
});
} else {
subLabel = subSegment
? t(`subnav.${subSegment}`, {

View File

@@ -117,8 +117,8 @@ export function AdminListPaginationFooter({
}) {
const { t } = useTranslation(["common"]);
return (
<div className="flex flex-col gap-4 border-t border-border pt-4 sm:flex-row sm:items-center sm:justify-between">
<p className="text-muted-foreground text-sm tabular-nums">
<div className="flex flex-col gap-4 border-t border-border/70 bg-muted/10 px-1 pt-4 sm:flex-row sm:items-center sm:justify-between">
<p className="text-sm tabular-nums text-muted-foreground">
{t("pagination.summary", {
total,
page,

View File

@@ -22,17 +22,21 @@ import { adminNavIconBySegment } from "@/modules/_config/admin-nav-icons";
import { ADMIN_BASE } from "@/modules/_config/admin-nav";
import { useAdminProfile } from "@/stores/admin-session";
function isActive(pathname: string, item: { href: string; activeMatchPrefix?: string }): boolean {
const { href, activeMatchPrefix } = item;
function isActive(pathname: string, item: { href: string; activeMatchPrefix?: string; segment?: string }): boolean {
const { href, activeMatchPrefix, segment } = item;
const prefix = activeMatchPrefix ?? href;
if (prefix === ADMIN_BASE || prefix === `${ADMIN_BASE}/`) {
return pathname === ADMIN_BASE || pathname === `${ADMIN_BASE}/`;
}
// Keep "settings" independent from its child routes like /admin/settings/currencies.
if (segment === "settings") {
return pathname === href;
}
return pathname === prefix || pathname.startsWith(`${prefix}/`);
}
export function AdminAppSidebar() {
const { t } = useTranslation(["common", "dashboard", "players", "draws", "config", "wallet", "risk", "settlement", "jackpot", "reconcile", "tickets", "reports", "audit"]);
const { t } = useTranslation(["common", "dashboard", "players", "draws", "config", "wallet", "risk", "settlement", "jackpot", "reconcile", "tickets", "audit"]);
const pathname = usePathname();
const profile = useAdminProfile();
const visibleNav = useMemo(

View File

@@ -9,5 +9,14 @@ type ModuleScaffoldProps = {
/** 内容区容器;模块标题由侧栏导航体现,此处不再重复大标题与说明。 */
export function ModuleScaffold({ children, className }: ModuleScaffoldProps) {
return <div className={cn("mx-auto w-full max-w-none min-w-0", className)}>{children}</div>;
return (
<div
className={cn(
"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",
className,
)}
>
{children}
</div>
);
}