diff --git a/spug_api/apps/alarm/urls.py b/spug_api/apps/alarm/urls.py index 950b1aa..d9fe2a7 100644 --- a/spug_api/apps/alarm/urls.py +++ b/spug_api/apps/alarm/urls.py @@ -9,4 +9,5 @@ urlpatterns = [ path('alarm/', AlarmView.as_view()), path('group/', GroupView.as_view()), path('contact/', ContactView.as_view()), + path('test/', handle_test), ] diff --git a/spug_api/apps/alarm/views.py b/spug_api/apps/alarm/views.py index 774aac0..eb51afd 100644 --- a/spug_api/apps/alarm/views.py +++ b/spug_api/apps/alarm/views.py @@ -3,6 +3,7 @@ # Released under the AGPL-3.0 License. from django.views.generic import View from libs import json_response, JsonParser, Argument, auth +from libs.spug import Notification from apps.alarm.models import Alarm, Group, Contact from apps.monitor.models import Detection import json @@ -87,3 +88,29 @@ class ContactView(View): return json_response(error=f'报警联系组【{group.name}】包含此联系人,请解除关联后再尝试删除该联系人') Contact.objects.filter(pk=form.id).delete() return json_response(error=error) + + +@auth('alarm.contact.add|alarm.contact.edit') +def handle_test(request): + form, error = JsonParser( + Argument('mode', help='参数错误'), + Argument('value', help='参数错误') + ).parse(request.body) + if error is None: + notify = Notification(None, '1', 'https://spug.cc', 'Spug官网(测试)', '这是一条测试告警信息', None) + if form.mode in ('1', '2', '4') and not notify.spug_key: + return json_response(error='未配置调用凭据(系统设置/基本设置),请配置后再尝试。') + + if form.mode == '1': + notify.monitor_by_wx([form.value]) + elif form.mode == '2': + return json_response(error='目前暂不支持短信告警,请关注后续更新。') + elif form.mode == '3': + notify.monitor_by_dd([form.value]) + elif form.mode == '4': + notify.monitor_by_email([form.value]) + elif form.mode == '5': + notify.monitor_by_qy_wx([form.value]) + else: + return json_response(error='不支持的报警方式') + return json_response(error=error) diff --git a/spug_api/libs/spug.py b/spug_api/libs/spug.py index 1144d33..0dd25c7 100644 --- a/spug_api/libs/spug.py +++ b/spug_api/libs/spug.py @@ -27,16 +27,14 @@ def send_login_wx_code(wx_token, code): class Notification: def __init__(self, grp, event, target, title, message, duration): + self.grp = grp self.event = event self.title = title self.target = target self.message = message self.duration = duration - self.spug_key, self.u_ids = self._parse_args(grp) - - def _parse_args(self, grp): - spug_key = AppSetting.get_default('spug_key') - return spug_key, sum([json.loads(x.contacts) for x in Group.objects.filter(id__in=grp)], []) + self.spug_key = AppSetting.get_default('spug_key') + self.u_ids = [] @staticmethod def handle_request(url, data, mode=None): @@ -63,7 +61,7 @@ class Notification: raise NotImplementedError Notify.make_system_notify('通知发送失败', f'返回数据:{res}') - def _monitor_by_wx(self, users): + def monitor_by_wx(self, users): if not self.spug_key: Notify.make_monitor_notify('发送报警信息失败', '未配置报警服务调用凭据,请在系统管理/系统设置/基本设置/调用凭据中配置。') return @@ -77,7 +75,7 @@ class Notification: } self.handle_request(f'{spug_server}/apis/notify/wx/', data, 'spug') - def _monitor_by_email(self, users): + def monitor_by_email(self, users): mail_service = AppSetting.get_default('mail_service', {}) body = [ f'告警名称:{self.title}', @@ -104,7 +102,7 @@ class Notification: else: Notify.make_monitor_notify('发送报警信息失败', '未配置报警服务调用凭据,请在系统管理/系统设置/报警服务设置中配置。') - def _monitor_by_dd(self, users): + def monitor_by_dd(self, users): texts = [ '## %s ## ' % ('监控告警通知' if self.event == '1' else '告警恢复通知'), f'**告警名称:** {self.title} ', @@ -127,7 +125,7 @@ class Notification: for url in users: self.handle_request(url, data, 'dd') - def _monitor_by_qy_wx(self, users): + def monitor_by_qy_wx(self, users): color, title = ('warning', '监控告警通知') if self.event == '1' else ('info', '告警恢复通知') texts = [ f'## {title}', @@ -148,28 +146,29 @@ class Notification: self.handle_request(url, data, 'wx') def dispatch_monitor(self, modes): + self.u_ids = sum([json.loads(x.contacts) for x in Group.objects.filter(id__in=self.grp)], []) for mode in modes: if mode == '1': users = set(x.wx_token for x in Contact.objects.filter(id__in=self.u_ids, wx_token__isnull=False)) if not users: Notify.make_monitor_notify('发送报警信息失败', '未找到可用的通知对象,请确保设置了相关报警联系人的微信Token。') continue - self._monitor_by_wx(users) + self.monitor_by_wx(users) elif mode == '3': users = set(x.ding for x in Contact.objects.filter(id__in=self.u_ids, ding__isnull=False)) if not users: Notify.make_monitor_notify('发送报警信息失败', '未找到可用的通知对象,请确保设置了相关报警联系人的钉钉。') continue - self._monitor_by_dd(users) + self.monitor_by_dd(users) elif mode == '4': users = set(x.email for x in Contact.objects.filter(id__in=self.u_ids, email__isnull=False)) if not users: Notify.make_monitor_notify('发送报警信息失败', '未找到可用的通知对象,请确保设置了相关报警联系人的邮件地址。') continue - self._monitor_by_email(users) + self.monitor_by_email(users) elif mode == '5': users = set(x.qy_wx for x in Contact.objects.filter(id__in=self.u_ids, qy_wx__isnull=False)) if not users: Notify.make_monitor_notify('发送报警信息失败', '未找到可用的通知对象,请确保设置了相关报警联系人的企业微信。') continue - self._monitor_by_qy_wx(users) + self.monitor_by_qy_wx(users) diff --git a/spug_web/src/pages/alarm/contact/Form.js b/spug_web/src/pages/alarm/contact/Form.js index 57a99a7..9f97c43 100644 --- a/spug_web/src/pages/alarm/contact/Form.js +++ b/spug_web/src/pages/alarm/contact/Form.js @@ -5,13 +5,15 @@ */ import React, { useState } from 'react'; import { observer } from 'mobx-react'; -import { Modal, Form, Input, message } from 'antd'; +import { Modal, Form, Input, Tooltip, message } from 'antd'; +import { ThunderboltOutlined, LoadingOutlined } from '@ant-design/icons'; import http from 'libs/http'; import store from './store'; export default observer(function () { const [form] = Form.useForm(); const [loading, setLoading] = useState(false); + const [testLoading, setTestLoading] = useState('0'); function handleSubmit() { setLoading(true); @@ -25,6 +27,34 @@ export default observer(function () { }, () => setLoading(false)) } + function handleTest(mode, name) { + const value = form.getFieldValue(name) + console.log(name, value) + if (!value) return message.error('请输入后再执行测试') + setTestLoading(mode) + http.post('/api/alarm/test/', {mode, value}) + .then(() => { + message.success('执行成功') + }) + .finally(() => setTestLoading('0')) + } + + function Test(props) { + return ( +
+ {testLoading === props.mode ? ( + + ) : ( + + handleTest(props.mode, props.name)}/> + + )} +
+ ) + } + return ( - - + + + + + - 如何获取微信 Token ?}> - + + + + - + 钉钉收不到通知?请参考 官方文档 }> - + + + + - - + + + + +