diff --git a/backend/app/api/v1/configs.py b/backend/app/api/v1/configs.py index 067b6a0..d712526 100644 --- a/backend/app/api/v1/configs.py +++ b/backend/app/api/v1/configs.py @@ -13,6 +13,7 @@ from app.services.amazing_data_adapter import AmazingDataAdapter from app.services.sdk_manager import sdk_manager from app.core.security import get_current_user from app.models.user import User +from app.models.config import SystemConfig router = APIRouter() @@ -164,11 +165,22 @@ async def get_system_configs( current_user: User = Depends(get_current_user) ): """获取系统配置(数据库、Redis等)""" - configs = { - "database": ConfigService.get_system_config(db, "DATABASE_URL") or "sqlite:///./amazing_data.db", - "redis": ConfigService.get_system_config(db, "REDIS_URL") or "redis://localhost:6379/0" - } - return ResponseModel(data=configs) + try: + configs = db.query(SystemConfig).all() + configs_list = [ + { + "configName": c.config_name, + "configKey": c.config_key, + "configValue": c.config_value, + "currentDbType": c.current_db_type, + "isActive": c.is_active + } + for c in configs + ] + + return ResponseModel(data={"configs": configs_list}) + except Exception as e: + raise HTTPException(status_code=500, detail="获取系统配置失败") @router.put("/system", response_model=ResponseModel) @@ -178,21 +190,28 @@ async def update_system_configs( current_user: User = Depends(get_current_user) ): """更新系统配置""" - if "database" in configs: - ConfigService.set_system_config( - db, - "DATABASE_URL", - configs["database"], - "数据库连接URL" - ) - - if "redis" in configs: - ConfigService.set_system_config( - db, - "REDIS_URL", - configs["redis"], - "Redis连接URL" - ) + if "configs" in configs: + try: + for config in configs["configs"]: + if not config.get("configKey") or not config.get("configValue"): + raise HTTPException(status_code=400, detail="配置键和配置值不能为空") + ConfigService.set_system_config( + db, + config.get("configKey"), + config.get("configValue"), + config.get("configName"), + config.get("currentDbType"), + config.get("description"), + config.get("isActive", True), + auto_commit=False + ) + db.commit() + except HTTPException: + db.rollback() + raise + except Exception as e: + db.rollback() + raise HTTPException(status_code=500, detail=f"更新系统配置失败: {str(e)}") return ResponseModel(message="更新成功") diff --git a/backend/app/models/cache.py b/backend/app/models/cache.py index 0d8860d..e6b6515 100644 --- a/backend/app/models/cache.py +++ b/backend/app/models/cache.py @@ -37,7 +37,7 @@ class CacheTaskDetail(Base): """缓存任务详情表""" __tablename__ = "cache_task_details" - id = Column(BigInteger, primary_key=True, index=True) + id = Column(BigInteger, primary_key=True, index=True, autoincrement=True) task_id = Column(Integer, ForeignKey("cache_tasks.id", ondelete="CASCADE"), nullable=False, index=True) code = Column(String(20), nullable=False, index=True) trade_date = Column(Date, nullable=False) diff --git a/backend/app/models/config.py b/backend/app/models/config.py index 3a79642..812ce4c 100644 --- a/backend/app/models/config.py +++ b/backend/app/models/config.py @@ -29,8 +29,11 @@ class SystemConfig(Base): __tablename__ = "system_configs" id = Column(Integer, primary_key=True, index=True) + config_name = Column(String(100), nullable=False) config_key = Column(String(100), unique=True, nullable=False) config_value = Column(Text, nullable=False) + current_db_type = Column(String(50)) + is_active = Column(Boolean, default=True) description = Column(Text) created_at = Column(DateTime(timezone=True), default=datetime.utcnow) updated_at = Column(DateTime(timezone=True), default=datetime.utcnow, onupdate=datetime.utcnow) diff --git a/backend/app/models/finance.py b/backend/app/models/finance.py index 066e5e7..50e24d3 100644 --- a/backend/app/models/finance.py +++ b/backend/app/models/finance.py @@ -10,7 +10,7 @@ class FinanceBalanceSheet(Base): """资产负债表""" __tablename__ = "finance_balance_sheet" - id = Column(BigInteger, primary_key=True, index=True) + id = Column(BigInteger, primary_key=True, index=True, autoincrement=True) code = Column(String(20), nullable=False, index=True) report_date = Column(Date, nullable=False, index=True) report_type = Column(Integer) @@ -65,7 +65,7 @@ class FinanceIncome(Base): """利润表""" __tablename__ = "finance_income" - id = Column(BigInteger, primary_key=True, index=True) + id = Column(BigInteger, primary_key=True, index=True, autoincrement=True) code = Column(String(20), nullable=False, index=True) report_date = Column(Date, nullable=False, index=True) report_type = Column(Integer) diff --git a/backend/app/models/future.py b/backend/app/models/future.py index 8163324..a920ed0 100644 --- a/backend/app/models/future.py +++ b/backend/app/models/future.py @@ -31,7 +31,7 @@ class FutureKlineDaily(Base): """期货日线数据表""" __tablename__ = "future_kline_daily" - id = Column(BigInteger, primary_key=True, index=True) + id = Column(BigInteger, primary_key=True, index=True, autoincrement=True) code = Column(String(20), nullable=False, index=True) trade_date = Column(Date, nullable=False, index=True) open = Column(Numeric(12, 4), nullable=False) @@ -51,7 +51,7 @@ class FutureKlineMin(Base): """期货分钟数据表""" __tablename__ = "future_kline_min" - id = Column(BigInteger, primary_key=True, index=True) + id = Column(BigInteger, primary_key=True, index=True, autoincrement=True) code = Column(String(20), nullable=False, index=True) period_type = Column(String(10), nullable=False) trade_datetime = Column(DateTime, nullable=False, index=True) diff --git a/backend/app/models/realtime.py b/backend/app/models/realtime.py index 58c652a..00a3c7b 100644 --- a/backend/app/models/realtime.py +++ b/backend/app/models/realtime.py @@ -10,7 +10,7 @@ class RealtimeSnapshot(Base): """实时快照数据表""" __tablename__ = "realtime_snapshot" - id = Column(BigInteger, primary_key=True, index=True) + id = Column(BigInteger, primary_key=True, index=True, autoincrement=True) code = Column(String(20), nullable=False, index=True) security_type = Column(String(20), nullable=False) # stock, future, index, etf, kzz, option trade_time = Column(DateTime, nullable=False, index=True) diff --git a/backend/app/models/stock.py b/backend/app/models/stock.py index cd6d7ca..31065aa 100644 --- a/backend/app/models/stock.py +++ b/backend/app/models/stock.py @@ -30,7 +30,7 @@ class StockKlineDaily(Base): """股票日线数据表""" __tablename__ = "stock_kline_daily" - id = Column(BigInteger, primary_key=True, index=True) + id = Column(BigInteger, primary_key=True, index=True, autoincrement=True) code = Column(String(20), nullable=False, index=True) trade_date = Column(Date, nullable=False, index=True) open = Column(Numeric(12, 4), nullable=False) @@ -48,7 +48,7 @@ class StockKlineMin(Base): """股票分钟数据表""" __tablename__ = "stock_kline_min" - id = Column(BigInteger, primary_key=True, index=True) + id = Column(BigInteger, primary_key=True, index=True, autoincrement=True) code = Column(String(20), nullable=False, index=True) period_type = Column(String(10), nullable=False) # min1, min5, min15, min30, min60 trade_datetime = Column(DateTime, nullable=False, index=True) diff --git a/backend/app/models/stock_basic.py b/backend/app/models/stock_basic.py index 26a6260..9a719f9 100644 --- a/backend/app/models/stock_basic.py +++ b/backend/app/models/stock_basic.py @@ -11,7 +11,7 @@ class StockBasic(Base): """股票基础数据表""" __tablename__ = "stock_basic" - id = Column(BigInteger, primary_key=True, index=True) + id = Column(BigInteger, primary_key=True, index=True, autoincrement=True) code = Column(String(20), unique=True, nullable=False, index=True) name = Column(String(50)) total_shares = Column(BigInteger) @@ -46,7 +46,7 @@ class IndexTrade(Base): """指数交易表""" __tablename__ = "index_trade" - id = Column(BigInteger, primary_key=True, index=True) + id = Column(BigInteger, primary_key=True, index=True, autoincrement=True) index_code = Column(String(20), ForeignKey("index_basic.code"), nullable=False, index=True) trade_date = Column(Date, nullable=False, index=True) open = Column(Numeric(10, 3)) diff --git a/backend/app/models/test.py b/backend/app/models/test.py index a4c01a7..2992cfb 100644 --- a/backend/app/models/test.py +++ b/backend/app/models/test.py @@ -24,7 +24,7 @@ class APITestLog(Base): """API测试日志表""" __tablename__ = "api_test_logs" - id = Column(BigInteger, primary_key=True, index=True) + id = Column(BigInteger, primary_key=True, index=True, autoincrement=True) test_name = Column(String(200), nullable=False) api_category = Column(String(50), nullable=False, index=True) api_endpoint = Column(String(200), nullable=False, index=True) diff --git a/backend/app/services/config_service.py b/backend/app/services/config_service.py index fb566da..939f4a4 100644 --- a/backend/app/services/config_service.py +++ b/backend/app/services/config_service.py @@ -130,23 +130,32 @@ class ConfigService: return config.config_value if config else None @staticmethod - def set_system_config(db: Session, key: str, value: str, description: str = None): + def set_system_config(db: Session, key: str, value: str, config_name: str = None, current_db_type: str = None, description: str = None, is_active: bool = True, auto_commit: bool = True): """设置系统配置""" config = db.query(SystemConfig).filter(SystemConfig.config_key == key).first() if config: config.config_value = value + config.is_active = is_active + if config_name: + config.config_name = config_name + if current_db_type: + config.current_db_type = current_db_type if description: config.description = description else: config = SystemConfig( config_key=key, config_value=value, + config_name=config_name or key, + current_db_type=current_db_type, + is_active=is_active, description=description ) db.add(config) - db.commit() + if auto_commit: + db.commit() @staticmethod def get_all_system_configs(db: Session) -> dict: diff --git a/frontend/src/views/ConfigManager.vue b/frontend/src/views/ConfigManager.vue index 8b7b57c..8a7cd84 100644 --- a/frontend/src/views/ConfigManager.vue +++ b/frontend/src/views/ConfigManager.vue @@ -59,12 +59,45 @@ +

当前系统配置

+ + + + + + + + + + + + + + + +

修改配置

+ + + + + + + @@ -90,9 +123,15 @@ - + + + + + + + 保存配置 @@ -198,7 +237,10 @@ const formRef = ref() const currentId = ref(null) // 系统配置相关 +const systemConfigsList = ref([]) const systemForm = reactive({ + configName: '数据库配置', + configKey: 'DATABASE_URL', dbType: 'sqlite', dbHost: 'localhost', dbPort: 5432, @@ -206,7 +248,9 @@ const systemForm = reactive({ dbPassword: '', dbName: 'amazing_data', dbPath: './amazing_data.db', - redis: 'redis://localhost:6379/0' + redis: 'redis://localhost:6379/0', + isActive: true, + redisEnabled: true }) const systemRules = { @@ -295,8 +339,18 @@ const fetchSystemConfigs = async () => { try { const res: any = await getSystemConfigs() if (res.data) { - parseDatabaseUrl(res.data.database || 'sqlite:///./amazing_data.db') - systemForm.redis = res.data.redis || 'redis://localhost:6379/0' + systemConfigsList.value = res.data.configs || [] + const dbConfig = systemConfigsList.value.find(c => c.configKey === 'DATABASE_URL') + if (dbConfig) { + parseDatabaseUrl(dbConfig.configValue || 'sqlite:///./amazing_data.db') + systemForm.configName = dbConfig.configName || '数据库配置' + systemForm.isActive = dbConfig.isActive ?? true + } + const redisConfig = systemConfigsList.value.find(c => c.configKey === 'REDIS_URL') + if (redisConfig) { + systemForm.redis = redisConfig.configValue || 'redis://localhost:6379/0' + systemForm.redisEnabled = redisConfig.isActive ?? true + } } } catch (error) { console.error(error) @@ -365,10 +419,25 @@ const handleSystemSubmit = async () => { try { const databaseUrl = buildDatabaseUrl() await updateSystemConfigs({ - database: databaseUrl, - redis: systemForm.redis + configs: [ + { + configName: systemForm.configName, + configKey: systemForm.configKey, + configValue: databaseUrl, + currentDbType: systemForm.dbType, + isActive: systemForm.isActive + }, + { + configName: 'Redis配置', + configKey: 'REDIS_URL', + configValue: systemForm.redis, + currentDbType: null, + isActive: systemForm.redisEnabled + } + ] }) ElMessage.success('保存成功') + fetchSystemConfigs() } catch (error) { console.error(error) } finally { @@ -377,6 +446,8 @@ const handleSystemSubmit = async () => { } const handleSystemReset = () => { + systemForm.configName = '数据库配置' + systemForm.configKey = 'DATABASE_URL' systemForm.dbType = 'sqlite' systemForm.dbHost = 'localhost' systemForm.dbPort = 5432 @@ -385,6 +456,8 @@ const handleSystemReset = () => { systemForm.dbName = 'amazing_data' systemForm.dbPath = './amazing_data.db' systemForm.redis = 'redis://localhost:6379/0' + systemForm.isActive = true + systemForm.redisEnabled = true dbStructureStatus.value = null showInitButton.value = false }