routes_alert_handles.ts 6.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229
  1. import { Hono } from "hono";
  2. import debug from "debug";
  3. import type {
  4. AlertHandleLog,
  5. } from "../client/share/monitorTypes.ts";
  6. import {
  7. AlertStatus,
  8. HandleType,
  9. } from "../client/share/monitorTypes.ts";
  10. import {
  11. DeleteStatus,
  12. } from "../client/share/types.ts";
  13. import type { Variables, WithAuth } from "./middlewares.ts";
  14. const log = {
  15. api: debug("api:monitor"),
  16. };
  17. // 告警处理记录路由
  18. export function createAlertHandlesRoutes(withAuth: WithAuth) {
  19. const alertHandlesRoutes = new Hono<{ Variables: Variables }>();
  20. // 获取告警处理记录列表
  21. alertHandlesRoutes.get("/", withAuth, async (c) => {
  22. try {
  23. const apiClient = c.get('apiClient');
  24. // 获取分页参数
  25. const page = Number(c.req.query("page")) || 1;
  26. const pageSize = Number(c.req.query("pageSize")) || 10;
  27. const offset = (page - 1) * pageSize;
  28. // 获取筛选参数
  29. const alertId = c.req.query("alert_id")
  30. ? Number(c.req.query("alert_id"))
  31. : null;
  32. const handlerId = c.req.query("handler_id")
  33. ? Number(c.req.query("handler_id"))
  34. : null;
  35. const handleType = c.req.query("handle_type");
  36. const problemType = c.req.query("problem_type");
  37. const startTime = c.req.query("start_time");
  38. const endTime = c.req.query("end_time");
  39. // 构建查询
  40. let query = apiClient.database
  41. .table("alert_handle_logs")
  42. .where("is_deleted", DeleteStatus.NOT_DELETED)
  43. .orderBy("handle_time", "desc");
  44. // 应用筛选条件
  45. if (alertId) {
  46. query = query.where("alert_id", alertId);
  47. }
  48. if (handlerId) {
  49. query = query.where("handler_id", handlerId);
  50. }
  51. if (handleType) {
  52. query = query.where("handle_type", handleType);
  53. }
  54. if (problemType) {
  55. query = query.where("problem_type", problemType);
  56. }
  57. if (startTime && endTime) {
  58. query = query.whereBetween("handle_time", [startTime, endTime]);
  59. } else if (startTime) {
  60. query = query.where("handle_time", ">=", startTime);
  61. } else if (endTime) {
  62. query = query.where("handle_time", "<=", endTime);
  63. }
  64. // 获取总记录数
  65. const total = await query.clone().count();
  66. // 获取分页数据
  67. const logs = await query.limit(pageSize).offset(offset);
  68. // 处理JSON字段
  69. const data = logs.map((log) => ({
  70. ...log,
  71. attachments: log.attachments || [],
  72. notify_items: log.notify_items || [],
  73. }));
  74. return c.json({
  75. data,
  76. total: Number(total),
  77. page,
  78. pageSize,
  79. });
  80. } catch (error) {
  81. log.api("获取告警处理记录失败:", error);
  82. return c.json({ error: "获取告警处理记录失败" }, 500);
  83. }
  84. });
  85. // 获取单个告警处理记录
  86. alertHandlesRoutes.get("/:id", withAuth, async (c) => {
  87. try {
  88. const id = Number(c.req.param("id"));
  89. if (!id || isNaN(id)) {
  90. return c.json({ error: "无效的处理记录ID" }, 400);
  91. }
  92. const apiClient = c.get('apiClient');
  93. const handleLog = await apiClient.database
  94. .table("alert_handle_logs")
  95. .where("id", id)
  96. .where("is_deleted", DeleteStatus.NOT_DELETED)
  97. .first();
  98. if (!handleLog) {
  99. return c.json({ error: "处理记录不存在" }, 404);
  100. }
  101. // 处理JSON字段
  102. handleLog.attachments = handleLog.attachments
  103. ? JSON.parse(handleLog.attachments)
  104. : [];
  105. handleLog.notify_items = handleLog.notify_items
  106. ? JSON.parse(handleLog.notify_items)
  107. : [];
  108. return c.json(handleLog);
  109. } catch (error) {
  110. log.api("获取告警处理记录详情失败:", error);
  111. return c.json({ error: "获取告警处理记录详情失败" }, 500);
  112. }
  113. });
  114. // 创建告警处理记录
  115. alertHandlesRoutes.post("/", withAuth, async (c) => {
  116. try {
  117. const data = (await c.req.json()) as Partial<AlertHandleLog>;
  118. const user = c.get("user")!;
  119. // 验证必填字段
  120. if (!data.alert_id) {
  121. return c.json({ error: "告警ID不能为空" }, 400);
  122. }
  123. if (!data.handle_type) {
  124. return c.json({ error: "处理类型不能为空" }, 400);
  125. }
  126. if (!data.problem_type) {
  127. return c.json({ error: "问题类型不能为空" }, 400);
  128. }
  129. const apiClient = c.get('apiClient');
  130. // 检查告警是否存在
  131. const alert = await apiClient.database
  132. .table("device_alerts")
  133. .where("id", data.alert_id)
  134. .where("is_deleted", DeleteStatus.NOT_DELETED)
  135. .first();
  136. if (!alert) {
  137. return c.json({ error: "告警不存在" }, 404);
  138. }
  139. // 处理JSON字段
  140. const insertData = {
  141. ...data,
  142. handler_id: user.id,
  143. attachments: data.attachments ? JSON.stringify(data.attachments) : null,
  144. notify_items: data.notify_items
  145. ? JSON.stringify(data.notify_items)
  146. : null,
  147. handle_time: apiClient.database.fn.now(),
  148. created_at: apiClient.database.fn.now(),
  149. updated_at: apiClient.database.fn.now(),
  150. };
  151. // 插入处理记录
  152. const [id] = await apiClient.database
  153. .table("alert_handle_logs")
  154. .insert(insertData);
  155. // 更新告警状态
  156. let newStatus = alert.status;
  157. switch (data.handle_type) {
  158. case HandleType.CONFIRM:
  159. newStatus = AlertStatus.HANDLING;
  160. break;
  161. case HandleType.RESOLVE:
  162. newStatus = AlertStatus.RESOLVED;
  163. break;
  164. case HandleType.IGNORE:
  165. newStatus = AlertStatus.IGNORED;
  166. break;
  167. }
  168. await apiClient.database
  169. .table("device_alerts")
  170. .where("id", data.alert_id)
  171. .update({
  172. status: newStatus,
  173. updated_at: apiClient.database.fn.now(),
  174. });
  175. // 获取插入的数据
  176. const [insertedLog] = await apiClient.database
  177. .table("alert_handle_logs")
  178. .where("id", id);
  179. // 处理返回的JSON字段
  180. insertedLog.attachments = insertedLog.attachments || [];
  181. insertedLog.notify_items = insertedLog.notify_items || [];
  182. return c.json({
  183. message: "告警处理记录创建成功",
  184. data: insertedLog,
  185. });
  186. } catch (error) {
  187. log.api("创建告警处理记录失败:", error);
  188. return c.json({ error: "创建告警处理记录失败" }, 500);
  189. }
  190. });
  191. return alertHandlesRoutes;
  192. }