feat: 全站 PageShell 设计系统与专业 UI 统一
- 新增 PageShell/PageTabs/ContentPanel/PageLoading/PageEmpty 页面骨架 - index.css 设计令牌文档化,布局令牌与纯色主按钮(去除渐变粉彩) - 全站路由页接入 PageShell,云账单三 Tab 为标杆 - 主题体系:跟随系统 + 主流/开发者分组,新增 Dracula/Tokyo Night,One Dark 暖灰差异化 - 登录页/侧栏/顶栏去渐变光球,企业克制风 - 修复 AIAlertAnalyzer JSX 与构建依赖导入问题
This commit is contained in:
1 parent
1acb0c49af
commit
e363ded445
213 files changed
+7148
-6818
No files matched your search
@@ -89,68 +89,69 @@ export function SystemSettingsTab(props: SystemSettingsTabProps) {
|
||||
handleLdapTest,
|
||||
} = props;
|
||||
|
||||
// 作为 SystemManager 子 Tab 渲染,外层已有 PageShell,此处仅输出配置内容 // Logan.Li
|
||||
return (
|
||||
<>
|
||||
<div className="max-w-3xl mx-auto w-full space-y-4">
|
||||
<div className="grid grid-cols-1 lg:grid-cols-2 gap-4">
|
||||
<Card className="bg-slate-900 border-slate-800">
|
||||
<Card className="dg-card">
|
||||
<CardHeader>
|
||||
<CardTitle className="text-slate-100 flex items-center gap-2">
|
||||
<Lock className="h-5 w-5 text-blue-400" />
|
||||
<CardTitle className="text-[var(--dg-text-primary)] flex items-center gap-2">
|
||||
<Lock className="h-5 w-5 dg-text-blue" />
|
||||
安全设置
|
||||
</CardTitle>
|
||||
<CardDescription className="text-slate-500">密码策略与登录安全</CardDescription>
|
||||
<CardDescription className="dg-text-muted">密码策略与登录安全</CardDescription>
|
||||
</CardHeader>
|
||||
<CardContent className="space-y-4">
|
||||
<div className="flex items-center justify-between">
|
||||
<div>
|
||||
<p className="text-sm font-medium text-slate-200">强制密码复杂度</p>
|
||||
<p className="text-xs text-slate-500">要求密码包含大小写字母、数字和特殊字符</p>
|
||||
<p className="text-sm font-medium text-[var(--dg-text-primary)]">强制密码复杂度</p>
|
||||
<p className="text-xs dg-text-muted">要求密码包含大小写字母、数字和特殊字符</p>
|
||||
</div>
|
||||
<Switch defaultChecked className="data-[state=checked]:bg-blue-600" />
|
||||
</div>
|
||||
<div className="flex items-center justify-between">
|
||||
<div>
|
||||
<p className="text-sm font-medium text-slate-200">登录失败锁定</p>
|
||||
<p className="text-xs text-slate-500">连续5次登录失败锁定账户30分钟</p>
|
||||
<p className="text-sm font-medium text-[var(--dg-text-primary)]">登录失败锁定</p>
|
||||
<p className="text-xs dg-text-muted">连续5次登录失败锁定账户30分钟</p>
|
||||
</div>
|
||||
<Switch defaultChecked className="data-[state=checked]:bg-blue-600" />
|
||||
</div>
|
||||
<div className="flex items-center justify-between">
|
||||
<div>
|
||||
<p className="text-sm font-medium text-slate-200">双因素认证</p>
|
||||
<p className="text-xs text-slate-500">启用后需要手机验证码登录</p>
|
||||
<p className="text-sm font-medium text-[var(--dg-text-primary)]">双因素认证</p>
|
||||
<p className="text-xs dg-text-muted">启用后需要手机验证码登录</p>
|
||||
</div>
|
||||
<Switch className="data-[state=checked]:bg-blue-600" />
|
||||
</div>
|
||||
</CardContent>
|
||||
</Card>
|
||||
|
||||
<Card className="bg-slate-900 border-slate-800">
|
||||
<Card className="dg-card">
|
||||
<CardHeader>
|
||||
<CardTitle className="text-slate-100 flex items-center gap-2">
|
||||
<History className="h-5 w-5 text-emerald-400" />
|
||||
<CardTitle className="text-[var(--dg-text-primary)] flex items-center gap-2">
|
||||
<History className="h-5 w-5 dg-text-green" />
|
||||
审计设置
|
||||
</CardTitle>
|
||||
<CardDescription className="text-slate-500">操作日志与审计策略</CardDescription>
|
||||
<CardDescription className="dg-text-muted">操作日志与审计策略</CardDescription>
|
||||
</CardHeader>
|
||||
<CardContent className="space-y-4">
|
||||
<div className="flex items-center justify-between">
|
||||
<div>
|
||||
<p className="text-sm font-medium text-slate-200">记录所有操作</p>
|
||||
<p className="text-xs text-slate-500">记录用户的所有操作行为</p>
|
||||
<p className="text-sm font-medium text-[var(--dg-text-primary)]">记录所有操作</p>
|
||||
<p className="text-xs dg-text-muted">记录用户的所有操作行为</p>
|
||||
</div>
|
||||
<Switch defaultChecked className="data-[state=checked]:bg-blue-600" />
|
||||
</div>
|
||||
<div className="flex items-center justify-between">
|
||||
<div>
|
||||
<p className="text-sm font-medium text-slate-200">日志保留时间</p>
|
||||
<p className="text-xs text-slate-500">操作日志保留180天</p>
|
||||
<p className="text-sm font-medium text-[var(--dg-text-primary)]">日志保留时间</p>
|
||||
<p className="text-xs dg-text-muted">操作日志保留180天</p>
|
||||
</div>
|
||||
<Select defaultValue="180">
|
||||
<SelectTrigger className="w-32 h-8 bg-slate-800 border-slate-700 text-slate-200">
|
||||
<SelectTrigger className="w-32 h-8 dg-input">
|
||||
<SelectValue />
|
||||
</SelectTrigger>
|
||||
<SelectContent className="bg-slate-800 border-slate-700">
|
||||
<SelectContent className="dg-input">
|
||||
<SelectItem value="30">30天</SelectItem>
|
||||
<SelectItem value="90">90天</SelectItem>
|
||||
<SelectItem value="180">180天</SelectItem>
|
||||
@@ -161,25 +162,25 @@ export function SystemSettingsTab(props: SystemSettingsTabProps) {
|
||||
</CardContent>
|
||||
</Card>
|
||||
|
||||
<Card className="bg-slate-900 border-slate-800">
|
||||
<Card className="dg-card">
|
||||
<CardHeader>
|
||||
<CardTitle className="text-slate-100 flex items-center gap-2">
|
||||
<Key className="h-5 w-5 text-amber-400" />
|
||||
<CardTitle className="text-[var(--dg-text-primary)] flex items-center gap-2">
|
||||
<Key className="h-5 w-5 dg-text-yellow" />
|
||||
会话设置
|
||||
</CardTitle>
|
||||
<CardDescription className="text-slate-500">会话超时与Token配置</CardDescription>
|
||||
<CardDescription className="dg-text-muted">会话超时与Token配置</CardDescription>
|
||||
</CardHeader>
|
||||
<CardContent className="space-y-4">
|
||||
<div className="flex items-center justify-between">
|
||||
<div>
|
||||
<p className="text-sm font-medium text-slate-200">会话超时时间</p>
|
||||
<p className="text-xs text-slate-500">用户无操作30分钟后自动登出</p>
|
||||
<p className="text-sm font-medium text-[var(--dg-text-primary)]">会话超时时间</p>
|
||||
<p className="text-xs dg-text-muted">用户无操作30分钟后自动登出</p>
|
||||
</div>
|
||||
<Select defaultValue="30">
|
||||
<SelectTrigger className="w-32 h-8 bg-slate-800 border-slate-700 text-slate-200">
|
||||
<SelectTrigger className="w-32 h-8 dg-input">
|
||||
<SelectValue />
|
||||
</SelectTrigger>
|
||||
<SelectContent className="bg-slate-800 border-slate-700">
|
||||
<SelectContent className="dg-input">
|
||||
<SelectItem value="15">15分钟</SelectItem>
|
||||
<SelectItem value="30">30分钟</SelectItem>
|
||||
<SelectItem value="60">1小时</SelectItem>
|
||||
@@ -189,103 +190,103 @@ export function SystemSettingsTab(props: SystemSettingsTabProps) {
|
||||
</div>
|
||||
<div className="flex items-center justify-between">
|
||||
<div>
|
||||
<p className="text-sm font-medium text-slate-200">单点登录</p>
|
||||
<p className="text-xs text-slate-500">同一账号只能在一个设备登录</p>
|
||||
<p className="text-sm font-medium text-[var(--dg-text-primary)]">单点登录</p>
|
||||
<p className="text-xs dg-text-muted">同一账号只能在一个设备登录</p>
|
||||
</div>
|
||||
<Switch className="data-[state=checked]:bg-blue-600" />
|
||||
</div>
|
||||
</CardContent>
|
||||
</Card>
|
||||
|
||||
<Card className="bg-slate-900 border-slate-800">
|
||||
<Card className="dg-card">
|
||||
<CardHeader>
|
||||
<CardTitle className="text-slate-100 flex items-center gap-2">
|
||||
<Settings className="h-5 w-5 text-purple-400" />
|
||||
<CardTitle className="text-[var(--dg-text-primary)] flex items-center gap-2">
|
||||
<Settings className="h-5 w-5 dg-text-purple" />
|
||||
系统信息
|
||||
</CardTitle>
|
||||
<CardDescription className="text-slate-500">版本与系统状态</CardDescription>
|
||||
<CardDescription className="dg-text-muted">版本与系统状态</CardDescription>
|
||||
</CardHeader>
|
||||
<CardContent className="space-y-4">
|
||||
<div className="flex items-center justify-between">
|
||||
<span className="text-sm text-slate-400">系统版本</span>
|
||||
<span className="text-sm text-slate-200">v2.5.1</span>
|
||||
<span className="text-sm dg-text-secondary">系统版本</span>
|
||||
<span className="text-sm text-[var(--dg-text-primary)]">v2.5.1</span>
|
||||
</div>
|
||||
<div className="flex items-center justify-between">
|
||||
<span className="text-sm text-slate-400">运行时间</span>
|
||||
<span className="text-sm text-slate-200">30天 12小时</span>
|
||||
<span className="text-sm dg-text-secondary">运行时间</span>
|
||||
<span className="text-sm text-[var(--dg-text-primary)]">30天 12小时</span>
|
||||
</div>
|
||||
</CardContent>
|
||||
</Card>
|
||||
</div>
|
||||
|
||||
{/* LDAP 配置 */}
|
||||
<Card className="bg-slate-900 border-slate-800 mt-4">
|
||||
<Card className="dg-card mt-4">
|
||||
<CardHeader>
|
||||
<div className="flex items-center justify-between">
|
||||
<div>
|
||||
<CardTitle className="text-slate-100 flex items-center gap-2">
|
||||
<Network className="h-5 w-5 text-cyan-400" />
|
||||
<CardTitle className="text-[var(--dg-text-primary)] flex items-center gap-2">
|
||||
<Network className="h-5 w-5 dg-text-cyan" />
|
||||
LDAP / Active Directory
|
||||
</CardTitle>
|
||||
<CardDescription className="text-slate-500 mt-1">配置 LDAP 服务器,实现统一身份认证</CardDescription>
|
||||
<CardDescription className="dg-text-muted mt-1">配置 LDAP 服务器,实现统一身份认证</CardDescription>
|
||||
</div>
|
||||
</div>
|
||||
</CardHeader>
|
||||
<CardContent>
|
||||
<div className="grid grid-cols-2 gap-4">
|
||||
<div className="space-y-1.5">
|
||||
<label className="text-xs text-slate-500">LDAP 服务器地址</label>
|
||||
<label className="text-xs dg-text-muted">LDAP 服务器地址</label>
|
||||
<Input
|
||||
value={ldapForm.ldap_host}
|
||||
onChange={(e) => setLdapForm({ ...ldapForm, ldap_host: e.target.value })}
|
||||
className="bg-slate-800/50 border-slate-700 text-slate-200 placeholder:text-slate-600"
|
||||
className="dg-input"
|
||||
placeholder="ldap.example.com"
|
||||
/>
|
||||
</div>
|
||||
<div className="space-y-1.5">
|
||||
<label className="text-xs text-slate-500">端口</label>
|
||||
<label className="text-xs dg-text-muted">端口</label>
|
||||
<Input
|
||||
type="number"
|
||||
value={ldapForm.ldap_port}
|
||||
onChange={(e) => setLdapForm({ ...ldapForm, ldap_port: Number(e.target.value) })}
|
||||
className="bg-slate-800/50 border-slate-700 text-slate-200"
|
||||
className="dg-input"
|
||||
placeholder="389"
|
||||
/>
|
||||
</div>
|
||||
<div className="space-y-1.5 col-span-2">
|
||||
<label className="text-xs text-slate-500">Base DN(用户搜索基础)</label>
|
||||
<label className="text-xs dg-text-muted">Base DN(用户搜索基础)</label>
|
||||
<Input
|
||||
value={ldapForm.base_dn}
|
||||
onChange={(e) => setLdapForm({ ...ldapForm, base_dn: e.target.value })}
|
||||
className="bg-slate-800/50 border-slate-700 text-slate-200 placeholder:text-slate-600"
|
||||
className="dg-input"
|
||||
placeholder="ou=users,dc=example,dc=com"
|
||||
/>
|
||||
</div>
|
||||
<div className="space-y-1.5">
|
||||
<label className="text-xs text-slate-500">管理员 Bind DN</label>
|
||||
<label className="text-xs dg-text-muted">管理员 Bind DN</label>
|
||||
<Input
|
||||
value={ldapForm.admin_dn}
|
||||
onChange={(e) => setLdapForm({ ...ldapForm, admin_dn: e.target.value })}
|
||||
className="bg-slate-800/50 border-slate-700 text-slate-200 placeholder:text-slate-600"
|
||||
className="dg-input"
|
||||
placeholder="cn=admin,dc=example,dc=com"
|
||||
/>
|
||||
</div>
|
||||
<div className="space-y-1.5">
|
||||
<label className="text-xs text-slate-500">管理员密码 {ldapConfig && '(留空不修改)'}</label>
|
||||
<label className="text-xs dg-text-muted">管理员密码 {ldapConfig && '(留空不修改)'}</label>
|
||||
<Input
|
||||
type="password"
|
||||
value={ldapForm.admin_password}
|
||||
onChange={(e) => setLdapForm({ ...ldapForm, admin_password: e.target.value })}
|
||||
className="bg-slate-800/50 border-slate-700 text-slate-200 placeholder:text-slate-600"
|
||||
className="dg-input"
|
||||
placeholder="******"
|
||||
/>
|
||||
</div>
|
||||
<div className="space-y-1.5 col-span-2">
|
||||
<label className="text-xs text-slate-500">搜索过滤器(可选,用 %s 代表用户名)</label>
|
||||
<label className="text-xs dg-text-muted">搜索过滤器(可选,用 %s 代表用户名)</label>
|
||||
<Input
|
||||
value={ldapForm.search_filter}
|
||||
onChange={(e) => setLdapForm({ ...ldapForm, search_filter: e.target.value })}
|
||||
className="bg-slate-800/50 border-slate-700 text-slate-200 placeholder:text-slate-600"
|
||||
className="dg-input"
|
||||
placeholder="(uid=%s)"
|
||||
/>
|
||||
</div>
|
||||
@@ -295,14 +296,14 @@ export function SystemSettingsTab(props: SystemSettingsTabProps) {
|
||||
onCheckedChange={(v) => setLdapForm({ ...ldapForm, use_ldaps: v })}
|
||||
className="data-[state=checked]:bg-blue-600"
|
||||
/>
|
||||
<span className="text-sm text-slate-300">启用 LDAPS(SSL 加密)</span>
|
||||
<span className="text-sm text-[var(--dg-text-secondary)]">启用 LDAPS(SSL 加密)</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* 测试/保存按钮 */}
|
||||
<div className="flex items-center gap-3 mt-4 pt-4 border-t border-slate-800">
|
||||
<div className="flex items-center gap-3 mt-4 pt-4 border-t border-[var(--dg-border)]">
|
||||
{ldapTestResult && (
|
||||
<span className={`text-xs ${ldapTestResult.includes('成功') ? 'text-emerald-400' : 'text-red-400'}`}>
|
||||
<span className={`text-xs ${ldapTestResult.includes('成功') ? 'dg-text-green' : 'dg-text-red'}`}>
|
||||
{ldapTestResult}
|
||||
</span>
|
||||
)}
|
||||
@@ -310,7 +311,7 @@ export function SystemSettingsTab(props: SystemSettingsTabProps) {
|
||||
<Button
|
||||
variant="outline"
|
||||
size="sm"
|
||||
className="border-slate-700 text-slate-300"
|
||||
className="dg-btn-secondary"
|
||||
onClick={handleLdapTest}
|
||||
disabled={ldapTesting}
|
||||
>
|
||||
@@ -319,7 +320,7 @@ export function SystemSettingsTab(props: SystemSettingsTabProps) {
|
||||
</Button>
|
||||
<Button
|
||||
size="sm"
|
||||
className="bg-blue-600 hover:bg-blue-700 text-white"
|
||||
className="dg-btn-primary"
|
||||
onClick={handleLdapSave}
|
||||
disabled={ldapSaving}
|
||||
>
|
||||
@@ -336,6 +337,6 @@ export function SystemSettingsTab(props: SystemSettingsTabProps) {
|
||||
<LdapManagementSection {...props} />
|
||||
</div>
|
||||
)}
|
||||
</>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
Reference in new issue
Block a user