增加管理配置界面

master
Lxy 3 months ago
parent 7c9ac8fae7
commit 8ed5e97ae7

@ -0,0 +1,309 @@
# 数据库使用说明
## 1. 数据库概述
本系统采用了多数据库架构,根据不同的数据类型和使用场景选择了合适的数据库技术。以下是系统中使用的数据库及其作用:
| 数据库类型 | 版本 | 作用 | 存储内容 |
|-----------|------|------|----------|
| MongoDB | 6.x | 分析结果和配置存储 | 分析结果、用户自选合约、交易信号、系统配置、用户配置、AI模型配置 |
| PostgreSQL | 15.x | 历史数据存储 | 合约基本信息、历史K线数据、市场事件记录 |
| Redis | 7.x | 缓存 | 热点数据、会话信息、API响应缓存 |
| InfluxDB | 2.x | 实时行情数据存储 | K线数据、逐笔成交数据 |
## 2. 数据库配置
### 2.1 MongoDB配置
**配置文件路径**`backend/src/config/index.ts`
**默认配置**
- 主机localhost
- 端口27017
- 数据库alpha-futures
- 认证源admin
- SSLfalse
**集合结构**
| 集合名称 | 描述 | 主要字段 |
|---------|------|----------|
| analysis_results | 分析结果 | _id, symbol, timestamp, technical_analysis, fundamental_analysis, sentiment_analysis, ai_prediction, risk_assessment |
| user_watchlists | 用户自选合约 | _id, user_id, symbols, created_at, updated_at |
| trading_signals | 交易信号 | _id, symbol, signal_type, direction, strength, timestamp, confidence, expiration |
| data_sources | 数据源配置 | _id, name, type, url, api_key, priority, enabled, status, response_time |
| ai_models | AI模型配置 | _id, name, type, api_key, url, parameters, accuracy, response_time, enabled |
| system_settings | 系统配置 | _id, key, value, description, updated_at |
| user_settings | 用户配置 | _id, user_id, preferences, notifications, created_at, updated_at |
### 2.2 PostgreSQL配置
**配置文件路径**`backend/src/config/index.ts`
**默认配置**
- 主机localhost
- 端口5432
- 数据库alpha-futures
- 用户名postgres
- 密码password
- SSLfalse
**表结构**
| 表名 | 描述 | 主要字段 |
|------|------|----------|
| futures_contracts | 合约基本信息 | id, symbol, name, exchange, type, size, price_tick, margin_rate, created_at, updated_at |
| historical_prices | 历史K线数据 | id, contract_id, timestamp, open, high, low, close, volume, open_interest |
| market_events | 市场事件记录 | id, event_type, event_date, title, content, impact_level, created_at |
### 2.3 Redis配置
**配置文件路径**`backend/src/config/index.ts`
**默认配置**
- 主机localhost
- 端口6379
- 密码:''
- 数据库0
**使用场景**
- 缓存热点数据,如市场概览、品种详情等
- 存储会话信息,如用户登录状态
- 缓存API响应减少数据库查询压力
- 存储临时数据,如速率限制计数器
### 2.4 InfluxDB配置
**配置文件路径**`backend/src/config/index.ts`
**默认配置**
- 主机localhost
- 端口8086
- 数据库alpha-futures
- 用户名:''
- 密码:''
- SSLfalse
**测量值结构**
| 测量值名称 | 描述 | 字段 | 标签 |
|-----------|------|------|------|
| futures_price | K线数据 | open, high, low, close, volume, open_interest | symbol, exchange, interval |
| market_tick | 逐笔成交数据 | price, volume, open_interest | symbol, exchange, timestamp |
## 3. 数据库使用方式
### 3.1 MongoDB使用
**连接方式**使用mongoose库连接MongoDB
**示例代码**
```typescript
import mongoose from 'mongoose';
import { config } from './config';
mongoose.connect(config.database.mongo.url)
.then(() => console.log('MongoDB连接成功'))
.catch((error) => console.error('MongoDB连接失败:', error));
```
**使用场景**
- 存储和查询分析结果
- 管理用户自选合约
- 存储交易信号
- 管理系统配置和用户配置
- 管理AI模型配置
### 3.2 PostgreSQL使用
**连接方式**使用pg库连接PostgreSQL
**示例代码**
```typescript
import { Client } from 'pg';
import { config } from './config';
const client = new Client({
host: config.database.postgres.host,
port: config.database.postgres.port,
user: config.database.postgres.user,
password: config.database.postgres.password,
database: config.database.postgres.database
});
client.connect()
.then(() => console.log('PostgreSQL连接成功'))
.catch((error) => console.error('PostgreSQL连接失败:', error));
```
**使用场景**
- 存储和查询历史K线数据
- 管理合约基本信息
- 存储市场事件记录
### 3.3 Redis使用
**连接方式**使用redis库连接Redis
**示例代码**
```typescript
import { createClient } from 'redis';
import { config } from './config';
const redisClient = createClient({
url: config.redis.url
});
redisClient.connect()
.then(() => console.log('Redis连接成功'))
.catch((error) => console.error('Redis连接失败:', error));
```
**使用场景**
- 缓存热点数据
- 存储会话信息
- 实现速率限制
- 缓存API响应
### 3.4 InfluxDB使用
**连接方式**使用influxdb-client库连接InfluxDB
**示例代码**
```typescript
import { InfluxDB, Point } from '@influxdata/influxdb-client';
import { config } from './config';
const influxDB = new InfluxDB({
url: `http://${config.database.influxDB.host}:${config.database.influxDB.port}`,
token: 'your-token' // 在生产环境中应该从环境变量获取
});
const writeApi = influxDB.getWriteApi('', config.database.influxDB.database);
// 写入数据示例
const point = new Point('futures_price')
.tag('symbol', 'AU')
.tag('exchange', 'SHFE')
.tag('interval', '1H')
.floatField('open', 2000)
.floatField('high', 2010)
.floatField('low', 1990)
.floatField('close', 2005)
.floatField('volume', 10000)
.floatField('open_interest', 50000)
.timestamp(new Date());
writeApi.writePoint(point);
writeApi.close();
```
**使用场景**
- 存储实时K线数据
- 存储逐笔成交数据
- 进行时间序列分析
## 4. 数据库迁移与备份
### 4.1 迁移策略
**MongoDB**
- 使用mongoose的Schema和Model进行数据迁移
- 对于结构变更使用mongoose的迁移工具或手动编写迁移脚本
**PostgreSQL**
- 使用数据库迁移工具如knex.js或sequelize进行迁移
- 对于结构变更编写SQL迁移脚本
### 4.2 备份策略
**MongoDB**
- 使用`mongodump`工具进行备份
- 配置定期备份任务
- 备份文件存储在安全的位置
**PostgreSQL**
- 使用`pg_dump`工具进行备份
- 配置定期备份任务
- 备份文件存储在安全的位置
**Redis**
- 使用`SAVE`或`BGSAVE`命令进行备份
- 配置定期备份任务
- 备份文件存储在安全的位置
**InfluxDB**
- 使用`influx backup`命令进行备份
- 配置定期备份任务
- 备份文件存储在安全的位置
## 5. 性能优化
### 5.1 MongoDB优化
- 创建合适的索引,加速查询
- 使用聚合管道优化复杂查询
- 限制返回字段,减少网络传输
- 使用批量操作,减少数据库请求次数
### 5.2 PostgreSQL优化
- 创建合适的索引,加速查询
- 使用视图和存储过程优化复杂查询
- 配置连接池,减少连接开销
- 使用分区表,优化大数据表查询
### 5.3 Redis优化
- 使用合适的数据结构如Hash、List、Set等
- 设置合理的过期时间,避免内存溢出
- 使用Pipeline减少网络往返时间
- 配置合适的内存策略如LRU
### 5.4 InfluxDB优化
- 使用合适的标签和字段设计
- 避免使用高基数标签
- 配置合适的保留策略
- 使用降采样,优化查询性能
## 6. 安全考虑
### 6.1 认证与授权
- 为所有数据库配置强密码
- 限制数据库用户的权限,遵循最小权限原则
- 对于生产环境使用SSL连接
### 6.2 数据加密
- 对于敏感数据如API密钥、密码等进行加密存储
- 传输过程中使用SSL加密
### 6.3 访问控制
- 限制数据库的网络访问范围,只允许应用服务器访问
- 使用防火墙规则,限制数据库端口的访问
### 6.4 审计与监控
- 启用数据库的审计日志
- 配置监控系统,监控数据库的运行状态和性能
- 定期检查数据库的安全配置
## 7. 开发建议
1. **选择合适的数据库**:根据数据类型和使用场景选择合适的数据库
2. **合理设计数据模型**:根据业务需求设计合理的数据模型
3. **使用连接池**:对于所有数据库,使用连接池管理连接
4. **实现错误处理**:对于数据库操作,实现完善的错误处理
5. **使用事务**:对于需要原子性的操作,使用数据库事务
6. **定期备份**:配置定期备份任务,确保数据安全
7. **监控性能**:监控数据库性能,及时发现和解决性能问题
8. **安全配置**:遵循数据库安全最佳实践,确保数据安全
## 8. 总结
本系统采用了多数据库架构根据不同的数据类型和使用场景选择了合适的数据库技术。MongoDB用于存储分析结果和配置数据PostgreSQL用于存储历史数据Redis用于缓存InfluxDB用于存储实时行情数据。通过合理配置和使用这些数据库可以提高系统的性能和可靠性。
在开发过程中,应该遵循数据库设计和使用的最佳实践,确保系统的性能、可靠性和安全性。同时,应该定期检查和优化数据库配置,以适应系统的不断发展和变化。

@ -9,6 +9,7 @@ const Detail = lazy(() => import('./pages/detail/Detail'));
const RiskControl = lazy(() => import('./pages/risk-control/RiskControl')); const RiskControl = lazy(() => import('./pages/risk-control/RiskControl'));
const Config = lazy(() => import('./pages/config/Config')); const Config = lazy(() => import('./pages/config/Config'));
const Watchlist = lazy(() => import('./pages/watchlist/Watchlist')); const Watchlist = lazy(() => import('./pages/watchlist/Watchlist'));
const AdminConfig = lazy(() => import('./pages/admin/AdminConfig'));
import './App.css'; import './App.css';
function App() { function App() {
@ -23,6 +24,7 @@ function App() {
<Route path="/detail/:code" element={<Detail />} /> <Route path="/detail/:code" element={<Detail />} />
<Route path="/risk-control" element={<RiskControl />} /> <Route path="/risk-control" element={<RiskControl />} />
<Route path="/config" element={<Config />} /> <Route path="/config" element={<Config />} />
<Route path="/admin" element={<AdminConfig />} />
</Routes> </Routes>
</Suspense> </Suspense>
</MainLayout> </MainLayout>

@ -0,0 +1,41 @@
.admin-config {
padding: 24px;
background-color: #f0f2f5;
min-height: 100vh;
}
.admin-config h2 {
margin-bottom: 24px;
color: #1890ff;
}
.admin-config-card {
border-radius: 8px;
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
}
.admin-config-actions {
margin-top: 24px;
text-align: right;
}
/* 响应式调整 */
@media (max-width: 768px) {
.admin-config {
padding: 16px;
}
.admin-config-card {
margin-bottom: 16px;
}
.admin-config-actions {
display: flex;
flex-direction: column;
}
.admin-config-actions Button {
margin-bottom: 8px;
margin-right: 0 !important;
}
}

@ -0,0 +1,647 @@
import React, { useState } from 'react';
import { Card, Row, Col, Form, Input, Button, Select, Switch, InputNumber, Alert, Divider, Tabs } from 'antd';
import { DatabaseOutlined, KeyOutlined, SettingOutlined, SaveOutlined, ToolOutlined } from '@ant-design/icons';
import './AdminConfig.css';
const { Option } = Select;
const { Item } = Form;
const { TabPane } = Tabs;
const AdminConfig = () => {
const [form] = Form.useForm();
//
const databaseConfig = {
// MongoDB
mongoDB: {
host: 'localhost',
port: 27017,
database: 'alpha-futures',
username: '',
password: '',
authSource: 'admin',
ssl: false,
enabled: true
},
// PostgreSQL
postgreSQL: {
host: 'localhost',
port: 5432,
database: 'alpha-futures',
username: 'postgres',
password: 'password',
ssl: false,
enabled: true
},
// Redis
redis: {
host: 'localhost',
port: 6379,
password: '',
db: 0,
enabled: true
},
// InfluxDB
influxDB: {
host: 'localhost',
port: 8086,
database: 'alpha-futures',
username: '',
password: '',
ssl: false,
enabled: true
}
};
//
const serverConfig = {
port: 3005,
host: '0.0.0.0',
environment: 'development',
debug: true,
timeout: 30000,
maxBodySize: '10mb'
};
//
const securityConfig = {
jwtSecret: 'your-secret-key',
jwtExpiresIn: '7d',
rateLimit: {
windowMs: 60000,
max: 120
},
cors: {
origin: '*',
methods: ['GET', 'POST', 'PUT', 'DELETE', 'OPTIONS'],
allowedHeaders: ['Content-Type', 'Authorization']
}
};
const [config, setConfig] = useState({
database: databaseConfig,
server: serverConfig,
security: securityConfig
});
//
const handleConfigChange = (section, key, value) => {
setConfig(prev => ({
...prev,
[section]: {
...prev[section],
[key]: value
}
}));
};
//
const handleDatabaseConfigChange = (dbType, key, value) => {
setConfig(prev => ({
...prev,
database: {
...prev.database,
[dbType]: {
...prev.database[dbType],
[key]: value
}
}
}));
};
//
const handleSubmit = (values) => {
console.log('配置保存:', values);
//
Alert.success('配置已保存');
};
//
const testDatabaseConnection = (dbType) => {
console.log(`测试${dbType}连接`);
//
setTimeout(() => {
Alert.success(`${dbType}连接测试成功`);
}, 1000);
};
return (
<div className="admin-config">
<h2>管理配置</h2>
<Alert
message="警告:此页面包含敏感配置信息,请谨慎操作"
type="warning"
style={{ marginBottom: 24 }}
/>
<Form form={form} layout="vertical" onFinish={handleSubmit}>
<Tabs defaultActiveKey="database">
{/* 数据库配置 */}
<TabPane tab={<span><DatabaseOutlined /> 数据库配置</span>} key="database">
{/* MongoDB配置 */}
<Card title="MongoDB配置" className="admin-config-card" style={{ marginBottom: 24 }}>
<Row gutter={[16, 16]}>
<Col span={6}>
<Item label="主机" name="database.mongoDB.host">
<Input
defaultValue={config.database.mongoDB.host}
onChange={(e) => handleDatabaseConfigChange('mongoDB', 'host', e.target.value)}
/>
</Item>
</Col>
<Col span={6}>
<Item label="端口" name="database.mongoDB.port">
<InputNumber
defaultValue={config.database.mongoDB.port}
min={1}
max={65535}
onChange={(value) => handleDatabaseConfigChange('mongoDB', 'port', value)}
/>
</Item>
</Col>
<Col span={6}>
<Item label="数据库" name="database.mongoDB.database">
<Input
defaultValue={config.database.mongoDB.database}
onChange={(e) => handleDatabaseConfigChange('mongoDB', 'database', e.target.value)}
/>
</Item>
</Col>
<Col span={6}>
<Item label="认证源" name="database.mongoDB.authSource">
<Input
defaultValue={config.database.mongoDB.authSource}
onChange={(e) => handleDatabaseConfigChange('mongoDB', 'authSource', e.target.value)}
/>
</Item>
</Col>
<Col span={6}>
<Item label="用户名" name="database.mongoDB.username">
<Input
defaultValue={config.database.mongoDB.username}
onChange={(e) => handleDatabaseConfigChange('mongoDB', 'username', e.target.value)}
/>
</Item>
</Col>
<Col span={6}>
<Item label="密码" name="database.mongoDB.password">
<Input.Password
defaultValue={config.database.mongoDB.password}
onChange={(e) => handleDatabaseConfigChange('mongoDB', 'password', e.target.value)}
/>
</Item>
</Col>
<Col span={6}>
<Item label="SSL" name="database.mongoDB.ssl">
<Switch
defaultChecked={config.database.mongoDB.ssl}
onChange={(checked) => handleDatabaseConfigChange('mongoDB', 'ssl', checked)}
/>
</Item>
</Col>
<Col span={6}>
<Item label="启用" name="database.mongoDB.enabled">
<Switch
defaultChecked={config.database.mongoDB.enabled}
onChange={(checked) => handleDatabaseConfigChange('mongoDB', 'enabled', checked)}
/>
</Item>
</Col>
</Row>
<div style={{ marginTop: 16 }}>
<Button
type="primary"
onClick={() => testDatabaseConnection('MongoDB')}
style={{ marginRight: 8 }}
>
测试连接
</Button>
<Button
type="default"
onClick={() => {
handleDatabaseConfigChange('mongoDB', 'host', 'localhost');
handleDatabaseConfigChange('mongoDB', 'port', 27017);
handleDatabaseConfigChange('mongoDB', 'database', 'alpha-futures');
handleDatabaseConfigChange('mongoDB', 'username', '');
handleDatabaseConfigChange('mongoDB', 'password', '');
handleDatabaseConfigChange('mongoDB', 'authSource', 'admin');
handleDatabaseConfigChange('mongoDB', 'ssl', false);
handleDatabaseConfigChange('mongoDB', 'enabled', true);
}}
>
恢复默认
</Button>
</div>
</Card>
{/* PostgreSQL配置 */}
<Card title="PostgreSQL配置" className="admin-config-card" style={{ marginBottom: 24 }}>
<Row gutter={[16, 16]}>
<Col span={6}>
<Item label="主机" name="database.postgreSQL.host">
<Input
defaultValue={config.database.postgreSQL.host}
onChange={(e) => handleDatabaseConfigChange('postgreSQL', 'host', e.target.value)}
/>
</Item>
</Col>
<Col span={6}>
<Item label="端口" name="database.postgreSQL.port">
<InputNumber
defaultValue={config.database.postgreSQL.port}
min={1}
max={65535}
onChange={(value) => handleDatabaseConfigChange('postgreSQL', 'port', value)}
/>
</Item>
</Col>
<Col span={6}>
<Item label="数据库" name="database.postgreSQL.database">
<Input
defaultValue={config.database.postgreSQL.database}
onChange={(e) => handleDatabaseConfigChange('postgreSQL', 'database', e.target.value)}
/>
</Item>
</Col>
<Col span={6}>
<Item label="用户名" name="database.postgreSQL.username">
<Input
defaultValue={config.database.postgreSQL.username}
onChange={(e) => handleDatabaseConfigChange('postgreSQL', 'username', e.target.value)}
/>
</Item>
</Col>
<Col span={6}>
<Item label="密码" name="database.postgreSQL.password">
<Input.Password
defaultValue={config.database.postgreSQL.password}
onChange={(e) => handleDatabaseConfigChange('postgreSQL', 'password', e.target.value)}
/>
</Item>
</Col>
<Col span={6}>
<Item label="SSL" name="database.postgreSQL.ssl">
<Switch
defaultChecked={config.database.postgreSQL.ssl}
onChange={(checked) => handleDatabaseConfigChange('postgreSQL', 'ssl', checked)}
/>
</Item>
</Col>
<Col span={12}>
<Item label="启用" name="database.postgreSQL.enabled">
<Switch
defaultChecked={config.database.postgreSQL.enabled}
onChange={(checked) => handleDatabaseConfigChange('postgreSQL', 'enabled', checked)}
/>
</Item>
</Col>
</Row>
<div style={{ marginTop: 16 }}>
<Button
type="primary"
onClick={() => testDatabaseConnection('PostgreSQL')}
style={{ marginRight: 8 }}
>
测试连接
</Button>
<Button
type="default"
onClick={() => {
handleDatabaseConfigChange('postgreSQL', 'host', 'localhost');
handleDatabaseConfigChange('postgreSQL', 'port', 5432);
handleDatabaseConfigChange('postgreSQL', 'database', 'alpha-futures');
handleDatabaseConfigChange('postgreSQL', 'username', 'postgres');
handleDatabaseConfigChange('postgreSQL', 'password', 'password');
handleDatabaseConfigChange('postgreSQL', 'ssl', false);
handleDatabaseConfigChange('postgreSQL', 'enabled', true);
}}
>
恢复默认
</Button>
</div>
</Card>
{/* Redis配置 */}
<Card title="Redis配置" className="admin-config-card" style={{ marginBottom: 24 }}>
<Row gutter={[16, 16]}>
<Col span={6}>
<Item label="主机" name="database.redis.host">
<Input
defaultValue={config.database.redis.host}
onChange={(e) => handleDatabaseConfigChange('redis', 'host', e.target.value)}
/>
</Item>
</Col>
<Col span={6}>
<Item label="端口" name="database.redis.port">
<InputNumber
defaultValue={config.database.redis.port}
min={1}
max={65535}
onChange={(value) => handleDatabaseConfigChange('redis', 'port', value)}
/>
</Item>
</Col>
<Col span={6}>
<Item label="密码" name="database.redis.password">
<Input.Password
defaultValue={config.database.redis.password}
onChange={(e) => handleDatabaseConfigChange('redis', 'password', e.target.value)}
/>
</Item>
</Col>
<Col span={6}>
<Item label="数据库" name="database.redis.db">
<InputNumber
defaultValue={config.database.redis.db}
min={0}
max={15}
onChange={(value) => handleDatabaseConfigChange('redis', 'db', value)}
/>
</Item>
</Col>
<Col span={24}>
<Item label="启用" name="database.redis.enabled">
<Switch
defaultChecked={config.database.redis.enabled}
onChange={(checked) => handleDatabaseConfigChange('redis', 'enabled', checked)}
/>
</Item>
</Col>
</Row>
<div style={{ marginTop: 16 }}>
<Button
type="primary"
onClick={() => testDatabaseConnection('Redis')}
style={{ marginRight: 8 }}
>
测试连接
</Button>
<Button
type="default"
onClick={() => {
handleDatabaseConfigChange('redis', 'host', 'localhost');
handleDatabaseConfigChange('redis', 'port', 6379);
handleDatabaseConfigChange('redis', 'password', '');
handleDatabaseConfigChange('redis', 'db', 0);
handleDatabaseConfigChange('redis', 'enabled', true);
}}
>
恢复默认
</Button>
</div>
</Card>
{/* InfluxDB配置 */}
<Card title="InfluxDB配置" className="admin-config-card" style={{ marginBottom: 24 }}>
<Row gutter={[16, 16]}>
<Col span={6}>
<Item label="主机" name="database.influxDB.host">
<Input
defaultValue={config.database.influxDB.host}
onChange={(e) => handleDatabaseConfigChange('influxDB', 'host', e.target.value)}
/>
</Item>
</Col>
<Col span={6}>
<Item label="端口" name="database.influxDB.port">
<InputNumber
defaultValue={config.database.influxDB.port}
min={1}
max={65535}
onChange={(value) => handleDatabaseConfigChange('influxDB', 'port', value)}
/>
</Item>
</Col>
<Col span={6}>
<Item label="数据库" name="database.influxDB.database">
<Input
defaultValue={config.database.influxDB.database}
onChange={(e) => handleDatabaseConfigChange('influxDB', 'database', e.target.value)}
/>
</Item>
</Col>
<Col span={6}>
<Item label="用户名" name="database.influxDB.username">
<Input
defaultValue={config.database.influxDB.username}
onChange={(e) => handleDatabaseConfigChange('influxDB', 'username', e.target.value)}
/>
</Item>
</Col>
<Col span={6}>
<Item label="密码" name="database.influxDB.password">
<Input.Password
defaultValue={config.database.influxDB.password}
onChange={(e) => handleDatabaseConfigChange('influxDB', 'password', e.target.value)}
/>
</Item>
</Col>
<Col span={6}>
<Item label="SSL" name="database.influxDB.ssl">
<Switch
defaultChecked={config.database.influxDB.ssl}
onChange={(checked) => handleDatabaseConfigChange('influxDB', 'ssl', checked)}
/>
</Item>
</Col>
<Col span={12}>
<Item label="启用" name="database.influxDB.enabled">
<Switch
defaultChecked={config.database.influxDB.enabled}
onChange={(checked) => handleDatabaseConfigChange('influxDB', 'enabled', checked)}
/>
</Item>
</Col>
</Row>
<div style={{ marginTop: 16 }}>
<Button
type="primary"
onClick={() => testDatabaseConnection('InfluxDB')}
style={{ marginRight: 8 }}
>
测试连接
</Button>
<Button
type="default"
onClick={() => {
handleDatabaseConfigChange('influxDB', 'host', 'localhost');
handleDatabaseConfigChange('influxDB', 'port', 8086);
handleDatabaseConfigChange('influxDB', 'database', 'alpha-futures');
handleDatabaseConfigChange('influxDB', 'username', '');
handleDatabaseConfigChange('influxDB', 'password', '');
handleDatabaseConfigChange('influxDB', 'ssl', false);
handleDatabaseConfigChange('influxDB', 'enabled', true);
}}
>
恢复默认
</Button>
</div>
</Card>
</TabPane>
{/* 服务器配置 */}
<TabPane tab={<span><ToolOutlined /> 服务器配置</span>} key="server">
<Card title="服务器配置" className="admin-config-card" style={{ marginBottom: 24 }}>
<Row gutter={[16, 16]}>
<Col span={6}>
<Item label="端口" name="server.port">
<InputNumber
defaultValue={config.server.port}
min={1}
max={65535}
onChange={(value) => handleConfigChange('server', 'port', value)}
/>
</Item>
</Col>
<Col span={6}>
<Item label="主机" name="server.host">
<Input
defaultValue={config.server.host}
onChange={(e) => handleConfigChange('server', 'host', e.target.value)}
/>
</Item>
</Col>
<Col span={6}>
<Item label="环境" name="server.environment">
<Select
defaultValue={config.server.environment}
onChange={(value) => handleConfigChange('server', 'environment', value)}
>
<Option value="development">开发环境</Option>
<Option value="production">生产环境</Option>
<Option value="testing">测试环境</Option>
</Select>
</Item>
</Col>
<Col span={6}>
<Item label="调试模式" name="server.debug">
<Switch
defaultChecked={config.server.debug}
onChange={(checked) => handleConfigChange('server', 'debug', checked)}
/>
</Item>
</Col>
<Col span={6}>
<Item label="超时时间(ms)" name="server.timeout">
<InputNumber
defaultValue={config.server.timeout}
min={1000}
max={60000}
step={1000}
onChange={(value) => handleConfigChange('server', 'timeout', value)}
/>
</Item>
</Col>
<Col span={6}>
<Item label="最大请求体大小" name="server.maxBodySize">
<Input
defaultValue={config.server.maxBodySize}
onChange={(e) => handleConfigChange('server', 'maxBodySize', e.target.value)}
/>
</Item>
</Col>
</Row>
</Card>
</TabPane>
{/* 安全配置 */}
<TabPane tab={<span><KeyOutlined /> 安全配置</span>} key="security">
{/* JWT配置 */}
<Card title="JWT配置" className="admin-config-card" style={{ marginBottom: 24 }}>
<Row gutter={[16, 16]}>
<Col span={12}>
<Item label="JWT密钥" name="security.jwtSecret">
<Input.Password
defaultValue={config.security.jwtSecret}
onChange={(e) => handleConfigChange('security', 'jwtSecret', e.target.value)}
/>
</Item>
</Col>
<Col span={12}>
<Item label="过期时间" name="security.jwtExpiresIn">
<Input
defaultValue={config.security.jwtExpiresIn}
onChange={(e) => handleConfigChange('security', 'jwtExpiresIn', e.target.value)}
/>
</Item>
</Col>
</Row>
</Card>
{/* 速率限制配置 */}
<Card title="速率限制配置" className="admin-config-card" style={{ marginBottom: 24 }}>
<Row gutter={[16, 16]}>
<Col span={12}>
<Item label="时间窗口(ms)" name="security.rateLimit.windowMs">
<InputNumber
defaultValue={config.security.rateLimit.windowMs}
min={1000}
max={3600000}
step={1000}
onChange={(value) => handleConfigChange('security', 'rateLimit', { ...config.security.rateLimit, windowMs: value })}
/>
</Item>
</Col>
<Col span={12}>
<Item label="最大请求数" name="security.rateLimit.max">
<InputNumber
defaultValue={config.security.rateLimit.max}
min={1}
max={1000}
step={10}
onChange={(value) => handleConfigChange('security', 'rateLimit', { ...config.security.rateLimit, max: value })}
/>
</Item>
</Col>
</Row>
</Card>
{/* CORS配置 */}
<Card title="CORS配置" className="admin-config-card" style={{ marginBottom: 24 }}>
<Row gutter={[16, 16]}>
<Col span={24}>
<Item label="允许的源" name="security.cors.origin">
<Input
defaultValue={config.security.cors.origin}
onChange={(e) => handleConfigChange('security', 'cors', { ...config.security.cors, origin: e.target.value })}
/>
</Item>
</Col>
<Col span={24}>
<Item label="允许的方法" name="security.cors.methods">
<Input
defaultValue={config.security.cors.methods.join(', ')}
onChange={(e) => handleConfigChange('security', 'cors', { ...config.security.cors, methods: e.target.value.split(', ').map(m => m.trim()) })}
/>
</Item>
</Col>
<Col span={24}>
<Item label="允许的头部" name="security.cors.allowedHeaders">
<Input
defaultValue={config.security.cors.allowedHeaders.join(', ')}
onChange={(e) => handleConfigChange('security', 'cors', { ...config.security.cors, allowedHeaders: e.target.value.split(', ').map(h => h.trim()) })}
/>
</Item>
</Col>
</Row>
</Card>
</TabPane>
</Tabs>
<Divider />
<div className="admin-config-actions">
<Button type="default" style={{ marginRight: 8 }}>
恢复默认配置
</Button>
<Button type="primary" htmlType="submit">
<SaveOutlined /> 保存配置
</Button>
</div>
</Form>
</div>
);
};
export default AdminConfig;
Loading…
Cancel
Save