fix: 增加mysql、redis缓存

master
Lxy 3 months ago
parent f45ee680d4
commit 955f22cd75

@ -16,6 +16,7 @@
"jsonwebtoken": "^9.0.2",
"mongoose": "^8.0.3",
"morgan": "^1.10.0",
"mysql2": "^3.9.1",
"pg": "^8.11.3",
"redis": "^4.6.12",
"socket.io": "^4.7.4"
@ -974,6 +975,15 @@
"dev": true,
"license": "MIT"
},
"node_modules/aws-ssl-profiles": {
"version": "1.1.2",
"resolved": "https://registry.npmjs.org/aws-ssl-profiles/-/aws-ssl-profiles-1.1.2.tgz",
"integrity": "sha512-NZKeq9AfyQvEeNlN0zSYAaWrmBffJh3IELMZfRpJVWgrpEbtEpnjvzqBPf+mxoI287JohRDoa+/nsfqqiZmF6g==",
"license": "MIT",
"engines": {
"node": ">= 6.0.0"
}
},
"node_modules/balanced-match": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz",
@ -1488,6 +1498,15 @@
"node": ">=0.4.0"
}
},
"node_modules/denque": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/denque/-/denque-2.1.0.tgz",
"integrity": "sha512-HVQE3AAb/pxF8fQAoiqpvg9i3evqug3hoiwakOyZAwJm+6vZehbkYXZ0l4JxS+I3QxM97v5aaRNhj8v5oBhekw==",
"license": "Apache-2.0",
"engines": {
"node": ">=0.10"
}
},
"node_modules/depd": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz",
@ -2264,6 +2283,15 @@
"url": "https://github.com/sponsors/ljharb"
}
},
"node_modules/generate-function": {
"version": "2.3.1",
"resolved": "https://registry.npmjs.org/generate-function/-/generate-function-2.3.1.tgz",
"integrity": "sha512-eeB5GfMNeevm/GRYq20ShmsaGcmI81kIX2K9XQx5miC8KdHaC6Jm0qQ8ZNeGOi7wYB8OsdxKs+Y2oVuTFuVwKQ==",
"license": "MIT",
"dependencies": {
"is-property": "^1.0.2"
}
},
"node_modules/generic-pool": {
"version": "3.9.0",
"resolved": "https://registry.npmjs.org/generic-pool/-/generic-pool-3.9.0.tgz",
@ -2690,6 +2718,12 @@
"node": ">=8"
}
},
"node_modules/is-property": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/is-property/-/is-property-1.0.2.tgz",
"integrity": "sha512-Ks/IoX00TtClbGQr4TWXemAnktAQvYB7HzcCxDGqEZU6oCmb2INHuOoKxbtR+HFkmYWBKv/dOZtGRiAjDhj92g==",
"license": "MIT"
},
"node_modules/is-unicode-supported": {
"version": "0.1.0",
"resolved": "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-0.1.0.tgz",
@ -2902,6 +2936,12 @@
"url": "https://github.com/sponsors/sindresorhus"
}
},
"node_modules/long": {
"version": "5.3.2",
"resolved": "https://registry.npmjs.org/long/-/long-5.3.2.tgz",
"integrity": "sha512-mNAgZ1GmyNhD7AuqnTG3/VQ26o760+ZYBPKjPvugO8+nLbYfX6TVpJPseBvopbdY+qpZ/lKUnmEc1LeZYS3QAA==",
"license": "Apache-2.0"
},
"node_modules/loupe": {
"version": "2.3.7",
"resolved": "https://registry.npmjs.org/loupe/-/loupe-2.3.7.tgz",
@ -2912,6 +2952,21 @@
"get-func-name": "^2.0.1"
}
},
"node_modules/lru.min": {
"version": "1.1.4",
"resolved": "https://registry.npmjs.org/lru.min/-/lru.min-1.1.4.tgz",
"integrity": "sha512-DqC6n3QQ77zdFpCMASA1a3Jlb64Hv2N2DciFGkO/4L9+q/IpIAuRlKOvCXabtRW6cQf8usbmM6BE/TOPysCdIA==",
"license": "MIT",
"engines": {
"bun": ">=1.0.0",
"deno": ">=1.30.0",
"node": ">=8.0.0"
},
"funding": {
"type": "github",
"url": "https://github.com/sponsors/wellwelwel"
}
},
"node_modules/make-error": {
"version": "1.3.6",
"resolved": "https://registry.npmjs.org/make-error/-/make-error-1.3.6.tgz",
@ -3270,6 +3325,56 @@
"integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==",
"license": "MIT"
},
"node_modules/mysql2": {
"version": "3.18.0",
"resolved": "https://registry.npmjs.org/mysql2/-/mysql2-3.18.0.tgz",
"integrity": "sha512-3rupyOFks7Vq0jcjBpmg1gtgfGuCcmgrRJPEfpGzzrB/ydutupbjKkoDJGsGkrJRU6j44o2tb0McduL03/v/dQ==",
"license": "MIT",
"dependencies": {
"aws-ssl-profiles": "^1.1.2",
"denque": "^2.1.0",
"generate-function": "^2.3.1",
"iconv-lite": "^0.7.2",
"long": "^5.3.2",
"lru.min": "^1.1.4",
"named-placeholders": "^1.1.6",
"sql-escaper": "^1.3.3"
},
"engines": {
"node": ">= 8.0"
},
"peerDependencies": {
"@types/node": ">= 8"
}
},
"node_modules/mysql2/node_modules/iconv-lite": {
"version": "0.7.2",
"resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.7.2.tgz",
"integrity": "sha512-im9DjEDQ55s9fL4EYzOAv0yMqmMBSZp6G0VvFyTMPKWxiSBHUj9NW/qqLmXUwXrrM7AvqSlTCfvqRb0cM8yYqw==",
"license": "MIT",
"dependencies": {
"safer-buffer": ">= 2.1.2 < 3.0.0"
},
"engines": {
"node": ">=0.10.0"
},
"funding": {
"type": "opencollective",
"url": "https://opencollective.com/express"
}
},
"node_modules/named-placeholders": {
"version": "1.1.6",
"resolved": "https://registry.npmjs.org/named-placeholders/-/named-placeholders-1.1.6.tgz",
"integrity": "sha512-Tz09sEL2EEuv5fFowm419c1+a/jSMiBjI9gHxVLrVdbUkkNUUfjsVYs9pVZu5oCon/kmRh9TfLEObFtkVxmY0w==",
"license": "MIT",
"dependencies": {
"lru.min": "^1.1.0"
},
"engines": {
"node": ">=8.0.0"
}
},
"node_modules/natural-compare": {
"version": "1.4.0",
"resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz",
@ -4228,6 +4333,21 @@
"node": ">= 10.x"
}
},
"node_modules/sql-escaper": {
"version": "1.3.3",
"resolved": "https://registry.npmjs.org/sql-escaper/-/sql-escaper-1.3.3.tgz",
"integrity": "sha512-BsTCV265VpTp8tm1wyIm1xqQCS+Q9NHx2Sr+WcnUrgLrQ6yiDIvHYJV5gHxsj1lMBy2zm5twLaZao8Jd+S8JJw==",
"license": "MIT",
"engines": {
"bun": ">=1.0.0",
"deno": ">=2.0.0",
"node": ">=12.0.0"
},
"funding": {
"type": "github",
"url": "https://github.com/mysqljs/sql-escaper?sponsor=1"
}
},
"node_modules/statuses": {
"version": "2.0.2",
"resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.2.tgz",

@ -19,6 +19,7 @@
"jsonwebtoken": "^9.0.2",
"mongoose": "^8.0.3",
"morgan": "^1.10.0",
"mysql2": "^3.9.1",
"pg": "^8.11.3",
"redis": "^4.6.12",
"socket.io": "^4.7.4"

@ -0,0 +1,2 @@
export * from './mysql';
export * from './redis';

@ -0,0 +1,86 @@
import mysql from 'mysql2/promise';
import { config } from '../index';
import { logger } from '../../utils/logger';
class MySQLConnection {
private pool: mysql.Pool | null = null;
async connect() {
try {
this.pool = mysql.createPool({
host: config.database.mysql.host,
port: config.database.mysql.port,
user: config.database.mysql.user,
password: config.database.mysql.password,
database: config.database.mysql.database,
waitForConnections: true,
connectionLimit: 10,
queueLimit: 0
});
// 测试连接
const connection = await this.pool.getConnection();
logger.log('MySQL连接成功');
connection.release();
// 初始化表结构
await this.initTables();
} catch (error) {
logger.error('MySQL连接失败:', error);
throw error;
}
}
async initTables() {
if (!this.pool) {
throw new Error('MySQL连接未初始化');
}
try {
// 创建市场数据表格
await this.pool.execute(`
CREATE TABLE IF NOT EXISTS market_data (
id INT AUTO_INCREMENT PRIMARY KEY,
symbol VARCHAR(20) NOT NULL,
type VARCHAR(20) NOT NULL,
data JSON NOT NULL,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
UNIQUE KEY unique_symbol_type (symbol, type)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
`);
logger.log('MySQL表结构初始化完成');
} catch (error) {
logger.error('初始化MySQL表结构失败:', error);
throw error;
}
}
async getConnection() {
if (!this.pool) {
await this.connect();
}
return this.pool!.getConnection();
}
async query(sql: string, values?: any[]) {
if (!this.pool) {
await this.connect();
}
if (values) {
return this.pool!.execute(sql, values);
} else {
return this.pool!.execute(sql);
}
}
async close() {
if (this.pool) {
await this.pool.end();
logger.log('MySQL连接已关闭');
}
}
}
export const mysqlConnection = new MySQLConnection();

@ -0,0 +1,84 @@
import { createClient } from 'redis';
import { config } from '../index';
import { logger } from '../../utils/logger';
class RedisConnection {
private client: ReturnType<typeof createClient> | null = null;
async connect() {
try {
this.client = createClient({
url: config.redis.url
});
this.client.on('error', (error) => {
logger.error('Redis连接错误:', error);
});
this.client.on('connect', () => {
logger.log('Redis连接成功');
});
this.client.on('end', () => {
logger.log('Redis连接已关闭');
});
await this.client.connect();
} catch (error) {
logger.error('Redis连接失败:', error);
throw error;
}
}
async getClient() {
if (!this.client || !this.client.isReady) {
await this.connect();
}
return this.client!;
}
async get(key: string) {
const client = await this.getClient();
return client.get(key);
}
async set(key: string, value: string | number | Buffer, options?: {
ex?: number;
px?: number;
nx?: boolean;
xx?: boolean;
}) {
const client = await this.getClient();
const stringValue = typeof value === 'object' ? JSON.stringify(value) : String(value);
if (options) {
// 使用Redis v4的正确set方法参数格式
const setOptions: any = {};
if (options.ex) setOptions.EX = options.ex;
if (options.px) setOptions.PX = options.px;
if (options.nx) setOptions.NX = options.nx;
if (options.xx) setOptions.XX = options.xx;
return client.set(key, stringValue, setOptions);
} else {
return client.set(key, stringValue);
}
}
async del(key: string) {
const client = await this.getClient();
return client.del(key);
}
async exists(key: string) {
const client = await this.getClient();
return client.exists(key);
}
async close() {
if (this.client) {
await this.client.quit();
logger.log('Redis连接已关闭');
}
}
}
export const redisConnection = new RedisConnection();

@ -61,6 +61,13 @@ export const config = {
user: process.env.PG_USER || (fileConfig.database?.postgreSQL?.username || 'postgres'),
password: process.env.PG_PASSWORD || (fileConfig.database?.postgreSQL?.password || 'password'),
database: process.env.PG_DATABASE || (fileConfig.database?.postgreSQL?.database || 'alpha-futures')
},
mysql: {
host: process.env.MYSQL_HOST || 'localhost',
port: parseInt(process.env.MYSQL_PORT || '3306'),
user: process.env.MYSQL_USER || 'root',
password: process.env.MYSQL_PASSWORD || 'password',
database: process.env.MYSQL_DATABASE || 'alpha-futures'
}
},
redis: {

@ -0,0 +1,128 @@
import { redisConnection, mysqlConnection } from '../config/database';
import { logger } from '../utils/logger';
interface CacheOptions {
expireTime?: number; // Redis过期时间
}
class CacheService {
/**
*
* Redis MySQL
*/
async get<T>(key: string, symbol: string, type: string, fetchFromSource: () => Promise<T>, options: CacheOptions = {}): Promise<T> {
try {
// 1. 先从Redis中读取
logger.log(`尝试从Redis获取缓存: ${key}`);
const redisData = await redisConnection.get(key);
if (redisData) {
logger.log(`从Redis获取缓存成功: ${key}`);
return JSON.parse(redisData) as T;
}
// 2. Redis中不存在从MySQL中获取
logger.log(`尝试从MySQL获取缓存: ${symbol}, ${type}`);
const [mysqlResults]: any = await mysqlConnection.query(
'SELECT data FROM market_data WHERE symbol = ? AND type = ?',
[symbol, type]
);
if (mysqlResults && mysqlResults.length > 0) {
const mysqlData = mysqlResults[0].data;
logger.log(`从MySQL获取缓存成功: ${symbol}, ${type}`);
// 将MySQL数据同步到Redis
await this.set(key, mysqlData, options);
return mysqlData as T;
}
// 3. MySQL中也不存在从数据源获取
logger.log(`从数据源获取数据: ${key}`);
const sourceData = await fetchFromSource();
// 将数据源数据同步到MySQL和Redis
await this.set(key, sourceData, options);
await this.saveToMySQL(symbol, type, sourceData);
return sourceData;
} catch (error) {
logger.error(`获取缓存数据失败: ${key}`, error);
// 出错时直接从数据源获取
return fetchFromSource();
}
}
/**
* Redis
*/
async set(key: string, value: any, options: CacheOptions = {}): Promise<void> {
try {
const jsonValue = JSON.stringify(value);
const redisOptions: any = {};
if (options.expireTime) {
redisOptions.ex = options.expireTime;
}
await redisConnection.set(key, jsonValue, redisOptions);
logger.log(`设置Redis缓存成功: ${key}`);
} catch (error) {
logger.error(`设置Redis缓存失败: ${key}`, error);
}
}
/**
* MySQL
*/
async saveToMySQL(symbol: string, type: string, data: any): Promise<void> {
try {
// 使用UPSERT操作存在则更新不存在则插入
await mysqlConnection.query(
`INSERT INTO market_data (symbol, type, data)
VALUES (?, ?, ?)
ON DUPLICATE KEY UPDATE data = VALUES(data)`,
[symbol, type, JSON.stringify(data)]
);
logger.log(`保存数据到MySQL成功: ${symbol}, ${type}`);
} catch (error) {
logger.error(`保存数据到MySQL失败: ${symbol}, ${type}`, error);
}
}
/**
*
*/
async delete(key: string): Promise<void> {
try {
await redisConnection.del(key);
logger.log(`删除Redis缓存成功: ${key}`);
} catch (error) {
logger.error(`删除Redis缓存失败: ${key}`, error);
}
}
/**
*
*/
async clearByType(symbol: string, type: string): Promise<void> {
try {
// 清除Redis缓存
const key = `${symbol}:${type}`;
await this.delete(key);
// 清除MySQL缓存
await mysqlConnection.query(
'DELETE FROM market_data WHERE symbol = ? AND type = ?',
[symbol, type]
);
logger.log(`清除缓存成功: ${symbol}, ${type}`);
} catch (error) {
logger.error(`清除缓存失败: ${symbol}, ${type}`, error);
}
}
}
export const cacheService = new CacheService();
export default cacheService;

@ -64,7 +64,7 @@ class HttpClient {
async post<T>(endpoint: string, data?: any): Promise<T> {
const url = `${this.baseUrl}${endpoint}`;
logger.log('发送POST请求:', url, '数据:', data);
logger.log(`发送POST请求: ${url} 数据: ${JSON.stringify(data)}`);
try {
// 设置20秒超时

File diff suppressed because it is too large Load Diff

@ -43,7 +43,7 @@ export const savePushSettings = async (symbol: string, settings: any) => {
await new Promise(resolve => setTimeout(resolve, 300));
pushSettings[symbol] = settings;
logger.log('保存推送设置:', symbol, settings);
logger.log(`保存推送设置: ${symbol} ${JSON.stringify(settings)}`);
return settings;
};
@ -53,7 +53,7 @@ export const testPush = async (method: string, content: string) => {
// 模拟API请求延迟
await new Promise(resolve => setTimeout(resolve, 500));
logger.log('测试推送:', method, content);
logger.log(`测试推送: ${method} ${content}`);
// 模拟推送成功
return { success: true, message: '测试推送成功' };

@ -22,23 +22,12 @@ const AdminConfig = () => {
//
const databaseConfig = {
// MongoDB
mongoDB: {
// MySQL
mysql: {
host: 'localhost',
port: 27017,
port: 3306,
database: 'alpha-futures',
username: '',
password: '',
authSource: 'admin',
ssl: false,
enabled: true
},
// PostgreSQL
postgreSQL: {
host: 'localhost',
port: 5432,
database: 'alpha-futures',
username: 'postgres',
username: 'root',
password: 'password',
ssl: false,
enabled: true
@ -50,16 +39,6 @@ const AdminConfig = () => {
password: '',
db: 0,
enabled: true
},
// InfluxDB
influxDB: {
host: 'localhost',
port: 8086,
database: 'alpha-futures',
username: '',
password: '',
ssl: false,
enabled: true
}
};
@ -339,11 +318,25 @@ const AdminConfig = () => {
//
const completeConfig = {
database: newConfig.database || {
mongoDB: { host: 'localhost', port: 27017, database: 'alpha-futures', username: '', password: '', authSource: 'admin', ssl: false, enabled: true },
postgreSQL: { host: 'localhost', port: 5432, database: 'alpha-futures', username: 'postgres', password: 'password', ssl: false, enabled: true },
redis: { host: 'localhost', port: 6379, password: '', db: 0, enabled: true },
influxDB: { host: 'localhost', port: 8086, database: 'alpha-futures', username: '', password: '', ssl: false, enabled: true }
database: {
mysql: {
host: 'localhost',
port: 3306,
database: 'alpha-futures',
username: 'root',
password: 'password',
ssl: false,
enabled: true,
...newConfig.database?.mysql
},
redis: {
host: 'localhost',
port: 6379,
password: '',
db: 0,
enabled: true,
...newConfig.database?.redis
}
},
server: newConfig.server || {
port: 3007, host: '0.0.0.0', environment: 'development', debug: true, timeout: 30000, maxBodySize: '10mb'
@ -496,22 +489,13 @@ const AdminConfig = () => {
//
form.setFieldsValue({
'database.mongoDB.host': completeConfig.database.mongoDB.host,
'database.mongoDB.port': completeConfig.database.mongoDB.port,
'database.mongoDB.database': completeConfig.database.mongoDB.database,
'database.mongoDB.username': completeConfig.database.mongoDB.username,
'database.mongoDB.password': completeConfig.database.mongoDB.password,
'database.mongoDB.authSource': completeConfig.database.mongoDB.authSource,
'database.mongoDB.ssl': completeConfig.database.mongoDB.ssl,
'database.mongoDB.enabled': completeConfig.database.mongoDB.enabled,
'database.postgreSQL.host': completeConfig.database.postgreSQL.host,
'database.postgreSQL.port': completeConfig.database.postgreSQL.port,
'database.postgreSQL.database': completeConfig.database.postgreSQL.database,
'database.postgreSQL.username': completeConfig.database.postgreSQL.username,
'database.postgreSQL.password': completeConfig.database.postgreSQL.password,
'database.postgreSQL.ssl': completeConfig.database.postgreSQL.ssl,
'database.postgreSQL.enabled': completeConfig.database.postgreSQL.enabled,
'database.mysql.host': completeConfig.database.mysql.host,
'database.mysql.port': completeConfig.database.mysql.port,
'database.mysql.database': completeConfig.database.mysql.database,
'database.mysql.username': completeConfig.database.mysql.username,
'database.mysql.password': completeConfig.database.mysql.password,
'database.mysql.ssl': completeConfig.database.mysql.ssl,
'database.mysql.enabled': completeConfig.database.mysql.enabled,
'database.redis.host': completeConfig.database.redis.host,
'database.redis.port': completeConfig.database.redis.port,
@ -519,14 +503,6 @@ const AdminConfig = () => {
'database.redis.db': completeConfig.database.redis.db,
'database.redis.enabled': completeConfig.database.redis.enabled,
'database.influxDB.host': completeConfig.database.influxDB.host,
'database.influxDB.port': completeConfig.database.influxDB.port,
'database.influxDB.database': completeConfig.database.influxDB.database,
'database.influxDB.username': completeConfig.database.influxDB.username,
'database.influxDB.password': completeConfig.database.influxDB.password,
'database.influxDB.ssl': completeConfig.database.influxDB.ssl,
'database.influxDB.enabled': completeConfig.database.influxDB.enabled,
'server.port': completeConfig.server.port,
'server.host': completeConfig.server.host,
'server.environment': completeConfig.server.environment,
@ -753,156 +729,64 @@ const AdminConfig = () => {
key: 'database',
children: (
<>
{/* MongoDB配置 */}
<Card title="MongoDB配置" className="admin-config-card" style={{ marginBottom: 24 }}>
{/* MySQL配置 */}
<Card title="MySQL配置" className="admin-config-card" style={{ marginBottom: 24 }}>
<Row gutter={[16, 16]}>
<Col span={6}>
<Item label="主机" name="database.mongoDB.host">
<Input
onChange={(e) => handleDatabaseConfigChange('mongoDB', 'host', e.target.value)}
/>
</Item>
</Col>
<Col span={6}>
<Item label="端口" name="database.mongoDB.port">
<InputNumber
min={1}
max={65535}
onChange={(value) => handleDatabaseConfigChange('mongoDB', 'port', value)}
/>
</Item>
</Col>
<Col span={6}>
<Item label="数据库" name="database.mongoDB.database">
<Input
onChange={(e) => handleDatabaseConfigChange('mongoDB', 'database', e.target.value)}
/>
</Item>
</Col>
<Col span={6}>
<Item label="认证源" name="database.mongoDB.authSource">
<Input
onChange={(e) => handleDatabaseConfigChange('mongoDB', 'authSource', e.target.value)}
/>
</Item>
</Col>
<Col span={6}>
<Item label="用户名" name="database.mongoDB.username">
<Item label="主机" name="database.mysql.host">
<Input
onChange={(e) => handleDatabaseConfigChange('mongoDB', 'username', e.target.value)}
/>
</Item>
</Col>
<Col span={6}>
<Item label="密码" name="database.mongoDB.password">
<Input.Password
onChange={(e) => handleDatabaseConfigChange('mongoDB', 'password', e.target.value)}
onChange={(e) => handleDatabaseConfigChange('mysql', 'host', 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
onChange={(e) => handleDatabaseConfigChange('postgreSQL', 'host', e.target.value)}
/>
</Item>
</Col>
<Col span={6}>
<Item label="端口" name="database.postgreSQL.port">
<Item label="端口" name="database.mysql.port">
<InputNumber
min={1}
max={65535}
onChange={(value) => handleDatabaseConfigChange('postgreSQL', 'port', value)}
onChange={(value) => handleDatabaseConfigChange('mysql', 'port', value)}
/>
</Item>
</Col>
<Col span={6}>
<Item label="数据库" name="database.postgreSQL.database">
<Item label="数据库" name="database.mysql.database">
<Input
onChange={(e) => handleDatabaseConfigChange('postgreSQL', 'database', e.target.value)}
onChange={(e) => handleDatabaseConfigChange('mysql', 'database', e.target.value)}
/>
</Item>
</Col>
<Col span={6}>
<Item label="用户名" name="database.postgreSQL.username">
<Item label="用户名" name="database.mysql.username">
<Input
onChange={(e) => handleDatabaseConfigChange('postgreSQL', 'username', e.target.value)}
onChange={(e) => handleDatabaseConfigChange('mysql', 'username', e.target.value)}
/>
</Item>
</Col>
<Col span={6}>
<Item label="密码" name="database.postgreSQL.password">
<Item label="密码" name="database.mysql.password">
<Input.Password
onChange={(e) => handleDatabaseConfigChange('postgreSQL', 'password', e.target.value)}
onChange={(e) => handleDatabaseConfigChange('mysql', 'password', e.target.value)}
/>
</Item>
</Col>
<Col span={6}>
<Item label="SSL" name="database.postgreSQL.ssl">
<Item label="SSL" name="database.mysql.ssl">
<Switch
defaultChecked={config.database.postgreSQL.ssl}
onChange={(checked) => handleDatabaseConfigChange('postgreSQL', 'ssl', checked)}
defaultChecked={config.database.mysql.ssl}
onChange={(checked) => handleDatabaseConfigChange('mysql', 'ssl', checked)}
/>
</Item>
</Col>
<Col span={12}>
<Item label="启用" name="database.postgreSQL.enabled">
<Item label="启用" name="database.mysql.enabled">
<Switch
defaultChecked={config.database.postgreSQL.enabled}
onChange={(checked) => handleDatabaseConfigChange('postgreSQL', 'enabled', checked)}
defaultChecked={config.database.mysql.enabled}
onChange={(checked) => handleDatabaseConfigChange('mysql', 'enabled', checked)}
/>
</Item>
</Col>
@ -910,7 +794,7 @@ const AdminConfig = () => {
<div style={{ marginTop: 16 }}>
<Button
type="primary"
onClick={() => testDatabaseConnection('PostgreSQL')}
onClick={() => testDatabaseConnection('MySQL')}
style={{ marginRight: 8 }}
>
测试连接
@ -918,13 +802,13 @@ const AdminConfig = () => {
<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);
handleDatabaseConfigChange('mysql', 'host', 'localhost');
handleDatabaseConfigChange('mysql', 'port', 3306);
handleDatabaseConfigChange('mysql', 'database', 'alpha-futures');
handleDatabaseConfigChange('mysql', 'username', 'root');
handleDatabaseConfigChange('mysql', 'password', 'password');
handleDatabaseConfigChange('mysql', 'ssl', false);
handleDatabaseConfigChange('mysql', 'enabled', true);
}}
>
恢复默认
@ -1003,92 +887,7 @@ const AdminConfig = () => {
</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
onChange={(e) => handleDatabaseConfigChange('influxDB', 'host', e.target.value)}
/>
</Item>
</Col>
<Col span={6}>
<Item label="端口" name="database.influxDB.port">
<InputNumber
min={1}
max={65535}
onChange={(value) => handleDatabaseConfigChange('influxDB', 'port', value)}
/>
</Item>
</Col>
<Col span={6}>
<Item label="数据库" name="database.influxDB.database">
<Input
onChange={(e) => handleDatabaseConfigChange('influxDB', 'database', e.target.value)}
/>
</Item>
</Col>
<Col span={6}>
<Item label="用户名" name="database.influxDB.username">
<Input
onChange={(e) => handleDatabaseConfigChange('influxDB', 'username', e.target.value)}
/>
</Item>
</Col>
<Col span={6}>
<Item label="密码" name="database.influxDB.password">
<Input.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>
</>
)
},

Loading…
Cancel
Save