From 7e6bcd12aef6eceddea06a16fc9c181cadbe5feb Mon Sep 17 00:00:00 2001 From: zaunist Date: Thu, 12 Jun 2025 22:00:12 +0800 Subject: [PATCH 1/2] fix: delete agent or monitor failed --- backend/src/repositories/agent.ts | 70 ++++++++++++--------- backend/src/repositories/monitor.ts | 14 ++--- backend/src/repositories/notification.ts | 55 ++++++++++------ backend/src/services/AgentService.ts | 3 + backend/src/services/MonitorService.ts | 12 +++- backend/src/services/NotificationService.ts | 30 ++++++++- 6 files changed, 124 insertions(+), 60 deletions(-) diff --git a/backend/src/repositories/agent.ts b/backend/src/repositories/agent.ts index 1c1be14..5ac827f 100644 --- a/backend/src/repositories/agent.ts +++ b/backend/src/repositories/agent.ts @@ -32,7 +32,11 @@ export async function getAgentMetricsByIds(agentIds: number[]) { // 获取单个客户端详情 export async function getAgentById(id: number) { - const agent = await db.select().from(agents).where(eq(agents.id, id)).limit(1); + const agent = await db + .select() + .from(agents) + .where(eq(agents.id, id)) + .limit(1); return agent[0]; } @@ -53,19 +57,22 @@ export async function createAgent( // 将 ipAddresses 数组转换为 JSON 字符串 const ipAddressesJson = ipAddresses ? JSON.stringify(ipAddresses) : null; - const result = await db.insert(agents).values({ - name, - token, - created_by: createdBy, - status, - created_at: now, - updated_at: now, - hostname, - ip_addresses: ipAddressesJson, - os, - version, - keepalive, - }).returning(); + const result = await db + .insert(agents) + .values({ + name, + token, + created_by: createdBy, + status, + created_at: now, + updated_at: now, + hostname, + ip_addresses: ipAddressesJson, + os, + version, + keepalive, + }) + .returning(); if (!result) { throw new Error("创建客户端失败"); @@ -74,17 +81,19 @@ export async function createAgent( } // 更新客户端信息 -export async function updateAgent( - agent: Agent -) { +export async function updateAgent(agent: Agent) { agent.updated_at = new Date().toISOString(); - + // 从 agent 对象中排除 id 等索引相关属性,避免更新主键 const { id, token, created_by, ...updateData } = agent; try { // 确保 updateData 中不包含 id - const updatedAgent = await db.update(agents).set(updateData).where(eq(agents.id, id)).returning(); + const updatedAgent = await db + .update(agents) + .set(updateData) + .where(eq(agents.id, id)) + .returning(); return updatedAgent[0]; } catch (error) { console.error("更新客户端失败:", error); @@ -94,12 +103,13 @@ export async function updateAgent( // 删除客户端 export async function deleteAgent(id: number) { - // 先删除关联的指标数据 - await db.delete(agentMetrics24h).where(eq(agentMetrics24h.agent_id, id)); - - const result = await db.delete(agents).where(eq(agents.id, id)); - - if (!result.success) { + try { + // 先删除关联的指标数据 + await db.delete(agentMetrics24h).where(eq(agentMetrics24h.agent_id, id)); + // 再删除客户端 + await db.delete(agents).where(eq(agents.id, id)); + } catch (error) { + console.error("删除客户端失败:", error); throw new Error("删除客户端失败"); } @@ -115,9 +125,9 @@ export async function getAgentByToken(token: string) { // 获取活跃状态的客户端 export async function getActiveAgents() { const activeAgents = await db - .select() - .from(agents) - .where(eq(agents.status, "active")); + .select() + .from(agents) + .where(eq(agents.status, "active")); return activeAgents; } @@ -133,7 +143,9 @@ export async function setAgentInactive(id: number) { // 插入客户端资源指标 export async function insertAgentMetrics(metrics: Metrics[]) { - return await db.batch(metrics.map(metric => db.insert(agentMetrics24h).values(metric))); + return await db.batch( + metrics.map((metric) => db.insert(agentMetrics24h).values(metric)) + ); } // 获取指定客户端资源指标 diff --git a/backend/src/repositories/monitor.ts b/backend/src/repositories/monitor.ts index e1b91af..7c24977 100644 --- a/backend/src/repositories/monitor.ts +++ b/backend/src/repositories/monitor.ts @@ -14,22 +14,18 @@ import { eq, desc, asc, lt } from "drizzle-orm"; // 获取需要检查的监控列表 export async function getMonitorsToCheck() { - // 使用SQL表达式或自定义函数来处理日期计算 - const allmonitors = await db - .select() - .from(monitors) - .execute(); - + const allmonitors = await db.select().from(monitors).execute(); + // 在JavaScript中进行日期计算筛选 const now = new Date().getTime(); const monitorsToCheck = allmonitors.filter((monitor: Monitor) => { if (!monitor.last_checked) return true; // 如果没有检查过,需要检查 - + const lastCheckedTime = new Date(monitor.last_checked).getTime(); const intervalMs = (monitor.interval || 60) * 1000; // 转换为毫秒 - - return now > (lastCheckedTime + intervalMs); + + return now > lastCheckedTime + intervalMs; }); // 解析所有监控的 headers 字段 diff --git a/backend/src/repositories/notification.ts b/backend/src/repositories/notification.ts index 179faaf..31f9326 100644 --- a/backend/src/repositories/notification.ts +++ b/backend/src/repositories/notification.ts @@ -61,7 +61,6 @@ export const updateNotificationChannel = async ( Omit > ): Promise => { - const result = await db .update(notificationChannels) .set({ @@ -245,7 +244,7 @@ export const getGlobalSettings = async (): Promise<{ .select() .from(notificationSettings) .where(eq(notificationSettings.target_type, "global-agent")); - + return { monitorSettings: monitorSettings[0], agentSettings: agentSettings[0], @@ -279,19 +278,19 @@ export const createOrUpdateSettings = async ( settings: Omit ): Promise => { // 确保target_id为0时使用isNull,否则使用eq - const condition = settings.target_id === 0 ? isNull(notificationSettings.target_id) : eq(notificationSettings.target_id, settings.target_id); + const condition = + settings.target_id === 0 + ? isNull(notificationSettings.target_id) + : eq(notificationSettings.target_id, settings.target_id); // 先检查是否已存在相同的设置 const existingSettings = await db .select() .from(notificationSettings) .where( - and( - eq(notificationSettings.target_type, settings.target_type), - condition - ) + and(eq(notificationSettings.target_type, settings.target_type), condition) ); - if (existingSettings.length === 1) { + if (existingSettings.length > 0) { const existingSetting = existingSettings[0]; // 如果已存在则更新 await db @@ -418,29 +417,19 @@ export const getNotificationConfig = async (): Promise => { // 获取所有渠道 const channels = await getNotificationChannels(); - console.log("channels", channels); - // 获取所有模板 const templates = await getNotificationTemplates(); - console.log("templates", templates); - // 获取全局设置 const globalSettings = await getGlobalSettings(); - console.log("globalSettings", globalSettings); - // 获取特定监控项设置 const monitorSettings = await getSpecificSettings("monitor"); - console.log("monitorSettings", monitorSettings); - // 获取特定客户端设置 const agentSettings = await getSpecificSettings("agent"); - console.log("agentSettings", agentSettings); - - // 构建通知配置 + // 构建通知配置 const config: NotificationConfig = { channels: channels, templates: templates, @@ -525,3 +514,31 @@ export const getNotificationConfig = async (): Promise => { return config; }; + +/** + * 删除通知设置 + * @param type 通知类型,"monitor" 或 "agent" + * @param id 目标ID,监控或客户端的ID + * @return {Promise} 删除是否成功 + */ +export const deleteNotificationSettings = async ( + type: "monitor" | "agent", + id: number +): Promise => { + // 执行删除操作 + try { + await db + .delete(notificationSettings) + .where( + and( + eq(notificationSettings.target_type, type), + eq(notificationSettings.target_id, id) + ) + ); + } catch (error) { + console.error("[删除通知设置] 删除通知设置失败:", error); + throw new Error("删除通知设置失败"); + } + + return true; +}; diff --git a/backend/src/services/AgentService.ts b/backend/src/services/AgentService.ts index fa81f18..d57c103 100644 --- a/backend/src/services/AgentService.ts +++ b/backend/src/services/AgentService.ts @@ -128,6 +128,9 @@ export async function deleteAgentService(agentId: number) { throw new Error("客户端不存在"); } + // 删除客户端通知设置 + await AgentRepository.deleteNotificationSettings("agent", agent.id); + // 执行删除客户端 await AgentRepository.deleteAgent(agent.id); diff --git a/backend/src/services/MonitorService.ts b/backend/src/services/MonitorService.ts index a959b0e..66ef14c 100644 --- a/backend/src/services/MonitorService.ts +++ b/backend/src/services/MonitorService.ts @@ -265,7 +265,17 @@ export async function deleteMonitor(id: number) { return { success: false, message: "监控不存在", status: 404 }; } - // 执行删除 + // 执行通知设置删除 + const notificationResult = await NotificationService.deleteNotificationSettings( + "monitor", + id + ); + if (!notificationResult.success) { + console.error("删除监控通知设置失败:", notificationResult.message); + // 继续执行监控删除,不影响主流程 + } + + // 执行monitor删除 const result = await repositories.deleteMonitor(id); if (!result.success) { diff --git a/backend/src/services/NotificationService.ts b/backend/src/services/NotificationService.ts index 092b440..856bc8a 100644 --- a/backend/src/services/NotificationService.ts +++ b/backend/src/services/NotificationService.ts @@ -511,7 +511,7 @@ export async function sendNotification( // 过滤掉不存在的渠道 const validChannels = channels.filter( (ch): ch is models.NotificationChannel => ch !== null - ) + ); console.log( `[发送通知] 有效渠道数量: ${validChannels.length},类型分布:`, @@ -651,7 +651,7 @@ export async function shouldSendNotification( // 获取此对象的特定设置 const specificSettings = await repositories.getSpecificSettings(type, id); - + console.log( `[通知触发检查] 获取到特定设置数量: ${ specificSettings ? specificSettings.length : 0 @@ -777,3 +777,29 @@ export async function shouldSendNotification( return { shouldSend, channels }; } + +/** + * 删除通知设置 + * @param type 通知类型 + * @param id 通知设置ID + */ +export async function deleteNotificationSettings( + type: "monitor" | "agent", + id: number +): Promise<{ success: boolean; message?: string }> { + try { + console.log(`[删除通知设置] 开始删除${type}通知设置,ID=${id}`); + // 执行删除操作 + await repositories.deleteNotificationSettings(type, id); + } catch (error) { + console.error("[删除通知设置] 删除通知设置失败:", error); + return { + success: false, + message: error instanceof Error ? error.message : "删除通知设置失败", + }; + } + return { + success: true, + message: `${type}通知设置删除成功`, + }; +} From 49d03771199503524181e2d3d3e7d2108ff79fc5 Mon Sep 17 00:00:00 2001 From: zaunist Date: Thu, 12 Jun 2025 22:01:40 +0800 Subject: [PATCH 2/2] chore: db migrate --- backend/drizzle/0001_fluffy_pestilence.sql | 7 + backend/drizzle/meta/0001_snapshot.json | 1287 ++++++++++++++++++++ backend/drizzle/meta/_journal.json | 7 + 3 files changed, 1301 insertions(+) create mode 100644 backend/drizzle/0001_fluffy_pestilence.sql create mode 100644 backend/drizzle/meta/0001_snapshot.json diff --git a/backend/drizzle/0001_fluffy_pestilence.sql b/backend/drizzle/0001_fluffy_pestilence.sql new file mode 100644 index 0000000..e54f1d4 --- /dev/null +++ b/backend/drizzle/0001_fluffy_pestilence.sql @@ -0,0 +1,7 @@ +ALTER TABLE `agents` DROP COLUMN `cpu_usage`;--> statement-breakpoint +ALTER TABLE `agents` DROP COLUMN `memory_total`;--> statement-breakpoint +ALTER TABLE `agents` DROP COLUMN `memory_used`;--> statement-breakpoint +ALTER TABLE `agents` DROP COLUMN `disk_total`;--> statement-breakpoint +ALTER TABLE `agents` DROP COLUMN `disk_used`;--> statement-breakpoint +ALTER TABLE `agents` DROP COLUMN `network_rx`;--> statement-breakpoint +ALTER TABLE `agents` DROP COLUMN `network_tx`; \ No newline at end of file diff --git a/backend/drizzle/meta/0001_snapshot.json b/backend/drizzle/meta/0001_snapshot.json new file mode 100644 index 0000000..5c6334c --- /dev/null +++ b/backend/drizzle/meta/0001_snapshot.json @@ -0,0 +1,1287 @@ +{ + "version": "6", + "dialect": "sqlite", + "id": "c3674fd1-f5ba-4032-8da8-b96fc21d8666", + "prevId": "2ca79ae3-64d2-4356-b051-31e89dbc3385", + "tables": { + "agent_metrics_24h": { + "name": "agent_metrics_24h", + "columns": { + "id": { + "name": "id", + "type": "integer", + "primaryKey": true, + "notNull": true, + "autoincrement": true + }, + "agent_id": { + "name": "agent_id", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "timestamp": { + "name": "timestamp", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false, + "default": "'CURRENT_TIMESTAMP'" + }, + "cpu_usage": { + "name": "cpu_usage", + "type": "real", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "cpu_cores": { + "name": "cpu_cores", + "type": "integer", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "cpu_model": { + "name": "cpu_model", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "memory_total": { + "name": "memory_total", + "type": "integer", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "memory_used": { + "name": "memory_used", + "type": "integer", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "memory_free": { + "name": "memory_free", + "type": "integer", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "memory_usage_rate": { + "name": "memory_usage_rate", + "type": "real", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "load_1": { + "name": "load_1", + "type": "real", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "load_5": { + "name": "load_5", + "type": "real", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "load_15": { + "name": "load_15", + "type": "real", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "disk_metrics": { + "name": "disk_metrics", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "network_metrics": { + "name": "network_metrics", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + } + }, + "indexes": {}, + "foreignKeys": { + "agent_metrics_24h_agent_id_agents_id_fk": { + "name": "agent_metrics_24h_agent_id_agents_id_fk", + "tableFrom": "agent_metrics_24h", + "tableTo": "agents", + "columnsFrom": [ + "agent_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "no action", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "checkConstraints": {} + }, + "agents": { + "name": "agents", + "columns": { + "id": { + "name": "id", + "type": "integer", + "primaryKey": true, + "notNull": true, + "autoincrement": true + }, + "name": { + "name": "name", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "token": { + "name": "token", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "created_by": { + "name": "created_by", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "status": { + "name": "status", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false, + "default": "'inactive'" + }, + "created_at": { + "name": "created_at", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "updated_at": { + "name": "updated_at", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "hostname": { + "name": "hostname", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "ip_addresses": { + "name": "ip_addresses", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "os": { + "name": "os", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "version": { + "name": "version", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "keepalive": { + "name": "keepalive", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + } + }, + "indexes": { + "agents_token_unique": { + "name": "agents_token_unique", + "columns": [ + "token" + ], + "isUnique": true + } + }, + "foreignKeys": { + "agents_created_by_users_id_fk": { + "name": "agents_created_by_users_id_fk", + "tableFrom": "agents", + "tableTo": "users", + "columnsFrom": [ + "created_by" + ], + "columnsTo": [ + "id" + ], + "onDelete": "no action", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "checkConstraints": {} + }, + "monitor_daily_stats": { + "name": "monitor_daily_stats", + "columns": { + "id": { + "name": "id", + "type": "integer", + "primaryKey": true, + "notNull": true, + "autoincrement": true + }, + "monitor_id": { + "name": "monitor_id", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "date": { + "name": "date", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "total_checks": { + "name": "total_checks", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": 0 + }, + "up_checks": { + "name": "up_checks", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": 0 + }, + "down_checks": { + "name": "down_checks", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": 0 + }, + "avg_response_time": { + "name": "avg_response_time", + "type": "integer", + "primaryKey": false, + "notNull": false, + "autoincrement": false, + "default": 0 + }, + "min_response_time": { + "name": "min_response_time", + "type": "integer", + "primaryKey": false, + "notNull": false, + "autoincrement": false, + "default": 0 + }, + "max_response_time": { + "name": "max_response_time", + "type": "integer", + "primaryKey": false, + "notNull": false, + "autoincrement": false, + "default": 0 + }, + "availability": { + "name": "availability", + "type": "real", + "primaryKey": false, + "notNull": false, + "autoincrement": false, + "default": 0 + }, + "created_at": { + "name": "created_at", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + } + }, + "indexes": {}, + "foreignKeys": { + "monitor_daily_stats_monitor_id_monitors_id_fk": { + "name": "monitor_daily_stats_monitor_id_monitors_id_fk", + "tableFrom": "monitor_daily_stats", + "tableTo": "monitors", + "columnsFrom": [ + "monitor_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "no action", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "checkConstraints": {} + }, + "monitor_status_history_24h": { + "name": "monitor_status_history_24h", + "columns": { + "id": { + "name": "id", + "type": "integer", + "primaryKey": true, + "notNull": true, + "autoincrement": true + }, + "monitor_id": { + "name": "monitor_id", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "status": { + "name": "status", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "timestamp": { + "name": "timestamp", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false, + "default": "'CURRENT_TIMESTAMP'" + }, + "response_time": { + "name": "response_time", + "type": "integer", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "status_code": { + "name": "status_code", + "type": "integer", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "error": { + "name": "error", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + } + }, + "indexes": {}, + "foreignKeys": { + "monitor_status_history_24h_monitor_id_monitors_id_fk": { + "name": "monitor_status_history_24h_monitor_id_monitors_id_fk", + "tableFrom": "monitor_status_history_24h", + "tableTo": "monitors", + "columnsFrom": [ + "monitor_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "no action", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "checkConstraints": {} + }, + "monitors": { + "name": "monitors", + "columns": { + "id": { + "name": "id", + "type": "integer", + "primaryKey": true, + "notNull": true, + "autoincrement": true + }, + "name": { + "name": "name", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "url": { + "name": "url", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "method": { + "name": "method", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "interval": { + "name": "interval", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "timeout": { + "name": "timeout", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "expected_status": { + "name": "expected_status", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "headers": { + "name": "headers", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "body": { + "name": "body", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "created_by": { + "name": "created_by", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "active": { + "name": "active", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "status": { + "name": "status", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false, + "default": "'pending'" + }, + "response_time": { + "name": "response_time", + "type": "integer", + "primaryKey": false, + "notNull": false, + "autoincrement": false, + "default": 0 + }, + "last_checked": { + "name": "last_checked", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "created_at": { + "name": "created_at", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "updated_at": { + "name": "updated_at", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + } + }, + "indexes": {}, + "foreignKeys": { + "monitors_created_by_users_id_fk": { + "name": "monitors_created_by_users_id_fk", + "tableFrom": "monitors", + "tableTo": "users", + "columnsFrom": [ + "created_by" + ], + "columnsTo": [ + "id" + ], + "onDelete": "no action", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "checkConstraints": {} + }, + "notification_channels": { + "name": "notification_channels", + "columns": { + "id": { + "name": "id", + "type": "integer", + "primaryKey": true, + "notNull": true, + "autoincrement": true + }, + "name": { + "name": "name", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "type": { + "name": "type", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "config": { + "name": "config", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "enabled": { + "name": "enabled", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": 1 + }, + "created_by": { + "name": "created_by", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "created_at": { + "name": "created_at", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false, + "default": "'CURRENT_TIMESTAMP'" + }, + "updated_at": { + "name": "updated_at", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false, + "default": "'CURRENT_TIMESTAMP'" + } + }, + "indexes": {}, + "foreignKeys": { + "notification_channels_created_by_users_id_fk": { + "name": "notification_channels_created_by_users_id_fk", + "tableFrom": "notification_channels", + "tableTo": "users", + "columnsFrom": [ + "created_by" + ], + "columnsTo": [ + "id" + ], + "onDelete": "no action", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "checkConstraints": {} + }, + "notification_history": { + "name": "notification_history", + "columns": { + "id": { + "name": "id", + "type": "integer", + "primaryKey": true, + "notNull": true, + "autoincrement": true + }, + "type": { + "name": "type", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "target_id": { + "name": "target_id", + "type": "integer", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "channel_id": { + "name": "channel_id", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "template_id": { + "name": "template_id", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "status": { + "name": "status", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "content": { + "name": "content", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "error": { + "name": "error", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "sent_at": { + "name": "sent_at", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false, + "default": "'CURRENT_TIMESTAMP'" + } + }, + "indexes": {}, + "foreignKeys": { + "notification_history_channel_id_notification_channels_id_fk": { + "name": "notification_history_channel_id_notification_channels_id_fk", + "tableFrom": "notification_history", + "tableTo": "notification_channels", + "columnsFrom": [ + "channel_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "no action", + "onUpdate": "no action" + }, + "notification_history_template_id_notification_templates_id_fk": { + "name": "notification_history_template_id_notification_templates_id_fk", + "tableFrom": "notification_history", + "tableTo": "notification_templates", + "columnsFrom": [ + "template_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "no action", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "checkConstraints": {} + }, + "notification_settings": { + "name": "notification_settings", + "columns": { + "id": { + "name": "id", + "type": "integer", + "primaryKey": true, + "notNull": true, + "autoincrement": true + }, + "user_id": { + "name": "user_id", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "target_type": { + "name": "target_type", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": "'global'" + }, + "target_id": { + "name": "target_id", + "type": "integer", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "enabled": { + "name": "enabled", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": 1 + }, + "on_down": { + "name": "on_down", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": 1 + }, + "on_recovery": { + "name": "on_recovery", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": 1 + }, + "on_offline": { + "name": "on_offline", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": 1 + }, + "on_cpu_threshold": { + "name": "on_cpu_threshold", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": 0 + }, + "cpu_threshold": { + "name": "cpu_threshold", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": 90 + }, + "on_memory_threshold": { + "name": "on_memory_threshold", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": 0 + }, + "memory_threshold": { + "name": "memory_threshold", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": 85 + }, + "on_disk_threshold": { + "name": "on_disk_threshold", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": 0 + }, + "disk_threshold": { + "name": "disk_threshold", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": 90 + }, + "channels": { + "name": "channels", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false, + "default": "'[]'" + }, + "created_at": { + "name": "created_at", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false, + "default": "'CURRENT_TIMESTAMP'" + }, + "updated_at": { + "name": "updated_at", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false, + "default": "'CURRENT_TIMESTAMP'" + } + }, + "indexes": {}, + "foreignKeys": { + "notification_settings_user_id_users_id_fk": { + "name": "notification_settings_user_id_users_id_fk", + "tableFrom": "notification_settings", + "tableTo": "users", + "columnsFrom": [ + "user_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "no action", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "checkConstraints": {} + }, + "notification_templates": { + "name": "notification_templates", + "columns": { + "id": { + "name": "id", + "type": "integer", + "primaryKey": true, + "notNull": true, + "autoincrement": true + }, + "name": { + "name": "name", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "type": { + "name": "type", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "subject": { + "name": "subject", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "content": { + "name": "content", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "is_default": { + "name": "is_default", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": 0 + }, + "created_by": { + "name": "created_by", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "created_at": { + "name": "created_at", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false, + "default": "'CURRENT_TIMESTAMP'" + }, + "updated_at": { + "name": "updated_at", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false, + "default": "'CURRENT_TIMESTAMP'" + } + }, + "indexes": {}, + "foreignKeys": { + "notification_templates_created_by_users_id_fk": { + "name": "notification_templates_created_by_users_id_fk", + "tableFrom": "notification_templates", + "tableTo": "users", + "columnsFrom": [ + "created_by" + ], + "columnsTo": [ + "id" + ], + "onDelete": "no action", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "checkConstraints": {} + }, + "status_page_agents": { + "name": "status_page_agents", + "columns": { + "config_id": { + "name": "config_id", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "agent_id": { + "name": "agent_id", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false + } + }, + "indexes": {}, + "foreignKeys": { + "status_page_agents_config_id_status_page_config_id_fk": { + "name": "status_page_agents_config_id_status_page_config_id_fk", + "tableFrom": "status_page_agents", + "tableTo": "status_page_config", + "columnsFrom": [ + "config_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "status_page_agents_agent_id_agents_id_fk": { + "name": "status_page_agents_agent_id_agents_id_fk", + "tableFrom": "status_page_agents", + "tableTo": "agents", + "columnsFrom": [ + "agent_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": { + "status_page_agents_config_id_agent_id_pk": { + "columns": [ + "config_id", + "agent_id" + ], + "name": "status_page_agents_config_id_agent_id_pk" + } + }, + "uniqueConstraints": {}, + "checkConstraints": {} + }, + "status_page_config": { + "name": "status_page_config", + "columns": { + "id": { + "name": "id", + "type": "integer", + "primaryKey": true, + "notNull": true, + "autoincrement": true + }, + "user_id": { + "name": "user_id", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "title": { + "name": "title", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": "'系统状态'" + }, + "description": { + "name": "description", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false, + "default": "'系统当前运行状态'" + }, + "logo_url": { + "name": "logo_url", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false, + "default": "''" + }, + "custom_css": { + "name": "custom_css", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false, + "default": "''" + }, + "created_at": { + "name": "created_at", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false, + "default": "'CURRENT_TIMESTAMP'" + }, + "updated_at": { + "name": "updated_at", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false, + "default": "'CURRENT_TIMESTAMP'" + } + }, + "indexes": {}, + "foreignKeys": { + "status_page_config_user_id_users_id_fk": { + "name": "status_page_config_user_id_users_id_fk", + "tableFrom": "status_page_config", + "tableTo": "users", + "columnsFrom": [ + "user_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "no action", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "checkConstraints": {} + }, + "status_page_monitors": { + "name": "status_page_monitors", + "columns": { + "config_id": { + "name": "config_id", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "monitor_id": { + "name": "monitor_id", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false + } + }, + "indexes": {}, + "foreignKeys": { + "status_page_monitors_config_id_status_page_config_id_fk": { + "name": "status_page_monitors_config_id_status_page_config_id_fk", + "tableFrom": "status_page_monitors", + "tableTo": "status_page_config", + "columnsFrom": [ + "config_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "status_page_monitors_monitor_id_monitors_id_fk": { + "name": "status_page_monitors_monitor_id_monitors_id_fk", + "tableFrom": "status_page_monitors", + "tableTo": "monitors", + "columnsFrom": [ + "monitor_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": { + "status_page_monitors_config_id_monitor_id_pk": { + "columns": [ + "config_id", + "monitor_id" + ], + "name": "status_page_monitors_config_id_monitor_id_pk" + } + }, + "uniqueConstraints": {}, + "checkConstraints": {} + }, + "users": { + "name": "users", + "columns": { + "id": { + "name": "id", + "type": "integer", + "primaryKey": true, + "notNull": true, + "autoincrement": true + }, + "username": { + "name": "username", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "password": { + "name": "password", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "email": { + "name": "email", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "role": { + "name": "role", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "created_at": { + "name": "created_at", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "updated_at": { + "name": "updated_at", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + } + }, + "indexes": { + "users_username_unique": { + "name": "users_username_unique", + "columns": [ + "username" + ], + "isUnique": true + } + }, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "checkConstraints": {} + } + }, + "views": {}, + "enums": {}, + "_meta": { + "schemas": {}, + "tables": {}, + "columns": {} + }, + "internal": { + "indexes": {} + } +} \ No newline at end of file diff --git a/backend/drizzle/meta/_journal.json b/backend/drizzle/meta/_journal.json index fb84885..ec97879 100644 --- a/backend/drizzle/meta/_journal.json +++ b/backend/drizzle/meta/_journal.json @@ -8,6 +8,13 @@ "when": 1748308256007, "tag": "0000_romantic_next_avengers", "breakpoints": true + }, + { + "idx": 1, + "version": "6", + "when": 1749736889133, + "tag": "0001_fluffy_pestilence", + "breakpoints": true } ] } \ No newline at end of file