From 0ae70701d1c46fedc12c7db1642f9d8254862c00 Mon Sep 17 00:00:00 2001 From: hardy <2545433047@qq.com> Date: Tue, 22 Sep 2026 11:52:59 +0800 Subject: [PATCH 1/5] feat(TAP-12848): edit task alarm receivers as users, groups, and emails Add a receiver selector on the task alarm tab and a three-mode batch dialog. An empty saved list stays custom instead of falling back to the system default. Deleting a user or group shows the alarm impact, and the operation log renders receiver changes. --- apps/daas/src/i18n/langs/en.js | 52 +- apps/daas/src/i18n/langs/zh-CN.js | 51 +- apps/daas/src/i18n/langs/zh-TW.js | 51 +- .../src/views/notification/UserOperation.vue | 101 +++ apps/daas/src/views/user/List.vue | 48 +- packages/api/src/core/alarm.ts | 98 ++- packages/api/src/core/user-groups.ts | 14 + packages/api/src/core/users.ts | 24 +- .../src/components/AlarmReceiverSelector.vue | 586 ++++++++++++++ packages/business/src/locale/lang/en.js | 73 +- packages/business/src/locale/lang/zh-CN.js | 77 +- packages/business/src/locale/lang/zh-TW.js | 77 +- .../src/views/task/BatchAlarmEmailDialog.vue | 719 +++++++++++++++--- packages/business/src/views/task/List.vue | 291 +------ packages/component/src/Classification.vue | 48 +- packages/component/src/locale/lang/en.js | 5 + packages/component/src/locale/lang/zh-CN.js | 5 + packages/component/src/locale/lang/zh-TW.js | 5 + packages/dag/src/components/SettingsPanel.vue | 83 +- .../components/form/alarm-receiver/index.tsx | 265 +++++++ packages/dag/src/components/form/index.ts | 1 + packages/dag/src/locale/lang/en.js | 32 + packages/dag/src/locale/lang/zh-CN.js | 28 + packages/dag/src/locale/lang/zh-TW.js | 28 + .../ldp/src/components/ClassificationTree.vue | 42 +- 25 files changed, 2306 insertions(+), 498 deletions(-) create mode 100644 packages/business/src/components/AlarmReceiverSelector.vue create mode 100644 packages/dag/src/components/form/alarm-receiver/index.tsx diff --git a/apps/daas/src/i18n/langs/en.js b/apps/daas/src/i18n/langs/en.js index dfcb1cf405..e25579719f 100644 --- a/apps/daas/src/i18n/langs/en.js +++ b/apps/daas/src/i18n/langs/en.js @@ -754,7 +754,9 @@ export default { setting_License_expiry_email_reminder_: 'License expiry advance reminder settings (days)', setting_flow_engine_version: 'Flow engine version', - setting_tapdata_agent_version: `${import.meta.env.VUE_APP_PAGE_TITLE} agent version`, + setting_tapdata_agent_version: `${ + import.meta.env.VUE_APP_PAGE_TITLE + } agent version`, setting_doc_base_url: 'Help document URL', setting_help: 'Help document', setting_Ip_addresses: 'Ipv4 addresses (separated by multiple commas)', @@ -970,8 +972,17 @@ export default { user_list_bulk_freeze: 'Bulk freeze', user_list_bulk_check: 'Bulk check', user_list_del_user: 'After deleting user {0}, this user cannot be recovered', - user_list_activetion_user: `After activating user {0}, this user will be able to use the ${import.meta.env.VUE_APP_PAGE_TITLE} system`, - user_list_freeze_user: `After freezing user {0}, this user will not be able to use the ${import.meta.env.VUE_APP_PAGE_TITLE} system`, + user_list_delete_alarm_confirm: + 'Delete user "{username}" ({email})? This user is a direct alert receiver for {count} tasks and belongs to these user groups: {groups}. After deletion, alerts will no longer be sent to this user directly or through those user groups.', + user_list_delete_alarm_no_group: 'None', + user_list_alarm_impact_failed: + 'Unable to load the alert impact. Please try again later.', + user_list_activetion_user: `After activating user {0}, this user will be able to use the ${ + import.meta.env.VUE_APP_PAGE_TITLE + } system`, + user_list_freeze_user: `After freezing user {0}, this user will not be able to use the ${ + import.meta.env.VUE_APP_PAGE_TITLE + } system`, user_list_check_user: 'After checking the mailbox of user {0}, this user can be activated', user_list_activetion_success: 'Activation successful', @@ -2145,6 +2156,29 @@ export default { notification_modular_user: 'user', notification_modular_role: 'role', notification_modular_accessCode: 'access code', + notification_modular_alarmReceiver: 'alert receivers', + notification_modular_userGroup: 'user group', + notification_operation_batch_update: ' batch updated ', + notification_alarm_receiver_update: + 'Updated the alert receivers of task [{parameter1}]', + notification_alarm_receiver_update_mode: + 'Updated the alert receivers of task [{parameter1}], operation mode [{parameter2}]', + notification_alarm_receiver_update_change: + 'Updated the alert receivers of task [{parameter1}], {parameter3}', + notification_alarm_receiver_update_mode_change: + 'Updated the alert receivers of task [{parameter1}], operation mode [{parameter2}], {parameter3}', + notification_alarm_receiver_batch_update: + 'Batch updated the alert receivers of task [{parameter1}] in [{parameter2}] mode', + notification_alarm_receiver_batch_update_change: + 'Batch updated the alert receivers of task [{parameter1}] in [{parameter2}] mode, {parameter3}', + notification_user_group_delete: 'Deleted user group [{parameter1}]', + notification_user_group_delete_mode: + 'Deleted user group [{parameter1}], operation mode [{parameter2}]', + notification_user_group_delete_change: + 'Deleted user group [{parameter1}], {parameter3}', + notification_user_group_delete_mode_change: + 'Deleted user group [{parameter1}], operation mode [{parameter2}], {parameter3}', + notification_alarm_receiver_before_after: 'Before: {before}, After: {after}', notification_operation_readnotification_modular_message: '', dialog_placeholderTable: 'Only supports English, numbers, underscores, minus signs, dots, and starts with English letter', @@ -2428,9 +2462,15 @@ export default { daas_feature_unavailable_upgrade_dec_li4: 'Permission management (Enterprise edition only)', daas_feature_unavailable_upgrade_dec_li5: 'More data sources', - daas_feature_unavailable_upgrade_dec_li1_desc: `${import.meta.env.VUE_APP_PAGE_TITLE} ensures data consistency with proprietary technology and supports data table validation to meet production requirements.`, - daas_feature_unavailable_upgrade_dec_li2_desc: `${import.meta.env.VUE_APP_PAGE_TITLE} reduces source database load by supporting shared incremental log cache, fetching events directly from the cache without repeated reads.`, - daas_feature_unavailable_upgrade_dec_li3_desc: `${import.meta.env.VUE_APP_PAGE_TITLE} sends alert emails via SMTP, allowing users to promptly receive anomaly notifications and ensure task stability.`, + daas_feature_unavailable_upgrade_dec_li1_desc: `${ + import.meta.env.VUE_APP_PAGE_TITLE + } ensures data consistency with proprietary technology and supports data table validation to meet production requirements.`, + daas_feature_unavailable_upgrade_dec_li2_desc: `${ + import.meta.env.VUE_APP_PAGE_TITLE + } reduces source database load by supporting shared incremental log cache, fetching events directly from the cache without repeated reads.`, + daas_feature_unavailable_upgrade_dec_li3_desc: `${ + import.meta.env.VUE_APP_PAGE_TITLE + } sends alert emails via SMTP, allowing users to promptly receive anomaly notifications and ensure task stability.`, daas_feature_unavailable_upgrade_dec_li4_desc: 'Roles are collections of permissions assigned to users. This simplifies management and enhances security by allowing role creation before user assignment.', daas_feature_unavailable_upgrade_dec_li5_desc: '', diff --git a/apps/daas/src/i18n/langs/zh-CN.js b/apps/daas/src/i18n/langs/zh-CN.js index 82633beea3..87c94f2f7f 100644 --- a/apps/daas/src/i18n/langs/zh-CN.js +++ b/apps/daas/src/i18n/langs/zh-CN.js @@ -718,7 +718,9 @@ export default { setting_License_expiry_email_reminder_: 'license 到期提前几天提醒设置', setting_newMongodbChangeStream: '111111', setting_flow_engine_version: ' 流程引擎版本', - setting_tapdata_agent_version: `${import.meta.env.VUE_APP_PAGE_TITLE} Agent 版本`, + setting_tapdata_agent_version: `${ + import.meta.env.VUE_APP_PAGE_TITLE + } Agent 版本`, setting_doc_base_url: ' 帮助文档URL', setting_help: ' 帮助文档', setting_Ip_addresses: ' Ipv4地址(多个逗号分隔)', @@ -915,8 +917,16 @@ export default { user_list_bulk_freeze: '批量冻结', user_list_bulk_check: '批量校验', user_list_del_user: '删除用户 {0} 后,此用户将无法恢复', - user_list_activetion_user: `激活用户 {0} 后,此用户将可以使用 ${import.meta.env.VUE_APP_PAGE_TITLE} 系统`, - user_list_freeze_user: `冻结用户 {0} 后,此用户将不可以使用 ${import.meta.env.VUE_APP_PAGE_TITLE} 系统`, + user_list_delete_alarm_confirm: + '删除用户「{username}」({email})?该用户直接作为告警接收对象的任务有 {count} 个,所属用户组:{groups}。删除后,将不再通过该用户本人或所属用户组接收告警。', + user_list_delete_alarm_no_group: '无', + user_list_alarm_impact_failed: '无法获取告警影响范围,请稍后重试', + user_list_activetion_user: `激活用户 {0} 后,此用户将可以使用 ${ + import.meta.env.VUE_APP_PAGE_TITLE + } 系统`, + user_list_freeze_user: `冻结用户 {0} 后,此用户将不可以使用 ${ + import.meta.env.VUE_APP_PAGE_TITLE + } 系统`, user_list_check_user: '通过校验用户 {0} 的邮箱后,此用户可以被激活', user_list_activetion_success: '激活成功', user_list_activetion_error: '激活失败', @@ -2041,6 +2051,29 @@ export default { notification_modular_user: '用户', notification_modular_role: '角色', notification_modular_accessCode: '访问码', + notification_modular_alarmReceiver: '告警接收对象', + notification_modular_userGroup: '用户组', + notification_operation_batch_update: ' 批量修改了 ', + notification_alarm_receiver_update: + '修改了任务【{parameter1}】的告警接收对象', + notification_alarm_receiver_update_mode: + '修改了任务【{parameter1}】的告警接收对象,操作模式【{parameter2}】', + notification_alarm_receiver_update_change: + '修改了任务【{parameter1}】的告警接收对象,{parameter3}', + notification_alarm_receiver_update_mode_change: + '修改了任务【{parameter1}】的告警接收对象,操作模式【{parameter2}】,{parameter3}', + notification_alarm_receiver_batch_update: + '以【{parameter2}】批量修改了任务【{parameter1}】的告警接收对象', + notification_alarm_receiver_batch_update_change: + '以【{parameter2}】批量修改了任务【{parameter1}】的告警接收对象,{parameter3}', + notification_user_group_delete: '删除了用户组【{parameter1}】', + notification_user_group_delete_mode: + '删除了用户组【{parameter1}】,操作模式【{parameter2}】', + notification_user_group_delete_change: + '删除了用户组【{parameter1}】,{parameter3}', + notification_user_group_delete_mode_change: + '删除了用户组【{parameter1}】,操作模式【{parameter2}】,{parameter3}', + notification_alarm_receiver_before_after: '修改前:{before},修改后:{after}', notification_modular_message: '', queryBuilder_addCond: '字段条件', account_accountSettings: '个人设置 ', @@ -2295,9 +2328,15 @@ export default { daas_feature_unavailable_upgrade_dec_li3: '告警设置', daas_feature_unavailable_upgrade_dec_li4: '权限管理(仅企业版)', daas_feature_unavailable_upgrade_dec_li5: '更多数据源', - daas_feature_unavailable_upgrade_dec_li1_desc: `基于自研技术,${import.meta.env.VUE_APP_PAGE_TITLE} 能最大程度保障数据一致性,还支持数据表数据校验,以验证和确保数据流转正确,满足生产环境要求。`, - daas_feature_unavailable_upgrade_dec_li2_desc: `为减轻源端数据库压力,${import.meta.env.VUE_APP_PAGE_TITLE} 支持共享挖掘增量日志缓存,开启此功能的任务可直接从缓存中获取增量事件,无需重复读取源库增量日志。`, - daas_feature_unavailable_upgrade_dec_li3_desc: `${import.meta.env.VUE_APP_PAGE_TITLE}支持通过 SMTP 协议发告警邮件,让用户在常用邮箱及时接收异常通知,助其感知异常,保障任务运行稳定可靠。`, + daas_feature_unavailable_upgrade_dec_li1_desc: `基于自研技术,${ + import.meta.env.VUE_APP_PAGE_TITLE + } 能最大程度保障数据一致性,还支持数据表数据校验,以验证和确保数据流转正确,满足生产环境要求。`, + daas_feature_unavailable_upgrade_dec_li2_desc: `为减轻源端数据库压力,${ + import.meta.env.VUE_APP_PAGE_TITLE + } 支持共享挖掘增量日志缓存,开启此功能的任务可直接从缓存中获取增量事件,无需重复读取源库增量日志。`, + daas_feature_unavailable_upgrade_dec_li3_desc: `${ + import.meta.env.VUE_APP_PAGE_TITLE + }支持通过 SMTP 协议发告警邮件,让用户在常用邮箱及时接收异常通知,助其感知异常,保障任务运行稳定可靠。`, daas_feature_unavailable_upgrade_dec_li4_desc: '角色是权限合集,可为其授予多权限并授予用户,用户继承所有权限,依此设计可先创角色再赋予用户,无需为每个用户配置权限,以简化运维管理和提升安全性。', daas_feature_unavailable_upgrade_dec_li5_desc: '', diff --git a/apps/daas/src/i18n/langs/zh-TW.js b/apps/daas/src/i18n/langs/zh-TW.js index bda2939348..e962beed30 100644 --- a/apps/daas/src/i18n/langs/zh-TW.js +++ b/apps/daas/src/i18n/langs/zh-TW.js @@ -713,7 +713,9 @@ export default { setting_license_alarm: ' license 到期提前提醒(天)', setting_License_expiry_email_reminder_: 'license 到期提前幾天提醒設置', setting_flow_engine_version: ' 流程引擎版本', - setting_tapdata_agent_version: `${import.meta.env.VUE_APP_PAGE_TITLE} agent版本`, + setting_tapdata_agent_version: `${ + import.meta.env.VUE_APP_PAGE_TITLE + } agent版本`, setting_doc_base_url: ' 幫助文檔URL', setting_help: ' 幫助文檔', setting_Ip_addresses: ' Ipv4地址(多個逗號分隔)', @@ -911,8 +913,16 @@ export default { user_list_bulk_freeze: '批量凍結', user_list_bulk_check: '批量校驗', user_list_del_user: '刪除用戶 {0} 後,此用戶將無法恢復', - user_list_activetion_user: `激活用戶 {0} 後,此用戶將可以使用 ${import.meta.env.VUE_APP_PAGE_TITLE} 系統`, - user_list_freeze_user: `凍結用戶 {0} 後,此用戶將不可以使用 ${import.meta.env.VUE_APP_PAGE_TITLE} 系統`, + user_list_delete_alarm_confirm: + '刪除用戶「{username}」({email})?該用戶直接作為告警接收對象的任務有 {count} 個,所屬用戶組:{groups}。刪除後,將不再通過該用戶本人或所屬用戶組接收告警。', + user_list_delete_alarm_no_group: '無', + user_list_alarm_impact_failed: '無法取得告警影響範圍,請稍後重試', + user_list_activetion_user: `激活用戶 {0} 後,此用戶將可以使用 ${ + import.meta.env.VUE_APP_PAGE_TITLE + } 系統`, + user_list_freeze_user: `凍結用戶 {0} 後,此用戶將不可以使用 ${ + import.meta.env.VUE_APP_PAGE_TITLE + } 系統`, user_list_check_user: '通過校驗用戶 {0} 的郵箱後,此用戶可以被激活', user_list_activetion_success: '激活成功', user_list_activetion_error: '激活失敗', @@ -2029,6 +2039,29 @@ export default { notification_modular_user: '用戶', notification_modular_role: '角色', notification_modular_accessCode: '訪問碼', + notification_modular_alarmReceiver: '告警接收對象', + notification_modular_userGroup: '用戶組', + notification_operation_batch_update: ' 批量修改了 ', + notification_alarm_receiver_update: + '修改了任務【{parameter1}】的告警接收對象', + notification_alarm_receiver_update_mode: + '修改了任務【{parameter1}】的告警接收對象,操作模式【{parameter2}】', + notification_alarm_receiver_update_change: + '修改了任務【{parameter1}】的告警接收對象,{parameter3}', + notification_alarm_receiver_update_mode_change: + '修改了任務【{parameter1}】的告警接收對象,操作模式【{parameter2}】,{parameter3}', + notification_alarm_receiver_batch_update: + '以【{parameter2}】批量修改了任務【{parameter1}】的告警接收對象', + notification_alarm_receiver_batch_update_change: + '以【{parameter2}】批量修改了任務【{parameter1}】的告警接收對象,{parameter3}', + notification_user_group_delete: '刪除了用戶組【{parameter1}】', + notification_user_group_delete_mode: + '刪除了用戶組【{parameter1}】,操作模式【{parameter2}】', + notification_user_group_delete_change: + '刪除了用戶組【{parameter1}】,{parameter3}', + notification_user_group_delete_mode_change: + '刪除了用戶組【{parameter1}】,操作模式【{parameter2}】,{parameter3}', + notification_alarm_receiver_before_after: '修改前:{before},修改後:{after}', notification_operation_readnotification_modular_message: '', dialog_placeholderTable: '僅支持英文、數字、下劃線、點、減號,並以英文字母開頭,不允許 system 開頭', @@ -2280,9 +2313,15 @@ export default { daas_feature_unavailable_upgrade_dec_li3: '告警設置', daas_feature_unavailable_upgrade_dec_li4: '權限管理(僅企業版)', daas_feature_unavailable_upgrade_dec_li5: '更多數據源', - daas_feature_unavailable_upgrade_dec_li1_desc: `基於自研技術,${import.meta.env.VUE_APP_PAGE_TITLE} 能最大程度保障數據一致性,還支持數據表數據校驗,以驗證和確保數據流轉正確,滿足生產環境要求。`, - daas_feature_unavailable_upgrade_dec_li2_desc: `為減輕源端數據庫壓力,${import.meta.env.VUE_APP_PAGE_TITLE} 支持共享挖掘增量日誌緩存,開啓此功能的任務可直接從緩存中獲取增量事件,無需重復讀取源庫增量日誌。`, - daas_feature_unavailable_upgrade_dec_li3_desc: `${import.meta.env.VUE_APP_PAGE_TITLE} 支持通過 SMTP 協議發告警郵件,讓用戶在常用郵箱及時接收異常通知,助其感知異常,保障任務運行穩定可靠。`, + daas_feature_unavailable_upgrade_dec_li1_desc: `基於自研技術,${ + import.meta.env.VUE_APP_PAGE_TITLE + } 能最大程度保障數據一致性,還支持數據表數據校驗,以驗證和確保數據流轉正確,滿足生產環境要求。`, + daas_feature_unavailable_upgrade_dec_li2_desc: `為減輕源端數據庫壓力,${ + import.meta.env.VUE_APP_PAGE_TITLE + } 支持共享挖掘增量日誌緩存,開啓此功能的任務可直接從緩存中獲取增量事件,無需重復讀取源庫增量日誌。`, + daas_feature_unavailable_upgrade_dec_li3_desc: `${ + import.meta.env.VUE_APP_PAGE_TITLE + } 支持通過 SMTP 協議發告警郵件,讓用戶在常用郵箱及時接收異常通知,助其感知異常,保障任務運行穩定可靠。`, daas_feature_unavailable_upgrade_dec_li4_desc: '角色是權限合集,可為其授予多權限並授予用戶,用戶繼承所有權限,依此設計可先創角色再賦予用戶,無需為每個用戶配置權限,以簡化運維管理和提升安全性。', daas_feature_unavailable_upgrade_dec_li5_desc: '', diff --git a/apps/daas/src/views/notification/UserOperation.vue b/apps/daas/src/views/notification/UserOperation.vue index 2f35884f4d..a247ee6475 100644 --- a/apps/daas/src/views/notification/UserOperation.vue +++ b/apps/daas/src/views/notification/UserOperation.vue @@ -54,6 +54,12 @@ const canOpenSource = computed( () => hasSourceId.value && !!sourceRouteName.value, ) +const RECEIVER_MODE_KEYS: Record = { + APPEND: 'packages_business_task_batch_alarm_mode_append', + REPLACE: 'packages_business_task_batch_alarm_mode_replace', + REMOVE: 'packages_business_task_batch_alarm_mode_remove', +} + const message = computed(() => { if (props.record.i18nMessage) { return props.record.i18nMessage @@ -61,6 +67,8 @@ const message = computed(() => { const modular = props.record.modular === 'migrate' ? 'migration' : props.record.modular + const specialMessage = buildSpecialMessage(modular) + if (specialMessage) return specialMessage return [ `${t('notification_account')} `, @@ -71,6 +79,87 @@ const message = computed(() => { ].join('') }) +function buildSpecialMessage(modular: unknown) { + const operation = toText(props.record.operation) + const hasMode = toText(props.record.parameter2) !== '' + const hasChange = formatChange(props.record.parameter3) !== '' + + if (modular === 'alarmReceiver' && operation === 'update') { + if (hasMode && hasChange) { + return t('notification_alarm_receiver_update_mode_change') + } + if (hasMode) return t('notification_alarm_receiver_update_mode') + if (hasChange) return t('notification_alarm_receiver_update_change') + return t('notification_alarm_receiver_update') + } + + if (modular === 'alarmReceiver' && operation === 'batch_update') { + if (hasChange) return t('notification_alarm_receiver_batch_update_change') + return t('notification_alarm_receiver_batch_update') + } + + if (modular === 'userGroup' && operation === 'delete') { + if (hasMode && hasChange) { + return t('notification_user_group_delete_mode_change') + } + if (hasMode) return t('notification_user_group_delete_mode') + if (hasChange) return t('notification_user_group_delete_change') + return t('notification_user_group_delete') + } + + return '' +} + +function formatMode(value: unknown) { + const text = toText(value) + const key = RECEIVER_MODE_KEYS[text] + return key ? t(key) : text +} + +function stringifyChange(value: unknown): string { + if (value == null || value === '') return '-' + if (typeof value === 'string' || typeof value === 'number') + return String(value) + try { + return JSON.stringify(value) + } catch { + return String(value) + } +} + +function formatChange(value: unknown): string { + if (value == null || value === '') return '' + if (typeof value === 'string') { + const trimmed = value.trim() + if ( + (trimmed.startsWith('{') && trimmed.endsWith('}')) || + (trimmed.startsWith('[') && trimmed.endsWith(']')) + ) { + try { + return formatChange(JSON.parse(trimmed)) + } catch { + return value + } + } + return value + } + if (typeof value === 'number' || typeof value === 'boolean') { + return String(value) + } + if (typeof value === 'object') { + const record = value as Record + const before = record.before ?? record.beforeValue ?? record.old + const after = record.after ?? record.afterValue ?? record.new + if (before !== undefined || after !== undefined) { + return t('notification_alarm_receiver_before_after', { + before: stringifyChange(before), + after: stringifyChange(after), + }) + } + } + return stringifyChange(value) +} + const UserOperationContent = () => renderMessage() function renderMessage() { @@ -123,6 +212,18 @@ function getPlaceholderText(key: string) { return toText(props.record.username) || toText(props.record.email) } + if (key === 'parameter2' && props.record.modular === 'alarmReceiver') { + return formatMode(props.record.parameter2) + } + + if ( + key === 'parameter3' && + (props.record.modular === 'alarmReceiver' || + props.record.modular === 'userGroup') + ) { + return formatChange(props.record.parameter3) || ' ' + } + return toText(props.record[key]) } diff --git a/apps/daas/src/views/user/List.vue b/apps/daas/src/views/user/List.vue index 502e03e6da..a94abc3fd9 100644 --- a/apps/daas/src/views/user/List.vue +++ b/apps/daas/src/views/user/List.vue @@ -7,6 +7,7 @@ import { countUsers, createUser, deleteUser, + fetchUserAlarmImpact, fetchUsers, updateUser, updateUserInfo, @@ -413,7 +414,9 @@ export default { this.table.fetch(1) }, handleSortTable({ order, prop }) { - this.order = `${order ? prop : 'last_updated'} ${order === 'ascending' ? 'ASC' : 'DESC'}` + this.order = `${order ? prop : 'last_updated'} ${ + order === 'ascending' ? 'ASC' : 'DESC' + }` this.table.fetch(1) }, // 选中数据 @@ -566,6 +569,7 @@ export default { .map((item) => ({ id: item.id, value: item.value, + gid: item.gid, })) params.listtags = listtags @@ -588,9 +592,32 @@ export default { } }) }, + countOf(value) { + if (Array.isArray(value)) return value.length + const numberValue = Number(value) + return Number.isFinite(numberValue) ? numberValue : 0 + }, // 删除用户 - remove(item) { - this.$confirm(this.$t('user_list_del_user', [item.username]), { + async remove(item) { + let impact + try { + impact = await fetchUserAlarmImpact(item.id) + } catch (error) { + console.error(error) + this.$message.error(this.$t('user_list_alarm_impact_failed')) + return + } + const groups = (impact?.groups || []) + .map((group) => group?.name) + .filter(Boolean) + .join(', ') + const message = this.$t('user_list_delete_alarm_confirm', { + username: impact?.username || item.username || '', + email: impact?.email || item.email || '-', + count: this.countOf(impact?.directTaskCount), + groups: groups || this.$t('user_list_delete_alarm_no_group'), + }) + this.$confirm(message, { beforeClose: (action, instance, done) => { if (action === 'confirm') { instance.confirmButtonLoading = true @@ -1120,12 +1147,18 @@ export default { v-for="i in 3" :key="i" class="password-strength__bar" - :class="`password-strength__bar--${passwordStrength >= i ? ['weak', 'medium', 'strong'][passwordStrength - 1] : 'empty'}`" + :class="`password-strength__bar--${ + passwordStrength >= i + ? ['weak', 'medium', 'strong'][passwordStrength - 1] + : 'empty' + }`" /> {{ [ @@ -1226,10 +1259,7 @@ export default { - + diff --git a/packages/api/src/core/alarm.ts b/packages/api/src/core/alarm.ts index a2bc46602e..2a040bf8c4 100644 --- a/packages/api/src/core/alarm.ts +++ b/packages/api/src/core/alarm.ts @@ -97,10 +97,74 @@ export function getAlarmChannels() { return requestClient.get(`${BASE_URL}/channels`) } +export type AlarmReceiverType = 'USER' | 'USER_GROUP' | 'EMAIL' + +export type AlarmReceiverStatus = 'SYSTEM_DEFAULT' | 'CUSTOM' | 'NONE' + +export type AlarmReceiverMode = 'APPEND' | 'REPLACE' | 'REMOVE' + +export interface AlarmReceiver { + type: AlarmReceiverType + id?: string + email?: string +} + +export interface AlarmReceiverCandidateUser { + id: string + username: string + email?: string +} + +export interface AlarmReceiverCandidateGroup { + id: string + name: string + gid?: string + parentId?: string + validEmailCount?: number +} + +export interface AlarmReceiverCandidates { + users?: AlarmReceiverCandidateUser[] + groups?: AlarmReceiverCandidateGroup[] +} + +export interface AlarmReceiverPreviewEmail { + email: string + sources?: string[] +} + +export interface AlarmReceiverPreviewInvalid { + type?: string + id?: string + reason?: string +} + +export interface AlarmReceiverPreview { + mode?: string + status?: AlarmReceiverStatus + emails?: AlarmReceiverPreviewEmail[] + invalid?: AlarmReceiverPreviewInvalid[] +} + +export interface BatchUpdateTaskAlarmDetail { + id: string + name?: string + code: string + message?: string +} + +export interface BatchUpdateTaskAlarmResult { + succeeded?: number + failed?: number + skipped?: number + details?: BatchUpdateTaskAlarmDetail[] +} + export function updateTaskAlarm(params: { alarmRules?: AlarmRuleVO[] | null alarmSettings?: AlarmSettingVO[] | null - emailReceivers?: string[] | null + alarmReceivers?: AlarmReceiver[] | null + useSystemDefaultReceivers?: boolean nodeId?: null | string taskId?: null | string }) { @@ -111,7 +175,35 @@ export function batchUpdateTaskAlarm(params: { taskIds: string[] alarmRules?: AlarmRuleVO[] | null alarmSettings?: AlarmSettingVO[] | null - emailReceivers?: string[] | null + alarmReceivers?: AlarmReceiver[] | null + receiverMode?: AlarmReceiverMode +}) { + return requestClient.post( + '/api/task/alarm/batch-update', + params, + ) +} + +export function fetchAlarmReceiverCandidates(params?: { + taskId?: string + taskIds?: string[] | string }) { - return requestClient.post('/api/task/alarm/batch-update', params) + const query: Record = {} + if (params?.taskId) query.taskId = params.taskId + if (params?.taskIds) { + query.taskIds = Array.isArray(params.taskIds) + ? params.taskIds.filter(Boolean).join(',') + : params.taskIds + } + return requestClient.get( + `${BASE_URL}/receiverCandidates`, + { params: query }, + ) +} + +export function fetchAlarmReceiverPreview(taskId: string) { + return requestClient.get( + `${BASE_URL}/receiverPreview`, + { params: { taskId } }, + ) } diff --git a/packages/api/src/core/user-groups.ts b/packages/api/src/core/user-groups.ts index c2bdc3727c..f70a3d1ba8 100644 --- a/packages/api/src/core/user-groups.ts +++ b/packages/api/src/core/user-groups.ts @@ -50,6 +50,20 @@ export function findOneUserGroup(params?: any) { return requestClient.get(`${BASE_URL}/findOne`, { params }) } +export interface UserGroupAlarmImpact { + name?: string + memberCount?: number + totalMemberCount?: number + affectedTasks?: number | unknown[] + highRiskTasks?: number | unknown[] +} + +export function fetchUserGroupAlarmImpact(id: string) { + return requestClient.get( + `${BASE_URL}/${encodeURIComponent(id)}/alarmImpact`, + ) +} + /** * Update user group */ diff --git a/packages/api/src/core/users.ts b/packages/api/src/core/users.ts index d1dd80f2c5..f272a6b926 100644 --- a/packages/api/src/core/users.ts +++ b/packages/api/src/core/users.ts @@ -71,7 +71,9 @@ export function getUserRoles(params: any) { export function upsertUserWithWhere(where: any, params: any) { return requestClient.post( - `${BASE_URL}/upsertWithWhere?where=${encodeURIComponent(JSON.stringify(where))}`, + `${BASE_URL}/upsertWithWhere?where=${encodeURIComponent( + JSON.stringify(where), + )}`, params, ) } @@ -140,3 +142,23 @@ export function batchUpdateUserListtags(params: any) { export function deleteUser(id: string) { return requestClient.delete(`${BASE_URL}/${id}`) } + +export interface UserAlarmImpactGroup { + id?: string + name?: string +} + +export interface UserAlarmImpact { + username?: string + email?: string + directTaskCount?: number + groups?: UserAlarmImpactGroup[] + affectedTasks?: number | unknown[] + highRiskTasks?: number | unknown[] +} + +export function fetchUserAlarmImpact(id: string) { + return requestClient.get( + `${BASE_URL}/${encodeURIComponent(id)}/alarmImpact`, + ) +} diff --git a/packages/business/src/components/AlarmReceiverSelector.vue b/packages/business/src/components/AlarmReceiverSelector.vue new file mode 100644 index 0000000000..da29748637 --- /dev/null +++ b/packages/business/src/components/AlarmReceiverSelector.vue @@ -0,0 +1,586 @@ + + + + + diff --git a/packages/business/src/locale/lang/en.js b/packages/business/src/locale/lang/en.js index 9737071e8e..efac0a48b9 100644 --- a/packages/business/src/locale/lang/en.js +++ b/packages/business/src/locale/lang/en.js @@ -258,8 +258,8 @@ export default { packages_business_dataFlow_bulkScheuled: 'Batch Start', packages_business_dataFlow_bulkStopping: 'Batch Stop', packages_business_dataFlow_taskBulkOperation: 'Batch Operation', - packages_business_task_batch_alarm_email_action: 'Batch Set Alert Receivers', - packages_business_task_batch_alarm_email_title: 'Batch Set Alert Receivers', + packages_business_task_batch_alarm_email_action: 'Batch Set Alerts', + packages_business_task_batch_alarm_email_title: 'Batch Set Alerts', packages_business_task_batch_alarm_email_label: 'Email Receivers', packages_business_task_batch_alarm_email_placeholder: 'Select email receivers', @@ -269,6 +269,47 @@ export default { 'No email receivers available. Save directly to clear alert receivers from the selected tasks.', packages_business_task_batch_alarm_email_no_edit_permission_tip: '{count} tasks do not have edit permission and will be skipped.', + packages_business_task_batch_alarm_rules: 'Alert Rules', + packages_business_task_batch_alarm_rules_hint: + 'Alert switches and notification interval', + packages_business_task_batch_alarm_rules_overwrite: + 'Saving will overwrite the alert rules of the selected tasks', + packages_business_task_batch_alarm_rules_clear: + 'Saving will clear the alert rules of the selected tasks', + packages_business_task_batch_alarm_thresholds: 'Alert Thresholds', + packages_business_task_batch_alarm_thresholds_hint: + 'Incremental delay and retry count', + packages_business_task_batch_alarm_thresholds_overwrite: + 'Saving will overwrite the alert thresholds of the selected tasks', + packages_business_task_batch_alarm_thresholds_clear: + 'Saving will clear the alert thresholds of the selected tasks', + packages_business_task_batch_alarm_receivers: 'Receivers', + packages_business_task_batch_alarm_keep: 'Do not change', + packages_business_task_batch_alarm_set: 'Set', + packages_business_task_batch_alarm_clear: 'Clear', + packages_business_task_batch_alarm_edit: 'Edit', + packages_business_task_batch_alarm_mode: 'Operation Mode', + packages_business_task_batch_alarm_mode_append: 'Append', + packages_business_task_batch_alarm_mode_replace: 'Replace', + packages_business_task_batch_alarm_mode_remove: 'Remove', + packages_business_task_batch_alarm_interval: + 'Notification interval (seconds)', + packages_business_task_batch_alarm_replace_warning: + 'Existing receivers will be overwritten. {count} tasks will be affected.', + packages_business_task_batch_alarm_result_title: 'Batch Update Result', + packages_business_task_batch_alarm_result_summary: + 'Succeeded {succeeded}, failed {failed}, skipped {skipped}', + packages_business_task_batch_alarm_only_failed: 'Failed only', + packages_business_task_batch_alarm_retry_failed: 'Retry failed items', + packages_business_task_batch_alarm_back: 'Back to edit', + packages_business_task_batch_alarm_col_task: 'Task', + packages_business_task_batch_alarm_col_result: 'Result', + packages_business_task_batch_alarm_col_message: 'Message', + packages_business_task_batch_alarm_result_ok: 'Succeeded', + packages_business_task_batch_alarm_result_failed: 'Failed', + packages_business_task_batch_alarm_result_skipped: 'Skipped', + packages_business_task_batch_alarm_no_edit_result: + 'No edit permission, skipped', packages_business_dataFlow_addTag: 'Add Tag', packages_business_dataVerify_dataVerify: 'Data Verify', packages_business_dataFlow_selectAll: 'Select All', @@ -423,10 +464,16 @@ export default { 'When using RocksDB as the shared mining storage, you need to manually specify an agent.', packages_business_components_connectiontypeselectorsort_wodeshujuyuan: 'My Data Source', - packages_business_components_connectiontypeselectorsort_jiaoyouTap: `Let ${import.meta.env.VUE_APP_PAGE_TITLE} conduct a comprehensive quality test to ensure the stability and quality of the plugin`, + packages_business_components_connectiontypeselectorsort_jiaoyouTap: `Let ${ + import.meta.env.VUE_APP_PAGE_TITLE + } conduct a comprehensive quality test to ensure the stability and quality of the plugin`, packages_business_components_connectiontypeselectorsort_zhuyizhelishi: 'Note: here is the data source plugin uploaded by yourself, if you want to use it for production tasks, please submit the source code on GitHub', - packages_business_components_connectiontypeselectorsort_zhuyiBet: `Note: Beta data sources have not passed ${import.meta.env.VUE_APP_PAGE_TITLE}'s certification testing process, and ${import.meta.env.VUE_APP_PAGE_TITLE} does not guarantee the stable operation of these data sources for the time being`, + packages_business_components_connectiontypeselectorsort_zhuyiBet: `Note: Beta data sources have not passed ${ + import.meta.env.VUE_APP_PAGE_TITLE + }'s certification testing process, and ${ + import.meta.env.VUE_APP_PAGE_TITLE + } does not guarantee the stable operation of these data sources for the time being`, packages_business_components_connectiontypeselectorsort_shiyongbanzanbu: 'Stay tuned for the following data sources to open', packages_business_components_connectiontypeselectorsort_betashu: @@ -1157,7 +1204,9 @@ export default { 'Task created successfully, click to view', packages_business_task_created_fail_no_primary_key: 'The task has been created, but since your table does not have a primary key, you need to enter the task editor to manually set the update condition field. Click to view the task.', - packages_business_fdm_create_task_dialog_desc_prefix: `${import.meta.env.VUE_APP_PAGE_TITLE} will automatically create a cloning pipeline task, which will automatically copy the structure and data of the selected`, + packages_business_fdm_create_task_dialog_desc_prefix: `${ + import.meta.env.VUE_APP_PAGE_TITLE + } will automatically create a cloning pipeline task, which will automatically copy the structure and data of the selected`, packages_business_fdm_create_task_dialog_desc_suffix: 'to the Foundational Data Model layer of the data platform and keep the source database and Foundational Data Model layer data in real-time synchronization and automatic validation. In most cases, the structure changes (DDL) of the source database will also be copied to the Foundational Data Model layer. You can monitor the running status of the pipeline task by clicking the ICON on the right side of the database name in the Foundational Data Model layer. You can also choose to modify the physical table name prefix in the Foundational Data Model layer now.', packages_business_mdm_create_task_dialog_desc_prefix: @@ -1174,8 +1223,12 @@ export default { 'Please enter the table name to be newly constructed in the Curated layer. If the table name already exists, the existing data will be overwritten by default.', packages_business_save_and_run_now: 'Save and Run', packages_business_save_only: 'Only Save', - packages_business_target_create_task_dialog_desc_prefix_clone: `${import.meta.env.VUE_APP_PAGE_TITLE} will create a cloning pipeline task to sync`, - packages_business_target_create_task_dialog_desc_prefix_sync: `${import.meta.env.VUE_APP_PAGE_TITLE} will create a sync pipeline task to sync`, + packages_business_target_create_task_dialog_desc_prefix_clone: `${ + import.meta.env.VUE_APP_PAGE_TITLE + } will create a cloning pipeline task to sync`, + packages_business_target_create_task_dialog_desc_prefix_sync: `${ + import.meta.env.VUE_APP_PAGE_TITLE + } will create a sync pipeline task to sync`, packages_business_target_create_task_dialog_desc_to: 'to', packages_business_target_create_task_dialog_desc_suffix: 'Please click button below to continue. You can also change the task name', @@ -1565,7 +1618,11 @@ export default { packages_business_relmig_import: 'MongoDB Relmig Import', packages_business_api_import: 'API Import', packages_business_functions_import: 'Functions Import', - packages_business_relmig_import_desc: `This feature is designed to seamlessly import MongoDB Relational Migrator-exportd relmig project files into ${import.meta.env.VUE_APP_PAGE_TITLE}. After the relmig file is imported, ${import.meta.env.VUE_APP_PAGE_TITLE} will automatically create a task to perform real time data synchronization from source database and transform into JSON data format in MongoDB database.`, + packages_business_relmig_import_desc: `This feature is designed to seamlessly import MongoDB Relational Migrator-exportd relmig project files into ${ + import.meta.env.VUE_APP_PAGE_TITLE + }. After the relmig file is imported, ${ + import.meta.env.VUE_APP_PAGE_TITLE + } will automatically create a task to perform real time data synchronization from source database and transform into JSON data format in MongoDB database.`, packages_business_relmig_upload: 'Upload relmig file', packages_business__relmig_import_connection_tip: "Click here to create one if you haven't done so already.", diff --git a/packages/business/src/locale/lang/zh-CN.js b/packages/business/src/locale/lang/zh-CN.js index 4f35fcbe78..d8460a1271 100644 --- a/packages/business/src/locale/lang/zh-CN.js +++ b/packages/business/src/locale/lang/zh-CN.js @@ -47,8 +47,12 @@ export default { packages_business_connection_form_source_and_target_tip: `此数据连接在 ${ import.meta.env.VUE_APP_PAGE_TITLE } 中能同时作为源和目标使用`, - packages_business_connection_form_source_tip: `此数据连接在 ${import.meta.env.VUE_APP_PAGE_TITLE} 中只能作为源使用,不能作用为目标`, - packages_business_connection_form_target_tip: `此数据连接在 ${import.meta.env.VUE_APP_PAGE_TITLE} 中只能作为目标使用,不能作用为源`, + packages_business_connection_form_source_tip: `此数据连接在 ${ + import.meta.env.VUE_APP_PAGE_TITLE + } 中只能作为源使用,不能作用为目标`, + packages_business_connection_form_target_tip: `此数据连接在 ${ + import.meta.env.VUE_APP_PAGE_TITLE + } 中只能作为目标使用,不能作用为源`, packages_business_connection_form_shared_mining: '使用共享挖掘', packages_business_connection_form_shared_mining_tip: '共享挖掘会挖掘增量日志,当有多个增量任务时不需要重复开启日志采集进程,能极大缓解源库资源的占用和浪费', @@ -232,8 +236,8 @@ export default { packages_business_dataFlow_bulkScheuled: '批量启动', packages_business_dataFlow_bulkStopping: '批量停止', packages_business_dataFlow_taskBulkOperation: '任务操作', - packages_business_task_batch_alarm_email_action: '批量设置告警接收人', - packages_business_task_batch_alarm_email_title: '批量设置告警接收人', + packages_business_task_batch_alarm_email_action: '批量设置告警', + packages_business_task_batch_alarm_email_title: '批量设置告警', packages_business_task_batch_alarm_email_label: '邮件接收人', packages_business_task_batch_alarm_email_placeholder: '请选择邮件接收人', packages_business_task_batch_alarm_email_overwrite_tip: @@ -242,6 +246,43 @@ export default { '暂无可选邮件接收人,可直接保存以清空所选任务的告警接收人', packages_business_task_batch_alarm_email_no_edit_permission_tip: '以下 {count} 个任务没有编辑权限,保存时将自动跳过', + packages_business_task_batch_alarm_rules: '告警规则', + packages_business_task_batch_alarm_rules_hint: '告警项开关与通知间隔', + packages_business_task_batch_alarm_rules_overwrite: + '保存后将覆盖所选任务的告警规则', + packages_business_task_batch_alarm_rules_clear: + '保存后将清空所选任务的告警规则', + packages_business_task_batch_alarm_thresholds: '告警阈值', + packages_business_task_batch_alarm_thresholds_hint: '增量延迟和重试次数', + packages_business_task_batch_alarm_thresholds_overwrite: + '保存后将覆盖所选任务的告警阈值', + packages_business_task_batch_alarm_thresholds_clear: + '保存后将清空所选任务的告警阈值', + packages_business_task_batch_alarm_receivers: '接收对象', + packages_business_task_batch_alarm_keep: '不修改', + packages_business_task_batch_alarm_set: '设置', + packages_business_task_batch_alarm_clear: '清空', + packages_business_task_batch_alarm_edit: '修改', + packages_business_task_batch_alarm_mode: '操作模式', + packages_business_task_batch_alarm_mode_append: '追加', + packages_business_task_batch_alarm_mode_replace: '替换', + packages_business_task_batch_alarm_mode_remove: '移除', + packages_business_task_batch_alarm_interval: '通知间隔(秒)', + packages_business_task_batch_alarm_replace_warning: + '原接收对象将被覆盖,将影响 {count} 个任务', + packages_business_task_batch_alarm_result_title: '批量设置结果', + packages_business_task_batch_alarm_result_summary: + '成功 {succeeded},失败 {failed},跳过 {skipped}', + packages_business_task_batch_alarm_only_failed: '只看失败', + packages_business_task_batch_alarm_retry_failed: '重试失败项', + packages_business_task_batch_alarm_back: '返回修改', + packages_business_task_batch_alarm_col_task: '任务', + packages_business_task_batch_alarm_col_result: '结果', + packages_business_task_batch_alarm_col_message: '说明', + packages_business_task_batch_alarm_result_ok: '成功', + packages_business_task_batch_alarm_result_failed: '失败', + packages_business_task_batch_alarm_result_skipped: '跳过', + packages_business_task_batch_alarm_no_edit_result: '没有编辑权限,已跳过', packages_business_dataFlow_addTag: '添加标签', packages_business_dataVerify_dataVerify: '数据校验', packages_business_dataFlow_selectAll: '全选', @@ -387,10 +428,16 @@ export default { '选用RocksDB作为共享挖掘外存时,需要手动指定一个Agent', packages_business_components_connectiontypeselectorsort_wodeshujuyuan: '我的数据源', - packages_business_components_connectiontypeselectorsort_jiaoyouTap: `交由 ${import.meta.env.VUE_APP_PAGE_TITLE} 进行全面的质量测试,以保证插件的稳定性和质量`, + packages_business_components_connectiontypeselectorsort_jiaoyouTap: `交由 ${ + import.meta.env.VUE_APP_PAGE_TITLE + } 进行全面的质量测试,以保证插件的稳定性和质量`, packages_business_components_connectiontypeselectorsort_zhuyizhelishi: '注意:这里是您自己上传的数据源插件,如果要用于生产任务,请在GitHub上提交源代码', - packages_business_components_connectiontypeselectorsort_zhuyiBet: `注意:Beta 数据源尚未通过 ${import.meta.env.VUE_APP_PAGE_TITLE} 的认证测试流程,${import.meta.env.VUE_APP_PAGE_TITLE} 暂不保证这些数据源的稳定运行`, + packages_business_components_connectiontypeselectorsort_zhuyiBet: `注意:Beta 数据源尚未通过 ${ + import.meta.env.VUE_APP_PAGE_TITLE + } 的认证测试流程,${ + import.meta.env.VUE_APP_PAGE_TITLE + } 暂不保证这些数据源的稳定运行`, packages_business_components_connectiontypeselectorsort_shiyongbanzanbu: '敬请期待以下数据源开放', packages_business_components_connectiontypeselectorsort_betashu: 'Beta数据源', @@ -1050,7 +1097,9 @@ export default { packages_business_task_created_success: '任务创建成功,点击查看', packages_business_task_created_fail_no_primary_key: '任务已经创建,但由于您的表没有主键,需要进入任务编辑手动设置更新条件字段,点击查看任务', - packages_business_fdm_create_task_dialog_desc_prefix: `${import.meta.env.VUE_APP_PAGE_TITLE} 将自动创建一个数据复制管道任务,将您选择的`, + packages_business_fdm_create_task_dialog_desc_prefix: `${ + import.meta.env.VUE_APP_PAGE_TITLE + } 将自动创建一个数据复制管道任务,将您选择的`, packages_business_fdm_create_task_dialog_desc_suffix: '的结构和数据自动复制到数据平台的 Cache 层并保持源库和Cache 层数据的准实时同步及自动校验。在大部分时候源库的结构改动(DDL)也会被复制到Cache 层。您可以在通过点击Cache 层里面的库名右侧的ICON来监控该管道任务的运行状态。您也可以选择现在修改在 Cache 层的物理表名前缀。', packages_business_mdm_create_task_dialog_desc_prefix: @@ -1067,8 +1116,12 @@ export default { '请输入打算新构建在Curated 层里面的表名。如果该表名已经存在,默认将覆盖已有的数据', packages_business_save_and_run_now: '保存并运行', packages_business_save_only: '仅保存', - packages_business_target_create_task_dialog_desc_prefix_clone: `${import.meta.env.VUE_APP_PAGE_TITLE} 将创建一个数据复制任务,将`, - packages_business_target_create_task_dialog_desc_prefix_sync: `${import.meta.env.VUE_APP_PAGE_TITLE} 将创建一个数据开发任务,将`, + packages_business_target_create_task_dialog_desc_prefix_clone: `${ + import.meta.env.VUE_APP_PAGE_TITLE + } 将创建一个数据复制任务,将`, + packages_business_target_create_task_dialog_desc_prefix_sync: `${ + import.meta.env.VUE_APP_PAGE_TITLE + } 将创建一个数据开发任务,将`, packages_business_target_create_task_dialog_desc_to: '同步到', packages_business_target_create_task_dialog_desc_suffix: '请点击下面的按钮继续,您也可以更改任务名称。', @@ -1403,7 +1456,11 @@ export default { packages_business_relmig_import: 'MongoDB Relmig 导入', packages_business_api_import: 'API 导入', packages_business_functions_import: '函数导入', - packages_business_relmig_import_desc: `这个功能旨在无缝导入 MongoDB 关系迁移器导出的 relmig 项目文件到 ${import.meta.env.VUE_APP_PAGE_TITLE}。在 relmig 文件被导入后, ${import.meta.env.VUE_APP_PAGE_TITLE} 将自动创建一个任务来执行源数据库的实时数据同步,并将其转换为 MongoDB 数据库中的 JSON 数据格式。`, + packages_business_relmig_import_desc: `这个功能旨在无缝导入 MongoDB 关系迁移器导出的 relmig 项目文件到 ${ + import.meta.env.VUE_APP_PAGE_TITLE + }。在 relmig 文件被导入后, ${ + import.meta.env.VUE_APP_PAGE_TITLE + } 将自动创建一个任务来执行源数据库的实时数据同步,并将其转换为 MongoDB 数据库中的 JSON 数据格式。`, packages_business_relmig_upload: '上传 relmig 文件', packages_business__relmig_import_connection_tip: '如果您还没有创建,请点击这里', diff --git a/packages/business/src/locale/lang/zh-TW.js b/packages/business/src/locale/lang/zh-TW.js index baa4d2dbf6..563606839d 100644 --- a/packages/business/src/locale/lang/zh-TW.js +++ b/packages/business/src/locale/lang/zh-TW.js @@ -47,8 +47,12 @@ export default { packages_business_connection_form_source_and_target_tip: `此數據連接在 ${ import.meta.env.VUE_APP_PAGE_TITLE } 中能同時作為源和目標使用`, - packages_business_connection_form_source_tip: `此數據連接在 ${import.meta.env.VUE_APP_PAGE_TITLE} 中只能作為源使用,不能作用為目標`, - packages_business_connection_form_target_tip: `此數據連接在 ${import.meta.env.VUE_APP_PAGE_TITLE} 中只能作為目標使用,不能作用為源`, + packages_business_connection_form_source_tip: `此數據連接在 ${ + import.meta.env.VUE_APP_PAGE_TITLE + } 中只能作為源使用,不能作用為目標`, + packages_business_connection_form_target_tip: `此數據連接在 ${ + import.meta.env.VUE_APP_PAGE_TITLE + } 中只能作為目標使用,不能作用為源`, packages_business_connection_form_shared_mining: '使用共享挖掘', packages_business_connection_form_shared_mining_tip: '共享挖掘会挖掘增量日志,当有多个增量任务时不需要重复开启日志采集进程,能极大缓解源库资源的占用和浪费', @@ -231,8 +235,8 @@ export default { packages_business_dataFlow_bulkScheuled: '批量啟動', packages_business_dataFlow_bulkStopping: '批量停止', packages_business_dataFlow_taskBulkOperation: '任務操作', - packages_business_task_batch_alarm_email_action: '批量設置告警接收人', - packages_business_task_batch_alarm_email_title: '批量設置告警接收人', + packages_business_task_batch_alarm_email_action: '批量設置告警', + packages_business_task_batch_alarm_email_title: '批量設置告警', packages_business_task_batch_alarm_email_label: '郵件接收人', packages_business_task_batch_alarm_email_placeholder: '請選擇郵件接收人', packages_business_task_batch_alarm_email_overwrite_tip: @@ -241,6 +245,43 @@ export default { '暫無可選郵件接收人,可直接保存以清空所選任務的告警接收人', packages_business_task_batch_alarm_email_no_edit_permission_tip: '以下 {count} 個任務沒有編輯權限,保存時將自動跳過', + packages_business_task_batch_alarm_rules: '告警規則', + packages_business_task_batch_alarm_rules_hint: '告警項開關與通知間隔', + packages_business_task_batch_alarm_rules_overwrite: + '保存後將覆蓋所選任務的告警規則', + packages_business_task_batch_alarm_rules_clear: + '保存後將清空所選任務的告警規則', + packages_business_task_batch_alarm_thresholds: '告警閾值', + packages_business_task_batch_alarm_thresholds_hint: '增量延遲和重試次數', + packages_business_task_batch_alarm_thresholds_overwrite: + '保存後將覆蓋所選任務的告警閾值', + packages_business_task_batch_alarm_thresholds_clear: + '保存後將清空所選任務的告警閾值', + packages_business_task_batch_alarm_receivers: '接收對象', + packages_business_task_batch_alarm_keep: '不修改', + packages_business_task_batch_alarm_set: '設置', + packages_business_task_batch_alarm_clear: '清空', + packages_business_task_batch_alarm_edit: '修改', + packages_business_task_batch_alarm_mode: '操作模式', + packages_business_task_batch_alarm_mode_append: '追加', + packages_business_task_batch_alarm_mode_replace: '替換', + packages_business_task_batch_alarm_mode_remove: '移除', + packages_business_task_batch_alarm_interval: '通知間隔(秒)', + packages_business_task_batch_alarm_replace_warning: + '原接收對象將被覆蓋,將影響 {count} 個任務', + packages_business_task_batch_alarm_result_title: '批量設置結果', + packages_business_task_batch_alarm_result_summary: + '成功 {succeeded},失敗 {failed},跳過 {skipped}', + packages_business_task_batch_alarm_only_failed: '只看失敗', + packages_business_task_batch_alarm_retry_failed: '重試失敗項', + packages_business_task_batch_alarm_back: '返回修改', + packages_business_task_batch_alarm_col_task: '任務', + packages_business_task_batch_alarm_col_result: '結果', + packages_business_task_batch_alarm_col_message: '說明', + packages_business_task_batch_alarm_result_ok: '成功', + packages_business_task_batch_alarm_result_failed: '失敗', + packages_business_task_batch_alarm_result_skipped: '跳過', + packages_business_task_batch_alarm_no_edit_result: '沒有編輯權限,已跳過', packages_business_dataFlow_addTag: '添加標籤', packages_business_dataVerify_dataVerify: '數據校驗', packages_business_dataFlow_selectAll: '全選', @@ -387,10 +428,16 @@ export default { '選用RocksDB作為共享挖掘外存時,需要手動指定一個Agent', packages_business_components_connectiontypeselectorsort_wodeshujuyuan: '我的數據源', - packages_business_components_connectiontypeselectorsort_jiaoyouTap: `交由 ${import.meta.env.VUE_APP_PAGE_TITLE} 進行全面的質量測試,以保證插件的穩定性和質量`, + packages_business_components_connectiontypeselectorsort_jiaoyouTap: `交由 ${ + import.meta.env.VUE_APP_PAGE_TITLE + } 進行全面的質量測試,以保證插件的穩定性和質量`, packages_business_components_connectiontypeselectorsort_zhuyizhelishi: '注意:這裡是您自己上傳的數據源插件,如果要用於生產任務,請在GitHub上提交源代碼', - packages_business_components_connectiontypeselectorsort_zhuyiBet: `注意:Beta 數據源尚未通過 ${import.meta.env.VUE_APP_PAGE_TITLE} 的認證測試流程,${import.meta.env.VUE_APP_PAGE_TITLE}暫不保證這些數據源的穩定運行`, + packages_business_components_connectiontypeselectorsort_zhuyiBet: `注意:Beta 數據源尚未通過 ${ + import.meta.env.VUE_APP_PAGE_TITLE + } 的認證測試流程,${ + import.meta.env.VUE_APP_PAGE_TITLE + }暫不保證這些數據源的穩定運行`, packages_business_components_connectiontypeselectorsort_shiyongbanzanbu: '敬請期待以下數據源開放', packages_business_components_connectiontypeselectorsort_betashu: 'Beta数据源', @@ -1049,7 +1096,9 @@ export default { packages_business_task_created_success: '任務創建成功,點擊查看', packages_business_task_created_fail_no_primary_key: '任務已經創建,但由於您的表沒有主鍵,需要進入任務編輯手動設置更新條件字段,點擊查看任務', - packages_business_fdm_create_task_dialog_desc_prefix: `${import.meta.env.VUE_APP_PAGE_TITLE} 將自動創建一個數據複製管道任務,將您選擇的`, + packages_business_fdm_create_task_dialog_desc_prefix: `${ + import.meta.env.VUE_APP_PAGE_TITLE + } 將自動創建一個數據複製管道任務,將您選擇的`, packages_business_fdm_create_task_dialog_desc_suffix: '的結構和數據自動複製到數據平台的 Cache 層並保持源庫和Cache 層數據的准實時同步及自動校驗。在大部分時候源庫的結構改動(DDL)也會被複製到Cache 層。您可以在通過點擊Cache 層裡面的庫名右側的ICON來監控該管道任務的運行狀態。您也可以選擇現在修改在Cache 層的物理表名前綴。', packages_business_mdm_create_task_dialog_desc_prefix: @@ -1066,8 +1115,12 @@ export default { '請輸入打算新構建在Curated 層裡面的表名。如果該表名已經存在,默認將覆蓋已有的數據', packages_business_save_and_run_now: '保存並運行', packages_business_save_only: '僅保存', - packages_business_target_create_task_dialog_desc_prefix_clone: `${import.meta.env.VUE_APP_PAGE_TITLE} 將創建一個數據複製任務,將`, - packages_business_target_create_task_dialog_desc_prefix_sync: `${import.meta.env.VUE_APP_PAGE_TITLE} 將創建一個數據開發任務,將`, + packages_business_target_create_task_dialog_desc_prefix_clone: `${ + import.meta.env.VUE_APP_PAGE_TITLE + } 將創建一個數據複製任務,將`, + packages_business_target_create_task_dialog_desc_prefix_sync: `${ + import.meta.env.VUE_APP_PAGE_TITLE + } 將創建一個數據開發任務,將`, packages_business_target_create_task_dialog_desc_to: '同步到', packages_business_target_create_task_dialog_desc_suffix: '請點擊下面的按鈕繼續,您也可以更改任務名稱。', @@ -1393,7 +1446,11 @@ export default { packages_business_relmig_import: 'MongoDB Relmig 導入', packages_business_api_import: 'API 導入', packages_business_functions_import: '函數導入', - packages_business_relmig_import_desc: `這個功能旨在無縫導入 MongoDB 關係遷移器導出的 relmig 項目文件到 ${import.meta.env.VUE_APP_PAGE_TITLE} 。在 relmig 文件被導入後,${import.meta.env.VUE_APP_PAGE_TITLE} 將自動創建一個任務來執行源數據庫的實時數據同步,並將其轉換為 MongoDB 數據庫中的 JSON 數據格式。`, + packages_business_relmig_import_desc: `這個功能旨在無縫導入 MongoDB 關係遷移器導出的 relmig 項目文件到 ${ + import.meta.env.VUE_APP_PAGE_TITLE + } 。在 relmig 文件被導入後,${ + import.meta.env.VUE_APP_PAGE_TITLE + } 將自動創建一個任務來執行源數據庫的實時數據同步,並將其轉換為 MongoDB 數據庫中的 JSON 數據格式。`, packages_business_relmig_upload: '上傳 relmig 文件', packages_business__relmig_import_connection_tip: '如果您還沒有創建,請點擊這裡', diff --git a/packages/business/src/views/task/BatchAlarmEmailDialog.vue b/packages/business/src/views/task/BatchAlarmEmailDialog.vue index b7ea01b8b1..66e52807f0 100644 --- a/packages/business/src/views/task/BatchAlarmEmailDialog.vue +++ b/packages/business/src/views/task/BatchAlarmEmailDialog.vue @@ -1,14 +1,19 @@