Skip to content

Commit af7a006

Browse files
committed
fix: get notification template error
1 parent a6a9976 commit af7a006

File tree

16 files changed

+9047
-4735
lines changed

16 files changed

+9047
-4735
lines changed

backend/drizzle/meta/0004_snapshot.json

Lines changed: 1345 additions & 0 deletions
Large diffs are not rendered by default.

backend/drizzle/meta/_journal.json

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -33,9 +33,9 @@
3333
{
3434
"idx": 4,
3535
"version": "6",
36-
"when": 1751016668000,
37-
"tag": "0004_lame_mercenary",
36+
"when": 1762361284317,
37+
"tag": "0004_many_avengers",
3838
"breakpoints": true
3939
}
4040
]
41-
}
41+
}

backend/src/db/generated-migrations.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -228,7 +228,7 @@ CREATE INDEX IF NOT EXISTS \`monitor_status_history_24h_monitor_timestamp_idx\`
228228
sql: `CREATE INDEX IF NOT EXISTS \`monitor_status_history_24h_timestamp_idx\` ON \`monitor_status_history_24h\` (\`timestamp\`);`
229229
},
230230
{
231-
name: "0004_lame_mercenary.sql",
231+
name: "0004_many_avengers.sql",
232232
sql: `CREATE TABLE IF NOT EXISTS \`settings\` (
233233
\`key\` text PRIMARY KEY NOT NULL,
234234
\`value\` text

backend/src/db/schema.ts

Lines changed: 144 additions & 77 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,11 @@
1-
import { int, sqliteTable, text, real, primaryKey, index } from "drizzle-orm/sqlite-core";
1+
import {
2+
int,
3+
sqliteTable,
4+
text,
5+
real,
6+
primaryKey,
7+
index,
8+
} from "drizzle-orm/sqlite-core";
29

310
// 用户表
411
export const users = sqliteTable("users", {
@@ -8,7 +15,7 @@ export const users = sqliteTable("users", {
815
email: text("email"),
916
role: text("role").notNull(),
1017
created_at: text("created_at").notNull(),
11-
updated_at: text("updated_at").notNull()
18+
updated_at: text("updated_at").notNull(),
1219
});
1320

1421
// 监控表
@@ -22,54 +29,77 @@ export const monitors = sqliteTable("monitors", {
2229
expected_status: int("expected_status").notNull(),
2330
headers: text("headers").notNull(),
2431
body: text("body"),
25-
created_by: int("created_by").notNull().references(() => users.id),
32+
created_by: int("created_by")
33+
.notNull()
34+
.references(() => users.id),
2635
active: int("active").notNull(), // SQLite 没有布尔类型,用 int 代替
2736
status: text("status").default("pending"),
2837
response_time: int("response_time").default(0),
2938
last_checked: text("last_checked"),
3039
created_at: text("created_at").notNull(),
31-
updated_at: text("updated_at").notNull()
40+
updated_at: text("updated_at").notNull(),
3241
});
3342

3443
// 24小时监控状态历史表
35-
export const monitorStatusHistory24h = sqliteTable("monitor_status_history_24h", {
36-
id: int("id").primaryKey({ autoIncrement: true }),
37-
monitor_id: int("monitor_id").notNull().references(() => monitors.id),
38-
status: text("status").notNull(),
39-
timestamp: text("timestamp").default("CURRENT_TIMESTAMP"),
40-
response_time: int("response_time"),
41-
status_code: int("status_code"),
42-
error: text("error")
43-
}, (table) => ({
44-
// monitor_id 和 timestamp 的联合索引,用于优化按监控项和时间查询的性能
45-
monitorTimestampIdx: index("monitor_status_history_24h_monitor_timestamp_idx").on(table.monitor_id, table.timestamp),
46-
// timestamp 单独索引,用于优化按时间排序和范围查询的性能
47-
timestampIdx: index("monitor_status_history_24h_timestamp_idx").on(table.timestamp)
48-
}));
44+
export const monitorStatusHistory24h = sqliteTable(
45+
"monitor_status_history_24h",
46+
{
47+
id: int("id").primaryKey({ autoIncrement: true }),
48+
monitor_id: int("monitor_id")
49+
.notNull()
50+
.references(() => monitors.id),
51+
status: text("status").notNull(),
52+
timestamp: text("timestamp").default("CURRENT_TIMESTAMP"),
53+
response_time: int("response_time"),
54+
status_code: int("status_code"),
55+
error: text("error"),
56+
},
57+
(table) => ({
58+
// monitor_id 和 timestamp 的联合索引,用于优化按监控项和时间查询的性能
59+
monitorTimestampIdx: index(
60+
"monitor_status_history_24h_monitor_timestamp_idx"
61+
).on(table.monitor_id, table.timestamp),
62+
// timestamp 单独索引,用于优化按时间排序和范围查询的性能
63+
timestampIdx: index("monitor_status_history_24h_timestamp_idx").on(
64+
table.timestamp
65+
),
66+
})
67+
);
4968

5069
// 监控每日统计表
51-
export const monitorDailyStats = sqliteTable("monitor_daily_stats", {
52-
id: int("id").primaryKey({ autoIncrement: true }),
53-
monitor_id: int("monitor_id").notNull().references(() => monitors.id),
54-
date: text("date").notNull(),
55-
total_checks: int("total_checks").notNull().default(0),
56-
up_checks: int("up_checks").notNull().default(0),
57-
down_checks: int("down_checks").notNull().default(0),
58-
avg_response_time: int("avg_response_time").default(0),
59-
min_response_time: int("min_response_time").default(0),
60-
max_response_time: int("max_response_time").default(0),
61-
availability: real("availability").default(0),
62-
created_at: text("created_at").notNull()
63-
}, (table) => ({
64-
monitorDateIdx: index("monitor_daily_stats_monitor_id_date_idx").on(table.monitor_id, table.date)
65-
}));
70+
export const monitorDailyStats = sqliteTable(
71+
"monitor_daily_stats",
72+
{
73+
id: int("id").primaryKey({ autoIncrement: true }),
74+
monitor_id: int("monitor_id")
75+
.notNull()
76+
.references(() => monitors.id),
77+
date: text("date").notNull(),
78+
total_checks: int("total_checks").notNull().default(0),
79+
up_checks: int("up_checks").notNull().default(0),
80+
down_checks: int("down_checks").notNull().default(0),
81+
avg_response_time: int("avg_response_time").default(0),
82+
min_response_time: int("min_response_time").default(0),
83+
max_response_time: int("max_response_time").default(0),
84+
availability: real("availability").default(0),
85+
created_at: text("created_at").notNull(),
86+
},
87+
(table) => ({
88+
monitorDateIdx: index("monitor_daily_stats_monitor_id_date_idx").on(
89+
table.monitor_id,
90+
table.date
91+
),
92+
})
93+
);
6694

6795
// 客户端表
6896
export const agents = sqliteTable("agents", {
6997
id: int("id").primaryKey({ autoIncrement: true }),
7098
name: text("name").notNull(),
7199
token: text("token").notNull().unique(),
72-
created_by: int("created_by").notNull().references(() => users.id),
100+
created_by: int("created_by")
101+
.notNull()
102+
.references(() => users.id),
73103
status: text("status").default("inactive"),
74104
created_at: text("created_at").notNull(),
75105
updated_at: text("updated_at").notNull(),
@@ -81,54 +111,81 @@ export const agents = sqliteTable("agents", {
81111
});
82112

83113
// 客户端资源指标表
84-
export const agentMetrics24h = sqliteTable("agent_metrics_24h", {
85-
id: int("id").primaryKey({ autoIncrement: true }),
86-
agent_id: int("agent_id").notNull().references(() => agents.id),
87-
timestamp: text("timestamp").default("CURRENT_TIMESTAMP"),
88-
cpu_usage: real("cpu_usage"),
89-
cpu_cores: int("cpu_cores"),
90-
cpu_model: text("cpu_model"),
91-
memory_total: int("memory_total"),
92-
memory_used: int("memory_used"),
93-
memory_free: int("memory_free"),
94-
memory_usage_rate: real("memory_usage_rate"),
95-
load_1: real("load_1"),
96-
load_5: real("load_5"),
97-
load_15: real("load_15"),
98-
disk_metrics: text("disk_metrics"),
99-
network_metrics: text("network_metrics")
100-
}, (table) => ({
101-
// agent_id 和 timestamp 的联合索引,用于优化按代理和时间查询的性能
102-
agentTimestampIdx: index("agent_metrics_24h_agent_timestamp_idx").on(table.agent_id, table.timestamp)
103-
}));
114+
export const agentMetrics24h = sqliteTable(
115+
"agent_metrics_24h",
116+
{
117+
id: int("id").primaryKey({ autoIncrement: true }),
118+
agent_id: int("agent_id")
119+
.notNull()
120+
.references(() => agents.id),
121+
timestamp: text("timestamp").default("CURRENT_TIMESTAMP"),
122+
cpu_usage: real("cpu_usage"),
123+
cpu_cores: int("cpu_cores"),
124+
cpu_model: text("cpu_model"),
125+
memory_total: int("memory_total"),
126+
memory_used: int("memory_used"),
127+
memory_free: int("memory_free"),
128+
memory_usage_rate: real("memory_usage_rate"),
129+
load_1: real("load_1"),
130+
load_5: real("load_5"),
131+
load_15: real("load_15"),
132+
disk_metrics: text("disk_metrics"),
133+
network_metrics: text("network_metrics"),
134+
},
135+
(table) => ({
136+
// agent_id 和 timestamp 的联合索引,用于优化按代理和时间查询的性能
137+
agentTimestampIdx: index("agent_metrics_24h_agent_timestamp_idx").on(
138+
table.agent_id,
139+
table.timestamp
140+
),
141+
})
142+
);
104143

105144
// 状态页配置表
106145
export const statusPageConfig = sqliteTable("status_page_config", {
107146
id: int("id").primaryKey({ autoIncrement: true }),
108-
user_id: int("user_id").notNull().references(() => users.id),
147+
user_id: int("user_id")
148+
.notNull()
149+
.references(() => users.id),
109150
title: text("title").notNull().default("系统状态"),
110151
description: text("description").default("系统当前运行状态"),
111152
logo_url: text("logo_url").default(""),
112153
custom_css: text("custom_css").default(""),
113154
created_at: text("created_at").default("CURRENT_TIMESTAMP"),
114-
updated_at: text("updated_at").default("CURRENT_TIMESTAMP")
155+
updated_at: text("updated_at").default("CURRENT_TIMESTAMP"),
115156
});
116157

117158
// 状态页监控项关联表
118-
export const statusPageMonitors = sqliteTable("status_page_monitors", {
119-
config_id: int("config_id").notNull().references(() => statusPageConfig.id, { onDelete: "cascade" }),
120-
monitor_id: int("monitor_id").notNull().references(() => monitors.id, { onDelete: "cascade" }),
121-
}, (table) => ({
122-
pk: primaryKey({ columns: [table.config_id, table.monitor_id] })
123-
}));
159+
export const statusPageMonitors = sqliteTable(
160+
"status_page_monitors",
161+
{
162+
config_id: int("config_id")
163+
.notNull()
164+
.references(() => statusPageConfig.id, { onDelete: "cascade" }),
165+
monitor_id: int("monitor_id")
166+
.notNull()
167+
.references(() => monitors.id, { onDelete: "cascade" }),
168+
},
169+
(table) => ({
170+
pk: primaryKey({ columns: [table.config_id, table.monitor_id] }),
171+
})
172+
);
124173

125174
// 状态页客户端关联表
126-
export const statusPageAgents = sqliteTable("status_page_agents", {
127-
config_id: int("config_id").notNull().references(() => statusPageConfig.id, { onDelete: "cascade" }),
128-
agent_id: int("agent_id").notNull().references(() => agents.id, { onDelete: "cascade" }),
129-
}, (table) => ({
130-
pk: primaryKey({ columns: [table.config_id, table.agent_id] })
131-
}));
175+
export const statusPageAgents = sqliteTable(
176+
"status_page_agents",
177+
{
178+
config_id: int("config_id")
179+
.notNull()
180+
.references(() => statusPageConfig.id, { onDelete: "cascade" }),
181+
agent_id: int("agent_id")
182+
.notNull()
183+
.references(() => agents.id, { onDelete: "cascade" }),
184+
},
185+
(table) => ({
186+
pk: primaryKey({ columns: [table.config_id, table.agent_id] }),
187+
})
188+
);
132189

133190
// 通知渠道表
134191
export const notificationChannels = sqliteTable("notification_channels", {
@@ -137,9 +194,11 @@ export const notificationChannels = sqliteTable("notification_channels", {
137194
type: text("type").notNull(),
138195
config: text("config").notNull(),
139196
enabled: int("enabled").notNull().default(1),
140-
created_by: int("created_by").notNull().references(() => users.id),
197+
created_by: int("created_by")
198+
.notNull()
199+
.references(() => users.id),
141200
created_at: text("created_at").default("CURRENT_TIMESTAMP"),
142-
updated_at: text("updated_at").default("CURRENT_TIMESTAMP")
201+
updated_at: text("updated_at").default("CURRENT_TIMESTAMP"),
143202
});
144203

145204
// 通知模板表
@@ -150,15 +209,19 @@ export const notificationTemplates = sqliteTable("notification_templates", {
150209
subject: text("subject").notNull(),
151210
content: text("content").notNull(),
152211
is_default: int("is_default").notNull().default(0),
153-
created_by: int("created_by").notNull().references(() => users.id),
212+
created_by: int("created_by")
213+
.notNull()
214+
.references(() => users.id),
154215
created_at: text("created_at").default("CURRENT_TIMESTAMP"),
155-
updated_at: text("updated_at").default("CURRENT_TIMESTAMP")
216+
updated_at: text("updated_at").default("CURRENT_TIMESTAMP"),
156217
});
157218

158219
// 通知设置表
159220
export const notificationSettings = sqliteTable("notification_settings", {
160221
id: int("id").primaryKey({ autoIncrement: true }),
161-
user_id: int("user_id").notNull().references(() => users.id),
222+
user_id: int("user_id")
223+
.notNull()
224+
.references(() => users.id),
162225
target_type: text("target_type").notNull().default("global"),
163226
target_id: int("target_id"),
164227
enabled: int("enabled").notNull().default(1),
@@ -173,20 +236,24 @@ export const notificationSettings = sqliteTable("notification_settings", {
173236
disk_threshold: int("disk_threshold").notNull().default(90),
174237
channels: text("channels").default("[]"),
175238
created_at: text("created_at").default("CURRENT_TIMESTAMP"),
176-
updated_at: text("updated_at").default("CURRENT_TIMESTAMP")
239+
updated_at: text("updated_at").default("CURRENT_TIMESTAMP"),
177240
});
178241

179242
// 通知历史记录表
180243
export const notificationHistory = sqliteTable("notification_history", {
181244
id: int("id").primaryKey({ autoIncrement: true }),
182245
type: text("type").notNull(),
183246
target_id: int("target_id"),
184-
channel_id: int("channel_id").notNull().references(() => notificationChannels.id),
185-
template_id: int("template_id").notNull().references(() => notificationTemplates.id),
247+
channel_id: int("channel_id")
248+
.notNull()
249+
.references(() => notificationChannels.id),
250+
template_id: int("template_id")
251+
.notNull()
252+
.references(() => notificationTemplates.id),
186253
status: text("status").notNull(),
187254
content: text("content").notNull(),
188255
error: text("error"),
189-
sent_at: text("sent_at").default("CURRENT_TIMESTAMP")
256+
sent_at: text("sent_at").default("CURRENT_TIMESTAMP"),
190257
});
191258

192259
// 新增:应用设置表

backend/src/repositories/notification.ts

Lines changed: 27 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -182,15 +182,35 @@ export const updateNotificationTemplate = async (
182182
Omit<NotificationTemplate, "id" | "created_at" | "updated_at">
183183
>
184184
): Promise<boolean> => {
185+
const updateData: Partial<typeof notificationTemplates.$inferInsert> = {};
186+
187+
if (template.name !== undefined) {
188+
updateData.name = template.name;
189+
}
190+
191+
if (template.type !== undefined) {
192+
updateData.type = template.type;
193+
}
194+
195+
if (template.subject !== undefined) {
196+
updateData.subject = template.subject;
197+
}
198+
199+
if (template.content !== undefined) {
200+
updateData.content = template.content;
201+
}
202+
203+
if (template.is_default !== undefined) {
204+
updateData.is_default = template.is_default ? 1 : 0;
205+
}
206+
207+
if (Object.keys(updateData).length === 0) {
208+
return true; // 没有需要更新的字段时视为成功
209+
}
210+
185211
const result = await db
186212
.update(notificationTemplates)
187-
.set({
188-
name: template.name,
189-
type: template.type,
190-
subject: template.subject,
191-
content: template.content,
192-
is_default: template.is_default ? 1 : 0,
193-
})
213+
.set(updateData)
194214
.where(and(eq(notificationTemplates.id, id), eq(notificationTemplates.created_by, userId)));
195215

196216
return result.success; // fix: 返回 success 布尔值

0 commit comments

Comments
 (0)