diff --git a/api/.vscode/launch.json b/api/.vscode/launch.json
index b93dda7..a12977d 100644
--- a/api/.vscode/launch.json
+++ b/api/.vscode/launch.json
@@ -44,6 +44,7 @@
"--clickHouseUrl http://10.8.30.161",
// "--clickHouseUrl https://clickhouse01.anxinyun.cn/play",
"--clickHousePort 30123",
+ // "--clickHousePort 8123",
// 似乎不能传空 先注释 * 2
// "--clickHouseUser ",
// "--clickHousePassword ",
@@ -55,12 +56,12 @@
// "--clickHouseDataAlarm default",
// "--clickHouseIot iot",
// 测试
- "--clickHouseAnxincloud anxinyun88",
+ "--clickHouseAnxincloud anxinyun",
"--clickHousePepEmis pepca8",
"--clickHouseProjectManage peppm",
"--clickHouseVcmp video_access_dev",
"--clickHouseDataAlarm default",
- "--clickHouseIot iot",
+ "--clickHouseIot iota",
"--confirmAlarmAnxinUserId 1",
"--vcmpAppId 5048b08d-c449-4d7f-b1ec-f741012aefe8",
"--vcmpAppSecret 5ba8c0ab-9fbd-4f07-9817-c48017c3cbad",
diff --git a/api/app/lib/controllers/project/index.js b/api/app/lib/controllers/project/index.js
index 45d0f77..6d7802c 100644
--- a/api/app/lib/controllers/project/index.js
+++ b/api/app/lib/controllers/project/index.js
@@ -23,11 +23,12 @@ async function pomsProject (ctx) {
const models = ctx.fs.dc.models;
const { clickHouse } = ctx.app.fs
const { userId, pepUserId, userInfo, pepUserInfo } = ctx.fs.api
- const { limit, page, global, pepId } = ctx.query
+ const { limit, page, global, pepId, keyword } = ctx.query
let findOption = {
where: {
- del: false
+ del: false,
+ // $or:[]
},
order: [['updateTime', 'desc']],
distinct: true,
@@ -47,6 +48,40 @@ async function pomsProject (ctx) {
if (page && limit) {
findOption.offset = page * limit
}
+ if (keyword) {
+ const project = await clickHouse.projectManage.query(
+ `
+ SELECT
+ t_pim_project.id AS id,
+ t_pim_project.project_name AS project_name,
+ t_pim_project.isdelete AS isdelete,
+ t_pim_project_construction.construction_status_id AS construction_status_id,
+ t_pim_project_state.construction_status AS construction_status
+ FROM t_pim_project
+ LEFT JOIN t_pim_project_construction
+ ON t_pim_project.id = t_pim_project_construction.project_id
+ LEFT JOIN t_pim_project_state
+ ON t_pim_project_construction.construction_status_id = t_pim_project_state.id
+ WHERE project_name LIKE '%${keyword}%'
+ `
+ ).toPromise() || []
+ const anxinProjectRes = await clickHouse.anxinyun.query(
+ `SELECT id,"name",
+ project_state AS projectState
+ FROM t_project
+ WHERE name LIKE '%${keyword}%'`).toPromise()
+ || []
+ let projectId = project.map(v => v.id)
+ let anxinProjectId = anxinProjectRes.map(v => v.id)
+
+ findOption.where.$or = [
+ { name: { $like: `%${keyword}%` } },
+ { pepProjectId: { $in: projectId } }]
+ if (projectId.length > 0) {
+ findOption.where.$or.push({ anxinProjectId: { $contains: anxinProjectId } })
+ }
+
+ }
const proRes = await models.ProjectCorrelation.findAndCountAll(findOption)
@@ -85,6 +120,7 @@ async function pomsProject (ctx) {
`
).toPromise() :
[]
+
const pepProjectRes = pepProjectIds.size ?
await clickHouse.projectManage.query(
`
diff --git a/api/app/lib/schedule/alarms_push.js b/api/app/lib/schedule/alarms_push.js
index c1a5e13..da54a83 100644
--- a/api/app/lib/schedule/alarms_push.js
+++ b/api/app/lib/schedule/alarms_push.js
@@ -1,7 +1,7 @@
const moment = require('moment')
let isDev = false
-// isDev = true
+// let isDev = true
let proDebug = false
proDebug = true
@@ -19,6 +19,7 @@ module.exports = function (app, opts) {
const { apMergeDeVeAnxinProjectId = '' } = opts
const { clickHouse } = app.fs
const { database: anxinyun } = clickHouse.anxinyun.opts.config
+ const { database: dataAlarm } = clickHouse.dataAlarm.opts.config
const { pushBySms, pushByEmail, sendNoticeToWeb } = app.fs.utils
const curMinOfYear = moment().diff(moment().startOf('year'), 'minutes')
const configListRes = await models.AlarmPushConfig.findAll({
@@ -68,11 +69,21 @@ module.exports = function (app, opts) {
if (!minute && minute != 0) {
return minute
}
+ let title = ''
let dm = 24 * 60
let d = Math.floor(minute / dm)
let h = Math.floor(minute % dm / 60)
let m = (minute % dm) % 60
- return `${d}天${h}时${m}分`
+ if (d) {
+ title = d + '天'
+ }
+ if (h) {
+ title = title + h + '时'
+ }
+ if (h) {
+ title = title + m + '分'
+ }
+ return title
}
for (let { dataValues: c } of configListRes) {
@@ -167,7 +178,8 @@ module.exports = function (app, opts) {
// !开发测试用的数据
if (isDev) {
- searchStrucIds = searchStrucIds.concat([991, 1052, 700])
+ // searchStrucIds = searchStrucIds.concat([991, 1052, 700])
+ searchStrucIds = searchStrucIds.concat([27, 4003, 700])
}
if (searchStrucIds.length) {
@@ -541,6 +553,80 @@ module.exports = function (app, opts) {
}
},]
+ let dataLnterruptTitle = [{
+ n: '项目',
+ k: '',
+ v: pepProjectName
+ }, {
+ n: '结构物',
+ k: '',
+ f: (d) => {
+ return (strucMap[d.StructureId] || { name: '' }).name
+ // return (strucListRes.find(s => s.id == d.StructureId) || { name: '' }).name
+ }
+ }, {
+ n: '监测因素(中断比例)',
+ k: '',
+ f: (d) => {
+ // d.factor.join('')
+ // console.log(21211231131,d.factor);
+ let data=[]
+ d.factor.map(f => data.push(f.name + '(' + f.breakData + '/' + f.sum + ')'))
+ return data.join('
')
+ }
+ }, {
+ n: '告警源名称',
+ k: 'SourceName'
+ }, {
+ n: '告警源类型',
+ k: '',
+ f: (d) => {
+ switch (d.SourceTypeId) {
+ case 0:
+ return 'DTU'
+ case 1:
+ return '传感器'
+ case 2:
+ return '测点'
+ default:
+ return ''
+ }
+ }
+ }, {
+ n: '告警信息',
+ k: 'AlarmContent'
+ }, {
+ n: '告警等级(当前)',
+ k: '',
+ f: (d) => {
+ switch (d.CurrentLevel) {
+ case 1:
+ return '一级'
+ case 2:
+ return '二级'
+ case 3:
+ return '三级'
+ default:
+ return ''
+ }
+ }
+ }, {
+ n: '持续时间',
+ k: '',
+ f: (d) => {
+ return d.StartTime ?
+ '超过' + calcMinute2DHM(moment().diff(moment(d.StartTime), 'minutes')) : ''
+ }
+ },
+ {
+ n: '中断时间',
+ k: '',
+ f: (d) => {
+ return d.StartTime ?
+ moment(d.StartTime).format('YYYY-MM-DD HH:mm:ss') : ''
+ }
+ },]
+
let videoAlarmTitle = [{
n: '项目',
k: '',
@@ -715,7 +801,64 @@ module.exports = function (app, opts) {
// }
if (d.AlarmGroup == 1) {
+ if (d.StructureId) {
+ //查询结构物的监测因素
+ const factorData = await clickHouse.anxinyun.query(
+ `
+ SELECT
+ t_structure_factor.structure AS structureId,
+ t_factor.name AS name,
+ t_factor.id AS id
+ FROM
+ t_structure_factor
+ LEFT JOIN t_factor
+ ON t_factor.id = t_structure_factor.factor
+ WHERE
+ t_structure_factor.structure = (${d.StructureId})
+
+ `
+ ).toPromise() || []
+ let factorId = factorData.map(f => f.id)
+
+ //查询结构物对应的设备
+ const equipment = await clickHouse.anxinyun.query(
+ `
+ SELECT
+ t_sensor.id AS id,
+ t_sensor.name AS name,
+ t_sensor.structure AS structureId,
+ t_sensor.factor AS factorId,
+ t_device_sensor.iota_device_id AS iotaDeviceId,
+ ${dataAlarm}.alarms.State AS state,
+ ${dataAlarm}.alarms.AlarmGroup AS alarmGroup,
+ ${dataAlarm}.alarms.SourceId AS sourceId
+ FROM
+ t_sensor
+ LEFT JOIN t_device_sensor
+ ON t_device_sensor.sensor = t_sensor.id
+ LEFT JOIN ${dataAlarm}.alarms
+ ON ${dataAlarm}.alarms.SourceId = t_device_sensor.iota_device_id
+ WHERE
+ t_sensor.structure = (${d.StructureId})
+ AND
+ t_sensor.factor IN (${factorId.join(',')})
+ `
+ ).toPromise() || []
+
+ d.factor = []
+ factorData.map(c => {
+ let breakData = equipment.filter(m => (m.iotaDeviceId && m.sourceId && m.state < 3 && m.alarmGroup == 1 && m.factorId == c.id))
+ d.factor.push({
+ name: c.name,
+ sum: equipment.length,
+ breakData: breakData.length
+ })
+ })
+
+ }
+
dataAlarmG1.push(d)
+
} else if (d.AlarmGroup == 2) {
dataAlarmG2.push(d)
/** 注1
@@ -862,7 +1005,7 @@ module.exports = function (app, opts) {
html += packageAlarmData2Table({
titlePrefix: '数据中断',
alarmData: dataAlarmG1,
- alarmTitleArr: dataAlarmTitle,
+ alarmTitleArr: dataLnterruptTitle,
})
}
if (c.alarmType.includes('data_exception')) {
@@ -990,7 +1133,8 @@ module.exports = function (app, opts) {
if (isDev) {
// !开发测试用的数据
- emails = ['1650192445@qq.com']
+ // emails = ['1650192445@qq.com']
+ emails = ['2798774060@qq.com']
}
if (emails.length) {
diff --git a/web/client/src/sections/install/containers/system.jsx b/web/client/src/sections/install/containers/system.jsx
index 2702f5d..e2d8f13 100644
--- a/web/client/src/sections/install/containers/system.jsx
+++ b/web/client/src/sections/install/containers/system.jsx
@@ -1,6 +1,6 @@
import React, { useEffect, useRef, useState } from 'react';
import { connect } from 'react-redux';
-import { Skeleton, Button, Pagination, Table, Popconfirm, Tooltip } from '@douyinfe/semi-ui';
+import { Skeleton, Button, Pagination, Table, Popconfirm, Tooltip, Input } from '@douyinfe/semi-ui';
import { SkeletonScreen, } from "$components";
import moment from "moment";
import SystemModal from '../components/systemModal'
@@ -28,6 +28,7 @@ const Example = (props) => {
const [tableKey, setTableKey] = useState([]) //修改时绑定的id
const page = useRef(query.page);//哪一页
const [mapping, setMapping] = useState() //修改时的映射类型
+ const [keyword, setKeyword] = useState() //搜索关键字
@@ -67,7 +68,7 @@ const Example = (props) => {
}, [query]);
function getProjectPomsList () {
- dispatch(install.getProjectPoms(query)).then((res) => {//获取已绑定项目
+ dispatch(install.getProjectPoms({ ...query, keyword })).then((res) => {//获取已绑定项目
if (res.success) {
let mytableData = JSON.parse(JSON.stringify(res.payload.data.rows));
let mytableKey = []
@@ -347,34 +348,58 @@ const Example = (props) => {