feat(frontend): 控制台 next-intl 中英双语

接入无 URL 前缀的 zh-CN/en,顶栏与外观设置可切换语言;选择写入 cookie 后刷新生效。
This commit is contained in:
ryan
2026-08-16 16:49:16 +08:00
parent 64fbaa7ef1
commit 5a8722ff07
219 changed files with 21437 additions and 5212 deletions
@@ -35,166 +35,167 @@ import { Switch } from '@/components/ui/switch';
import services from '@/lib/services';
import type { SystemConfig } from '@/lib/services/admin';
import { toast } from 'sonner';
import { useTranslations } from 'next-intl';
interface MenuItem {
path: string;
label: string;
description: string;
labelKey: string;
descKey: string;
icon: ComponentType<{ className?: string }>;
readOnly?: boolean;
}
interface MenuGroup {
name: string;
nameKey: string;
items: MenuItem[];
}
const MENU_GROUPS: MenuGroup[] = [
{
name: '业务菜单',
nameKey: 'groupBusiness',
items: [
{
path: '/',
label: '数据看板',
description: '查看边缘节点请求、访客与流量等多维度图表看板',
labelKey: 'dashboard',
descKey: 'descDashboard',
icon: LayoutDashboard,
readOnly: true,
},
{
path: '/nodes',
label: '节点管理',
description: '注册与管理反向代理边缘节点服务状态',
labelKey: 'nodes',
descKey: 'descNodes',
icon: Server,
},
{
path: '/proxy-routes',
label: '规则管理',
description: '配置和发布反代路由规则、负载均衡与源站绑定',
labelKey: 'proxyRoutes',
descKey: 'descProxyRoutes',
icon: Route,
},
{
path: '/websites',
label: '域名列表',
description: '配置站点根域名并查看关联网站详情',
labelKey: 'websites',
descKey: 'descWebsites',
icon: Globe,
},
{
path: '/certificates',
label: 'TLS证书',
description: '管理和下发网站 SSL/TLS 证书',
labelKey: 'certificates',
descKey: 'descCertificates',
icon: ShieldCheck,
},
{
path: '/dns-accounts',
label: 'DNS账号',
description: '配置 Cloudflare/Alidns 等 DNS 服务商 API 凭证',
labelKey: 'dnsAccounts',
descKey: 'descDnsAccounts',
icon: Settings,
},
{
path: '/origins',
label: '源站地址',
description: '集中维护和管理后端业务源站服务器组',
labelKey: 'origins',
descKey: 'descOrigins',
icon: Home,
},
{
path: '/waf',
label: 'WAF 管理',
description: '配置 Web 应用防火墙自定义规则与频率限制',
labelKey: 'waf',
descKey: 'descWaf',
icon: ShieldCheck,
},
{
path: '/ip-groups',
label: 'IP 组',
description: '管理黑白名单 IP 集合,用于 WAF 规则过滤',
labelKey: 'ipGroups',
descKey: 'descIpGroups',
icon: Layers,
},
{
path: '/pages',
label: 'Pages 静态站',
description: '托管和发布静态网页项目,支持自动关联域名',
labelKey: 'pages',
descKey: 'descPages',
icon: FileText,
},
{
path: '/config-versions',
label: '版本发布',
description: '查看规则快照版本并进行配置热更新分发与回滚',
labelKey: 'configVersions',
descKey: 'descConfigVersions',
icon: GitBranch,
},
{
path: '/access-logs',
label: '访问日志',
description: '多维度实时浏览边缘节点请求访问明细',
labelKey: 'accessLogs',
descKey: 'descAccessLogs',
icon: ScrollText,
},
{
path: '/performance',
label: '性能调优',
description: '配置缓存、图片压缩等页面性能加速策略',
labelKey: 'performance',
descKey: 'descPerformance',
icon: Gauge,
},
],
},
{
name: '管理菜单',
nameKey: 'groupAdmin',
items: [
{
path: '/admin/users',
label: '用户管理',
description: '查看和管理系统用户列表及其状态',
labelKey: 'users',
descKey: 'descUsers',
icon: UserRound,
},
{
path: '/admin/tasks',
label: '任务管理',
description: '查看和调度系统异步及定时任务',
labelKey: 'tasks',
descKey: 'descTasks',
icon: Layers,
},
{
path: '/admin/files',
label: '存储管理',
description: '管理系统文件存储和清理无用文件',
labelKey: 'storage',
descKey: 'descStorage',
icon: FolderOpen,
},
{
path: '/admin/database',
label: '数据管理',
description: '监控物理数据库状态、分页浏览表数据及交互式 SQL 查询',
labelKey: 'database',
descKey: 'descDatabase',
icon: Database,
},
{
path: '/admin/push',
label: '通知推送',
description: '配置和发送系统通知及推送消息',
labelKey: 'push',
descKey: 'descPush',
icon: Bell,
},
{
path: '/admin/logs',
label: '系统日志',
description: '查看异步任务执行日志和系统运行情况',
labelKey: 'logs',
descKey: 'descLogs',
icon: Terminal,
},
{
path: '/admin/system',
label: '系统配置',
description: '管理和维护系统基础键值对配置',
labelKey: 'system',
descKey: 'descSystem',
icon: ShieldCheck,
},
{
path: '/admin/settings',
label: '系统设置',
description: '配置安全验证、邮箱服务及目录显示',
labelKey: 'adminSettings',
descKey: 'descAdminSettings',
icon: Settings,
readOnly: true,
},
],
},
{
name: '文档菜单',
nameKey: 'groupDocs',
items: [
{
path: 'https://open-flare.pages.dev/',
label: '使用文档',
description: '面向开发与运营的部署使用指南',
labelKey: 'usageDocs',
descKey: 'descUsageDocs',
icon: FileText,
},
],
@@ -207,6 +208,8 @@ interface OtherTabProps {
export function OtherTab({ configs }: OtherTabProps) {
const queryClient = useQueryClient();
const t = useTranslations('settings.other');
const tNav = useTranslations('layout.nav');
const menuDisplayConfig = useMemo(() => {
const raw = configs['menu_display_config']?.value;
@@ -243,10 +246,10 @@ export function OtherTab({ configs }: OtherTabProps) {
queryKey: ['admin', 'system-configs'],
});
await queryClient.invalidateQueries({ queryKey: ['public-config'] });
toast.success('目录显示配置已更新');
toast.success(t('menuDisplayUpdated'));
},
onError: (error: Error) => {
toast.error(error.message || '更新配置失败');
toast.error(error.message || t('updateConfigFailed'));
},
});
@@ -263,20 +266,20 @@ export function OtherTab({ configs }: OtherTabProps) {
</div>
<div>
<CardTitle className='text-base font-semibold'>
目录显示管理
{t('menuDisplayManagement')}
</CardTitle>
<CardDescription className='text-xs'>
配置系统左侧菜单的显示与隐藏状态,适用于所有登录用户。
{t('menuDisplayManagementDesc')}
</CardDescription>
</div>
</div>
</CardHeader>
<CardContent className='pt-6 space-y-6'>
{MENU_GROUPS.map((group) => (
<div key={group.name} className='space-y-3'>
<div key={group.nameKey} className='space-y-3'>
<div className='flex items-center gap-2'>
<span className='text-xs font-semibold text-muted-foreground tracking-wider uppercase'>
{group.name}
{t(group.nameKey)}
</span>
<div className='h-px bg-border/40 flex-1' />
</div>
@@ -297,16 +300,16 @@ export function OtherTab({ configs }: OtherTabProps) {
<Icon className='size-4 text-primary shrink-0' />
)}
<span className='font-medium text-sm text-foreground truncate'>
{item.label}
{tNav(item.labelKey)}
</span>
{isReadOnly && (
<span className='text-[9px] px-1.5 py-0.5 rounded bg-muted text-muted-foreground border shrink-0'>
不可隐藏
{t('notHideable')}
</span>
)}
</div>
<p className='text-xs text-muted-foreground leading-normal line-clamp-2'>
{item.description}
{t(item.descKey)}
</p>
</div>
<div className='flex items-center'>
@@ -330,8 +333,10 @@ export function OtherTab({ configs }: OtherTabProps) {
<div className='p-3.5 rounded-lg border border-dashed border-primary/20 bg-primary/5 flex items-start gap-2.5'>
<Info className='size-4 text-primary shrink-0 mt-0.5' />
<div className='text-xs text-muted-foreground leading-relaxed'>
<span className='font-semibold text-foreground'>安全提示:</span>
为了防止管理员在关闭“系统设置”后导致无法重新访问此配置页,系统限制了“系统设置”的关闭权限。其它所有菜单均可自由开关,隐藏后对应的分组标题在为空时也会自动隐藏。
<span className='font-semibold text-foreground'>
{t('securityTipTitle')}
</span>
{t('securityTipDesc')}
</div>
</div>
</CardContent>