monitoring.js 5.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179
  1. /**
  2. * 监控配置路由
  3. */
  4. const express = require('express');
  5. const router = express.Router();
  6. const fs = require('fs').promises;
  7. const path = require('path');
  8. const { requireLogin } = require('../middleware/auth');
  9. const logger = require('../logger');
  10. // 监控配置文件路径
  11. const CONFIG_FILE = path.join(__dirname, '../config/monitoring.json');
  12. // 确保配置文件存在
  13. async function ensureConfigFile() {
  14. try {
  15. await fs.access(CONFIG_FILE);
  16. } catch (err) {
  17. // 文件不存在,创建默认配置
  18. const defaultConfig = {
  19. isEnabled: false,
  20. notificationType: 'wechat',
  21. webhookUrl: '',
  22. telegramToken: '',
  23. telegramChatId: '',
  24. monitorInterval: 60
  25. };
  26. await fs.mkdir(path.dirname(CONFIG_FILE), { recursive: true });
  27. await fs.writeFile(CONFIG_FILE, JSON.stringify(defaultConfig, null, 2), 'utf8');
  28. return defaultConfig;
  29. }
  30. // 文件存在,读取配置
  31. const data = await fs.readFile(CONFIG_FILE, 'utf8');
  32. return JSON.parse(data);
  33. }
  34. // 获取监控配置
  35. router.get('/monitoring-config', requireLogin, async (req, res) => {
  36. try {
  37. const config = await ensureConfigFile();
  38. res.json(config);
  39. } catch (err) {
  40. logger.error('获取监控配置失败:', err);
  41. res.status(500).json({ error: '获取监控配置失败' });
  42. }
  43. });
  44. // 保存监控配置
  45. router.post('/monitoring-config', requireLogin, async (req, res) => {
  46. try {
  47. const {
  48. notificationType,
  49. webhookUrl,
  50. telegramToken,
  51. telegramChatId,
  52. monitorInterval,
  53. isEnabled
  54. } = req.body;
  55. // 简单验证
  56. if (notificationType === 'wechat' && !webhookUrl) {
  57. return res.status(400).json({ error: '企业微信通知需要设置 webhook URL' });
  58. }
  59. if (notificationType === 'telegram' && (!telegramToken || !telegramChatId)) {
  60. return res.status(400).json({ error: 'Telegram 通知需要设置 Token 和 Chat ID' });
  61. }
  62. const config = await ensureConfigFile();
  63. // 更新配置
  64. const updatedConfig = {
  65. ...config,
  66. notificationType,
  67. webhookUrl: webhookUrl || '',
  68. telegramToken: telegramToken || '',
  69. telegramChatId: telegramChatId || '',
  70. monitorInterval: parseInt(monitorInterval, 10) || 60,
  71. isEnabled: isEnabled !== undefined ? isEnabled : config.isEnabled
  72. };
  73. await fs.writeFile(CONFIG_FILE, JSON.stringify(updatedConfig, null, 2), 'utf8');
  74. res.json({ success: true, message: '监控配置已保存' });
  75. // 通知监控服务重新加载配置
  76. if (global.monitoringService && typeof global.monitoringService.reload === 'function') {
  77. global.monitoringService.reload();
  78. }
  79. } catch (err) {
  80. logger.error('保存监控配置失败:', err);
  81. res.status(500).json({ error: '保存监控配置失败' });
  82. }
  83. });
  84. // 切换监控状态
  85. router.post('/toggle-monitoring', requireLogin, async (req, res) => {
  86. try {
  87. const { isEnabled } = req.body;
  88. const config = await ensureConfigFile();
  89. config.isEnabled = !!isEnabled;
  90. await fs.writeFile(CONFIG_FILE, JSON.stringify(config, null, 2), 'utf8');
  91. res.json({
  92. success: true,
  93. message: `监控已${isEnabled ? '启用' : '禁用'}`
  94. });
  95. // 通知监控服务重新加载配置
  96. if (global.monitoringService && typeof global.monitoringService.reload === 'function') {
  97. global.monitoringService.reload();
  98. }
  99. } catch (err) {
  100. logger.error('切换监控状态失败:', err);
  101. res.status(500).json({ error: '切换监控状态失败' });
  102. }
  103. });
  104. // 测试通知
  105. router.post('/test-notification', requireLogin, async (req, res) => {
  106. try {
  107. const {
  108. notificationType,
  109. webhookUrl,
  110. telegramToken,
  111. telegramChatId
  112. } = req.body;
  113. // 简单验证
  114. if (notificationType === 'wechat' && !webhookUrl) {
  115. return res.status(400).json({ error: '企业微信通知需要设置 webhook URL' });
  116. }
  117. if (notificationType === 'telegram' && (!telegramToken || !telegramChatId)) {
  118. return res.status(400).json({ error: 'Telegram 通知需要设置 Token 和 Chat ID' });
  119. }
  120. // 发送测试通知
  121. const notifier = require('../services/notificationService');
  122. const testMessage = {
  123. title: '测试通知',
  124. content: '这是一条测试通知,如果您收到这条消息,说明您的通知配置工作正常。',
  125. time: new Date().toLocaleString()
  126. };
  127. await notifier.sendNotification(testMessage, {
  128. type: notificationType,
  129. webhookUrl,
  130. telegramToken,
  131. telegramChatId
  132. });
  133. res.json({ success: true, message: '测试通知已发送' });
  134. } catch (err) {
  135. logger.error('发送测试通知失败:', err);
  136. res.status(500).json({ error: '发送测试通知失败: ' + err.message });
  137. }
  138. });
  139. // 获取已停止的容器
  140. router.get('/stopped-containers', async (req, res) => {
  141. try {
  142. const dockerService = require('../services/dockerService');
  143. const containers = await dockerService.getStoppedContainers();
  144. res.json(containers);
  145. } catch (err) {
  146. logger.error('获取已停止容器失败:', err);
  147. res.status(500).json({ error: '获取已停止容器失败', details: err.message });
  148. }
  149. });
  150. logger.success('✓ 监控配置路由已加载');
  151. // 导出路由
  152. module.exports = router;