From 14a8a308c50c44251ca01efaefc452fe4367e308 Mon Sep 17 00:00:00 2001 From: AoXuan Date: Sat, 27 Sep 2025 16:54:50 +0800 Subject: [PATCH] =?UTF-8?q?refactor(notify):=20=E9=87=8D=E6=9E=84=E9=80=9A?= =?UTF-8?q?=E7=9F=A5=E8=AE=BE=E7=BD=AE=EF=BC=8C=E6=94=AF=E6=8C=81=E8=87=AA?= =?UTF-8?q?=E5=AE=9A=E4=B9=89Webhook=E7=AE=A1=E7=90=86=E4=B8=8E=E6=A8=A1?= =?UTF-8?q?=E6=9D=BF=E9=85=8D=E7=BD=AE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- frontend/src/api/index.ts | 10 +- frontend/src/api/models/CustomWebhook.ts | 35 ++ ...erConfig.ts => GeneralUserConfig_Input.ts} | 2 +- .../api/models/GeneralUserConfig_Output.ts | 22 + ...{GlobalConfig.ts => GlobalConfig_Input.ts} | 2 +- .../src/api/models/GlobalConfig_Notify.ts | 9 +- .../src/api/models/GlobalConfig_Output.ts | 37 ++ ...aaUserConfig.ts => MaaUserConfig_Input.ts} | 2 +- .../src/api/models/MaaUserConfig_Output.ts | 27 + frontend/src/api/models/SettingGetOut.ts | 4 +- frontend/src/api/models/SettingUpdateIn.ts | 4 +- frontend/src/api/models/UserConfig_Notify.ts | 9 +- frontend/src/api/models/UserCreateOut.ts | 6 +- frontend/src/api/models/UserGetOut.ts | 6 +- frontend/src/api/models/UserUpdateIn.ts | 6 +- frontend/src/api/services/Service.ts | 80 +++ frontend/src/components/WebhookManager.vue | 524 ++++++++++++++++++ frontend/src/composables/useScriptApi.ts | 6 +- frontend/src/types/script.ts | 11 +- frontend/src/types/settings.ts | 14 +- frontend/src/utils/webhookTemplates.ts | 119 ++++ frontend/src/views/GeneralUserEdit.vue | 511 +++++++++-------- frontend/src/views/MAAUserEdit.vue | 55 +- .../views/MAAUserEdit/NotifyConfigSection.vue | 38 +- frontend/src/views/setting/TabNotify.vue | 54 +- frontend/src/views/setting/index.vue | 3 +- 26 files changed, 1207 insertions(+), 389 deletions(-) create mode 100644 frontend/src/api/models/CustomWebhook.ts rename frontend/src/api/models/{GeneralUserConfig.ts => GeneralUserConfig_Input.ts} (93%) create mode 100644 frontend/src/api/models/GeneralUserConfig_Output.ts rename frontend/src/api/models/{GlobalConfig.ts => GlobalConfig_Input.ts} (96%) create mode 100644 frontend/src/api/models/GlobalConfig_Output.ts rename frontend/src/api/models/{MaaUserConfig.ts => MaaUserConfig_Input.ts} (95%) create mode 100644 frontend/src/api/models/MaaUserConfig_Output.ts create mode 100644 frontend/src/components/WebhookManager.vue create mode 100644 frontend/src/utils/webhookTemplates.ts diff --git a/frontend/src/api/index.ts b/frontend/src/api/index.ts index 8bdd32b..7338ec1 100644 --- a/frontend/src/api/index.ts +++ b/frontend/src/api/index.ts @@ -9,19 +9,22 @@ export type { OpenAPIConfig } from './core/OpenAPI'; export type { ComboBoxItem } from './models/ComboBoxItem'; export type { ComboBoxOut } from './models/ComboBoxOut'; +export type { CustomWebhook } from './models/CustomWebhook'; export type { DispatchIn } from './models/DispatchIn'; export type { GeneralConfig } from './models/GeneralConfig'; export type { GeneralConfig_Game } from './models/GeneralConfig_Game'; export type { GeneralConfig_Info } from './models/GeneralConfig_Info'; export type { GeneralConfig_Run } from './models/GeneralConfig_Run'; export type { GeneralConfig_Script } from './models/GeneralConfig_Script'; -export type { GeneralUserConfig } from './models/GeneralUserConfig'; export type { GeneralUserConfig_Data } from './models/GeneralUserConfig_Data'; export type { GeneralUserConfig_Info } from './models/GeneralUserConfig_Info'; +export type { GeneralUserConfig_Input } from './models/GeneralUserConfig_Input'; +export type { GeneralUserConfig_Output } from './models/GeneralUserConfig_Output'; export { GetStageIn } from './models/GetStageIn'; -export type { GlobalConfig } from './models/GlobalConfig'; export type { GlobalConfig_Function } from './models/GlobalConfig_Function'; +export type { GlobalConfig_Input } from './models/GlobalConfig_Input'; export type { GlobalConfig_Notify } from './models/GlobalConfig_Notify'; +export type { GlobalConfig_Output } from './models/GlobalConfig_Output'; export type { GlobalConfig_Start } from './models/GlobalConfig_Start'; export type { GlobalConfig_UI } from './models/GlobalConfig_UI'; export type { GlobalConfig_Update } from './models/GlobalConfig_Update'; @@ -40,9 +43,10 @@ export type { MaaConfig_Run } from './models/MaaConfig_Run'; export type { MaaPlanConfig } from './models/MaaPlanConfig'; export type { MaaPlanConfig_Info } from './models/MaaPlanConfig_Info'; export type { MaaPlanConfig_Item } from './models/MaaPlanConfig_Item'; -export type { MaaUserConfig } from './models/MaaUserConfig'; export type { MaaUserConfig_Data } from './models/MaaUserConfig_Data'; export type { MaaUserConfig_Info } from './models/MaaUserConfig_Info'; +export type { MaaUserConfig_Input } from './models/MaaUserConfig_Input'; +export type { MaaUserConfig_Output } from './models/MaaUserConfig_Output'; export type { MaaUserConfig_Task } from './models/MaaUserConfig_Task'; export type { NoticeOut } from './models/NoticeOut'; export type { OutBase } from './models/OutBase'; diff --git a/frontend/src/api/models/CustomWebhook.ts b/frontend/src/api/models/CustomWebhook.ts new file mode 100644 index 0000000..cb39dc4 --- /dev/null +++ b/frontend/src/api/models/CustomWebhook.ts @@ -0,0 +1,35 @@ +/* generated using openapi-typescript-codegen -- do not edit */ +/* istanbul ignore file */ +/* tslint:disable */ +/* eslint-disable */ +export type CustomWebhook = { + /** + * Webhook唯一标识 + */ + id: string; + /** + * Webhook名称 + */ + name: string; + /** + * Webhook URL + */ + url: string; + /** + * 消息模板 + */ + template: string; + /** + * 是否启用 + */ + enabled?: boolean; + /** + * 自定义请求头 + */ + headers?: (Record | null); + /** + * 请求方法 + */ + method?: ('POST' | 'GET' | null); +}; + diff --git a/frontend/src/api/models/GeneralUserConfig.ts b/frontend/src/api/models/GeneralUserConfig_Input.ts similarity index 93% rename from frontend/src/api/models/GeneralUserConfig.ts rename to frontend/src/api/models/GeneralUserConfig_Input.ts index 0bf20fb..26f2671 100644 --- a/frontend/src/api/models/GeneralUserConfig.ts +++ b/frontend/src/api/models/GeneralUserConfig_Input.ts @@ -5,7 +5,7 @@ import type { GeneralUserConfig_Data } from './GeneralUserConfig_Data'; import type { GeneralUserConfig_Info } from './GeneralUserConfig_Info'; import type { UserConfig_Notify } from './UserConfig_Notify'; -export type GeneralUserConfig = { +export type GeneralUserConfig_Input = { /** * 用户信息 */ diff --git a/frontend/src/api/models/GeneralUserConfig_Output.ts b/frontend/src/api/models/GeneralUserConfig_Output.ts new file mode 100644 index 0000000..67e8295 --- /dev/null +++ b/frontend/src/api/models/GeneralUserConfig_Output.ts @@ -0,0 +1,22 @@ +/* generated using openapi-typescript-codegen -- do not edit */ +/* istanbul ignore file */ +/* tslint:disable */ +/* eslint-disable */ +import type { GeneralUserConfig_Data } from './GeneralUserConfig_Data'; +import type { GeneralUserConfig_Info } from './GeneralUserConfig_Info'; +import type { UserConfig_Notify } from './UserConfig_Notify'; +export type GeneralUserConfig_Output = { + /** + * 用户信息 + */ + Info?: (GeneralUserConfig_Info | null); + /** + * 用户数据 + */ + Data?: (GeneralUserConfig_Data | null); + /** + * 单独通知 + */ + Notify?: (UserConfig_Notify | null); +}; + diff --git a/frontend/src/api/models/GlobalConfig.ts b/frontend/src/api/models/GlobalConfig_Input.ts similarity index 96% rename from frontend/src/api/models/GlobalConfig.ts rename to frontend/src/api/models/GlobalConfig_Input.ts index 548f600..e64e5d1 100644 --- a/frontend/src/api/models/GlobalConfig.ts +++ b/frontend/src/api/models/GlobalConfig_Input.ts @@ -8,7 +8,7 @@ import type { GlobalConfig_Start } from './GlobalConfig_Start'; import type { GlobalConfig_UI } from './GlobalConfig_UI'; import type { GlobalConfig_Update } from './GlobalConfig_Update'; import type { GlobalConfig_Voice } from './GlobalConfig_Voice'; -export type GlobalConfig = { +export type GlobalConfig_Input = { /** * 功能相关配置 */ diff --git a/frontend/src/api/models/GlobalConfig_Notify.ts b/frontend/src/api/models/GlobalConfig_Notify.ts index cc2b68b..e1cc8b9 100644 --- a/frontend/src/api/models/GlobalConfig_Notify.ts +++ b/frontend/src/api/models/GlobalConfig_Notify.ts @@ -2,6 +2,7 @@ /* istanbul ignore file */ /* tslint:disable */ /* eslint-disable */ +import type { CustomWebhook } from './CustomWebhook'; export type GlobalConfig_Notify = { /** * 任务结果推送时机 @@ -48,12 +49,8 @@ export type GlobalConfig_Notify = { */ ServerChanKey?: (string | null); /** - * 是否使用企微Webhook推送 + * 自定义Webhook列表 */ - IfCompanyWebHookBot?: (boolean | null); - /** - * 企微Webhook Bot URL - */ - CompanyWebHookBotUrl?: (string | null); + CustomWebhooks?: (Array | null); }; diff --git a/frontend/src/api/models/GlobalConfig_Output.ts b/frontend/src/api/models/GlobalConfig_Output.ts new file mode 100644 index 0000000..95cea9a --- /dev/null +++ b/frontend/src/api/models/GlobalConfig_Output.ts @@ -0,0 +1,37 @@ +/* generated using openapi-typescript-codegen -- do not edit */ +/* istanbul ignore file */ +/* tslint:disable */ +/* eslint-disable */ +import type { GlobalConfig_Function } from './GlobalConfig_Function'; +import type { GlobalConfig_Notify } from './GlobalConfig_Notify'; +import type { GlobalConfig_Start } from './GlobalConfig_Start'; +import type { GlobalConfig_UI } from './GlobalConfig_UI'; +import type { GlobalConfig_Update } from './GlobalConfig_Update'; +import type { GlobalConfig_Voice } from './GlobalConfig_Voice'; +export type GlobalConfig_Output = { + /** + * 功能相关配置 + */ + Function?: (GlobalConfig_Function | null); + /** + * 语音相关配置 + */ + Voice?: (GlobalConfig_Voice | null); + /** + * 启动相关配置 + */ + Start?: (GlobalConfig_Start | null); + /** + * 界面相关配置 + */ + UI?: (GlobalConfig_UI | null); + /** + * 通知相关配置 + */ + Notify?: (GlobalConfig_Notify | null); + /** + * 更新相关配置 + */ + Update?: (GlobalConfig_Update | null); +}; + diff --git a/frontend/src/api/models/MaaUserConfig.ts b/frontend/src/api/models/MaaUserConfig_Input.ts similarity index 95% rename from frontend/src/api/models/MaaUserConfig.ts rename to frontend/src/api/models/MaaUserConfig_Input.ts index a514d50..8ab6e94 100644 --- a/frontend/src/api/models/MaaUserConfig.ts +++ b/frontend/src/api/models/MaaUserConfig_Input.ts @@ -6,7 +6,7 @@ import type { MaaUserConfig_Data } from './MaaUserConfig_Data'; import type { MaaUserConfig_Info } from './MaaUserConfig_Info'; import type { MaaUserConfig_Task } from './MaaUserConfig_Task'; import type { UserConfig_Notify } from './UserConfig_Notify'; -export type MaaUserConfig = { +export type MaaUserConfig_Input = { /** * 基础信息 */ diff --git a/frontend/src/api/models/MaaUserConfig_Output.ts b/frontend/src/api/models/MaaUserConfig_Output.ts new file mode 100644 index 0000000..4f73104 --- /dev/null +++ b/frontend/src/api/models/MaaUserConfig_Output.ts @@ -0,0 +1,27 @@ +/* generated using openapi-typescript-codegen -- do not edit */ +/* istanbul ignore file */ +/* tslint:disable */ +/* eslint-disable */ +import type { MaaUserConfig_Data } from './MaaUserConfig_Data'; +import type { MaaUserConfig_Info } from './MaaUserConfig_Info'; +import type { MaaUserConfig_Task } from './MaaUserConfig_Task'; +import type { UserConfig_Notify } from './UserConfig_Notify'; +export type MaaUserConfig_Output = { + /** + * 基础信息 + */ + Info?: (MaaUserConfig_Info | null); + /** + * 用户数据 + */ + Data?: (MaaUserConfig_Data | null); + /** + * 任务列表 + */ + Task?: (MaaUserConfig_Task | null); + /** + * 单独通知 + */ + Notify?: (UserConfig_Notify | null); +}; + diff --git a/frontend/src/api/models/SettingGetOut.ts b/frontend/src/api/models/SettingGetOut.ts index e909ef6..be80afa 100644 --- a/frontend/src/api/models/SettingGetOut.ts +++ b/frontend/src/api/models/SettingGetOut.ts @@ -2,7 +2,7 @@ /* istanbul ignore file */ /* tslint:disable */ /* eslint-disable */ -import type { GlobalConfig } from './GlobalConfig'; +import type { GlobalConfig_Output } from './GlobalConfig_Output'; export type SettingGetOut = { /** * 状态码 @@ -19,6 +19,6 @@ export type SettingGetOut = { /** * 全局设置数据 */ - data: GlobalConfig; + data: GlobalConfig_Output; }; diff --git a/frontend/src/api/models/SettingUpdateIn.ts b/frontend/src/api/models/SettingUpdateIn.ts index 51e8991..4d11565 100644 --- a/frontend/src/api/models/SettingUpdateIn.ts +++ b/frontend/src/api/models/SettingUpdateIn.ts @@ -2,11 +2,11 @@ /* istanbul ignore file */ /* tslint:disable */ /* eslint-disable */ -import type { GlobalConfig } from './GlobalConfig'; +import type { GlobalConfig_Input } from './GlobalConfig_Input'; export type SettingUpdateIn = { /** * 全局设置需要更新的数据 */ - data: GlobalConfig; + data: GlobalConfig_Input; }; diff --git a/frontend/src/api/models/UserConfig_Notify.ts b/frontend/src/api/models/UserConfig_Notify.ts index dfca928..7bf9cbf 100644 --- a/frontend/src/api/models/UserConfig_Notify.ts +++ b/frontend/src/api/models/UserConfig_Notify.ts @@ -2,6 +2,7 @@ /* istanbul ignore file */ /* tslint:disable */ /* eslint-disable */ +import type { CustomWebhook } from './CustomWebhook'; export type UserConfig_Notify = { /** * 是否启用通知 @@ -32,12 +33,8 @@ export type UserConfig_Notify = { */ ServerChanKey?: (string | null); /** - * 是否使用Webhook推送 + * 用户自定义Webhook列表 */ - IfCompanyWebHookBot?: (boolean | null); - /** - * 企微Webhook Bot URL - */ - CompanyWebHookBotUrl?: (string | null); + CustomWebhooks?: (Array | null); }; diff --git a/frontend/src/api/models/UserCreateOut.ts b/frontend/src/api/models/UserCreateOut.ts index 630d5ac..560f95b 100644 --- a/frontend/src/api/models/UserCreateOut.ts +++ b/frontend/src/api/models/UserCreateOut.ts @@ -2,8 +2,8 @@ /* istanbul ignore file */ /* tslint:disable */ /* eslint-disable */ -import type { GeneralUserConfig } from './GeneralUserConfig'; -import type { MaaUserConfig } from './MaaUserConfig'; +import type { GeneralUserConfig_Output } from './GeneralUserConfig_Output'; +import type { MaaUserConfig_Output } from './MaaUserConfig_Output'; export type UserCreateOut = { /** * 状态码 @@ -24,6 +24,6 @@ export type UserCreateOut = { /** * 用户配置数据 */ - data: (MaaUserConfig | GeneralUserConfig); + data: (MaaUserConfig_Output | GeneralUserConfig_Output); }; diff --git a/frontend/src/api/models/UserGetOut.ts b/frontend/src/api/models/UserGetOut.ts index 3b4d7bd..5d83ea4 100644 --- a/frontend/src/api/models/UserGetOut.ts +++ b/frontend/src/api/models/UserGetOut.ts @@ -2,8 +2,8 @@ /* istanbul ignore file */ /* tslint:disable */ /* eslint-disable */ -import type { GeneralUserConfig } from './GeneralUserConfig'; -import type { MaaUserConfig } from './MaaUserConfig'; +import type { GeneralUserConfig_Output } from './GeneralUserConfig_Output'; +import type { MaaUserConfig_Output } from './MaaUserConfig_Output'; import type { UserIndexItem } from './UserIndexItem'; export type UserGetOut = { /** @@ -25,6 +25,6 @@ export type UserGetOut = { /** * 用户数据字典, key来自于index列表的uid */ - data: Record; + data: Record; }; diff --git a/frontend/src/api/models/UserUpdateIn.ts b/frontend/src/api/models/UserUpdateIn.ts index 91f6b06..ac6ab93 100644 --- a/frontend/src/api/models/UserUpdateIn.ts +++ b/frontend/src/api/models/UserUpdateIn.ts @@ -2,8 +2,8 @@ /* istanbul ignore file */ /* tslint:disable */ /* eslint-disable */ -import type { GeneralUserConfig } from './GeneralUserConfig'; -import type { MaaUserConfig } from './MaaUserConfig'; +import type { GeneralUserConfig_Input } from './GeneralUserConfig_Input'; +import type { MaaUserConfig_Input } from './MaaUserConfig_Input'; export type UserUpdateIn = { /** * 所属脚本ID @@ -16,6 +16,6 @@ export type UserUpdateIn = { /** * 用户更新数据 */ - data: (MaaUserConfig | GeneralUserConfig); + data: (MaaUserConfig_Input | GeneralUserConfig_Input); }; diff --git a/frontend/src/api/services/Service.ts b/frontend/src/api/services/Service.ts index 9936ba4..d44ed71 100644 --- a/frontend/src/api/services/Service.ts +++ b/frontend/src/api/services/Service.ts @@ -994,6 +994,86 @@ export class Service { url: '/api/setting/test_notify', }); } + /** + * 创建自定义Webhook + * 创建自定义Webhook + * @param requestBody + * @returns OutBase Successful Response + * @throws ApiError + */ + public static createWebhookApiSettingWebhookCreatePost( + requestBody: Record, + ): CancelablePromise { + return __request(OpenAPI, { + method: 'POST', + url: '/api/setting/webhook/create', + body: requestBody, + mediaType: 'application/json', + errors: { + 422: `Validation Error`, + }, + }); + } + /** + * 更新自定义Webhook + * 更新自定义Webhook + * @param requestBody + * @returns OutBase Successful Response + * @throws ApiError + */ + public static updateWebhookApiSettingWebhookUpdatePost( + requestBody: Record, + ): CancelablePromise { + return __request(OpenAPI, { + method: 'POST', + url: '/api/setting/webhook/update', + body: requestBody, + mediaType: 'application/json', + errors: { + 422: `Validation Error`, + }, + }); + } + /** + * 删除自定义Webhook + * 删除自定义Webhook + * @param requestBody + * @returns OutBase Successful Response + * @throws ApiError + */ + public static deleteWebhookApiSettingWebhookDeletePost( + requestBody: Record, + ): CancelablePromise { + return __request(OpenAPI, { + method: 'POST', + url: '/api/setting/webhook/delete', + body: requestBody, + mediaType: 'application/json', + errors: { + 422: `Validation Error`, + }, + }); + } + /** + * 测试自定义Webhook + * 测试自定义Webhook + * @param requestBody + * @returns OutBase Successful Response + * @throws ApiError + */ + public static testWebhookApiSettingWebhookTestPost( + requestBody: Record, + ): CancelablePromise { + return __request(OpenAPI, { + method: 'POST', + url: '/api/setting/webhook/test', + body: requestBody, + mediaType: 'application/json', + errors: { + 422: `Validation Error`, + }, + }); + } /** * 检查更新 * @param requestBody diff --git a/frontend/src/components/WebhookManager.vue b/frontend/src/components/WebhookManager.vue new file mode 100644 index 0000000..821d577 --- /dev/null +++ b/frontend/src/components/WebhookManager.vue @@ -0,0 +1,524 @@ + + + + + \ No newline at end of file diff --git a/frontend/src/composables/useScriptApi.ts b/frontend/src/composables/useScriptApi.ts index 26a76a7..fed4cd5 100644 --- a/frontend/src/composables/useScriptApi.ts +++ b/frontend/src/composables/useScriptApi.ts @@ -154,8 +154,7 @@ export function useScriptApi() { ToAddress: maaUserData.Notify?.ToAddress !== undefined ? maaUserData.Notify.ToAddress : '', IfServerChan: maaUserData.Notify?.IfServerChan !== undefined ? maaUserData.Notify.IfServerChan : false, ServerChanKey: maaUserData.Notify?.ServerChanKey !== undefined ? maaUserData.Notify.ServerChanKey : '', - IfCompanyWebHookBot: maaUserData.Notify?.IfCompanyWebHookBot !== undefined ? maaUserData.Notify.IfCompanyWebHookBot : false, - CompanyWebHookBotUrl: maaUserData.Notify?.CompanyWebHookBotUrl !== undefined ? maaUserData.Notify.CompanyWebHookBotUrl : '', + CustomWebhooks: maaUserData.Notify?.CustomWebhooks !== undefined ? maaUserData.Notify.CustomWebhooks : [], }, Data: { LastAnnihilationDate: maaUserData.Data?.LastAnnihilationDate !== undefined ? maaUserData.Data.LastAnnihilationDate : '', @@ -188,8 +187,7 @@ export function useScriptApi() { ToAddress: generalUserData.Notify?.ToAddress !== undefined ? generalUserData.Notify.ToAddress : '', IfServerChan: generalUserData.Notify?.IfServerChan !== undefined ? generalUserData.Notify.IfServerChan : false, ServerChanKey: generalUserData.Notify?.ServerChanKey !== undefined ? generalUserData.Notify.ServerChanKey : '', - IfCompanyWebHookBot: generalUserData.Notify?.IfCompanyWebHookBot !== undefined ? generalUserData.Notify.IfCompanyWebHookBot : false, - CompanyWebHookBotUrl: generalUserData.Notify?.CompanyWebHookBotUrl !== undefined ? generalUserData.Notify.CompanyWebHookBotUrl : '', + CustomWebhooks: generalUserData.Notify?.CustomWebhooks !== undefined ? generalUserData.Notify.CustomWebhooks : [], }, Data: { LastProxyDate: generalUserData.Data?.LastProxyDate !== undefined ? generalUserData.Data.LastProxyDate : '', diff --git a/frontend/src/types/script.ts b/frontend/src/types/script.ts index e9336d0..096108a 100644 --- a/frontend/src/types/script.ts +++ b/frontend/src/types/script.ts @@ -109,11 +109,18 @@ export interface User { Status: boolean } Notify: { - CompanyWebHookBotUrl: string Enabled: boolean - IfCompanyWebHookBot: boolean IfSendMail: boolean IfSendSixStar: boolean + CustomWebhooks: Array<{ + id: string + name: string + url: string + template: string + enabled: boolean + headers?: Record + method?: 'POST' | 'GET' + }> IfSendStatistic: boolean IfServerChan: boolean ServerChanChannel: string diff --git a/frontend/src/types/settings.ts b/frontend/src/types/settings.ts index c240ec7..f701501 100644 --- a/frontend/src/types/settings.ts +++ b/frontend/src/types/settings.ts @@ -1,3 +1,14 @@ +// 自定义Webhook配置 +export interface CustomWebhook { + id: string + name: string + url: string + template: string + enabled: boolean + headers?: Record + method?: 'POST' | 'GET' +} + // 设置相关类型定义 export interface SettingsData { UI: { @@ -26,8 +37,7 @@ export interface SettingsData { ServerChanKey: string ServerChanChannel: string ServerChanTag: string - IfCompanyWebHookBot: boolean - CompanyWebHookBotUrl: string + CustomWebhooks: CustomWebhook[] } Update: { IfAutoUpdate: boolean diff --git a/frontend/src/utils/webhookTemplates.ts b/frontend/src/utils/webhookTemplates.ts new file mode 100644 index 0000000..1ad345c --- /dev/null +++ b/frontend/src/utils/webhookTemplates.ts @@ -0,0 +1,119 @@ +// Webhook 模板配置 +export interface WebhookTemplate { + name: string + description: string + template: string + headers?: Record + method: 'POST' | 'GET' + example?: string +} + +export const WEBHOOK_TEMPLATES: WebhookTemplate[] = [ + { + name: 'Bark (iOS推送)', + description: 'Bark是一款iOS推送通知应用', + template: '{"title": "{title}", "body": "{content}", "sound": "default"}', + method: 'POST', + example: 'https://api.day.app/your_key/', + headers: { + 'Content-Type': 'application/json' + } + }, + { + name: 'Server酱 (微信推送)', + description: 'Server酱微信推送服务', + template: '{"title": "{title}", "desp": "{content}"}', + method: 'POST', + example: 'https://sctapi.ftqq.com/your_key.send', + headers: { + 'Content-Type': 'application/json' + } + }, + { + name: '企业微信机器人', + description: '企业微信群机器人推送', + template: '{"msgtype": "text", "text": {"content": "{title}\\n{content}"}}', + method: 'POST', + example: 'https://qyapi.weixin.qq.com/cgi-bin/webhook/send?key=your_key', + headers: { + 'Content-Type': 'application/json' + } + }, + { + name: 'DingTalk (钉钉机器人)', + description: '钉钉群机器人推送', + template: '{"msgtype": "text", "text": {"content": "{title}\\n{content}"}}', + method: 'POST', + example: 'https://oapi.dingtalk.com/robot/send?access_token=your_token', + headers: { + 'Content-Type': 'application/json' + } + }, + { + name: 'Telegram Bot', + description: 'Telegram机器人推送', + template: '{"chat_id": "your_chat_id", "text": "{title}\\n{content}"}', + method: 'POST', + example: 'https://api.telegram.org/bot{your_bot_token}/sendMessage', + headers: { + 'Content-Type': 'application/json' + } + }, + { + name: 'Discord Webhook', + description: 'Discord频道Webhook推送', + template: '{"content": "**{title}**\\n{content}"}', + method: 'POST', + example: 'https://discord.com/api/webhooks/your_webhook_url', + headers: { + 'Content-Type': 'application/json' + } + }, + { + name: 'Slack Webhook', + description: 'Slack频道Webhook推送', + template: '{"text": "{title}\\n{content}"}', + method: 'POST', + example: 'https://hooks.slack.com/services/your/webhook/url', + headers: { + 'Content-Type': 'application/json' + } + }, + { + name: 'PushPlus (微信推送)', + description: 'PushPlus微信推送服务', + template: '{"token": "your_token", "title": "{title}", "content": "{content}"}', + method: 'POST', + example: 'http://www.pushplus.plus/send', + headers: { + 'Content-Type': 'application/json' + } + }, + { + name: '自定义JSON', + description: '自定义JSON格式推送', + template: '{"message": "{title}: {content}", "timestamp": "{datetime}"}', + method: 'POST', + example: 'https://your-api.com/webhook', + headers: { + 'Content-Type': 'application/json' + } + }, + { + name: '自定义GET请求', + description: '通过GET请求发送通知', + template: 'title={title}&content={content}&time={datetime}', + method: 'GET', + example: 'https://your-api.com/notify', + headers: {} + } +] + +// 获取模板变量说明 +export const TEMPLATE_VARIABLES = [ + { name: '{title}', description: '通知标题' }, + { name: '{content}', description: '通知内容' }, + { name: '{datetime}', description: '完整日期时间 (YYYY-MM-DD HH:MM:SS)' }, + { name: '{date}', description: '日期 (YYYY-MM-DD)' }, + { name: '{time}', description: '时间 (HH:MM:SS)' } +] \ No newline at end of file diff --git a/frontend/src/views/GeneralUserEdit.vue b/frontend/src/views/GeneralUserEdit.vue index d0a7b32..52105ce 100644 --- a/frontend/src/views/GeneralUserEdit.vue +++ b/frontend/src/views/GeneralUserEdit.vue @@ -85,85 +85,85 @@

基本信息

- - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - + + + + @@ -171,90 +171,90 @@

额外脚本

- - - - - - - - - + + + + - - - 选择文件 - - - - - - - - - - - - - - + + + + + + 选择文件 + + + + + + + + + + - - - 选择文件 - - - - - + + + + + + + 选择文件 + + + + + @@ -262,92 +262,77 @@

通知配置

- - - 启用通知 - - - - 启用后将发送任务通知 - - + + + 启用通知 + + + + 启用后将发送任务通知 + + - - - - 通知内容 - - - 统计信息 - - - + + + + 通知内容 + + + 统计信息 + + + - - - - 邮件通知 - - - - + + + 邮件通知 + + + + + + + + + + + Server酱 + + + + + + + + +
+ - - - - - - - Server酱 - - - - - - - - - - - 企业微信群机器人 - - - - - - +
@@ -384,6 +369,7 @@ import { useScriptApi } from '@/composables/useScriptApi' import { useWebSocket } from '@/composables/useWebSocket' import { Service } from '@/api' import { TaskCreateIn } from '@/api/models/TaskCreateIn' +import WebhookManager from '@/components/WebhookManager.vue' const router = useRouter() const route = useRoute() @@ -426,11 +412,10 @@ const getDefaultGeneralUserData = () => ({ IfSendMail: false, IfSendStatistic: false, IfServerChan: false, - IfCompanyWebHookBot: false, ServerChanKey: '', ServerChanChannel: '', ServerChanTag: '', - CompanyWebHookBotUrl: '', + CustomWebhooks: [], }, Data: { LastProxyDate: '2000-01-01', @@ -639,16 +624,19 @@ const handleGeneralConfig = async () => { message.success(`已开始配置用户 ${formData.userName} 的通用设置`) // 设置 30 分钟超时自动断开 - generalConfigTimeout = window.setTimeout(() => { - if (generalWebsocketId.value) { - const id = generalWebsocketId.value - unsubscribe(id) - generalWebsocketId.value = null - showGeneralConfigMask.value = false - message.info(`用户 ${formData.userName} 的配置会话已超时断开`) - } - generalConfigTimeout = null - }, 30 * 60 * 1000) + generalConfigTimeout = window.setTimeout( + () => { + if (generalWebsocketId.value) { + const id = generalWebsocketId.value + unsubscribe(id) + generalWebsocketId.value = null + showGeneralConfigMask.value = false + message.info(`用户 ${formData.userName} 的配置会话已超时断开`) + } + generalConfigTimeout = null + }, + 30 * 60 * 1000 + ) } else { message.error(response?.message || '启动通用配置失败') } @@ -695,7 +683,7 @@ const selectScriptBeforeTask = async () => { { name: '脚本文件', extensions: ['py', 'js', 'sh'] }, { name: '所有文件', extensions: ['*'] }, ]) - + if (path && path.length > 0) { formData.Info.ScriptBeforeTask = path[0] message.success('任务前脚本路径选择成功') @@ -713,7 +701,7 @@ const selectScriptAfterTask = async () => { { name: '脚本文件', extensions: ['py', 'js', 'sh'] }, { name: '所有文件', extensions: ['*'] }, ]) - + if (path && path.length > 0) { formData.Info.ScriptAfterTask = path[0] message.success('任务后脚本路径选择成功') @@ -724,6 +712,13 @@ const selectScriptAfterTask = async () => { } } +// 处理 Webhook 变化 +const handleWebhookChange = () => { + // 这里可以添加额外的处理逻辑,比如验证或保存 + console.log('User webhooks changed:', formData.Notify.CustomWebhooks) + // 注意:实际保存会在用户点击保存按钮时进行,这里只是更新本地数据 +} + const handleCancel = () => { if (generalWebsocketId.value) { unsubscribe(generalWebsocketId.value) @@ -991,4 +986,4 @@ onMounted(() => { display: flex; justify-content: center; } - \ No newline at end of file + diff --git a/frontend/src/views/MAAUserEdit.vue b/frontend/src/views/MAAUserEdit.vue index 90758ea..0aafa70 100644 --- a/frontend/src/views/MAAUserEdit.vue +++ b/frontend/src/views/MAAUserEdit.vue @@ -41,7 +41,13 @@
- + - + - + - +
@@ -459,11 +456,10 @@ const getDefaultMAAUserData = () => ({ IfSendSixStar: false, IfSendStatistic: false, IfServerChan: false, - IfCompanyWebHookBot: false, ServerChanKey: '', ServerChanChannel: '', ServerChanTag: '', - CompanyWebHookBotUrl: '', + CustomWebhooks: [], }, Data: { CustomInfrastPlanIndex: '', @@ -790,7 +786,10 @@ const handleMAAConfig = async () => { subscribe(wsId, { onMessage: (wsMessage: any) => { if (wsMessage.type === 'error') { - console.error(`用户 ${formData.Info?.Name || formData.userName} MAA配置错误:`, wsMessage.data) + console.error( + `用户 ${formData.Info?.Name || formData.userName} MAA配置错误:`, + wsMessage.data + ) message.error(`MAA配置连接失败: ${wsMessage.data}`) unsubscribe(wsId) maaWebsocketId.value = null @@ -812,16 +811,19 @@ const handleMAAConfig = async () => { message.success(`已开始配置用户 ${formData.Info?.Name || formData.userName} 的MAA设置`) // 设置 30 分钟超时自动断开 - maaConfigTimeout = window.setTimeout(() => { - if (maaWebsocketId.value) { - const id = maaWebsocketId.value - unsubscribe(id) - maaWebsocketId.value = null - showMAAConfigMask.value = false - message.info(`用户 ${formData.Info?.Name || formData.userName} 的配置会话已超时断开`) - } - maaConfigTimeout = null - }, 30 * 60 * 1000) + maaConfigTimeout = window.setTimeout( + () => { + if (maaWebsocketId.value) { + const id = maaWebsocketId.value + unsubscribe(id) + maaWebsocketId.value = null + showMAAConfigMask.value = false + message.info(`用户 ${formData.Info?.Name || formData.userName} 的配置会话已超时断开`) + } + maaConfigTimeout = null + }, + 30 * 60 * 1000 + ) } else { message.error(response?.message || '启动MAA配置失败') } @@ -1017,7 +1019,6 @@ const updateStageRemain = (value: string) => { } } - // 初始化加载 onMounted(() => { if (!scriptId) { diff --git a/frontend/src/views/MAAUserEdit/NotifyConfigSection.vue b/frontend/src/views/MAAUserEdit/NotifyConfigSection.vue index 5414188..c10dcc2 100644 --- a/frontend/src/views/MAAUserEdit/NotifyConfigSection.vue +++ b/frontend/src/views/MAAUserEdit/NotifyConfigSection.vue @@ -71,36 +71,30 @@
- - - - 企业微信群机器人 - - - - - - + +
+ +