import { Hono } from "hono"; import debug from "debug"; import type { DeviceInstance } from "../client/share/monitorTypes.ts"; import { EnableStatus, DeleteStatus, } from "../client/share/types.ts"; import type { Variables, WithAuth } from "./middlewares.ts"; const log = { api: debug("d8d:device:api"), }; // 创建设备实例路由 export function createDeviceInstancesRoutes(withAuth: WithAuth) { const deviceInstancesRoutes = new Hono<{ Variables: Variables }>(); // 获取设备列表 deviceInstancesRoutes.get("/", withAuth, async (c) => { try { const apiClient = c.get('apiClient'); // 获取分页参数 const page = Number(c.req.query("page")) || 1; const limit = Number(c.req.query("limit")) || 10; const offset = (page - 1) * limit; // 获取筛选参数 const typeId = c.req.query("type_id"); const protocol = c.req.query("protocol"); const status = c.req.query("status"); // 构建查询 let query = apiClient.database .table("device_instances as di") .leftJoin("zichan_info as zi", "di.id", "zi.id") .select( "di.*", "zi.asset_name", "zi.device_category", "zi.area", "zi.supplier", "zi.device_status" ) .where("di.is_deleted", DeleteStatus.NOT_DELETED) .orderBy("di.id", "desc"); // 应用筛选条件 if (typeId) { const typeIdNum = Number(typeId); if (!isNaN(typeIdNum)) { query = query.where("di.type_id", typeIdNum); } } if (protocol) { query = query.where("di.protocol", "like", `%${protocol}%`); } if (status) { const statusNum = Number(status); if (!isNaN(statusNum)) { query = query.where("di.is_enabled", statusNum); } } // 克隆查询以获取总数 const countQuery = query.clone(); // 执行分页查询 const devices = await query.limit(limit).offset(offset); // 获取总数 const count = await countQuery.count(); return c.json({ data: devices, pagination: { total: Number(count), current: page, pageSize: limit, totalPages: Math.ceil(Number(count) / limit), }, }); } catch (error) { log.api("获取设备列表失败:", error); return c.json({ error: "获取设备列表失败" }, 500); } }); // 获取单个设备 deviceInstancesRoutes.get("/:id", withAuth, async (c) => { try { const id = Number(c.req.param("id")); if (!id || isNaN(id)) { return c.json({ error: "无效的设备ID" }, 400); } const apiClient = c.get('apiClient'); const [device] = await apiClient.database .table("device_instances") .where({ id, is_deleted: DeleteStatus.NOT_DELETED }); if (!device) { return c.json({ error: "设备不存在" }, 404); } // 获取关联的资产信息 const [asset] = await apiClient.database .table("zichan_info") .where("id", id); // 获取关联的设备类型信息 const [deviceType] = await apiClient.database .table("device_types") .where("id", device.type_id); return c.json({ ...device, asset_info: asset, type_info: deviceType, }); } catch (error) { log.api("获取设备详情失败:", error); return c.json({ error: "获取设备详情失败" }, 500); } }); // 创建设备 deviceInstancesRoutes.post("/", withAuth, async (c) => { try { const apiClient = c.get('apiClient'); const data = (await c.req.json()) as Partial; // 验证必填字段 if (!data.id || !data.type_id || !data.protocol || !data.address) { return c.json( { error: "关联资产、设备类型、通信协议和通信地址不能为空" }, 400 ); } // 检查关联的资产是否存在 const [asset] = await apiClient.database .table("zichan_info") .where({ id: data.id, is_deleted: DeleteStatus.NOT_DELETED }); if (!asset) { return c.json({ error: "关联的资产不存在" }, 404); } // 检查设备类型是否存在 const [deviceType] = await apiClient.database .table("device_types") .where({ id: data.type_id, is_deleted: DeleteStatus.NOT_DELETED }); if (!deviceType) { return c.json({ error: "设备类型不存在" }, 404); } // 检查该资产是否已经关联了设备 const [existingDevice] = await apiClient.database .table("device_instances") .where({ id: data.id, is_deleted: DeleteStatus.NOT_DELETED }); if (existingDevice) { return c.json({ error: "该资产已关联了设备" }, 400); } // 创建设备 await apiClient.database.table("device_instances").insert({ id: data.id, type_id: data.type_id, protocol: data.protocol, address: data.address, collect_interval: data.collect_interval || 60, remark: data.remark, is_enabled: data.is_enabled ?? EnableStatus.ENABLED, is_deleted: DeleteStatus.NOT_DELETED, }); // 获取创建的设备 const [createdDevice] = await apiClient.database .table("device_instances") .where("id", data.id); return c.json({ message: "设备创建成功", data: createdDevice, }); } catch (error) { log.api("创建设备失败:", error); return c.json({ error: "创建设备失败" }, 500); } }); // 更新设备 deviceInstancesRoutes.put("/:id", withAuth, async (c) => { try { const id = Number(c.req.param("id")); if (!id || isNaN(id)) { return c.json({ error: "无效的设备ID" }, 400); } const apiClient = c.get('apiClient'); const data = (await c.req.json()) as Partial; // 检查设备是否存在 const [existingDevice] = await apiClient.database .table("device_instances") .where({ id, is_deleted: DeleteStatus.NOT_DELETED }); if (!existingDevice) { return c.json({ error: "设备不存在" }, 404); } // 如果更新设备类型,检查该类型是否存在 if (data.type_id) { const [deviceType] = await apiClient.database .table("device_types") .where({ id: data.type_id, is_deleted: DeleteStatus.NOT_DELETED }); if (!deviceType) { return c.json({ error: "设备类型不存在" }, 404); } } // 更新设备 await apiClient.database .table("device_instances") .where("id", id) .update({ ...data, updated_at: apiClient.database.fn.now(), }); // 获取更新后的设备 const [updatedDevice] = await apiClient.database .table("device_instances") .where("id", id); return c.json({ message: "设备更新成功", data: updatedDevice, }); } catch (error) { log.api("更新设备失败:", error); return c.json({ error: "更新设备失败" }, 500); } }); // 删除设备(软删除) deviceInstancesRoutes.delete("/:id", withAuth, async (c) => { try { const id = Number(c.req.param("id")); if (!id || isNaN(id)) { return c.json({ error: "无效的设备ID" }, 400); } const apiClient = c.get('apiClient'); // 检查设备是否存在 const [existingDevice] = await apiClient.database .table("device_instances") .where({ id, is_deleted: DeleteStatus.NOT_DELETED }); if (!existingDevice) { return c.json({ error: "设备不存在" }, 404); } // 软删除设备 await apiClient.database.table("device_instances").where("id", id).update({ is_deleted: DeleteStatus.DELETED, updated_at: apiClient.database.fn.now(), }); return c.json({ message: "设备删除成功", id, }); } catch (error) { log.api("删除设备失败:", error); return c.json({ error: "删除设备失败" }, 500); } }); return deviceInstancesRoutes; }