From 8ed5e97ae7facd55288cdec0372c058bcec9fe1e Mon Sep 17 00:00:00 2001 From: Lxy Date: Thu, 19 Feb 2026 10:03:58 +0800 Subject: [PATCH] =?UTF-8?q?=E5=A2=9E=E5=8A=A0=E7=AE=A1=E7=90=86=E9=85=8D?= =?UTF-8?q?=E7=BD=AE=E7=95=8C=E9=9D=A2?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/数据库使用说明.md | 309 +++++++++++++++ src/App.jsx | 2 + src/pages/admin/AdminConfig.css | 41 ++ src/pages/admin/AdminConfig.jsx | 647 ++++++++++++++++++++++++++++++++ 4 files changed, 999 insertions(+) create mode 100644 docs/数据库使用说明.md create mode 100644 src/pages/admin/AdminConfig.css create mode 100644 src/pages/admin/AdminConfig.jsx diff --git a/docs/数据库使用说明.md b/docs/数据库使用说明.md new file mode 100644 index 0000000..6f57c75 --- /dev/null +++ b/docs/数据库使用说明.md @@ -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 +- SSL:false + +**集合结构**: + +| 集合名称 | 描述 | 主要字段 | +|---------|------|----------| +| 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 +- SSL:false + +**表结构**: + +| 表名 | 描述 | 主要字段 | +|------|------|----------| +| 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 +- 用户名:'' +- 密码:'' +- SSL:false + +**测量值结构**: + +| 测量值名称 | 描述 | 字段 | 标签 | +|-----------|------|------|------| +| 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用于存储实时行情数据。通过合理配置和使用这些数据库,可以提高系统的性能和可靠性。 + +在开发过程中,应该遵循数据库设计和使用的最佳实践,确保系统的性能、可靠性和安全性。同时,应该定期检查和优化数据库配置,以适应系统的不断发展和变化。 \ No newline at end of file diff --git a/src/App.jsx b/src/App.jsx index f1b3e6a..f1abf88 100644 --- a/src/App.jsx +++ b/src/App.jsx @@ -9,6 +9,7 @@ const Detail = lazy(() => import('./pages/detail/Detail')); const RiskControl = lazy(() => import('./pages/risk-control/RiskControl')); const Config = lazy(() => import('./pages/config/Config')); const Watchlist = lazy(() => import('./pages/watchlist/Watchlist')); +const AdminConfig = lazy(() => import('./pages/admin/AdminConfig')); import './App.css'; function App() { @@ -23,6 +24,7 @@ function App() { } /> } /> } /> + } /> diff --git a/src/pages/admin/AdminConfig.css b/src/pages/admin/AdminConfig.css new file mode 100644 index 0000000..e340257 --- /dev/null +++ b/src/pages/admin/AdminConfig.css @@ -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; + } +} \ No newline at end of file diff --git a/src/pages/admin/AdminConfig.jsx b/src/pages/admin/AdminConfig.jsx new file mode 100644 index 0000000..c689be2 --- /dev/null +++ b/src/pages/admin/AdminConfig.jsx @@ -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 ( +
+

管理配置

+ + +
+ + {/* 数据库配置 */} + 数据库配置} key="database"> + {/* MongoDB配置 */} + + + + + handleDatabaseConfigChange('mongoDB', 'host', e.target.value)} + /> + + + + + handleDatabaseConfigChange('mongoDB', 'port', value)} + /> + + + + + handleDatabaseConfigChange('mongoDB', 'database', e.target.value)} + /> + + + + + handleDatabaseConfigChange('mongoDB', 'authSource', e.target.value)} + /> + + + + + handleDatabaseConfigChange('mongoDB', 'username', e.target.value)} + /> + + + + + handleDatabaseConfigChange('mongoDB', 'password', e.target.value)} + /> + + + + + handleDatabaseConfigChange('mongoDB', 'ssl', checked)} + /> + + + + + handleDatabaseConfigChange('mongoDB', 'enabled', checked)} + /> + + + +
+ + +
+
+ + {/* PostgreSQL配置 */} + + + + + handleDatabaseConfigChange('postgreSQL', 'host', e.target.value)} + /> + + + + + handleDatabaseConfigChange('postgreSQL', 'port', value)} + /> + + + + + handleDatabaseConfigChange('postgreSQL', 'database', e.target.value)} + /> + + + + + handleDatabaseConfigChange('postgreSQL', 'username', e.target.value)} + /> + + + + + handleDatabaseConfigChange('postgreSQL', 'password', e.target.value)} + /> + + + + + handleDatabaseConfigChange('postgreSQL', 'ssl', checked)} + /> + + + + + handleDatabaseConfigChange('postgreSQL', 'enabled', checked)} + /> + + + +
+ + +
+
+ + {/* Redis配置 */} + + + + + handleDatabaseConfigChange('redis', 'host', e.target.value)} + /> + + + + + handleDatabaseConfigChange('redis', 'port', value)} + /> + + + + + handleDatabaseConfigChange('redis', 'password', e.target.value)} + /> + + + + + handleDatabaseConfigChange('redis', 'db', value)} + /> + + + + + handleDatabaseConfigChange('redis', 'enabled', checked)} + /> + + + +
+ + +
+
+ + {/* InfluxDB配置 */} + + + + + handleDatabaseConfigChange('influxDB', 'host', e.target.value)} + /> + + + + + handleDatabaseConfigChange('influxDB', 'port', value)} + /> + + + + + handleDatabaseConfigChange('influxDB', 'database', e.target.value)} + /> + + + + + handleDatabaseConfigChange('influxDB', 'username', e.target.value)} + /> + + + + + handleDatabaseConfigChange('influxDB', 'password', e.target.value)} + /> + + + + + handleDatabaseConfigChange('influxDB', 'ssl', checked)} + /> + + + + + handleDatabaseConfigChange('influxDB', 'enabled', checked)} + /> + + + +
+ + +
+
+
+ + {/* 服务器配置 */} + 服务器配置} key="server"> + + + + + handleConfigChange('server', 'port', value)} + /> + + + + + handleConfigChange('server', 'host', e.target.value)} + /> + + + + + + + + + + handleConfigChange('server', 'debug', checked)} + /> + + + + + handleConfigChange('server', 'timeout', value)} + /> + + + + + handleConfigChange('server', 'maxBodySize', e.target.value)} + /> + + + + + + + {/* 安全配置 */} + 安全配置} key="security"> + {/* JWT配置 */} + + + + + handleConfigChange('security', 'jwtSecret', e.target.value)} + /> + + + + + handleConfigChange('security', 'jwtExpiresIn', e.target.value)} + /> + + + + + + {/* 速率限制配置 */} + + + + + handleConfigChange('security', 'rateLimit', { ...config.security.rateLimit, windowMs: value })} + /> + + + + + handleConfigChange('security', 'rateLimit', { ...config.security.rateLimit, max: value })} + /> + + + + + + {/* CORS配置 */} + + + + + handleConfigChange('security', 'cors', { ...config.security.cors, origin: e.target.value })} + /> + + + + + handleConfigChange('security', 'cors', { ...config.security.cors, methods: e.target.value.split(', ').map(m => m.trim()) })} + /> + + + + + handleConfigChange('security', 'cors', { ...config.security.cors, allowedHeaders: e.target.value.split(', ').map(h => h.trim()) })} + /> + + + + + +
+ + + +
+ + +
+ +
+ ); +}; + +export default AdminConfig; \ No newline at end of file