import { AppDataSource, SystemConfig, User, PlatformAccount, PublishTask } from '../models/index.js'; import type { SystemConfig as SystemConfigType } from '@media-manager/shared'; import { AVAILABLE_PLATFORM_TYPES } from '@media-manager/shared'; import { wsManager } from '../websocket/index.js'; import { RegionService, type ChinaRegionOption } from './RegionService.js'; interface UpdateConfigParams { allowRegistration?: boolean; defaultUserRole?: string; } export interface PublishProxyAdminConfig { enabled: boolean; productKey: string; signature: string; } export interface UpdatePublishProxyAdminConfig { productKey?: string; signature?: string; } interface SystemStatus { database: 'connected' | 'disconnected'; redis: 'connected' | 'disconnected'; onlineUsers: number; totalUsers: number; totalAccounts: number; totalTasks: number; uptime: number; } export class SystemService { private configRepository = AppDataSource.getRepository(SystemConfig); private userRepository = AppDataSource.getRepository(User); private accountRepository = AppDataSource.getRepository(PlatformAccount); private taskRepository = AppDataSource.getRepository(PublishTask); private regionService = new RegionService(); async getPublicConfig(): Promise { const configs = await this.configRepository.find(); const configMap = new Map(configs.map(c => [c.configKey, c.configValue])); const productKey = (configMap.get('publish_proxy_shenlong_product_key') || '').trim(); const signature = (configMap.get('publish_proxy_shenlong_signature') || '').trim(); return { allowRegistration: configMap.get('allow_registration') === 'true', defaultUserRole: configMap.get('default_user_role') || 'operator', maxUploadSize: 4096 * 1024 * 1024, // 4GB supportedPlatforms: AVAILABLE_PLATFORM_TYPES, publishProxy: { enabled: Boolean(productKey && signature), provider: 'shenlong', cities: [], }, }; } async updateConfig(params: UpdateConfigParams): Promise { if (params.allowRegistration !== undefined) { await this.setConfig('allow_registration', String(params.allowRegistration)); } if (params.defaultUserRole) { await this.setConfig('default_user_role', params.defaultUserRole); } } async getPublishProxyAdminConfig(): Promise { const configs = await this.configRepository.find(); const configMap = new Map(configs.map(c => [c.configKey, c.configValue])); const productKey = (configMap.get('publish_proxy_shenlong_product_key') || '').trim(); const signature = (configMap.get('publish_proxy_shenlong_signature') || '').trim(); return { enabled: Boolean(productKey && signature), productKey, signature, }; } async updatePublishProxyAdminConfig(params: UpdatePublishProxyAdminConfig): Promise { if (params.productKey !== undefined) { await this.setConfig('publish_proxy_shenlong_product_key', String(params.productKey || '').trim()); } if (params.signature !== undefined) { await this.setConfig('publish_proxy_shenlong_signature', String(params.signature || '').trim()); } } async getPublishProxyCitiesFromApi(): Promise { const regions = await this.regionService.getChinaRegionsFromCsv(); const citySet = new Set(); for (const province of regions) { for (const city of province.children || []) { const name = String(city.label || '').trim(); if (name) citySet.add(name); } } return Array.from(citySet).sort((a, b) => a.localeCompare(b, 'zh-CN')); } async getPublishProxyRegionsFromCsv(): Promise { return this.regionService.getChinaRegionsFromCsv(); } async getSystemStatus(): Promise { const [totalUsers, totalAccounts, totalTasks] = await Promise.all([ this.userRepository.count(), this.accountRepository.count(), this.taskRepository.count(), ]); return { database: AppDataSource.isInitialized ? 'connected' : 'disconnected', redis: 'connected', // TODO: 实际检查 Redis 连接状态 onlineUsers: wsManager.getOnlineUserCount(), totalUsers, totalAccounts, totalTasks, uptime: process.uptime(), }; } private async setConfig(key: string, value: string): Promise { const existing = await this.configRepository.findOne({ where: { configKey: key } }); if (existing) { await this.configRepository.update(existing.id, { configValue: value }); } else { await this.configRepository.save({ configKey: key, configValue: value }); } } }