refactor: 系统设置拆分顶部 Tab 分页

- 4 个 Tab:通用(外观主题+通知+语言区域)/ AI 助手 / 消息通知 /
  用户目录(LDAP),复用编辑器 TopBar 下划线样式
- AI/消息通知/用户目录 Tab 标题带启用状态小圆点(绿=已启用)
- 原「保存设置/恢复默认」按钮移入通用 Tab(只作用于外观与通知)
- 内容区只渲染当前 Tab 卡片,纯布局重构,表单逻辑不变
This commit is contained in:
Logan.Li committed 2026-10-27 14:33:21 +08:00
1 parent 97193eb090
commit 8bd323cc73
1 file changed
+65 -13
+65 -13
View File
@@ -261,6 +261,21 @@ export default function SystemSettings() {
toast.info('已恢复默认设置', { description: '仅本地重置,点击「保存设置」后生效' });
};
// 顶部 Tab 分页:通用 / AI 助手 / 消息通知 / 用户目录
type SettingsTab = 'general' | 'ai' | 'notify' | 'directory';
const [activeTab, setActiveTab] = useState<SettingsTab>('general');
const aiOn = !!settings?.llmEnabled && !!settings?.llmApiKeySet;
const larkOn = !!settings?.larkEnabled && !!settings?.larkWebhook;
const ldapOn = !!settings?.ldapEnabled && !!settings?.ldapHost && !!settings?.ldapBindDN && !!settings?.ldapBaseDN;
const tabs: { id: SettingsTab; label: string; dot?: boolean | null }[] = [
{ id: 'general', label: '通用' },
{ id: 'ai', label: 'AI 助手', dot: aiOn },
{ id: 'notify', label: '消息通知', dot: larkOn },
{ id: 'directory', label: '用户目录', dot: ldapOn },
];
return (
<div className="h-full flex flex-col" style={{ background: 'var(--canvas-bg)' }}>
{/* Header */}
@@ -273,21 +288,44 @@ export default function SystemSettings() {
</span>
)}
</div>
<div className="flex items-center gap-2">
<button onClick={handleReset} className="flex items-center gap-1 px-3 py-[5px] text-[12px] font-medium rounded-md border" style={{ borderColor: 'var(--border-color-light)', color: 'var(--text-secondary)' }}>
<RotateCcw className="w-3.5 h-3.5" />恢复默认
</div>
{/* Tab 栏(与流水线编辑器 TopBar 同款下划线样式) */}
<div className="px-5 border-b flex items-center gap-0 flex-shrink-0" style={{ background: 'var(--panel-bg)', borderColor: 'var(--border-color)' }}>
{tabs.map((t) => (
<button
key={t.id}
onClick={() => setActiveTab(t.id)}
className="relative px-3 py-2 text-[12px] font-medium flex items-center gap-1.5"
style={{ color: activeTab === t.id ? 'var(--accent-blue)' : 'var(--text-secondary)' }}
>
{t.label}
{t.dot != null && (
<span className="w-1.5 h-1.5 rounded-full" style={{ background: t.dot ? '#1a7f37' : 'var(--text-tertiary)', opacity: t.dot ? 1 : 0.5 }} title={t.dot ? '已启用' : '未启用'} />
)}
{activeTab === t.id && (
<span className="absolute bottom-0 left-1 right-1 h-0.5 rounded-full" style={{ background: 'var(--accent-blue)' }} />
)}
</button>
<button onClick={() => saveMutation.mutate()} disabled={saveMutation.isPending}
className="flex items-center gap-1 px-3 py-[5px] text-[12px] font-medium rounded-md text-white disabled:opacity-60" style={{ background: 'var(--accent-blue)' }}>
{saveMutation.isPending ? <Loader2 className="w-3.5 h-3.5 animate-spin" /> : <Save className="w-3.5 h-3.5" />}
{saveMutation.isPending ? '保存中...' : '保存设置'}
</button>
</div>
))}
</div>
{/* Content */}
<div className="flex-1 overflow-y-auto custom-scrollbar p-5">
<div className="max-w-3xl mx-auto space-y-4">
{activeTab === 'general' && (
<>
{/* 外观主题保存/恢复操作 */}
<div className="flex items-center justify-end gap-2">
<button onClick={handleReset} className="flex items-center gap-1 px-3 py-[5px] text-[12px] font-medium rounded-md border" style={{ borderColor: 'var(--border-color-light)', color: 'var(--text-secondary)' }}>
<RotateCcw className="w-3.5 h-3.5" />恢复默认
</button>
<button onClick={() => saveMutation.mutate()} disabled={saveMutation.isPending}
className="flex items-center gap-1 px-3 py-[5px] text-[12px] font-medium rounded-md text-white disabled:opacity-60" style={{ background: 'var(--accent-blue)' }}>
{saveMutation.isPending ? <Loader2 className="w-3.5 h-3.5 animate-spin" /> : <Save className="w-3.5 h-3.5" />}
{saveMutation.isPending ? '保存中...' : '保存设置'}
</button>
</div>
{/* Appearance */}
<div className="rounded-lg border overflow-hidden" style={{ background: 'var(--panel-bg)', borderColor: 'var(--border-color)' }}>
<div className="px-4 py-2.5 border-b flex items-center gap-2" style={{ borderColor: 'var(--border-color)', background: 'var(--panel-bg-secondary)' }}>
@@ -478,10 +516,13 @@ export default function SystemSettings() {
<p className="text-[11px]" style={{ color: 'var(--text-tertiary)' }}>语言与时区暂未生效,仅作展示</p>
</div>
</div>
</div>
</>
)}
{activeTab === 'ai' && (
<>
{/* AI 助手配置 */}
<div className="rounded-lg border overflow-hidden mt-4" style={{ background: 'var(--panel-bg)', borderColor: 'var(--border-color)' }}>
<div className="rounded-lg border overflow-hidden" style={{ background: 'var(--panel-bg)', borderColor: 'var(--border-color)' }}>
<div className="px-5 py-3 border-b flex items-center justify-between" style={{ borderColor: 'var(--border-color)' }}>
<div className="flex items-center gap-2">
<span className="text-[13px] font-semibold" style={{ color: 'var(--text-primary)' }}>AI 助手(智能发布)</span>
@@ -555,9 +596,13 @@ export default function SystemSettings() {
</div>
</div>
</div>
</>
)}
{activeTab === 'notify' && (
<>
{/* 飞书 / Lark 通知 */}
<div className="rounded-lg border overflow-hidden mt-4" style={{ background: 'var(--panel-bg)', borderColor: 'var(--border-color)' }}>
<div className="rounded-lg border overflow-hidden" style={{ background: 'var(--panel-bg)', borderColor: 'var(--border-color)' }}>
<div className="px-5 py-3 border-b flex items-center justify-between" style={{ borderColor: 'var(--border-color)' }}>
<div className="flex items-center gap-2">
<span className="text-[13px] font-semibold" style={{ color: 'var(--text-primary)' }}>飞书 / Lark 群通知</span>
@@ -593,9 +638,13 @@ export default function SystemSettings() {
</div>
</div>
</div>
</>
)}
{activeTab === 'directory' && (
<>
{/* LDAP 目录服务 */}
<div className="rounded-lg border overflow-hidden mt-4" style={{ background: 'var(--panel-bg)', borderColor: 'var(--border-color)' }}>
<div className="rounded-lg border overflow-hidden" style={{ background: 'var(--panel-bg)', borderColor: 'var(--border-color)' }}>
<div className="px-5 py-3 border-b flex items-center justify-between" style={{ borderColor: 'var(--border-color)' }}>
<div className="flex items-center gap-2">
<span className="text-[13px] font-semibold" style={{ color: 'var(--text-primary)' }}>LDAP 目录服务</span>
@@ -693,6 +742,9 @@ export default function SystemSettings() {
</div>
)}
</div>
</>
)}
</div>
</div>
</div>
);