SystemService.ts 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133
  1. import { AppDataSource, SystemConfig, User, PlatformAccount, PublishTask } from '../models/index.js';
  2. import type { SystemConfig as SystemConfigType } from '@media-manager/shared';
  3. import { AVAILABLE_PLATFORM_TYPES } from '@media-manager/shared';
  4. import { wsManager } from '../websocket/index.js';
  5. import { RegionService, type ChinaRegionOption } from './RegionService.js';
  6. interface UpdateConfigParams {
  7. allowRegistration?: boolean;
  8. defaultUserRole?: string;
  9. }
  10. export interface PublishProxyAdminConfig {
  11. enabled: boolean;
  12. productKey: string;
  13. signature: string;
  14. }
  15. export interface UpdatePublishProxyAdminConfig {
  16. productKey?: string;
  17. signature?: string;
  18. }
  19. interface SystemStatus {
  20. database: 'connected' | 'disconnected';
  21. redis: 'connected' | 'disconnected';
  22. onlineUsers: number;
  23. totalUsers: number;
  24. totalAccounts: number;
  25. totalTasks: number;
  26. uptime: number;
  27. }
  28. export class SystemService {
  29. private configRepository = AppDataSource.getRepository(SystemConfig);
  30. private userRepository = AppDataSource.getRepository(User);
  31. private accountRepository = AppDataSource.getRepository(PlatformAccount);
  32. private taskRepository = AppDataSource.getRepository(PublishTask);
  33. private regionService = new RegionService();
  34. async getPublicConfig(): Promise<SystemConfigType> {
  35. const configs = await this.configRepository.find();
  36. const configMap = new Map(configs.map(c => [c.configKey, c.configValue]));
  37. const productKey = (configMap.get('publish_proxy_shenlong_product_key') || '').trim();
  38. const signature = (configMap.get('publish_proxy_shenlong_signature') || '').trim();
  39. return {
  40. allowRegistration: configMap.get('allow_registration') === 'true',
  41. defaultUserRole: configMap.get('default_user_role') || 'operator',
  42. maxUploadSize: 4096 * 1024 * 1024, // 4GB
  43. supportedPlatforms: AVAILABLE_PLATFORM_TYPES,
  44. publishProxy: {
  45. enabled: Boolean(productKey && signature),
  46. provider: 'shenlong',
  47. cities: [],
  48. },
  49. };
  50. }
  51. async updateConfig(params: UpdateConfigParams): Promise<void> {
  52. if (params.allowRegistration !== undefined) {
  53. await this.setConfig('allow_registration', String(params.allowRegistration));
  54. }
  55. if (params.defaultUserRole) {
  56. await this.setConfig('default_user_role', params.defaultUserRole);
  57. }
  58. }
  59. async getPublishProxyAdminConfig(): Promise<PublishProxyAdminConfig> {
  60. const configs = await this.configRepository.find();
  61. const configMap = new Map(configs.map(c => [c.configKey, c.configValue]));
  62. const productKey = (configMap.get('publish_proxy_shenlong_product_key') || '').trim();
  63. const signature = (configMap.get('publish_proxy_shenlong_signature') || '').trim();
  64. return {
  65. enabled: Boolean(productKey && signature),
  66. productKey,
  67. signature,
  68. };
  69. }
  70. async updatePublishProxyAdminConfig(params: UpdatePublishProxyAdminConfig): Promise<void> {
  71. if (params.productKey !== undefined) {
  72. await this.setConfig('publish_proxy_shenlong_product_key', String(params.productKey || '').trim());
  73. }
  74. if (params.signature !== undefined) {
  75. await this.setConfig('publish_proxy_shenlong_signature', String(params.signature || '').trim());
  76. }
  77. }
  78. async getPublishProxyCitiesFromApi(): Promise<string[]> {
  79. const regions = await this.regionService.getChinaRegionsFromCsv();
  80. const citySet = new Set<string>();
  81. for (const province of regions) {
  82. for (const city of province.children || []) {
  83. const name = String(city.label || '').trim();
  84. if (name) citySet.add(name);
  85. }
  86. }
  87. return Array.from(citySet).sort((a, b) => a.localeCompare(b, 'zh-CN'));
  88. }
  89. async getPublishProxyRegionsFromCsv(): Promise<ChinaRegionOption[]> {
  90. return this.regionService.getChinaRegionsFromCsv();
  91. }
  92. async getSystemStatus(): Promise<SystemStatus> {
  93. const [totalUsers, totalAccounts, totalTasks] = await Promise.all([
  94. this.userRepository.count(),
  95. this.accountRepository.count(),
  96. this.taskRepository.count(),
  97. ]);
  98. return {
  99. database: AppDataSource.isInitialized ? 'connected' : 'disconnected',
  100. redis: 'connected', // TODO: 实际检查 Redis 连接状态
  101. onlineUsers: wsManager.getOnlineUserCount(),
  102. totalUsers,
  103. totalAccounts,
  104. totalTasks,
  105. uptime: process.uptime(),
  106. };
  107. }
  108. private async setConfig(key: string, value: string): Promise<void> {
  109. const existing = await this.configRepository.findOne({ where: { configKey: key } });
  110. if (existing) {
  111. await this.configRepository.update(existing.id, { configValue: value });
  112. } else {
  113. await this.configRepository.save({ configKey: key, configValue: value });
  114. }
  115. }
  116. }