From c84f57cb825a9386fd60f5522f90f683d2a892e0 Mon Sep 17 00:00:00 2001 From: wenlele Date: Tue, 22 Nov 2022 16:48:41 +0800 Subject: [PATCH] =?UTF-8?q?=E9=80=89=E6=8B=A9=E7=9B=91=E5=90=AC=E9=97=AE?= =?UTF-8?q?=E9=A2=98=E6=A8=A1=E5=9D=97=E7=BB=86=E9=A1=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- api/app/lib/controllers/alarm/data.js | 18 +- api/app/lib/controllers/alarm/video.js | 16 +- api/app/lib/controllers/push/config.js | 4 +- api/app/lib/models/alarm_push_config.js | 9 + api/app/lib/schedule/alarms_push.js | 26 +- .../0.10/schema/1.alter_alarm_push_config.sql | 8 + .../src/sections/problem/actions/problem.jsx | 24 +- .../sections/service/components/pushModal.jsx | 379 ++--- .../sections/service/containers/emPush.jsx | 1402 +++++++++-------- 9 files changed, 891 insertions(+), 995 deletions(-) create mode 100644 script/0.10/schema/1.alter_alarm_push_config.sql diff --git a/api/app/lib/controllers/alarm/data.js b/api/app/lib/controllers/alarm/data.js index ca1204a..f1d2b82 100644 --- a/api/app/lib/controllers/alarm/data.js +++ b/api/app/lib/controllers/alarm/data.js @@ -8,17 +8,23 @@ async function groupList (ctx) { const { clickHouse } = ctx.app.fs const { database: dataAlarm } = clickHouse.dataAlarm.opts.config + const { showAll } = ctx.query const groupRes = await clickHouse.anxinyun.query(` SELECT * FROM t_alarm_group `).toPromise(); + let whereOption = [] + if (!showAll) { + whereOption.push(` INNER JOIN ${dataAlarm}.alarms + ON t_alarm_group_unit.id = ${dataAlarm}.alarms.AlarmGroupUnit`) + } + for (let g of groupRes) { g.unit = await await clickHouse.anxinyun.query(` SELECT DISTINCT t_alarm_group_unit.id AS id,t_alarm_group_unit.name AS name,t_alarm_group_unit.group_id AS groupId FROM t_alarm_group_unit - INNER JOIN ${dataAlarm}.alarms - ON t_alarm_group_unit.id = ${dataAlarm}.alarms.AlarmGroupUnit + ${whereOption} WHERE group_id = ${g.id} `).toPromise(); } @@ -90,7 +96,7 @@ async function list (ctx) { whereOption.push(`DeviceStatus.Status = ${0}`) } } - + let alarmQueryOptionStr = ` FROM alarms @@ -218,7 +224,7 @@ async function list (ctx) { } } -async function getAlarmGroups(ctx) { +async function getAlarmGroups (ctx) { try { const { clickHouse } = ctx.app.fs const groupRes = await clickHouse.anxinyun.query(` @@ -239,7 +245,7 @@ async function getAlarmGroups(ctx) { } } } -async function exportDataAlarms(ctx, alarmList, groupId) { +async function exportDataAlarms (ctx, alarmList, groupId) { try { const { utils: { simpleExcelDown, getExportAlarmHeader } } = ctx.app.fs; let header = await getExportAlarmHeader(groupId); @@ -303,7 +309,7 @@ async function exportDataAlarms(ctx, alarmList, groupId) { } } } -async function detail(ctx) { +async function detail (ctx) { try { const { models } = ctx.fs.dc; const { clickHouse } = ctx.app.fs diff --git a/api/app/lib/controllers/alarm/video.js b/api/app/lib/controllers/alarm/video.js index ab2cff1..b9a0dbf 100644 --- a/api/app/lib/controllers/alarm/video.js +++ b/api/app/lib/controllers/alarm/video.js @@ -8,11 +8,18 @@ async function deviceType (ctx) { const { clickHouse } = ctx.app.fs const { database: anxinyun } = clickHouse.anxinyun.opts.config const { utils: { judgeSuper, anxinStrucIdRange } } = ctx.app.fs + const { showAll } = ctx.query let anxinStruc = await anxinStrucIdRange({ ctx, }) const anxinStrucIds = anxinStruc.map(a => a.strucId) - + let whereOption = [] + if (!showAll) { + whereOption.push(`INNER JOIN ${anxinyun}.t_video_ipc + ON toString(${anxinyun}.t_video_ipc.channel_no) = camera_status_alarm.channel_no + AND ${anxinyun}.t_video_ipc.serial_no = camera_status_alarm.serial_no + ${`WHERE ${anxinyun}.t_video_ipc.structure IN (${anxinStrucIds.join(',')})`}`) + } const kindRes = await clickHouse.vcmp.query(` SELECT DISTINCT camera_kind.id AS id,camera_kind.kind AS kind @@ -22,10 +29,7 @@ async function deviceType (ctx) { INNER JOIN camera_status_alarm ON camera.channel_no = camera_status_alarm.channel_no AND camera.serial_no = camera_status_alarm.serial_no - INNER JOIN ${anxinyun}.t_video_ipc - ON toString(${anxinyun}.t_video_ipc.channel_no) = camera_status_alarm.channel_no - AND ${anxinyun}.t_video_ipc.serial_no = camera_status_alarm.serial_no - ${`WHERE ${anxinyun}.t_video_ipc.structure IN (${anxinStrucIds.join(',')})`} + ${whereOption} `).toPromise() ctx.status = 200; ctx.body = kindRes @@ -38,7 +42,7 @@ async function deviceType (ctx) { } } -async function exceptionType(ctx) { +async function exceptionType (ctx) { try { const { models } = ctx.fs.dc; const { clickHouse } = ctx.app.fs diff --git a/api/app/lib/controllers/push/config.js b/api/app/lib/controllers/push/config.js index 0566837..831be16 100644 --- a/api/app/lib/controllers/push/config.js +++ b/api/app/lib/controllers/push/config.js @@ -165,11 +165,11 @@ async function edit (ctx) { const models = ctx.fs.dc.models; const { userId, pepUserId } = ctx.fs.api const { pushId, name, pomsProjectId, alarmType = [], receiverPepUserId = [], timeType = [], disable, - strucId = [], tactics, tacticsParams } = ctx.request.body + strucId = [], tactics, tacticsParams, alarmSubType = {} } = ctx.request.body let storageData = { name, pomsProjectId, alarmType, receiverPepUserId, timeType, disable, - strucId, tactics, tacticsParams + strucId, tactics, tacticsParams,alarmSubType } let repeatOption = { diff --git a/api/app/lib/models/alarm_push_config.js b/api/app/lib/models/alarm_push_config.js index 7ea7a19..07606cf 100644 --- a/api/app/lib/models/alarm_push_config.js +++ b/api/app/lib/models/alarm_push_config.js @@ -42,6 +42,15 @@ module.exports = dc => { field: "alarm_type", autoIncrement: false }, + alarmSubType: { + type: DataTypes.JSONB, + allowNull: true, + defaultValue: null, + comment: "监听的告警类型", + primaryKey: false, + field: "alarm_sub_type", + autoIncrement: false + }, receiverPepUserId: { type: DataTypes.ARRAY(DataTypes.INTEGER), allowNull: true, diff --git a/api/app/lib/schedule/alarms_push.js b/api/app/lib/schedule/alarms_push.js index 57f8736..c8bd06b 100644 --- a/api/app/lib/schedule/alarms_push.js +++ b/api/app/lib/schedule/alarms_push.js @@ -135,6 +135,7 @@ module.exports = function (app, opts) { let dataAlarmOption = [] let dataAlarmGroupOption = [] + let dataAlarmSubType = [] let dataAlarms = [] let videoAlarmWhereOption = [] @@ -211,15 +212,21 @@ module.exports = function (app, opts) { // 判断告警数据范围 if (c.alarmType.includes('data_outages')) { dataAlarmGroupOption.push(1) + if (c.alarmSubType) dataAlarmSubType = dataAlarmSubType.concat(c.alarmSubType['data_outages']) } if (c.alarmType.includes('data_exception')) { dataAlarmGroupOption.push(2) + if (c.alarmSubType) dataAlarmSubType = dataAlarmSubType.concat(c.alarmSubType['data_exception']) + } if (c.alarmType.includes('strategy_hit')) { dataAlarmGroupOption.push(3) + if (c.alarmSubType) dataAlarmSubType = dataAlarmSubType.concat(c.alarmSubType['strategy_hit']) } if (c.alarmType.includes('video_exception')) { - videoAlarms = searchStrucIds.length ? await clickHouse.vcmp.query( + let videoAlarmSubType = c.alarmSubType ? c.alarmSubType['data_exception'] : [] + if (videoAlarmSubType.length == 1) videoAlarmSubType.push(-1) + videoAlarms = searchStrucIds.length && videoAlarmSubType.length ? await clickHouse.vcmp.query( ` SELECT cameraAlarm.cameraId AS cameraId, @@ -263,6 +270,7 @@ module.exports = function (app, opts) { AND camera.channel_no = camera_status_alarm.channel_no AND camera.delete = false AND camera.recycle_time is null + ${!c.alarmSubType ? `AND camera.kind_id in (${videoAlarmSubType.join(',')})` : ""} WHERE camera_status_alarm.confirm_time IS null ${videoAlarmWhereOption.length ? ` AND ${videoAlarmWhereOption.join(' AND ')}` : ''} @@ -353,7 +361,10 @@ module.exports = function (app, opts) { videoAlarms = returnD } if (c.alarmType.includes('app_exception')) { - appAlarms = await models.AppAlarm.findAll({ + if (c.alarmSubType) { + appAlarmWhereOption.type = { $in: c.alarmSubType['app_exception'] || [] } + } + appAlarms = c.alarmSubType && c.alarmSubType['app_exception'].length ? await models.AppAlarm.findAll({ where: appAlarmWhereOption, order: [['createTime', 'DESC']], include: [{ @@ -367,25 +378,30 @@ module.exports = function (app, opts) { required: true, }] }] - }) + }) : [] } if (c.alarmType.includes('device_exception')) { dataAlarmGroupOption.push(4) dataAlarmGroupOption.push(5) + if (c.alarmSubType) dataAlarmSubType = dataAlarmSubType.concat(c.alarmSubType['device_exception']) } // 查数据告警 三警合一 if (dataAlarmGroupOption.length && searchStrucIds.length) { dataAlarmGroupOption.push(-1) dataAlarmOption.push(`AlarmGroup IN (${dataAlarmGroupOption.join(',')})`) - dataAlarms = await clickHouse.dataAlarm.query(` + if (c.alarmSubType && dataAlarmSubType.length) { + dataAlarmSubType.push(-1) + dataAlarmOption.push(`AlarmGroupUnit IN (${dataAlarmSubType.join(',')})`) + } + dataAlarms = (!c.alarmSubType || dataAlarmSubType.length) ? await clickHouse.dataAlarm.query(` SELECT * FROM alarms WHERE ${`State NOT IN (3, 4) AND `} StructureId IN (${searchStrucIds.join(',')}) ${dataAlarmOption.length ? ' AND ' + dataAlarmOption.join(' AND ') : ''} ORDER BY StartTime DESC - `).toPromise() + `).toPromise() : [] console.log(dataAlarms); } diff --git a/script/0.10/schema/1.alter_alarm_push_config.sql b/script/0.10/schema/1.alter_alarm_push_config.sql new file mode 100644 index 0000000..08ad5b3 --- /dev/null +++ b/script/0.10/schema/1.alter_alarm_push_config.sql @@ -0,0 +1,8 @@ +alter table alarm_push_config + add alarm_sub_type jsonb + +comment on column alarm_push_config.alarm_sub_type is '存对应监听模块(alarm_type)的子类( + 数据告警:alarms.AlarmGroupUnit, + 视频异常:camera.kind_id, + 应用异常:app_alarm.errType +)'; diff --git a/web/client/src/sections/problem/actions/problem.jsx b/web/client/src/sections/problem/actions/problem.jsx index 91d4913..495e7a5 100644 --- a/web/client/src/sections/problem/actions/problem.jsx +++ b/web/client/src/sections/problem/actions/problem.jsx @@ -64,10 +64,11 @@ export function postApiConfirm (data) { //确认应用接口/元素错误信 }); } -export function getAlarmDataGroup () { //获取数据告警分类 +export function getAlarmDataGroup (query) { //获取数据告警分类 return dispatch => basicAction({ type: 'get', dispatch: dispatch, + query, actionType: 'GET_ALARM_DATA_GROUP', url: `${ApiTable.getAlarmDataGroup}`, msg: { option: '获取数据告警分类' }, @@ -138,10 +139,11 @@ export function getAlarmVideoList (query) { //查询视频告警列表 -export function getAlarmVideoDeviceKind () { //查询视频设备类型 +export function getAlarmVideoDeviceKind (query) { //查询视频设备类型 return dispatch => basicAction({ type: 'get', dispatch: dispatch, + query, actionType: 'GET_ALARM_VIDEO_DEVICE_KIND', url: `${ApiTable.getAlarmVideoDeviceKind}`, msg: { option: '查询视频设备类型' }, @@ -150,15 +152,15 @@ export function getAlarmVideoDeviceKind () { //查询视频设备类型 } export function getAlarmVideoExceptionType () { //查询视频异常类型 - return dispatch => basicAction({ - type: 'get', - dispatch: dispatch, - actionType: 'GET_ALARM_VIDEO_EXCEPTION_TYPE', - url: `${ApiTable.getAlarmVideoExceptionType}`, - msg: { option: '查询视频异常类型' }, - reducer: { name: '' } - }); - } + return dispatch => basicAction({ + type: 'get', + dispatch: dispatch, + actionType: 'GET_ALARM_VIDEO_EXCEPTION_TYPE', + url: `${ApiTable.getAlarmVideoExceptionType}`, + msg: { option: '查询视频异常类型' }, + reducer: { name: '' } + }); +} export function putAlarmVideoConfirm (data) { //确认视频告警 return dispatch => basicAction({ diff --git a/web/client/src/sections/service/components/pushModal.jsx b/web/client/src/sections/service/components/pushModal.jsx index 0b547ff..78cdbfe 100644 --- a/web/client/src/sections/service/components/pushModal.jsx +++ b/web/client/src/sections/service/components/pushModal.jsx @@ -15,9 +15,10 @@ function pushModal (props) { actions, pushEdit,//是否是编辑 editObj, - user + user, + subTypeData } = props; - const { service } = actions; + const { service, problem } = actions; const form = useRef();//表单 const [abnormal, setAbnormal] = useState(false); //异常率推送机制disable const [usersList, setUsersList] = useState([]); //获取全部未删除用户 @@ -32,20 +33,19 @@ function pushModal (props) { const [interval2, setInterval2] = useState(undefined); // const [interval3, setInterval3] = useState(undefined); // const [deviceProportion, setDeviceProportion] = useState(undefined); // - - + const [subType, setSubType] = useState([]); //监听模块中的子类 //初始化 useEffect(() => { + if (editObj?.alarmType) setSubType(editObj?.alarmType) getOrganizationUsersList()//获取全部未删除用户 getProjectPomsList()//获取已绑定项目 if (editObj.id) { getProjectStructureList(editObj.pomsProjectId) if (editObj.pomsProject?.pepProjectId) { getProjectStatusList()//获取项目状态列表 - } - else { + } else { setProjectStatus([{ construction_status: 'POMS', id: 'POMS' }]) timeTypePOMS.current = ['POMS'] } @@ -58,7 +58,7 @@ function pushModal (props) { setDeviceProportion(editObj.tacticsParams?.deviceProportion) } } - }, []); + }, []) function getOrganizationUsersList () {//获取全部未删除用户 dispatch(service.getOrganizationUsers()).then((res) => { if (res.success) { @@ -101,278 +101,58 @@ function pushModal (props) { } }) } + function caution (tactics, interval, deviceProportion) { + let regu = /^[0-9]*[1-9][0-9]*$/; + let title = tactics == 'immediately' ? '即时' : tactics == 'continue' ? '持续时长' : '异常率' + if (!regu.test(interval) || (tactics == 'abnormal_rate' && interval > 720) || interval > 1440) { + console.log(interval); + Notification.error({ + content: title + (interval ? `推送时间不能大于${tactics == 'abnormal_rate' ? 720 : 1440}分钟` : '推送时间应为正整数'), + duration: 2, + }) + return false + } + if (!deviceProportion || deviceProportion > 100) { + Notification.error({ + content: '异常率推送异常率应为正整数且不超过100%', + duration: 2, + }) + return false + } + return true + } + function handleOk () { //点击弹框确定 右边按钮 form.current .validate() - .then((values) => { - if (pushEdit) { - let obj = JSON.parse(JSON.stringify(values)) - if (obj.timeType[0] == 'POMS') { - obj.timeType = [] - } - let regu = /^[0-9]*[1-9][0-9]*$/; - if (obj.tactics == 'immediately') { - if (obj.interval1) { - if (regu.test(obj.interval1)) { - if (obj.interval1 <= 1440) { - obj.tacticsParams = { - interval: obj.interval1 - } - delete obj.interval1 - delete obj.interval2 - delete obj.interval3 - delete obj.deviceProportion - dispatch(service.postPush({ pushId: editObj.id, ...obj, msg: '编辑推送配置' })).then((res) => {//获取项企(PEP)全部部门及其下用户 - if (res.success) { - close(); - } - }) - } else { - Notification.error({ - content: '即时推送时间不能大于1440分钟', - duration: 2, - }) - } - } else { - Notification.error({ - content: '即时推送时间应为正整数', - duration: 2, - }) - } - } else { - Notification.error({ - content: '即时推送时间应为正整数', - duration: 2, - }) - } - } - else if (obj.tactics == 'continue') { - if (obj.interval2) { - if (regu.test(obj.interval2)) { - if (obj.interval2 <= 1440) { - obj.tacticsParams = { - interval: obj.interval2 - } - delete obj.interval1 - delete obj.interval2 - delete obj.interval3 - delete obj.deviceProportion - dispatch(service.postPush({ pushId: editObj.id, ...obj, msg: '编辑推送配置' })).then((res) => {//获取项企(PEP)全部部门及其下用户 - if (res.success) { - close(); - } - }) - } else { - Notification.error({ - content: '持续时长推送时间不能大于1440分钟', - duration: 2, - }) - } - } else { - Notification.error({ - content: '持续时长推送时间应为正整数', - duration: 2, - }) - } - } else { - Notification.error({ - content: '持续时长推送时间应为正整数', - duration: 2, - }) - } - } - else { - if (regu.test(obj.interval3) && regu.test(obj.deviceProportion)) { - if (obj.interval3 <= 720 && obj.deviceProportion <= 100) { - obj.tacticsParams = { - interval: obj.interval3, - deviceProportion: obj.deviceProportion - } - delete obj.interval1 - delete obj.interval2 - delete obj.interval3 - delete obj.deviceProportion - dispatch(service.postPush({ pushId: editObj.id, ...obj, msg: '编辑推送配置' })).then((res) => {//获取项企(PEP)全部部门及其下用户 - if (res.success) { - close(); - } - }) - } else if (obj.interval3 <= 720 && obj.deviceProportion > 100) { - Notification.error({ - content: '异常率推送异常率不能超过100%', - duration: 2, - }) - } else if (obj.interval3 > 720 && obj.deviceProportion <= 100) { - Notification.error({ - content: '异常率推送时间不能超过720小时', - duration: 2, - }) - } else { - Notification.error({ - content: '异常率推送时间不能超过720小时', - duration: 2, - }) - Notification.error({ - content: '异常率推送异常率不能超过100%', - duration: 2, - }) - } - } else if (regu.test(obj.interval3) && !regu.test(obj.deviceProportion)) { - Notification.error({ - content: '异常率推送异常率应为正整数', - duration: 2, - }) - } else if (!regu.test(obj.interval3) && regu.test(obj.deviceProportion)) { - Notification.error({ - content: '异常率推送时间应为正整数', - duration: 2, - }) - } else { - Notification.error({ - content: '异常率推送异常率应为正整数', - duration: 2, - }) - Notification.error({ - content: '异常率推送时间应为正整数', - duration: 2, - }) - } - } + .then((v) => { + let data = { + name: v.name, + pomsProjectId: v.pomsProjectId, + strucId: v.strucId || [], + tactics: v.tactics, + tacticsParams: { + interval: v.tactics == 'immediately' ? v.interval1 : (v.tactics == 'continue' ? v.interval2 : v.interval3), + deviceProportion: v.deviceProportion + }, + alarmType: v.alarmType, + timeType: v.timeType[0] == 'POMS' ? [] : v.timeType, + receiverPepUserId: v.receiverPepUserId || [], + disable: v.disable, + alarmSubType: {} } - else { - let obj = JSON.parse(JSON.stringify(values)) - if (obj.timeType[0] == 'POMS') { - obj.timeType = [] + for (let key in v) { + if (['app_exception', 'data_exception', 'data_outages', 'device_exception', 'video_exception', 'strategy_hit'].includes(key)) { + data.alarmSubType = { ...data.alarmSubType, [key]: v[key] } } - let regu = /^[0-9]*[1-9][0-9]*$/; - if (obj.tactics == 'immediately') { - if (obj.interval1) { - if (regu.test(obj.interval1)) { - if (obj.interval1 <= 1440) { - obj.tacticsParams = { - interval: obj.interval1 - } - delete obj.interval1 - delete obj.interval2 - delete obj.interval3 - delete obj.deviceProportion - dispatch(service.postPush({ ...obj, msg: '新增推送配置' })).then((res) => {//获取项企(PEP)全部部门及其下用户 - if (res.success) { - close(); - } - }) - } else { - Notification.error({ - content: '即时推送时间不能大于1440分钟', - duration: 2, - }) - } - } else { - Notification.error({ - content: '即时推送时间应为正整数', - duration: 2, - }) - } - } else { - Notification.error({ - content: '即时推送时间应为正整数', - duration: 2, - }) - } - } - else if (obj.tactics == 'continue') { - if (obj.interval2) { - if (regu.test(obj.interval2)) { - if (obj.interval2 <= 1440) { - obj.tacticsParams = { - interval: obj.interval2 - } - delete obj.interval1 - delete obj.interval2 - delete obj.interval3 - delete obj.deviceProportion - dispatch(service.postPush({ ...obj, msg: '新增推送配置' })).then((res) => {//获取项企(PEP)全部部门及其下用户 - if (res.success) { - close(); - } - }) - } else { - Notification.error({ - content: '持续时长推送时间不能大于1440分钟', - duration: 2, - }) - } - } else { - Notification.error({ - content: '持续时长推送时间应为正整数', - duration: 2, - }) - } - } else { - Notification.error({ - content: '持续时长推送时间应为正整数', - duration: 2, - }) - } - } - else { - if (regu.test(obj.interval3) && regu.test(obj.deviceProportion)) { - if (obj.interval3 <= 720 && obj.deviceProportion <= 100) { - obj.tacticsParams = { - interval: obj.interval3, - deviceProportion: obj.deviceProportion - } - delete obj.interval1 - delete obj.interval2 - delete obj.interval3 - delete obj.deviceProportion - dispatch(service.postPush({ ...obj, msg: '新增推送配置' })).then((res) => {//获取项企(PEP)全部部门及其下用户 - if (res.success) { - close(); - } - }) - } else if (obj.interval3 <= 720 && obj.deviceProportion > 100) { - Notification.error({ - content: '异常率推送异常率不能超过100%', - duration: 2, - }) - } else if (obj.interval3 > 720 && obj.deviceProportion <= 100) { - Notification.error({ - content: '异常率推送时间不能超过720小时', - duration: 2, - }) - } else { - Notification.error({ - content: '异常率推送时间不能超过720小时', - duration: 2, - }) - Notification.error({ - content: '异常率推送异常率不能超过100%', - duration: 2, - }) - } - } else if (regu.test(obj.interval3) && !regu.test(obj.deviceProportion)) { - Notification.error({ - content: '异常率推送异常率应为正整数', - duration: 2, - }) - } else if (!regu.test(obj.interval3) && regu.test(obj.deviceProportion)) { - Notification.error({ - content: '异常率推送时间应为正整数', - duration: 2, - }) - } else { - Notification.error({ - content: '异常率推送异常率应为正整数', - duration: 2, - }) - Notification.error({ - content: '异常率推送时间应为正整数', - duration: 2, - }) + } + if (caution(data.tactics, data.tacticsParams.interval, data.tacticsParams.deviceProportion)) { + dispatch(service.postPush({ pushId: editObj.id, ...data, msg: pushEdit ? '编辑推送配置' : "新增推送策略" })).then((res) => {//获取项企(PEP)全部部门及其下用户 + if (res.success) { + close(); } - } + }) } }) } @@ -403,8 +183,7 @@ function pushModal (props) { if (values.tactics == 'abnormal_rate') { form.current.setValue('alarmType', undefined) setAbnormal(true) - } - else { + } else { setAbnormal(false) } } @@ -423,6 +202,9 @@ function pushModal (props) { } } } + if (key == 'alarmType') { + setSubType(field['alarmType']) + } } }} getFormApi={(formApi) => (form.current = formApi)} @@ -496,9 +278,10 @@ function pushModal (props) { direction='horizontal' initValue={editObj?.tactics || ''} rules={[{ required: true, message: '请选择推送策略' }]}> -
+
中台每分钟查询,若有告警源新增,则每 @@ -512,7 +295,7 @@ function pushModal (props) { 分钟通过【信鸽服务】发送一条通知信息。 } - style={{ width: 198 }}> + style={{ width: 217 }}> 即时推送机制 - 数据中断 - 数据异常 - 策略命中 - 视频异常 - 应用异常 - 设备异常 + { + [ + { name: '数据中断', value: "data_outages" }, + { name: '数据异常', value: "data_exception" }, + { name: '策略命中', value: "strategy_hit" }, + { name: '视频异常', value: "video_exception" }, + { name: '应用异常', value: "app_exception" }, + { name: '设备异常', value: "device_exception" }, + ].map((v, index) => + + {v.name}) + } + {[ + { name: '数据中断', value: "data_outages", data: subTypeData['data_outages'][0] }, + { name: '数据异常', value: "data_exception", data: subTypeData['data_exception'][0] }, + { name: '策略命中', value: "strategy_hit", data: subTypeData['strategy_hit'][0] }, + { name: '视频异常', value: "video_exception", data: subTypeData['video_exception'][0]?.map(v => ({ id: v.id, name: v.kind })) }, + { name: '应用异常', value: "app_exception", data: subTypeData['app_exception'][0] }, + { name: '设备异常', value: "device_exception", data: [...subTypeData['device_exception'][0], ...subTypeData['device_exception'][1]] }, + ].filter(v => subType?.includes(v.value))?.map((u, index) => { + return v.id)) || []} + direction='horizontal' + showClear + > + { + u.data?.map((v, index) => + {v.name}) + } + + }) + }
接收信息配置 diff --git a/web/client/src/sections/service/containers/emPush.jsx b/web/client/src/sections/service/containers/emPush.jsx index 2017936..ca73760 100644 --- a/web/client/src/sections/service/containers/emPush.jsx +++ b/web/client/src/sections/service/containers/emPush.jsx @@ -9,714 +9,750 @@ import '../style.less' import { Setup } from "$components"; const EmPush = (props) => { - const form = useRef();//表单 - const { dispatch, actions, user, loading, socket } = props - const { service } = actions; - const [setup, setSetup] = useState(false); //表格设置是否显现 - const [setupp, setSetupp] = useState([]);//实际显示的表格列表 - const [query, setQuery] = useState({ limit: 10, page: 0 }); //页码信息 - const [limits, setLimits] = useState()//每页实际条数 - const mylimits = useRef(); //每页实际条数 - const [pushModal, setPushModal] = useState(false) //信鸽弹框 - const [pushEdit, setPushEdit] = useState(false) //是否是修改 - const [change, setChange] = useState(false) //是否改变 - const [allTableData, setAllTableData] = useState([]) //获取到的所有表格信息 - const [editObj, setEditObj] = useState({});//管理员弹框修改内容 - const [projectStatus, setProjectStatus] = useState([]); //获取项目状态列表 - const page = useRef(query.page);//哪一页 - const EMPUSH = "empush"; - const tableList = [//表格属性 - { - title: '推送信息', - list: [ - { name: "关联项目", value: "projectName" }, - { name: "策略名称", value: "name" }, - { name: "创建时间", value: "createTime" }, - { name: "接收人", value: "receiverPepUser" }, - { name: "推送方式", value: "pushType" }, - { name: "监听问题模块", value: "alarmType" }, - { name: "生效项目节点", value: "timeType" }, - { name: "推送机制", value: "tactics" }, - { name: "启用状态", value: "disable" }, - { name: "推送次数", value: "pushCount" }, - ] - }, - ]; - const alarmTypeObj = { - data_outages: '数据中断', - data_exception: '数据异常', - strategy_hit: '策略命中', - video_exception: '视频异常', - app_exception: '应用异常', - device_exception: '设备异常', - } - const tacticsObj = { - immediately: '即时推送机制', - continue: '持续时长推送机制', - abnormal_rate: '异常率推送机制', - } + const form = useRef();//表单 + const { dispatch, actions, user, loading, socket } = props + const { service, problem } = actions; + const [setup, setSetup] = useState(false); //表格设置是否显现 + const [setupp, setSetupp] = useState([]);//实际显示的表格列表 + const [query, setQuery] = useState({ limit: 10, page: 0 }); //页码信息 + const [limits, setLimits] = useState()//每页实际条数 + const mylimits = useRef(); //每页实际条数 + const [pushModal, setPushModal] = useState(false) //信鸽弹框 + const [pushEdit, setPushEdit] = useState(false) //是否是修改 + const [change, setChange] = useState(false) //是否改变 + const [allTableData, setAllTableData] = useState([]) //获取到的所有表格信息 + const [editObj, setEditObj] = useState({});//管理员弹框修改内容 + const [projectStatus, setProjectStatus] = useState([]); //获取项目状态列表 + const [subTypeData, setSubTypedata] = useState({ + data_outages: [], + data_exception: [], + strategy_hit: [], + video_exception: [], + app_exception: [], + device_exception: [], + }); //数据类监听模块中的子类 + const page = useRef(query.page);//哪一页 + const EMPUSH = "empush"; + const tableList = [//表格属性 + { + title: '推送信息', + list: [ + { name: "关联项目", value: "projectName" }, + { name: "策略名称", value: "name" }, + { name: "创建时间", value: "createTime" }, + { name: "接收人", value: "receiverPepUser" }, + { name: "推送方式", value: "pushType" }, + { name: "监听问题模块", value: "alarmType" }, + { name: "生效项目节点", value: "timeType" }, + { name: "推送机制", value: "tactics" }, + { name: "启用状态", value: "disable" }, + { name: "推送次数", value: "pushCount" }, + ] + }, + ]; + const alarmTypeObj = { + data_outages: '数据中断', + data_exception: '数据异常', + strategy_hit: '策略命中', + video_exception: '视频异常', + app_exception: '应用异常', + device_exception: '设备异常', + } + const tacticsObj = { + immediately: '即时推送机制', + continue: '持续时长推送机制', + abnormal_rate: '异常率推送机制', + } - function handleRow (record, index) {//斑马条纹 - // 给偶数行设置斑马纹 - if (index % 2 === 0) { - return { - style: { - background: '#FAFCFF', - } - }; - } else { - return {}; - } - } - const [tableData, setTableData] = useState([]) //表格数据 + function handleRow (record, index) {//斑马条纹 + // 给偶数行设置斑马纹 + if (index % 2 === 0) { + return { + style: { + background: '#FAFCFF', + } + }; + } else { + return {}; + } + } + const [tableData, setTableData] = useState([]) //表格数据 + + useEffect(() => { + localStorage.getItem(EMPUSH) == null + ? localStorage.setItem( + EMPUSH, + JSON.stringify(['projectName', 'name', 'createTime', 'receiverPepUser', 'alarmType', 'timeType', 'tactics', 'disable']) + ) + : ""; + getProjectStatusList() + getPushList(query); - useEffect(() => { - localStorage.getItem(EMPUSH) == null - ? localStorage.setItem( - EMPUSH, - JSON.stringify(['projectName', 'name', 'createTime', 'receiverPepUser', 'alarmType', 'timeType', 'tactics', 'disable']) - ) - : ""; - getProjectStatusList() - getPushList(query); - }, []) - useEffect(() => { - let showTableData = JSON.parse(JSON.stringify(allTableData)).slice(query.page * query.limit, (query.page + 1) * query.limit) - setTableData(showTableData) - mylimits.current = showTableData.length - }, [change]); + //数据异常异常类型子类 + dispatch(problem.getAlarmDataGroup({ showAll: 'true' })).then((res) => { + if (res.success) { + let data = { ...subTypeData } + res.payload.data?.map(v => { + if (v.id === 1) { + data['data_outages'].push(v.unit) + } else if (v.id === 2) { + data['data_exception'].push(v.unit) + } else if (v.id == 3) { + data['strategy_hit'].push(v.unit) + } else { + data['device_exception'].push(v.unit) + } + }) + //视频异常异常类型子类 + dispatch(problem.getAlarmVideoDeviceKind({ showAll: true })).then((res) => { + if (res.success) { + data['video_exception'].push(res.payload.data) + } + }) + data['app_exception'].push([{ id: 'apiError', name: "接口报错", }, { id: 'element', name: "元素异常", }, { id: 'timeout', name: "加载超时", },]) + setSubTypedata(data) + } + }) + }, []) - function getPushList (query) { - let val = form.current.getValues() - dispatch(service.getPush({ ...val })).then((res) => {//获取已绑定项目 - if (res.success) { - let mytableData = JSON.parse(JSON.stringify(res.payload.data)); - for (let index = 0; index < mytableData.length; index++) { - mytableData[index].key = String(mytableData[index].id) - } - setAllTableData(mytableData) - let showTableData = mytableData.slice(query.page * query.limit, (query.page + 1) * query.limit) - setTableData(showTableData) - setQuery(query) - setLimits(res.payload.data.length) - mylimits.current = showTableData.length + useEffect(() => { + let showTableData = JSON.parse(JSON.stringify(allTableData)).slice(query.page * query.limit, (query.page + 1) * query.limit) + setTableData(showTableData) + mylimits.current = showTableData.length + }, [change]); + + function getPushList (query) { + let val = form.current.getValues() + dispatch(service.getPush({ ...val })).then((res) => {//获取已绑定项目 + if (res.success) { + let mytableData = JSON.parse(JSON.stringify(res.payload.data)); + for (let index = 0; index < mytableData.length; index++) { + mytableData[index].key = String(mytableData[index].id) } - }) - } - function getProjectStatusList () {//获取项目状态列表 - dispatch(service.getProjectStatus()).then((res) => { - if (res.success) { - setProjectStatus(res.payload?.data) - attribute(res.payload?.data); + setAllTableData(mytableData) + let showTableData = mytableData.slice(query.page * query.limit, (query.page + 1) * query.limit) + setTableData(showTableData) + setQuery(query) + setLimits(res.payload.data.length) + mylimits.current = showTableData.length + } + }) + } + function getProjectStatusList () {//获取项目状态列表 + dispatch(service.getProjectStatus()).then((res) => { + if (res.success) { + setProjectStatus(res.payload?.data) + attribute(res.payload?.data); + } + }) + } + const columns = [//表格属性 + { + title: "操作", + width: "12%", + dataIndex: "text", + key: 'text', + render: (_, row) => { + return ( +
+ + {row?.disable ? ( + + ) : ( + { + dispatch(service.putPushPushId({ pushId: row?.id, del: false, disable: true, msg: '更改推送配置状态' })).then(() => { + getPushList({ limit: query.limit, page: page.current }); + }) + }} + > + + + )} + { + dispatch(service.putPushPushId({ pushId: row?.id, del: true, disable: false, msg: '删除推送配置' })).then(() => { + if (page.current > 0 && mylimits.current < 2) { + getPushList({ limit: query.limit, page: page.current - 1 }); + } else { + getPushList({ limit: query.limit, page: page.current }); + } + }) + }} + > + + +
+ ); + }, + }, + ] + function expandRowRender (record, index) { + return ( +
+ 结构物: + { + record.structure?.map((item, index) => { + return ( + + {item.name} + + ) + }) } - }) - } - const columns = [//表格属性 - { - title: "操作", - width: "12%", - dataIndex: "text", - key: 'text', +
+ ) + } + //获取表格属性设置 + function attribute (val) { + const arr = localStorage.getItem(EMPUSH) + ? JSON.parse(localStorage.getItem(EMPUSH)) + : []; + const column = [ + { + title: '关联项目', + dataIndex: "projectName", + key: "projectName", render: (_, row) => { - return ( -
- - {row?.disable ? ( - + } +
+
) : ( - { - dispatch(service.putPushPushId({ pushId: row?.id, del: false, disable: true, msg: '更改推送配置状态' })).then(() => { - getPushList({ limit: query.limit, page: page.current }); - }) - }} - > - - - )} - { - dispatch(service.putPushPushId({ pushId: row?.id, del: true, disable: false, msg: '删除推送配置' })).then(() => { - if (page.current > 0 && mylimits.current < 2) { - getPushList({ limit: query.limit, page: page.current - 1 }); - } else { - getPushList({ limit: query.limit, page: page.current }); - } - }) - }} - > - - -
- ); - }, - }, - ] - function expandRowRender (record, index) { - return ( -
- 结构物: - { - record.structure?.map((item, index) => { - return ( - - {item.name} - +
+
+ +
+
+ POMS +
+
) - }) - } -
- ) - } - //获取表格属性设置 - function attribute (val) { - const arr = localStorage.getItem(EMPUSH) - ? JSON.parse(localStorage.getItem(EMPUSH)) - : []; - const column = [ - { - title: '关联项目', - dataIndex: "projectName", - key: "projectName", - render: (_, row) => { - let anxinerror = false - let anxinerrorArr = '' - if (row.pomsProject.del == true) { - anxinerror = true - anxinerrorArr = row.pomsProject.pepProject?.projectName || row.pomsProject.name - } - return ( -
- { - anxinerror ? ( - -
- -
-
) : ('') - } - { -
- -
7 || row.pomsProject?.name?.length > 7 ? '112px' : '', whiteSpace: 'nowrap', overflow: 'hidden', textOverflow: 'ellipsis', color: row.pomsProject.del ? '#F93920' : '' }}> - {row.pomsProject.pepProject?.projectName || row.pomsProject.name} -
-
-
- } - { - row.pomsProject?.pepProject?.projectName ? ( -
-
- -
-
- { - val.map((ite, idx) => { - return ( -
- {ite.id == row.pomsProject?.pepProject.constructionStatusId ? ite.construction_status : ''} -
- ) - }) - } -
-
- ) : ( -
-
- -
-
- POMS -
-
- ) - } -
- ) - } - }, - { - title: '策略名称', - dataIndex: "name", - key: 'name', - render: (_, row) => { - return row.name - } - }, - { - title: "创建时间", - dataIndex: "createTime", - key: "createTime", - render: (_, r, index) => { - return moment(r.createTime).format('YYYY-MM-DD HH:mm:ss'); - }, - }, - { - title: '接收人', - dataIndex: "receiverPepUser", - key: 'receiverPepUser', - render: (_, row) => { - return ( -
- { - row.receiverPepUser.map((item, index) => { - return ( -
-
1 ? 'none' : '', color: '#005ABD' }}> - {item.name} -
-
0 ? 'none' : '' }}>
-
- ) - }) - } - { - row.receiverPepUser.length > 2 ? ( - - { - row.receiverPepUser.map((item, index) => { - return ( -
- {item.name}, -
- ) - }) - } -
- } trigger="click" style={{ lineHeight: 2 }}> -
- +{row.receiverPepUser.length - 2} -
- - ) : ('') - } - - ) - } - }, - { - title: "推送方式", - dataIndex: "pushType", - key: "pushType", - render: (_, r, index) => { - return '邮件通知'; - }, + } + + ) + } + }, + { + title: '策略名称', + dataIndex: "name", + key: 'name', + render: (_, row) => { + return row.name + } + }, + { + title: "创建时间", + dataIndex: "createTime", + key: "createTime", + render: (_, r, index) => { + return moment(r.createTime).format('YYYY-MM-DD HH:mm:ss'); }, - { - title: "监听问题模块", - dataIndex: "alarmType", - key: "alarmType", - render: (_, row) => { - return ( -
- { - row.alarmType.map((item, index) => { - return ( -
-
1 ? 'none' : '' }}> - {alarmTypeObj[item]} -
-
0 ? 'none' : '' }}>
-
- ) - }) - } - { - row.alarmType.length > 2 ? ( - - { - row.alarmType.map((item, index) => { - return ( -
- {alarmTypeObj[item]}, -
- ) - }) - } -
- } trigger="click" style={{ lineHeight: 2 }}> -
- +{row.alarmType.length - 2} -
- - ) : ('') - } - - ) - } + }, + { + title: '接收人', + dataIndex: "receiverPepUser", + key: 'receiverPepUser', + render: (_, row) => { + return ( +
+ { + row.receiverPepUser.map((item, index) => { + return ( +
+
1 ? 'none' : '', color: '#005ABD' }}> + {item.name} +
+
0 ? 'none' : '' }}>
+
+ ) + }) + } + { + row.receiverPepUser.length > 2 ? ( + + { + row.receiverPepUser.map((item, index) => { + return ( +
+ {item.name}, +
+ ) + }) + } +
+ } trigger="click" style={{ lineHeight: 2 }}> +
+ +{row.receiverPepUser.length - 2} +
+ + ) : ('') + } + + ) + } + }, + { + title: "推送方式", + dataIndex: "pushType", + key: "pushType", + render: (_, r, index) => { + return '邮件通知'; }, - { - title: "生效项目节点", - dataIndex: "timeType", - key: "timeType", - render: (_, row, index) => { - return ( -
- { - row.timeType.length > 0 ? ( - row.timeType.map((item, index) => { - return ( -
1 ? 'none' : 'flex', alignItems: 'center' - }}> -
- -
-
- { - val.map((ite, idx) => { - return ( -
- {ite.id == item ? ite.construction_status : ''} -
- ) - }) - } -
-
- ) + }, + { + title: "监听问题模块", + dataIndex: "alarmType", + key: "alarmType", + render: (_, row) => { + return ( +
+ { + row.alarmType.map((item, index) => { + return ( +
+
1 ? 'none' : '' }}> + {alarmTypeObj[item]} +
+
0 ? 'none' : '' }}>
+
+ ) + }) + } + { + row.alarmType.length > 2 ? ( + + { + row.alarmType.map((item, index) => { + return ( +
+ {alarmTypeObj[item]}, +
+ ) }) - ) : ( -
-
- -
-
- POMS -
+ } +
+ } trigger="click" style={{ lineHeight: 2 }}> +
+ +{row.alarmType.length - 2} +
+
+ ) : ('') + } +
+ ) + } + }, + { + title: "生效项目节点", + dataIndex: "timeType", + key: "timeType", + render: (_, row, index) => { + return ( +
+ { + row.timeType.length > 0 ? ( + row.timeType.map((item, index) => { + return ( +
1 ? 'none' : 'flex', alignItems: 'center' + }}> +
+ +
+
+ { + val.map((ite, idx) => { + return ( +
+ {ite.id == item ? ite.construction_status : ''} +
+ ) + }) + }
- ) - } - { - row.timeType.length > 2 ? ( - - { - row.timeType.map((item, index) => { - return ( -
- { - val.map((ite, idx) => { - return ( - - {ite.id == item ? ite.construction_status : ''} - - ) - }) - }, -
- ) +
+ ) + }) + ) : ( +
+
+ +
+
+ POMS +
+
+ ) + } + { + row.timeType.length > 2 ? ( + + { + row.timeType.map((item, index) => { + return ( +
+ { + val.map((ite, idx) => { + return ( + + {ite.id == item ? ite.construction_status : ''} + + ) }) - } -
- } trigger="click" style={{ lineHeight: 2 }}> -
- +{row.timeType.length - 2} -
-
- ) : ('') - } -
- ) - }, + }, +
+ ) + }) + } + + } trigger="click" style={{ lineHeight: 2 }}> +
+ +{row.timeType.length - 2} +
+ + ) : ('') + } + + ) }, - { - title: "推送机制", - dataIndex: "tactics", - key: "tactics", - render: (_, r, index) => { - return tacticsObj[r.tactics] - }, + }, + { + title: "推送机制", + dataIndex: "tactics", + key: "tactics", + render: (_, r, index) => { + return tacticsObj[r.tactics] }, - { - title: "启用状态", - dataIndex: "disable", - key: "disable", - render: (_, row, index) => { - let enableType = '' - if (row.disable) { - enableType = '禁用' - } - else { - if (row.timeType.length > 0) { - for (let i = 0; i < row.timeType.length; i++) { - if (row.timeType[i] == row.pomsProject?.pepProject?.constructionStatusId) { - enableType = '已生效' - break; - } else { - enableType = '未生效' - } - } - } - else { - enableType = '已生效' + }, + { + title: "启用状态", + dataIndex: "disable", + key: "disable", + render: (_, row, index) => { + let enableType = '' + if (row.disable) { + enableType = '禁用' + } + else { + if (row.timeType.length > 0) { + for (let i = 0; i < row.timeType.length; i++) { + if (row.timeType[i] == row.pomsProject?.pepProject?.constructionStatusId) { + enableType = '已生效' + break; + } else { + enableType = '未生效' } - } - return ( -
- {enableType} -
- ) - }, + } + } + else { + enableType = '已生效' + } + } + return ( +
+ {enableType} +
+ ) }, - { - title: "推送次数", - dataIndex: "pushCount", - key: "pushCount", - render: (_, r, index) => { - return (r.pushCount||0) + '次' - }, + }, + { + title: "推送次数", + dataIndex: "pushCount", + key: "pushCount", + render: (_, r, index) => { + return (r.pushCount || 0) + '次' }, - ]; - for (let i = 0; i < arr.length; i++) { - let colum = column.filter((item) => { - return item.key === arr[i]; - }); - columns.splice(columns.length - 1, 0, colum[0]); - } - setSetupp(columns); - } - return ( - <> -
-
-
-
-
EM推送
-
Em push
-
-
-
console.log(values)} - getFormApi={(formApi) => (form.current = formApi)} - layout="horizontal" - style={{ position: "relative", width: "100%", flex: 1 }} - > - - 项目 - 结构物 - 策略名 - - } - field="keyword" - pure - showClear - style={{ width: 260, marginLeft: 12, marginRight: 12 }} - placeholder="请输入或选择关键词" - /> - - 即时推送机制 - 持续时长推送机制 - 异常率推送机制 - - - 已生效 - 未生效 - 禁用 - - - -
- setSetup(true)} /> -
- -
-
-
-
EM推送提供对映射关系组的项目、结构物问题的监听和通知服务,支持对设备异常率、问题持续时间、即时响应等策略定义的动态推送。
-
-
- - s)} - dataSource={tableData} - bordered={false} - hideExpandedColumn={false} - empty="暂无数据" - expandedRowRender={expandRowRender} - pagination={false} - onRow={handleRow} - /> - -
-
-
-
- - 共{limits}条信息 - - { - setQuery({ limit: pageSize, page: currentPage - 1 }); - page.current = currentPage - 1 - setChange(!change) - }} - /> -
-
- + }, + ]; + for (let i = 0; i < arr.length; i++) { + let colum = column.filter((item) => { + return item.key === arr[i]; + }); + columns.splice(columns.length - 1, 0, colum[0]); + } + setSetupp(columns); + } + return ( + <> +
+
+
+
+
EM推送
+
Em push
+
+
+
console.log(values)} + getFormApi={(formApi) => (form.current = formApi)} + layout="horizontal" + style={{ position: "relative", width: "100%", flex: 1 }} + > + + 项目 + 结构物 + 策略名 + + } + field="keyword" + pure + showClear + style={{ width: 260, marginLeft: 12, marginRight: 12 }} + placeholder="请输入或选择关键词" + /> + + 即时推送机制 + 持续时长推送机制 + 异常率推送机制 + + + 已生效 + 未生效 + 禁用 + + + +
+ setSetup(true)} /> +
+ +
- {//推送配置弹框 - pushModal ? - { - setPushModal(false); +
+
EM推送提供对映射关系组的项目、结构物问题的监听和通知服务,支持对设备异常率、问题持续时间、即时响应等策略定义的动态推送。
+
+
+ +
s)} + dataSource={tableData} + bordered={false} + hideExpandedColumn={false} + empty="暂无数据" + expandedRowRender={expandRowRender} + pagination={false} + onRow={handleRow} + /> + +
+
+
+
+ + 共{limits}条信息 + + { + setQuery({ limit: pageSize, page: currentPage - 1 }); + page.current = currentPage - 1 + setChange(!change) }} - close={() => { - setPushModal(false); - getPushList(query) - }} > - : '' - } - {setup ? ( - { - setSetup(false); - attribute(projectStatus); - }} - /> - ) : ( - "" - )} - - ) + /> +
+
+ + + {//推送配置弹框 + pushModal ? + { + setPushModal(false); + }} + close={() => { + setPushModal(false); + getPushList(query) + }} > + : '' + } + {setup ? ( + { + setSetup(false); + attribute(projectStatus); + }} + /> + ) : ( + "" + )} + + ) } function mapStateToProps (state) { - const { auth, global, getPush } = state; - return { - loading: getPush.isRequesting, - user: auth.user, - actions: global.actions, - // members: members.data, - }; + const { auth, global, getPush } = state; + return { + loading: getPush.isRequesting, + user: auth.user, + actions: global.actions, + // members: members.data, + }; } export default connect(mapStateToProps)(EmPush);