routes_zichan_category.ts 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192
  1. import { Hono } from "hono";
  2. import debug from "debug";
  3. import type {
  4. ZichanCategory
  5. } from "../client/share/monitorTypes.ts";
  6. import type { Variables, WithAuth } from "./middlewares.ts";
  7. const log = {
  8. api: debug("d8d:zichan:api"),
  9. };
  10. // 创建资产分类管理路由
  11. export function createZichanCategoryRoutes(withAuth: WithAuth) {
  12. const zichanCategoryRoutes = new Hono<{ Variables: Variables }>();
  13. // 获取资产分类列表
  14. zichanCategoryRoutes.get("/", withAuth, async (c) => {
  15. try {
  16. const apiClient = c.get('apiClient');
  17. // 获取分页参数
  18. const page = Number(c.req.query("page")) || 1;
  19. const limit = Number(c.req.query("limit")) || 10;
  20. const offset = (page - 1) * limit;
  21. // 获取筛选参数
  22. const name = c.req.query("name");
  23. const code = c.req.query("code");
  24. let query = apiClient.database
  25. .table("zichan_category")
  26. .where("is_deleted", 0)
  27. .orderBy("id", "desc")
  28. .limit(limit)
  29. .offset(offset);
  30. if (name) {
  31. query = query.where("name", "like", `%${name}%`);
  32. }
  33. if (code) {
  34. query = query.where("code", "like", `%${code}%`);
  35. }
  36. // 克隆查询以获取总数
  37. const countQuery = query.clone();
  38. // 执行分页查询
  39. const categories = await query.limit(limit).offset(offset);
  40. // 获取总数
  41. const count = await countQuery.count();
  42. return c.json({
  43. data: categories,
  44. pagination: {
  45. total: Number(count),
  46. current: page,
  47. pageSize: limit,
  48. totalPages: Math.ceil(Number(count) / limit),
  49. },
  50. });
  51. } catch (error) {
  52. log.api("获取资产分类列表失败:", error);
  53. return c.json({ error: "获取资产分类列表失败" }, 500);
  54. }
  55. });
  56. // 创建资产分类
  57. zichanCategoryRoutes.post("/", withAuth, async (c) => {
  58. try {
  59. const apiClient = c.get('apiClient');
  60. const categoryData = (await c.req.json()) as Partial<ZichanCategory>;
  61. // 验证必填字段
  62. if (!categoryData.name || !categoryData.code) {
  63. return c.json({ error: "名称和编码不能为空" }, 400);
  64. }
  65. // 检查是否已存在相同编码的分类
  66. const existingCategory = await apiClient.database
  67. .table("zichan_category")
  68. .where("code", categoryData.code)
  69. .where("is_deleted", 0)
  70. .first();
  71. if (existingCategory) {
  72. return c.json({ error: "相同编码的分类已存在" }, 400);
  73. }
  74. // 插入新分类
  75. const [id] = await apiClient.database
  76. .table("zichan_category")
  77. .insert(categoryData);
  78. return c.json({
  79. message: "资产分类创建成功",
  80. data: { id, ...categoryData },
  81. });
  82. } catch (error) {
  83. log.api("创建资产分类失败:", error);
  84. return c.json({ error: "创建资产分类失败" }, 500);
  85. }
  86. });
  87. // 更新资产分类
  88. zichanCategoryRoutes.put("/:id", withAuth, async (c) => {
  89. try {
  90. const apiClient = c.get('apiClient');
  91. const id = Number(c.req.param("id"));
  92. const categoryData = (await c.req.json()) as Partial<ZichanCategory>;
  93. // 验证必填字段
  94. if (!categoryData.name || !categoryData.code) {
  95. return c.json({ error: "名称和编码不能为空" }, 400);
  96. }
  97. // 检查是否已存在相同编码的分类
  98. const existingCategory = await apiClient.database
  99. .table("zichan_category")
  100. .where("code", categoryData.code)
  101. .where("is_deleted", 0)
  102. .where("id", "!=", id)
  103. .first();
  104. if (existingCategory) {
  105. return c.json({ error: "相同编码的分类已存在" }, 400);
  106. }
  107. // 更新分类
  108. await apiClient.database
  109. .table("zichan_category")
  110. .where("id", id)
  111. .update({
  112. ...categoryData,
  113. updated_at: apiClient.database.fn.now(),
  114. });
  115. return c.json({
  116. message: "资产分类更新成功",
  117. data: { id, ...categoryData },
  118. });
  119. } catch (error) {
  120. log.api("更新资产分类失败:", error);
  121. return c.json({ error: "更新资产分类失败" }, 500);
  122. }
  123. });
  124. // 删除资产分类
  125. zichanCategoryRoutes.delete("/:id", withAuth, async (c) => {
  126. try {
  127. const apiClient = c.get('apiClient');
  128. const id = Number(c.req.param("id"));
  129. if (!id || isNaN(id)) {
  130. return c.json({ error: "无效的资产分类ID" }, 400);
  131. }
  132. // 检查是否有关联的资产
  133. const assetCount = await apiClient.database
  134. .table("zichan_info")
  135. .where("device_category", id)
  136. .where("is_deleted", 0)
  137. .count();
  138. if (assetCount > 0) {
  139. return c.json({ error: "该分类下有关联的资产,无法删除" }, 400);
  140. }
  141. // 软删除分类
  142. await apiClient.database.table("zichan_category").where("id", id).update({
  143. is_deleted: 1,
  144. updated_at: apiClient.database.fn.now(),
  145. });
  146. return c.json({
  147. message: "资产分类删除成功",
  148. id,
  149. });
  150. } catch (error) {
  151. log.api("删除资产分类失败:", error);
  152. return c.json({ error: "删除资产分类失败" }, 500);
  153. }
  154. });
  155. return zichanCategoryRoutes;
  156. }