first commit

This commit is contained in:
rayd1o
2026-03-05 11:46:58 +08:00
commit e7033775d8
20657 changed files with 1988940 additions and 0 deletions

View File

@@ -0,0 +1,421 @@
import { useState, useEffect } from 'react'
import {
Layout,
Menu,
Card,
Row,
Col,
Typography,
Button,
Form,
Input,
Switch,
Select,
Divider,
message,
Spin,
Tabs,
InputNumber,
} from 'antd'
import {
SettingOutlined,
DashboardOutlined,
DatabaseOutlined,
UserOutlined,
BellOutlined,
SafetyOutlined,
SaveOutlined,
} from '@ant-design/icons'
import { Link, useNavigate } from 'react-router-dom'
import { useAuthStore } from '../../stores/auth'
const { Header, Sider, Content } = Layout
const { Title, Text } = Typography
const { TabPane } = Tabs
interface SystemSettings {
system_name: string
refresh_interval: number
auto_refresh: boolean
data_retention_days: number
max_concurrent_tasks: number
}
interface NotificationSettings {
email_enabled: boolean
email_address: string
critical_alerts: boolean
warning_alerts: boolean
daily_summary: boolean
}
interface SecuritySettings {
session_timeout: number
max_login_attempts: number
password_policy: string
}
function Settings() {
const { user, logout, token, clearAuth } = useAuthStore()
const navigate = useNavigate()
const [loading, setLoading] = useState(true)
const [saving, setSaving] = useState(false)
const [systemSettings, setSystemSettings] = useState<SystemSettings>({
system_name: '智能星球',
refresh_interval: 60,
auto_refresh: true,
data_retention_days: 30,
max_concurrent_tasks: 5,
})
const [notificationSettings, setNotificationSettings] = useState<NotificationSettings>({
email_enabled: false,
email_address: '',
critical_alerts: true,
warning_alerts: true,
daily_summary: false,
})
const [securitySettings, setSecuritySettings] = useState<SecuritySettings>({
session_timeout: 60,
max_login_attempts: 5,
password_policy: 'medium',
})
const [form] = Form.useForm()
useEffect(() => {
if (!token) {
navigate('/')
return
}
fetchSettings()
}, [token, navigate])
const fetchSettings = async () => {
try {
setLoading(true)
const res = await fetch('/api/v1/settings/system', {
headers: { Authorization: `Bearer ${token}` },
})
if (res.status === 401) {
clearAuth()
navigate('/')
return
}
if (res.ok) {
const data = await res.json()
setSystemSettings(data.system || systemSettings)
setNotificationSettings(data.notifications || notificationSettings)
setSecuritySettings(data.security || securitySettings)
form.setFieldsValue({
...data.system,
...data.notifications,
...data.security,
})
}
} catch (err) {
message.error('获取设置失败')
console.error(err)
} finally {
setLoading(false)
}
}
const handleSaveSystem = async (values: any) => {
try {
setSaving(true)
const res = await fetch('/api/v1/settings/system', {
method: 'PUT',
headers: {
'Content-Type': 'application/json',
Authorization: `Bearer ${token}`,
},
body: JSON.stringify(values),
})
if (res.ok) {
message.success('系统设置已保存')
setSystemSettings(values)
} else {
message.error('保存失败')
}
} catch (err) {
message.error('保存设置失败')
console.error(err)
} finally {
setSaving(false)
}
}
const handleSaveNotifications = async (values: any) => {
try {
setSaving(true)
const res = await fetch('/api/v1/settings/notifications', {
method: 'PUT',
headers: {
'Content-Type': 'application/json',
Authorization: `Bearer ${token}`,
},
body: JSON.stringify(values),
})
if (res.ok) {
message.success('通知设置已保存')
setNotificationSettings(values)
} else {
message.error('保存失败')
}
} catch (err) {
message.error('保存设置失败')
console.error(err)
} finally {
setSaving(false)
}
}
const handleSaveSecurity = async (values: any) => {
try {
setSaving(true)
const res = await fetch('/api/v1/settings/security', {
method: 'PUT',
headers: {
'Content-Type': 'application/json',
Authorization: `Bearer ${token}`,
},
body: JSON.stringify(values),
})
if (res.ok) {
message.success('安全设置已保存')
setSecuritySettings(values)
} else {
message.error('保存失败')
}
} catch (err) {
message.error('保存设置失败')
console.error(err)
} finally {
setSaving(false)
}
}
const handleLogout = () => {
logout()
navigate('/')
}
const menuItems = [
{ key: '/', icon: <DashboardOutlined />, label: <Link to="/"></Link> },
{ key: '/datasources', icon: <DatabaseOutlined />, label: <Link to="/datasources"></Link> },
{ key: '/users', icon: <UserOutlined />, label: <Link to="/users"></Link> },
{ key: '/settings', icon: <SettingOutlined />, label: '系统配置' },
]
if (loading && !token) {
return (
<div style={{ display: 'flex', justifyContent: 'center', alignItems: 'center', height: '100vh' }}>
<Spin size="large" tip="加载中..." />
</div>
)
}
return (
<Layout className="dashboard-layout">
<Sider width={240} className="dashboard-sider">
<div style={{ height: 64, display: 'flex', alignItems: 'center', justifyContent: 'center' }}>
<Title level={4} style={{ color: 'white', margin: 0 }}></Title>
</div>
<Menu theme="dark" mode="inline" defaultSelectedKeys={['/settings']} items={menuItems} />
</Sider>
<Layout>
<Header className="dashboard-header" style={{ display: 'flex', alignItems: 'center', justifyContent: 'space-between' }}>
<Text strong>, {user?.username}</Text>
<div style={{ display: 'flex', alignItems: 'center', gap: 12 }}>
<Button type="link" danger onClick={handleLogout}>退</Button>
</div>
</Header>
<Content className="dashboard-content">
<Title level={3}><SettingOutlined /> </Title>
<Tabs defaultActiveKey="system" tabPosition="left">
<TabPane
tab={<span><SettingOutlined /> </span>}
key="system"
>
<Card title="基本设置">
<Form
form={form}
layout="vertical"
onFinish={handleSaveSystem}
initialValues={systemSettings}
>
<Row gutter={16}>
<Col span={12}>
<Form.Item
name="system_name"
label="系统名称"
rules={[{ required: true, message: '请输入系统名称' }]}
>
<Input placeholder="智能星球" />
</Form.Item>
</Col>
<Col span={12}>
<Form.Item
name="refresh_interval"
label="数据刷新间隔 (秒)"
>
<InputNumber min={10} max={3600} style={{ width: '100%' }} />
</Form.Item>
</Col>
</Row>
<Row gutter={16}>
<Col span={12}>
<Form.Item
name="data_retention_days"
label="数据保留天数"
>
<InputNumber min={1} max={365} style={{ width: '100%' }} />
</Form.Item>
</Col>
<Col span={12}>
<Form.Item
name="max_concurrent_tasks"
label="最大并发任务数"
>
<InputNumber min={1} max={20} style={{ width: '100%' }} />
</Form.Item>
</Col>
</Row>
<Form.Item
name="auto_refresh"
label="自动刷新"
valuePropName="checked"
>
<Switch />
</Form.Item>
<Form.Item>
<Button type="primary" htmlType="submit" icon={<SaveOutlined />} loading={saving}>
</Button>
</Form.Item>
</Form>
</Card>
</TabPane>
<TabPane
tab={<span><BellOutlined /> </span>}
key="notifications"
>
<Card title="通知配置">
<Form
form={form}
layout="vertical"
onFinish={handleSaveNotifications}
initialValues={notificationSettings}
>
<Divider orientation="left"></Divider>
<Row gutter={16}>
<Col span={12}>
<Form.Item
name="email_enabled"
label="启用邮件通知"
valuePropName="checked"
>
<Switch />
</Form.Item>
</Col>
<Col span={12}>
<Form.Item
name="email_address"
label="通知邮箱"
rules={[{ type: 'email', message: '请输入有效的邮箱地址' }]}
>
<Input placeholder="admin@example.com" disabled={!notificationSettings.email_enabled} />
</Form.Item>
</Col>
</Row>
<Divider orientation="left"></Divider>
<Row gutter={16}>
<Col span={8}>
<Form.Item
name="critical_alerts"
label="严重告警"
valuePropName="checked"
>
<Switch />
</Form.Item>
</Col>
<Col span={8}>
<Form.Item
name="warning_alerts"
label="警告告警"
valuePropName="checked"
>
<Switch />
</Form.Item>
</Col>
<Col span={8}>
<Form.Item
name="daily_summary"
label="每日摘要"
valuePropName="checked"
>
<Switch />
</Form.Item>
</Col>
</Row>
<Form.Item>
<Button type="primary" htmlType="submit" icon={<SaveOutlined />} loading={saving}>
</Button>
</Form.Item>
</Form>
</Card>
</TabPane>
<TabPane
tab={<span><SafetyOutlined /> </span>}
key="security"
>
<Card title="安全配置">
<Form
form={form}
layout="vertical"
onFinish={handleSaveSecurity}
initialValues={securitySettings}
>
<Row gutter={16}>
<Col span={12}>
<Form.Item
name="session_timeout"
label="会话超时 (分钟)"
>
<InputNumber min={5} max={1440} style={{ width: '100%' }} />
</Form.Item>
</Col>
<Col span={12}>
<Form.Item
name="max_login_attempts"
label="最大登录尝试次数"
>
<InputNumber min={1} max={10} style={{ width: '100%' }} />
</Form.Item>
</Col>
</Row>
<Form.Item
name="password_policy"
label="密码策略"
>
<Select>
<Select.Option value="low"> (6)</Select.Option>
<Select.Option value="medium"> (8,)</Select.Option>
<Select.Option value="high"> (12,)</Select.Option>
</Select>
</Form.Item>
<Divider />
<Button type="primary" htmlType="submit" icon={<SaveOutlined />} loading={saving}>
</Button>
</Form>
</Card>
</TabPane>
</Tabs>
</Content>
</Layout>
</Layout>
)
}
export default Settings