routes_rack.ts 6.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264
  1. import { Hono } from "hono";
  2. import debug from "debug";
  3. import type {
  4. RackInfo
  5. } from "../client/share/monitorTypes.ts";
  6. import {
  7. DeleteStatus
  8. } from "../client/share/types.ts";
  9. import type { Variables , WithAuth } from "./middlewares.ts";
  10. const log = {
  11. api: debug("d8d:rack:api"),
  12. };
  13. // 创建机柜管理 API 的工厂函数
  14. export function createRackRoutes(withAuth: WithAuth) {
  15. const rackRoutes = new Hono<{ Variables: Variables }>();
  16. // 获取机柜列表
  17. rackRoutes.get("/", withAuth, async (c) => {
  18. try {
  19. const apiClient = c.get('apiClient');
  20. // 获取分页参数
  21. const page = Number(c.req.query("page")) || 1;
  22. const limit = Number(c.req.query("limit")) || 10;
  23. const offset = (page - 1) * limit;
  24. // 获取筛选参数
  25. const rackName = c.req.query("rack_name") || "";
  26. const rackCode = c.req.query("rack_code") || "";
  27. const area = c.req.query("area") || "";
  28. const room = c.req.query("room") || "";
  29. // 构建查询
  30. let query = apiClient.database
  31. .table("rack_info")
  32. .where("is_deleted", DeleteStatus.NOT_DELETED);
  33. // 应用筛选条件
  34. if (rackName) {
  35. query = query.where("rack_name", "like", `%${rackName}%`);
  36. }
  37. if (rackCode) {
  38. query = query.where("rack_code", "like", `%${rackCode}%`);
  39. }
  40. if (area) {
  41. query = query.where("area", "like", `%${area}%`);
  42. }
  43. if (room) {
  44. query = query.where("room", "like", `%${room}%`);
  45. }
  46. // 获取总记录数
  47. const total = await query.clone().count();
  48. // 获取分页数据
  49. const racks = await query
  50. .select("*")
  51. .limit(limit)
  52. .offset(offset)
  53. .orderBy("created_at", "desc");
  54. // 返回结果
  55. return c.json({
  56. data: racks,
  57. pagination: {
  58. total,
  59. current: page,
  60. pageSize: limit,
  61. },
  62. });
  63. } catch (error: any) {
  64. log.api("获取机柜列表失败:", error);
  65. return c.json({ error: "获取机柜列表失败" }, 500);
  66. }
  67. });
  68. // 获取机柜详情
  69. rackRoutes.get("/:id", withAuth, async (c) => {
  70. try {
  71. const id = Number(c.req.param("id"));
  72. if (!id || isNaN(id)) {
  73. return c.json({ error: "无效的机柜ID" }, 400);
  74. }
  75. const apiClient = c.get('apiClient');
  76. // 查询机柜
  77. const rack = await apiClient.database
  78. .table("rack_info")
  79. .where("id", id)
  80. .where("is_deleted", DeleteStatus.NOT_DELETED)
  81. .first();
  82. if (!rack) {
  83. return c.json({ error: "机柜不存在" }, 404);
  84. }
  85. return c.json(rack);
  86. } catch (error) {
  87. log.api("获取机柜详情失败:", error);
  88. return c.json({ error: "获取机柜详情失败" }, 500);
  89. }
  90. });
  91. // 创建机柜
  92. rackRoutes.post("/", withAuth, async (c) => {
  93. try {
  94. const rackData = (await c.req.json()) as Partial<RackInfo>;
  95. // 验证必填字段
  96. if (!rackData.rack_name) {
  97. return c.json({ error: "机柜名称不能为空" }, 400);
  98. }
  99. if (!rackData.rack_code) {
  100. return c.json({ error: "机柜编号不能为空" }, 400);
  101. }
  102. const apiClient = c.get('apiClient');
  103. // 检查是否已存在相同编号的机柜
  104. const existingRack = await apiClient.database
  105. .table("rack_info")
  106. .where("rack_code", rackData.rack_code)
  107. .where("is_deleted", DeleteStatus.NOT_DELETED)
  108. .first();
  109. if (existingRack) {
  110. return c.json({ error: "已存在相同编号的机柜" }, 400);
  111. }
  112. // 插入机柜
  113. const [id] = await apiClient.database.table("rack_info").insert({
  114. ...rackData,
  115. created_at: apiClient.database.fn.now(),
  116. updated_at: apiClient.database.fn.now(),
  117. });
  118. return c.json({
  119. message: "创建机柜成功",
  120. id,
  121. });
  122. } catch (error) {
  123. log.api("创建机柜失败:", error);
  124. return c.json({ error: "创建机柜失败" }, 500);
  125. }
  126. });
  127. // 更新机柜
  128. rackRoutes.put("/:id", withAuth, async (c) => {
  129. try {
  130. const id = Number(c.req.param("id"));
  131. if (!id || isNaN(id)) {
  132. return c.json({ error: "无效的机柜ID" }, 400);
  133. }
  134. const rackData = (await c.req.json()) as Partial<RackInfo>;
  135. const apiClient = c.get('apiClient');
  136. // 检查机柜是否存在
  137. const existingRack = await apiClient.database
  138. .table("rack_info")
  139. .where("id", id)
  140. .where("is_deleted", DeleteStatus.NOT_DELETED)
  141. .first();
  142. if (!existingRack) {
  143. return c.json({ error: "机柜不存在" }, 404);
  144. }
  145. // 检查编号是否与其他机柜冲突
  146. if (rackData.rack_code !== existingRack.rack_code) {
  147. const conflictRack = await apiClient.database
  148. .table("rack_info")
  149. .where("rack_code", rackData.rack_code || "")
  150. .where("id", "!=", id)
  151. .where("is_deleted", DeleteStatus.NOT_DELETED)
  152. .first();
  153. if (conflictRack) {
  154. return c.json({ error: "已存在相同编号的机柜" }, 400);
  155. }
  156. }
  157. // 更新机柜
  158. await apiClient.database
  159. .table("rack_info")
  160. .where("id", id)
  161. .update({
  162. ...rackData,
  163. updated_at: apiClient.database.fn.now(),
  164. });
  165. return c.json({
  166. message: "更新机柜成功",
  167. id,
  168. });
  169. } catch (error) {
  170. log.api("更新机柜失败:", error);
  171. return c.json({ error: "更新机柜失败" }, 500);
  172. }
  173. });
  174. // 删除机柜
  175. rackRoutes.delete("/:id", withAuth, async (c) => {
  176. try {
  177. const id = Number(c.req.param("id"));
  178. if (!id || isNaN(id)) {
  179. return c.json({ error: "无效的机柜ID" }, 400);
  180. }
  181. const apiClient = c.get('apiClient');
  182. // 检查机柜是否存在
  183. const existingRack = await apiClient.database
  184. .table("rack_info")
  185. .where("id", id)
  186. .where("is_deleted", DeleteStatus.NOT_DELETED)
  187. .first();
  188. if (!existingRack) {
  189. return c.json({ error: "机柜不存在" }, 404);
  190. }
  191. // 检查是否有关联的服务器
  192. const relatedServers = await apiClient.database
  193. .table("rack_server")
  194. .where("rack_id", id)
  195. .where("is_deleted", DeleteStatus.NOT_DELETED)
  196. .first();
  197. if (relatedServers) {
  198. return c.json({ error: "该机柜下存在服务器设备,无法删除" }, 400);
  199. }
  200. // 软删除机柜
  201. await apiClient.database.table("rack_info").where("id", id).update({
  202. is_deleted: DeleteStatus.DELETED,
  203. updated_at: apiClient.database.fn.now(),
  204. });
  205. return c.json({
  206. message: "删除机柜成功",
  207. id,
  208. });
  209. } catch (error) {
  210. log.api("删除机柜失败:", error);
  211. return c.json({ error: "删除机柜失败" }, 500);
  212. }
  213. });
  214. return rackRoutes;
  215. }