Skip to content

Commit 3b7da47

Browse files
authored
Merge pull request #73 from gujiangjiang/main
feat: 为新用户添加默认的通知渠道和消息模板、完善PWA应用
2 parents e1604da + 7290a86 commit 3b7da47

File tree

14 files changed

+1778
-1847
lines changed

14 files changed

+1778
-1847
lines changed

.github/workflows/deploy.yml

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -72,9 +72,21 @@ jobs:
7272
D1_DATABASE_ID: ${{ secrets.D1_DATABASE_ID }}
7373
D1_DATABASE_NAME: ${{ secrets.D1_DATABASE_NAME }}
7474

75+
# 新增步骤:检查 Cloudflare 密钥是否存在
76+
- name: Check for Cloudflare credentials
77+
id: cf_creds
78+
run: |
79+
if [ -z "${{ secrets.CF_API_TOKEN }}" ] || [ -z "${{ secrets.CF_ACCOUNT_ID }}" ]; then
80+
echo "Cloudflare credentials not found, skipping deployment."
81+
echo "has_creds=false" >> $GITHUB_ENV
82+
else
83+
echo "has_creds=true" >> $GITHUB_ENV
84+
fi
85+
7586
# 第八步:部署到 Cloudflare
76-
# 使用 Cloudflare 官方的 'wrangler-action' 来执行部署
87+
# 仅在检测到密钥存在时执行
7788
- name: Deploy to Cloudflare
89+
if: env.has_creds == 'true'
7890
uses: cloudflare/wrangler-action@v3
7991
with:
8092
# 传入 API 令牌用于身份验证

.github/workflows/docker-build.yml

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,14 +18,26 @@ jobs:
1818
-
1919
name: Set up Docker Buildx
2020
uses: docker/setup-buildx-action@v2
21+
-
22+
name: Check for Docker Hub credentials
23+
id: docker_creds
24+
run: |
25+
if [ -z "${{ secrets.DOCKERHUB_USERNAME }}" ] || [ -z "${{ secrets.DOCKERHUB_TOKEN }}" ]; then
26+
echo "Docker Hub credentials not found, skipping login and push."
27+
echo "has_creds=false" >> $GITHUB_ENV
28+
else
29+
echo "has_creds=true" >> $GITHUB_ENV
30+
fi
2131
-
2232
name: Login to Docker Hub
33+
if: env.has_creds == 'true'
2334
uses: docker/login-action@v2
2435
with:
2536
username: ${{ secrets.DOCKERHUB_USERNAME }}
2637
password: ${{ secrets.DOCKERHUB_TOKEN }}
2738
-
2839
name: Build and push
40+
if: env.has_creds == 'true'
2941
uses: docker/build-push-action@v3
3042
with:
3143
context: .

backend/src/repositories/notification.ts

Lines changed: 2 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -182,41 +182,6 @@ export const updateNotificationTemplate = async (
182182
Omit<NotificationTemplate, "id" | "created_at" | "updated_at">
183183
>
184184
): Promise<boolean> => {
185-
const sets: string[] = [];
186-
const values: any[] = [];
187-
188-
if (template.name !== undefined) {
189-
sets.push("name = ?");
190-
values.push(template.name);
191-
}
192-
193-
if (template.type !== undefined) {
194-
sets.push("type = ?");
195-
values.push(template.type);
196-
}
197-
198-
if (template.subject !== undefined) {
199-
sets.push("subject = ?");
200-
values.push(template.subject);
201-
}
202-
203-
if (template.content !== undefined) {
204-
sets.push("content = ?");
205-
values.push(template.content);
206-
}
207-
208-
if (template.is_default !== undefined) {
209-
sets.push("is_default = ?");
210-
values.push(template.is_default ? 1 : 0);
211-
}
212-
213-
if (sets.length === 0) {
214-
return false;
215-
}
216-
217-
sets.push("updated_at = CURRENT_TIMESTAMP");
218-
values.push(id);
219-
220185
const result = await db
221186
.update(notificationTemplates)
222187
.set({
@@ -228,7 +193,7 @@ export const updateNotificationTemplate = async (
228193
})
229194
.where(and(eq(notificationTemplates.id, id), eq(notificationTemplates.created_by, userId)));
230195

231-
return result.length > 0;
196+
return result.success; // fix: 返回 success 布尔值
232197
};
233198

234199
// 删除通知模板
@@ -240,7 +205,7 @@ export const deleteNotificationTemplate = async (
240205
.delete(notificationTemplates)
241206
.where(and(eq(notificationTemplates.id, id), eq(notificationTemplates.created_by, userId)));
242207

243-
return result.length > 0;
208+
return result.success; // fix: 返回 success 布尔值
244209
};
245210

246211

backend/src/services/AuthService.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import * as repositories from "../repositories";
99
import { getJwtSecret } from "../utils/jwt";
1010
import { Bindings } from "../models/db";
1111
import * as SettingsService from "./SettingsService";
12+
import * as NotificationService from "./NotificationService";
1213

1314
/**
1415
* 用户登录
@@ -143,6 +144,11 @@ export async function registerUser(
143144
"user"
144145
);
145146

147+
// 为新用户创建默认的通知设置
148+
if (newUser && newUser.id) {
149+
await NotificationService.createDefaultNotificationSettingsForUser(newUser.id);
150+
}
151+
146152
return {
147153
success: true,
148154
message: "注册成功",

backend/src/services/NotificationService.ts

Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -998,3 +998,85 @@ export async function deleteNotificationSettings(
998998
message: `${type}通知设置删除成功`,
999999
};
10001000
}
1001+
1002+
/**
1003+
* 为新用户创建默认的通知设置
1004+
* @param userId 新用户的ID
1005+
*/
1006+
export async function createDefaultNotificationSettingsForUser(userId: number): Promise<void> {
1007+
try {
1008+
console.log(`为新用户 ${userId} 创建默认通知设置...`);
1009+
const now = new Date().toISOString();
1010+
1011+
// 创建默认通知模板
1012+
await repositories.createNotificationTemplate({
1013+
name: "Monitor监控模板",
1014+
type: "monitor",
1015+
subject: "【${status}】${name} 监控状态变更",
1016+
content:
1017+
"🔔 网站监控状态变更通知\n\n📊 服务: ${name}\n🔄 状态: ${status} (之前: ${previous_status})\n🕒 时间: ${time}\n\n🔗 地址: ${url}\n⏱️ 响应时间: ${response_time}\n📝 实际状态码: ${status_code}\n🎯 期望状态码: ${expected_status}\n\n❗ 错误信息: ${error}",
1018+
is_default: true, // 修复: 将 1 修改为 true
1019+
created_by: userId,
1020+
});
1021+
1022+
await repositories.createNotificationTemplate({
1023+
name: "Agent监控模板",
1024+
type: "agent",
1025+
subject: "【${status}】${name} 客户端状态变更",
1026+
content:
1027+
"🔔 客户端状态变更通知\n\n📊 主机: ${name}\n🔄 状态: ${status} (之前: ${previous_status})\n🕒 时间: ${time}\n\n🖥️ 主机信息:\n 主机名: ${hostname}\n IP地址: ${ip_addresses}\n 操作系统: ${os}\n\n❗ 错误信息: ${error}",
1028+
is_default: true, // 修复: 将 1 修改为 true
1029+
created_by: userId,
1030+
});
1031+
1032+
// 创建默认通知渠道
1033+
const defaultChannelId = await repositories.createNotificationChannel({
1034+
name: "默认Telegram通知渠道",
1035+
type: "telegram",
1036+
config:
1037+
'{"botToken": "8163201319:AAGyY7FtdaRb6o8NCVXSbBUb6ofDK45cNJU", "chatId": "-1002608818360"}',
1038+
enabled: true,
1039+
created_by: userId,
1040+
});
1041+
1042+
// 创建默认通知设置
1043+
await repositories.createOrUpdateSettings({
1044+
user_id: userId,
1045+
target_type: "global-monitor",
1046+
target_id: 0,
1047+
enabled: false,
1048+
on_down: true,
1049+
on_recovery: true,
1050+
on_offline: true, // 确保所有布尔字段都有值
1051+
on_cpu_threshold: false,
1052+
cpu_threshold: 90,
1053+
on_memory_threshold: false,
1054+
memory_threshold: 85,
1055+
on_disk_threshold: false,
1056+
disk_threshold: 90,
1057+
channels: JSON.stringify([defaultChannelId]),
1058+
});
1059+
1060+
await repositories.createOrUpdateSettings({
1061+
user_id: userId,
1062+
target_type: "global-agent",
1063+
target_id: 0,
1064+
enabled: false,
1065+
on_down: true,
1066+
on_recovery: true,
1067+
on_offline: true,
1068+
on_cpu_threshold: true,
1069+
cpu_threshold: 80,
1070+
on_memory_threshold: true,
1071+
memory_threshold: 80,
1072+
on_disk_threshold: true,
1073+
disk_threshold: 90,
1074+
channels: JSON.stringify([defaultChannelId]),
1075+
});
1076+
1077+
console.log(`为新用户 ${userId} 创建默认通知设置成功`);
1078+
} catch (error) {
1079+
console.error(`为新用户 ${userId} 创建默认通知设置失败:`, error);
1080+
// 此处不向上抛出异常,以免影响用户创建的主流程
1081+
}
1082+
}

backend/src/services/UserService.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import { compare, hash } from "bcryptjs";
22
import * as repositories from "../repositories";
3+
import * as NotificationService from "./NotificationService"; // 导入通知服务
34

45
export async function getAllUsersService(userRole: string) {
56
try {
@@ -91,6 +92,11 @@ export async function createUserService(
9192
userData.role
9293
);
9394

95+
// 为新用户创建默认的通知设置
96+
if (newUser && newUser.id) {
97+
await NotificationService.createDefaultNotificationSettingsForUser(newUser.id);
98+
}
99+
94100
return { success: true, user: newUser, status: 201 };
95101
} catch (error) {
96102
console.error("创建用户错误:", error);

frontend/index.html

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
<link rel="icon" type="image/png" sizes="32x32" href="/favicon-32x32.png" />
77
<link rel="icon" type="image/png" sizes="16x16" href="/favicon-16x16.png" />
88
<link rel="apple-touch-icon" sizes="180x180" href="/apple-touch-icon.png" />
9-
<link rel="manifest" href="/manifest.webmanifest" />
9+
<!-- 移除了 manifest 链接,插件会自动注入 -->
1010
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
1111
<title>XUGOU - 轻量化监控平台</title>
1212
</head>

frontend/package.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,7 @@
6161
"globals": "^13.24.0",
6262
"tw-animate-css": "^1.3.0",
6363
"typescript": "~5.1.6",
64-
"vite": "^6.0.0"
64+
"vite": "^6.0.0",
65+
"vite-plugin-pwa": "^0.20.1"
6566
}
6667
}

frontend/public/sw.js

Lines changed: 16 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,20 @@
1-
self.addEventListener("install", (event) => {
1+
// 这个文件可以保留为空,或者删除。
2+
// vite-plugin-pwa 会在构建时自动生成新的 sw.js 文件到输出目录(dist)。
3+
// 开发环境中,为了避免旧的 Service Worker 缓存导致问题,我们最好确保它被正确地注销。
4+
// 如果您在开发时遇到缓存问题,可以取消下面代码的注释来强制注销。
5+
6+
/*
7+
self.addEventListener('install', (e) => {
28
self.skipWaiting();
39
});
410
5-
self.addEventListener("activate", (event) => {
6-
self.clients.claim();
11+
self.addEventListener('activate', (e) => {
12+
e.waitUntil(
13+
self.registration.unregister().then(() => {
14+
return self.clients.matchAll();
15+
}).then(clients => {
16+
clients.forEach(client => client.navigate(client.url));
17+
})
18+
);
719
});
8-
9-
self.addEventListener("fetch", (event) => {
10-
event.respondWith(fetch(event.request));
11-
});
20+
*/

frontend/src/i18n/en-US.ts

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -516,6 +516,21 @@ const enUS = {
516516
"notifications.save.error": "Failed to save notification settings",
517517
"notifications.globalSettings.description": "Configure global notification settings, including notification channels, monitor settings, and message templates. These settings will apply to all monitors and agents unless overridden by specific configurations.",
518518

519+
// Notification Variables
520+
"notifications.variables.name": "Name",
521+
"notifications.variables.status": "Status",
522+
"notifications.variables.previous_status": "Previous Status",
523+
"notifications.variables.time": "Time",
524+
"notifications.variables.url": "URL",
525+
"notifications.variables.response_time": "Response Time",
526+
"notifications.variables.status_code": "Status Code",
527+
"notifications.variables.expected_status": "Expected Status",
528+
"notifications.variables.error": "Error",
529+
"notifications.variables.details": "Details",
530+
"notifications.variables.hostname": "Hostname",
531+
"notifications.variables.ip_addresses": "IP Addresses",
532+
"notifications.variables.os": "Operating System",
533+
519534
// Notification Event Types
520535
"notifications.events.onDownOnly": "Send notification only when service goes down",
521536
"notifications.events.onRecovery": "Send notification when service recovers",
@@ -565,7 +580,15 @@ const enUS = {
565580

566581
// StatusSummaryCard Component
567582
"statusSummary.title": "Status Summary",
583+
584+
//补全
585+
"notifications.fetch.error": "Failed to fetch notification configuration.",
586+
"notifications.templates.createSuccess": "Template created successfully.",
587+
"notifications.templates.updateSuccess": "Template updated successfully.",
588+
"notifications.templates.deleteConfirmTitle": "Confirm Delete",
589+
"notifications.templates.deleteConfirmMessage": "Are you sure you want to delete this template?",
590+
"notifications.templates.deleteSuccess": "Template deleted successfully."
568591
},
569592
};
570593

571-
export default enUS;
594+
export default enUS;

0 commit comments

Comments
 (0)