Browse Source

feat:3.9版本代码

dev
zhaobing’ 1 year ago
parent
commit
8831933303
  1. 12
      api/app/lib/controllers/alarm/data.js
  2. 24
      api/app/lib/controllers/dataCacl/index.js
  3. 1
      api/app/lib/controllers/monitor/index.js
  4. 181
      api/app/lib/controllers/organization/index.js
  5. 193
      api/app/lib/controllers/project/group.js
  6. 15
      api/app/lib/controllers/project/index.js
  7. 11
      api/app/lib/models/report_automatic.js
  8. 2
      api/app/lib/routes/project/index.js
  9. 30
      api/app/lib/schedule/alarms_push.js
  10. 4
      api/app/lib/schedule/workOrder.js
  11. 5
      script/3.9/schema/1.update_report_automatic.sql
  12. 4
      web/client/src/layout/components/header/index.jsx
  13. 34
      web/client/src/sections/control/containers/control.jsx
  14. 9
      web/client/src/sections/install/containers/AbnRecognize.jsx
  15. 57
      web/client/src/sections/install/containers/burr.jsx
  16. 43
      web/client/src/sections/install/containers/cacl.jsx
  17. 57
      web/client/src/sections/install/containers/interrupt.jsx
  18. 38
      web/client/src/sections/install/containers/roles.jsx
  19. 11
      web/client/src/sections/install/containers/system.jsx
  20. 57
      web/client/src/sections/install/containers/trend.jsx
  21. 2
      web/client/src/sections/install/style.less
  22. 2
      web/client/src/sections/problem/actions/problem.jsx
  23. 29
      web/client/src/sections/problem/components/tableData.jsx
  24. 2
      web/client/src/sections/problem/containers/dataAlarm.jsx
  25. 16
      web/client/src/sections/projectGroup/actions/group.js
  26. 368
      web/client/src/sections/projectGroup/containers/bigscreen.jsx
  27. 40
      web/client/src/sections/projectGroup/style.less
  28. 16
      web/client/src/sections/service/components/automatic-Modal.jsx
  29. 4
      web/client/src/sections/workOrder/containers/initiated.jsx
  30. 2
      web/client/src/utils/webapi.js

12
api/app/lib/controllers/alarm/data.js

@ -46,7 +46,7 @@ async function list (ctx) {
const { utils: { judgeSuper, anxinStrucIdRange } } = ctx.app.fs const { utils: { judgeSuper, anxinStrucIdRange } } = ctx.app.fs
const { database: anxinyun } = clickHouse.anxinyun.opts.config const { database: anxinyun } = clickHouse.anxinyun.opts.config
const { pepProjectId, keywordTarget, keyword, groupId, groupUnitId, sustainTimeStart, sustainTimeEnd, limit, page, state, onlineState, toExport } = ctx.query const { timestamps,pepProjectId, keywordTarget, keyword, groupId, groupUnitId, sustainTimeStart, sustainTimeEnd, limit, page, state, onlineState, toExport } = ctx.query
let anxinStruc = await anxinStrucIdRange({ let anxinStruc = await anxinStrucIdRange({
ctx, pepProjectId, keywordTarget, keyword ctx, pepProjectId, keywordTarget, keyword
@ -100,10 +100,10 @@ async function list (ctx) {
let alarmQueryOptionStr = ` let alarmQueryOptionStr = `
FROM FROM
alarms alarms
LEFT JOIN ( ${timestamps?`LEFT JOIN (
SELECT DeviceId, any(Status) AS Status,max(Time) FROM DeviceStatus GROUP BY DeviceId SELECT DeviceId, any(Status) AS Status,max(Time) FROM DeviceStatus GROUP BY DeviceId
) AS DeviceStatus ) AS DeviceStatus
ON DeviceStatus.DeviceId = alarms.SourceId ON DeviceStatus.DeviceId = alarms.SourceId`:''}
LEFT JOIN ${anxinyun}.t_structure LEFT JOIN ${anxinyun}.t_structure
ON ${anxinyun}.t_structure.id = alarms.StructureId ON ${anxinyun}.t_structure.id = alarms.StructureId
LEFT JOIN ${anxinyun}.t_alarm_code LEFT JOIN ${anxinyun}.t_alarm_code
@ -121,7 +121,7 @@ async function list (ctx) {
SourceTypeId, SourceTypeId,
AlarmAdviceProblem, AlarmGroup, AlarmGroupUnit, AlarmAdviceProblem, AlarmAdviceProblem, AlarmGroup, AlarmGroupUnit, AlarmAdviceProblem,
alarms.StructureId AS StructureId, alarms.StructureId AS StructureId,
${`DeviceStatus.Status AS DeviceStatus,`} ${timestamps?`DeviceStatus.Status AS DeviceStatus,`:''}
${anxinyun}.t_structure.name AS StructureName, ${anxinyun}.t_structure.name AS StructureName,
${anxinyun}.t_structure.longitude AS StructureLongitude, ${anxinyun}.t_structure.longitude AS StructureLongitude,
${anxinyun}.t_structure.latitude AS StructureLatitude, ${anxinyun}.t_structure.latitude AS StructureLatitude,

24
api/app/lib/controllers/dataCacl/index.js

@ -26,16 +26,28 @@ async function findAbnMethods(ctx, next) {
} }
//获取异常参数配置 //获取异常参数配置
async function findAbnParamList(ctx) { async function findAbnParamList(ctx) {
const { factorId } = ctx.query const { factorId,limit,page,keywords,type } = ctx.query
const id=factorId.split(',') const id=factorId.split(',')
let rslt = null; let rslt = null;
let error = { name: 'FindError', message: '异常参数配置获取失败' }; let error = { name: 'FindError', message: '异常参数配置获取失败' };
let abnParamList
try { try {
let findOption= {where:{ factorId:{$in:id},abnTypeId:Number(type) }}
if (limit) {
findOption.limit = limit
}
if (page && limit) {
findOption.offset = page * limit
}
if(keywords){
findOption.where.$or = [
{ sensorLocationDescription: { $like: `%${keywords}%` } },
{ factor: { $like: `%${keywords}%` } }
]
}
const models = ctx.fs.dc.models; const models = ctx.fs.dc.models;
let abnParamList = await models.AbnReportParams.findAll({ abnParamList= await models.AbnReportParams.findAndCountAll(findOption)
where: { factorId:{$in:id} } rslt = abnParamList.rows.map(s => ({
})
rslt = abnParamList.map(s => ({
key: s.id, key: s.id,
id: s.id, id: s.id,
sensorId: s.sensorId, sensorId: s.sensorId,
@ -56,7 +68,7 @@ async function findAbnParamList(ctx) {
ctx.body = error; ctx.body = error;
} else { } else {
ctx.status = 200; ctx.status = 200;
ctx.body = rslt; ctx.body ={count:abnParamList.count,rows:rslt}
} }
} }

1
api/app/lib/controllers/monitor/index.js

@ -284,7 +284,6 @@ async function exportMaterialEnterList(ctx, data, columns) {
// exportData.push(item) // exportData.push(item)
// } // }
const fileName = `${siteName}` + '.xls' const fileName = `${siteName}` + '.xls'
console.log('x11111111',data,fileName,header)
const filePath = await simpleExcelDown({ data: data, header, fileName: fileName, needIndexCell: false }) const filePath = await simpleExcelDown({ data: data, header, fileName: fileName, needIndexCell: false })
const fileData = fs.readFileSync(filePath) const fileData = fs.readFileSync(filePath)
ctx.status = 200 ctx.status = 200

181
api/app/lib/controllers/organization/index.js

@ -1,7 +1,7 @@
'use strict'; 'use strict';
const moment = require('moment') const moment = require('moment')
async function allDeps (ctx) { async function allDeps(ctx) {
try { try {
const models = ctx.fs.dc.models; const models = ctx.fs.dc.models;
const { redis } = ctx.app const { redis } = ctx.app
@ -22,7 +22,7 @@ async function allDeps (ctx) {
} }
} }
async function allUsers (ctx) { async function allUsers(ctx) {
try { try {
const { models } = ctx.fs.dc; const { models } = ctx.fs.dc;
const { clickHouse } = ctx.app.fs const { clickHouse } = ctx.app.fs
@ -43,7 +43,7 @@ async function allUsers (ctx) {
} }
} }
async function editUser (ctx) { async function editUser(ctx) {
try { try {
const models = ctx.fs.dc.models; const models = ctx.fs.dc.models;
const { pomsUserId, pepUserId, role = [], correlationProject = [] } = ctx.request.body const { pomsUserId, pepUserId, role = [], correlationProject = [] } = ctx.request.body
@ -113,7 +113,7 @@ async function editUser (ctx) {
} }
} }
async function putUser (ctx) { async function putUser(ctx) {
try { try {
const models = ctx.fs.dc.models; const models = ctx.fs.dc.models;
const { pomsUserId } = ctx.params const { pomsUserId } = ctx.params
@ -153,7 +153,7 @@ async function putUser (ctx) {
} }
} }
async function delAdmin (ctx) { async function delAdmin(ctx) {
try { try {
const models = ctx.fs.dc.models; const models = ctx.fs.dc.models;
const { pomsUserId } = ctx.params const { pomsUserId } = ctx.params
@ -189,13 +189,13 @@ async function delAdmin (ctx) {
} }
} }
async function user (ctx) { async function user(ctx) {
try { try {
const models = ctx.fs.dc.models; const models = ctx.fs.dc.models;
const { clickHouse } = ctx.app.fs const { clickHouse } = ctx.app.fs
const sequelize = ctx.fs.dc.orm; const sequelize = ctx.fs.dc.orm;
const { role, limit, page, } = ctx.query const { role, limit, page, keywords } = ctx.query
const excludeField = ['lastInTime', 'inTimes', 'onlineDuration', 'lastInAddress', 'deleted', 'updateTime'] const excludeField = ['lastInTime', 'inTimes', 'onlineDuration', 'lastInAddress', 'deleted', 'updateTime']
@ -222,14 +222,107 @@ async function user (ctx) {
findOption.where.role = { $contains: [role] } findOption.where.role = { $contains: [role] }
} }
if (limit) { if (limit) {
findOption.limit = limit findOption.limit = limit
} }
if (page && limit) { if (page && limit) {
findOption.offset = page * limit findOption.offset = page * limit
} }
if(keywords){
let userPepRes =await clickHouse.pepEmis.query(`
SELECT DISTINCT
user.id AS id, "user"."name" AS name, department.name AS depName, department.id AS depId
FROM department_user
LEFT JOIN user
ON department_user.user=user.id
LEFT JOIN department
ON department.id=department_user.department
WHERE
department.delete='0'
AND "user"."name" LIKE '%${keywords}%'`||[]
).toPromise() ||[]
let userId=new Set()
userPepRes.forEach(item=>{
userId.add(item.id)
})
findOption.where.pepUserId =Array.from(userId)
let userRes = await models.User.findAndCountAll(findOption)
const adminRes = await models.User.findAll({
where: {
role: { $contains: ['admin'] }
},
attributes: {
exclude: excludeField,
},
order: [['updateTime', 'DESC']]
})
let pomsProjectIds = new Set()
for (let u of userRes.rows.concat(adminRes)) {
for (let pid of u.correlationProject) {
pomsProjectIds.add(pid)
}
}
// 获取响应的绑定的 项企项目的 id
let pomsProjectRes = await models.ProjectCorrelation.findAll({
where: {
id: { $in: [...pomsProjectIds] },
// del: false
}
})
let pepPojectIds = new Set()
for (let p of pomsProjectRes) {
if (p.pepProjectId) {
pepPojectIds.add(p.pepProjectId)
}
}
// 查对应的项企项目信息
let pepProjectRes = pepPojectIds.size ?
await clickHouse.projectManage.query(`
SELECT id, project_name, isdelete FROM t_pim_project WHERE id IN (${[...pepPojectIds]},-1)
`).toPromise() :
[]
for (let u of userRes.rows.concat(adminRes)) {
// 用户信息
const corUsers = userPepRes
u.dataValues.name = corUsers.length ? corUsers[0].name : ''
u.dataValues.departments = corUsers.length ? corUsers.map(cu => {
return {
name: cu.depName,
id: cu.depId
}
}) : []
// pep项目信息
u.dataValues.correlationProject = u.dataValues.correlationProject.map(cpid => {
let returnData = {
id: cpid,
}
const corPomsProject = pomsProjectRes.find(ppr => ppr.id == cpid)
if (corPomsProject) {
returnData.name = corPomsProject.name
returnData.del = corPomsProject.del
if (corPomsProject.pepProjectId) {
returnData.pepProjectId = corPomsProject.pepProjectId
const corPepProject = pepProjectRes.find(ppr => ppr.id == corPomsProject.pepProjectId)
if (corPepProject) {
returnData.pepProjectName = corPepProject.project_name
returnData.pepIsdelete = corPepProject.isdelete
}
}
}
return returnData
})
}
ctx.status = 200
ctx.body = {
admin: adminRes,
users: userRes
}
const userRes = await models.User.findAndCountAll(findOption) }
let userRes = await models.User.findAndCountAll(findOption)
const adminRes = await models.User.findAll({ const adminRes = await models.User.findAll({
where: { where: {
role: { $contains: ['admin'] } role: { $contains: ['admin'] }
@ -260,7 +353,8 @@ async function user (ctx) {
ON department.id=department_user.department ON department.id=department_user.department
WHERE WHERE
user.id IN (${[...userIds].join(',')},-1) user.id IN (${[...userIds].join(',')},-1)
AND department.delete='0'` AND department.delete='0'
`
).toPromise() : ).toPromise() :
[] []
@ -285,38 +379,45 @@ async function user (ctx) {
`).toPromise() : `).toPromise() :
[] []
const data = userRes.rows.filter(item => {
return userPepRes.some(f => f.id == item.dataValues.pepUserId)
})
userRes.rows = data
userRes.count = data.length
// 遍历用户并将查到的信息拼合 // 遍历用户并将查到的信息拼合
for (let u of userRes.rows.concat(adminRes)) { for (let u of userRes.rows.concat(adminRes)) {
// 用户信息 // 用户信息
const corUsers = userPepRes.filter(up => up.id == u.pepUserId) const corUsers = userPepRes.filter(up => up.id == u.pepUserId)
u.dataValues.name = corUsers.length ? corUsers[0].name : '' u.dataValues.name = corUsers.length ? corUsers[0].name : ''
u.dataValues.departments = corUsers.length ? corUsers.map(cu => { u.dataValues.departments = corUsers.length ? corUsers.map(cu => {
return { return {
name: cu.depName, name: cu.depName,
id: cu.depId id: cu.depId
} }
}) : [] }) : []
// pep项目信息 // pep项目信息
u.dataValues.correlationProject = u.dataValues.correlationProject.map(cpid => { u.dataValues.correlationProject = u.dataValues.correlationProject.map(cpid => {
let returnData = { let returnData = {
id: cpid, id: cpid,
} }
const corPomsProject = pomsProjectRes.find(ppr => ppr.id == cpid) const corPomsProject = pomsProjectRes.find(ppr => ppr.id == cpid)
if (corPomsProject) { if (corPomsProject) {
returnData.name = corPomsProject.name returnData.name = corPomsProject.name
returnData.del = corPomsProject.del returnData.del = corPomsProject.del
if (corPomsProject.pepProjectId) { if (corPomsProject.pepProjectId) {
returnData.pepProjectId = corPomsProject.pepProjectId returnData.pepProjectId = corPomsProject.pepProjectId
const corPepProject = pepProjectRes.find(ppr => ppr.id == corPomsProject.pepProjectId) const corPepProject = pepProjectRes.find(ppr => ppr.id == corPomsProject.pepProjectId)
if (corPepProject) { if (corPepProject) {
returnData.pepProjectName = corPepProject.project_name returnData.pepProjectName = corPepProject.project_name
returnData.pepIsdelete = corPepProject.isdelete returnData.pepIsdelete = corPepProject.isdelete
}
} }
} }
} return returnData
return returnData })
}) }
}
ctx.status = 200 ctx.status = 200
ctx.body = { ctx.body = {

193
api/app/lib/controllers/project/group.js

@ -435,114 +435,54 @@ async function groupStatisticOnline (ctx) {
// 查在线率 // 查在线率
const strucOnlineClient = ctx.app.fs.esclient.strucOnline const strucOnlineClient = ctx.app.fs.esclient.strucOnline
// let arr = [1,2,3,4,5,6,7] let arr = [1,2,3,4,5,6,7]
// let onlineRes={ let onlineRes={
// hits: { hits: {
// hits: [] hits: []
// } }
// } }
// if(strucIdArr.length){ if(strucIdArr.length){
// for(let i = 0;i<arr.length;i++){ for(let i = 0;i<arr.length;i++){
// const res=await strucOnlineClient.search({ const res=await strucOnlineClient.search({
// index: strucOnlineClient.config.index, index: strucOnlineClient.config.index,
// type: strucOnlineClient.config.type, type: strucOnlineClient.config.type,
// body: { body: {
// "query": { "query": {
// "bool": { "bool": {
// "filter": [ "filter": [
// { {
// "range": { "range": {
// "collect_time": { "collect_time": {
// "gte": `${moment().subtract(24*(i+1)+8, 'hours').format('YYYY-MM-DDTHH:mm:ss.SSS')}Z`, "gte": `${moment().subtract(24*(i+1)+8, 'hours').format('YYYY-MM-DDTHH:mm:ss.SSS')}Z`,
// // "gte": "2023-08-24T08:00:00.000Z", // "gte": "2023-08-24T08:00:00.000Z",
// "lt":`${moment().subtract(8+24*i, 'hours').format('YYYY-MM-DDTHH:mm:ss.SSS')}Z` "lt":`${moment().subtract(8+24*i, 'hours').format('YYYY-MM-DDTHH:mm:ss.SSS')}Z`
// } }
// }
// },
// {
// "terms": {
// "structure": strucIdArr,
// // "structure": [1, 2, 3]
// }
// }
// ]
// }
// },
// "sort": [
// {
// "collect_time": {
// "order": "asc"
// }
// }
// ],
// "size": 10000
// }
// })
// onlineRes.hits.hits=[...onlineRes.hits.hits,...res.hits.hits]
// }
// }
// for (let struc of strucRes) {
// let curOnline =
// onlineRes.hits.hits
// .filter((h) => h._source.structure == struc.id)
// // .sort((a, b) => {
// // return a._source.collect_time - b._source.collect_time
// // })
// .map(s => {
// return {
// ...s._source,
// rate: s._source.online / s._source.total * 100
// }
// })
// let curOffline = maxOfflineTimeRes.find((o) => o.structure == struc.id)
// struc.online = curOnline
// struc.offline = curOffline || {}
// }
// 查在线率
const onlineRes = strucIdArr.length ?
await strucOnlineClient.search({
index: strucOnlineClient.config.index,
type: strucOnlineClient.config.type,
body: {
"query": {
"bool": {
"filter": [
{
"range": {
"collect_time": {
"gte": `${moment().subtract(32, 'hours').format('YYYY-MM-DDTHH:mm:ss.SSS')}Z`,
// "gte": "2023-08-24T08:00:00.000Z",
} }
} },
}, {
{ "terms": {
"terms": { "structure": strucIdArr,
"structure": strucIdArr,
// "structure": [1, 2, 3] // "structure": [1, 2, 3]
} }
}
]
}
},
"sort": [
{
"collect_time": {
"order": "asc"
} }
]
}
},
"sort": [
{
"collect_time": {
"order": "asc"
} }
} ],
], "size": 10000
"size": 10000 }
} })
}) onlineRes.hits.hits=[...onlineRes.hits.hits,...res.hits.hits]
: {
hits: { }
hits: [] }
}
}
for (let struc of strucRes) { for (let struc of strucRes) {
let curOnline = let curOnline =
@ -821,6 +761,50 @@ async function getWorkOrdersRepairRank (ctx) {
} }
} }
async function getworkOrdersAvgTimes (ctx) {
try {
// 计算一个月前的日期
const oneMonthAgo = moment().subtract(1, 'months').toDate()
const { models } = ctx.fs.dc
const sequelize = ctx.fs.dc.ORM
const { projectIds } = ctx.query
if (projectIds && projectIds.length) {
const res= await models.FormDataTable.findAll({
where: {
projectId: {
$in: projectIds.split(',').map(Number)
},
startTime: {
$gte: oneMonthAgo,
}
},
attributes: [
'project_id',
[
sequelize.literal('AVG(EXTRACT(EPOCH FROM "end_time" + INTERVAL \'8 hours\' - "start_time"))'),
'avgTime',
],
],
group: ['project_id'],
order: [[sequelize.literal('AVG(EXTRACT(EPOCH FROM "end_time" + INTERVAL \'8 hours\' - "start_time"))'), 'DESC']],
limit: 5,
})
ctx.body = res
ctx.status = 200
} else {
ctx.body = '没有查询到信息'
ctx.status = 204
}
}catch(error){
ctx.fs.logger.error(`path: ${ctx.path}, error: ${error}`);
ctx.status = 400;
ctx.body = {
message: typeof error == 'string' ? error : undefined
}
}
}
module.exports = { module.exports = {
groupList, groupList,
@ -832,5 +816,6 @@ module.exports = {
groupStatisticAlarm, groupStatisticAlarm,
groupProject, groupProject,
getProjectWorkOrders, getProjectWorkOrders,
getWorkOrdersRepairRank getWorkOrdersRepairRank,
getworkOrdersAvgTimes
}; };

15
api/app/lib/controllers/project/index.js

@ -24,7 +24,6 @@ async function pomsProject (ctx) {
const { clickHouse } = ctx.app.fs const { clickHouse } = ctx.app.fs
const { userId, pepUserId, userInfo, pepUserInfo } = ctx.fs.api const { userId, pepUserId, userInfo, pepUserInfo } = ctx.fs.api
const { limit, page, global, pepId, keyword } = ctx.query const { limit, page, global, pepId, keyword } = ctx.query
let findOption = { let findOption = {
where: { where: {
del: false, del: false,
@ -87,7 +86,6 @@ async function pomsProject (ctx) {
} }
const proRes = await models.ProjectCorrelation.findAndCountAll(findOption) const proRes = await models.ProjectCorrelation.findAndCountAll(findOption)
let pepProjectIds = new Set() let pepProjectIds = new Set()
let anxinProjectIds = new Set() let anxinProjectIds = new Set()
let createUsers = new Set() let createUsers = new Set()
@ -104,6 +102,17 @@ async function pomsProject (ctx) {
} }
} }
} }
let pepmCustomerLevelRes = pepProjectIds.size ? await clickHouse.projectManage.query(
`
SELECT t_rpm_customer_level.id AS id, t_rpm_customer_level.name AS name, t_pim_project.id AS projectId
FROM t_pim_project
LEFT JOIN t_rpm_customer
ON t_rpm_customer.id = t_pim_project.related_customers_id
LEFT JOIN t_rpm_customer_level
ON t_rpm_customer_level.id = t_rpm_customer.level
WHERE t_pim_project.id IN (${[...pepProjectIds].join(',')},-1)
`
).toPromise() : []
const pomsUser = await models.User.findAll({ const pomsUser = await models.User.findAll({
where: { where: {
id: { $in: [...createUsers] } id: { $in: [...createUsers] }
@ -124,6 +133,7 @@ async function pomsProject (ctx) {
).toPromise() : ).toPromise() :
[] []
const pepProjectRes = pepProjectIds.size ? const pepProjectRes = pepProjectIds.size ?
await clickHouse.projectManage.query( await clickHouse.projectManage.query(
` `
@ -161,6 +171,7 @@ async function pomsProject (ctx) {
p.dataValues.anxinProject = nextAnxinProject p.dataValues.anxinProject = nextAnxinProject
p.dataValues.pepUserName = pepUserName p.dataValues.pepUserName = pepUserName
delete p.dataValues.anxinProjectId delete p.dataValues.anxinProjectId
p.dataValues.customerLevel=(pepmCustomerLevelRes.find(pp => pp.projectId == p.dataValues.pepProjectId)||{name:'--'}).name
} }
ctx.status = 200; ctx.status = 200;
ctx.body = proRes ctx.body = proRes

11
api/app/lib/models/report_automatic.js

@ -53,7 +53,7 @@ module.exports = dc => {
}, },
reportPicPath: { reportPicPath: {
type: DataTypes.STRING, type: DataTypes.STRING,
allowNull: false, allowNull: true,
defaultValue: null, defaultValue: null,
comment: "", comment: "",
primaryKey: false, primaryKey: false,
@ -141,6 +141,15 @@ module.exports = dc => {
field: "factors", field: "factors",
autoIncrement: false autoIncrement: false
}, },
overview: {
type: DataTypes.STRING,
allowNull: true,
defaultValue: null,
comment: "",
primaryKey: false,
field: "overview",
autoIncrement: false
},
}, { }, {
tableName: "report_automatic", tableName: "report_automatic",
comment: "", comment: "",

2
api/app/lib/routes/project/index.js

@ -62,4 +62,6 @@ module.exports = function (app, router, opts) {
app.fs.api.logAttr['GET/project/workOrders/repairRank'] = { content: '获取工单修复信息', visible: true }; app.fs.api.logAttr['GET/project/workOrders/repairRank'] = { content: '获取工单修复信息', visible: true };
router.get('project/workOrders/repairRank', projectGroup.getWorkOrdersRepairRank); router.get('project/workOrders/repairRank', projectGroup.getWorkOrdersRepairRank);
app.fs.api.logAttr['GET/project/workOrders/avgTime'] = { content: '获取工单平均修复时长', visible: true };
router.get('project/workOrders/avgTime', projectGroup.getworkOrdersAvgTimes);
}; };

30
api/app/lib/schedule/alarms_push.js

@ -1503,16 +1503,38 @@ module.exports = function (app, opts) {
let alarmHtmlTitle = packageTableTitle(alarmTitleArr) let alarmHtmlTitle = packageTableTitle(alarmTitleArr)
let accumulate = 0 let accumulate = 0
if (type == 1) { if (type == 1) {
console.log('xx111112222',alarmData) //调整结构物位置
alarmData.map((h, hi) => {
if (h.projects && h.projects.length) {
h.projects.map((x, xi) => {
let problem = 0;
let count = 0;
if (x.factor && x.factor.length) {
x.factor.map((f, fi) => {
problem += f.problem;
count += f.devicesLength;
});
// 如果 problem 等于 count,将该结构物移到前面
if (problem === count) {
h.projects.splice(xi, 1); // 先移除当前元素
h.projects.unshift(x); // 然后将该结构物移到数组前面
}
}
});
}
})
alarmData.map((h, hi) => { alarmData.map((h, hi) => {
accumulate += h.rowspan || 0 accumulate += h.rowspan || 0
if (h.projects && h.projects.length) { if (h.projects && h.projects.length) {
h.projects.map((x, xi) => { h.projects.map((x, xi) => {
let flag //用于设备全部中断做特殊标记
let problem=0
let count=0
let showOne1 = (xi == 0) ? true : false let showOne1 = (xi == 0) ? true : false
if (x.factor && x.factor.length) { if (x.factor && x.factor.length) {
x.factor.map((f, fi) => { x.factor.map((f, fi) => {
problem+=f.problem
count+=f.devicesLength
let showOne2 = (fi == 0) ? true : false let showOne2 = (fi == 0) ? true : false
if (f.devices && f.devices.length) { if (f.devices && f.devices.length) {
f.devices.map((c, ci) => { f.devices.map((c, ci) => {
@ -1537,7 +1559,7 @@ module.exports = function (app, opts) {
break; break;
case 'Structure': case 'Structure':
if (showOne2 && showOne3 && showOne4) { if (showOne2 && showOne3 && showOne4) {
tableData += `<th rowspan=${x.rowspan}>${x['name'] || ''}</th>` tableData +=problem==count?`<th style="color: red;" rowspan=${x.rowspan}>${x['name'](测点数据全部中断) || ''}</th>`: `<th rowspan=${x.rowspan}>${x['name'] || ''}</th>`
} }
break; break;
case 'factor': case 'factor':

4
api/app/lib/schedule/workOrder.js

@ -64,17 +64,15 @@ module.exports = function (app, opts,ctx) {
: ''}` : ''}`
).toPromise() ).toPromise()
const procinstIds = [...new Set(formRes.map(e => e.procinstId))]; const procinstIds = [...new Set(formRes.map(e => e.procinstId))];
console.log('formRes1',procinstIds)
// 获取流程实例变量 // 获取流程实例变量
if(formRes && formRes.length > 0){ if(formRes && formRes.length > 0){
let procinstsVariables = await request.post(encodeURI(opts.camundarest.host+'/'+opts.camundarest.root+`/engine-rest/history/variable-instance`)) let procinstsVariables = await request.post(encodeURI(opts.camundarest.host+'/'+opts.camundarest.root+`/engine-rest/history/variable-instance`))
.auth(username, password) .auth(username, password)
.set('Content-Type', 'application/json') .set('Content-Type', 'application/json')
.send({processInstanceIdIn: procinstIds}) .send({processInstanceIdIn: procinstIds})
console.log('formRes2',procinstsVariables)
if(procinstsVariables.body&&procinstsVariables.body.length){ if(procinstsVariables.body&&procinstsVariables.body.length){
for (let f of formRes) { for (let f of formRes) {
const parseData = parseProcessData({ const parseData =f.formSchema&& parseProcessData({
formSchema: JSON.parse(f.formSchema), formSchema: JSON.parse(f.formSchema),
formData: JSON.parse(f.formData) formData: JSON.parse(f.formData)
}) })

5
script/3.9/schema/1.update_report_automatic.sql

@ -0,0 +1,5 @@
alter table report_automatic
add overview varchar(300);
alter table report_automatic
alter column reportpic_path drop not null;

4
web/client/src/layout/components/header/index.jsx

@ -13,7 +13,7 @@ import layout from '../../containers/layout';
let newScrollbar; let newScrollbar;
const Header = (props) => { const Header = (props) => {
const { dispatch, history, user, actions, socket, headerItems, tochange, projectGroup } = props; const { dispatch, history, user, actions, socket, headerItems, tochange, projectGroup } = props;
const { install, projectGroup: projectGroupAC, layout } = actions const { install, projectGroup: projectGroupAC, layout,problem } = actions
const [pomsList, setPomsList] = useState([]) const [pomsList, setPomsList] = useState([])
const [pomsName, setPomsName] = useState('全局') const [pomsName, setPomsName] = useState('全局')
const [pepProjectId, setPepProjectId] = useState() const [pepProjectId, setPepProjectId] = useState()
@ -63,7 +63,7 @@ const Header = (props) => {
setCount(res.payload.data?.count) setCount(res.payload.data?.count)
} }
}) })
dispatch(problem.getAlarmDataGroup())
} }
}, []) }, [])

34
web/client/src/sections/control/containers/control.jsx

@ -202,7 +202,8 @@ const Control = ({ dispatch, actions, user, history, loading, socket, pepProject
useEffect(() => { useEffect(() => {
// //
let data = ['overall', 'workbench', 'statistical', 'analyse', 'dynamic'] let data = ['overall_new', 'workbench', 'statistical', 'analyse', 'dynamic']
localStorage.getItem('overall')?localStorage.removeItem('overall'):""
data.map(v => { data.map(v => {
localStorage.getItem(v) == null localStorage.getItem(v) == null
? localStorage.setItem(v, JSON.stringify(show[v])) ? localStorage.setItem(v, JSON.stringify(show[v]))
@ -226,14 +227,13 @@ const Control = ({ dispatch, actions, user, history, loading, socket, pepProject
}, [pepProjectId]) }, [pepProjectId])
useEffect(() => { useEffect(() => {
if (exhibition.current?.overall?.find(v => v.key == 'tool')) { if (exhibition.current?.overall_new?.find(v => v.key == 'tool')) {
consoleToollink() consoleToollink()
} }
}, [exhibition.current]) }, [exhibition.current])
useEffect(() => { useEffect(() => {
async function concentration2 () { async function concentration2 () {
if (exhibition.current?.overall?.find(v => v.key == 'analyse')) { if (exhibition.current?.overall_new?.find(v => v.key == 'analyse')) {
// BI- // BI-
await dispatch(control.getDataAlarmsAggDay({ pepProjectId: pepProjectId })).then(res => { await dispatch(control.getDataAlarmsAggDay({ pepProjectId: pepProjectId })).then(res => {
if (res.success) setDataBI(res.payload.data) if (res.success) setDataBI(res.payload.data)
@ -329,7 +329,7 @@ const Control = ({ dispatch, actions, user, history, loading, socket, pepProject
} }
}) })
} }
if (exhibition.current?.overall?.find(v => v.key == 'statistical')) { if (exhibition.current?.overall_new?.find(v => v.key == 'statistical')) {
concentration4() concentration4()
} }
}, [projectId, exhibition.current]) }, [projectId, exhibition.current])
@ -391,7 +391,7 @@ const Control = ({ dispatch, actions, user, history, loading, socket, pepProject
} }
} }
if (exhibition.current?.overall?.find(v => v.key == 'dynamic')) { if (exhibition.current?.overall_new?.find(v => v.key == 'dynamic')) {
concentration3() concentration3()
} }
@ -580,14 +580,14 @@ const Control = ({ dispatch, actions, user, history, loading, socket, pepProject
let Select = { let Select = {
overall: ['workbench', 'statistical', 'dataAnalyse', 'analyse', 'dynamic', 'tool'], overall_new: ['workbench', 'statistical', 'dataAnalyse', 'analyse', 'dynamic', 'tool'],
workbench: ['project', 'data', 'app', 'device'], workbench: ['project', 'data', 'app', 'device'],
statistical: ['milestone', 'personnel', 'DeviceAccess', 'web', 'problem'], statistical: ['milestone', 'personnel', 'DeviceAccess', 'web', 'problem'],
analyse: ['dataInterrupt', 'dataAbnormal', 'policyHit', 'videoException', 'appAbnormal', 'deviceAbnormal', 'problemAnalysis'], analyse: ['dataInterrupt', 'dataAbnormal', 'policyHit', 'videoException', 'appAbnormal', 'deviceAbnormal', 'problemAnalysis'],
dynamic: ['discovery', 'notice', 'handle', 'confirm'], dynamic: ['discovery', 'notice', 'handle', 'confirm'],
} }
let show = { let show = {
overall: ['workbench', 'dataAnalyse'], overall_new: ['workbench', 'dataAnalyse'],
workbench: ['project', 'data', 'app', 'device'], workbench: ['project', 'data', 'app', 'device'],
statistical: ['milestone', 'personnel', 'web', 'problem'], statistical: ['milestone', 'personnel', 'web', 'problem'],
analyse: ['dataInterrupt', 'dataAbnormal', 'policyHit', 'videoException', 'appAbnormal', 'deviceAbnormal', 'problemAnalysis'], analyse: ['dataInterrupt', 'dataAbnormal', 'policyHit', 'videoException', 'appAbnormal', 'deviceAbnormal', 'problemAnalysis'],
@ -662,8 +662,8 @@ const Control = ({ dispatch, actions, user, history, loading, socket, pepProject
<div style={{ width: 25, height: 25, cursor: "pointer" }}> <div style={{ width: 25, height: 25, cursor: "pointer" }}>
<img src="/assets/images/console/icon_all.png" alt="" style={{ width: '100%', height: '100%' }} onClick={() => { <img src="/assets/images/console/icon_all.png" alt="" style={{ width: '100%', height: '100%' }} onClick={() => {
setSetup(true) setSetup(true)
setTableType('overall') setTableType('overall_new')
attribute('overall') attribute('overall_new')
setSetData(6) setSetData(6)
}} /> }} />
</div> </div>
@ -672,7 +672,7 @@ const Control = ({ dispatch, actions, user, history, loading, socket, pepProject
<div style={{ display: 'flex', width: '100%' }}> <div style={{ display: 'flex', width: '100%' }}>
{/* 左边 */} {/* 左边 */}
<div style={{ <div style={{
width: exhibition.current?.overall?.find(v => v.key == 'dynamic' || v.key == 'tool') ? width: exhibition.current?.overall_new?.find(v => v.key == 'dynamic' || v.key == 'tool') ?
'calc(100% - 434px)' : "calc(100%)" 'calc(100% - 434px)' : "calc(100%)"
}}> }}>
{/* 工作台和统计概览 */} {/* 工作台和统计概览 */}
@ -750,7 +750,7 @@ const Control = ({ dispatch, actions, user, history, loading, socket, pepProject
{/* 统计概览 */} {/* 统计概览 */}
{ {
exhibition.current?.overall?.find(v => v.key == 'statistical') ? <> exhibition.current?.overall_new?.find(v => v.key == 'statistical') ? <>
<div style={{ display: 'flex', alignItems: 'center', justifyContent: 'space-between', marginTop: 25 }}> <div style={{ display: 'flex', alignItems: 'center', justifyContent: 'space-between', marginTop: 25 }}>
<div style={{ display: 'flex', alignItems: 'center' }}> <div style={{ display: 'flex', alignItems: 'center' }}>
<div style={{ width: 0, height: 20, borderLeft: '3px solid #005ABD', borderTop: '3px solid transparent', borderBottom: '3px solid transparent' }}></div> <div style={{ width: 0, height: 20, borderLeft: '3px solid #005ABD', borderTop: '3px solid transparent', borderBottom: '3px solid transparent' }}></div>
@ -994,12 +994,12 @@ const Control = ({ dispatch, actions, user, history, loading, socket, pepProject
{/* 图表 */} {/* 图表 */}
{ {
exhibition.current?.overall?.find(v => v.key == 'dataAnalyse') && exhibition.current?.overall_new?.find(v => v.key == 'dataAnalyse') &&
<AlarmChart /> <AlarmChart />
} }
{/* BI分析模块 */} {/* BI分析模块 */}
{exhibition.current?.overall?.find(v => v.key == 'analyse') ? {exhibition.current?.overall_new?.find(v => v.key == 'analyse') ?
<div style={{ background: '#FFFFFF', boxShadow: '0px 0px 12px 2px rgba(220,222,224,0.2)', borderRadius: 2, paddingTop: 20, paddingLeft: 24, marginTop: 22 }}> <div style={{ background: '#FFFFFF', boxShadow: '0px 0px 12px 2px rgba(220,222,224,0.2)', borderRadius: 2, paddingTop: 20, paddingLeft: 24, marginTop: 22 }}>
<div style={{ display: 'flex', alignItems: 'center', justifyContent: 'space-between' }}> <div style={{ display: 'flex', alignItems: 'center', justifyContent: 'space-between' }}>
<div style={{ display: 'flex', alignItems: 'center' }}> <div style={{ display: 'flex', alignItems: 'center' }}>
@ -1193,10 +1193,10 @@ const Control = ({ dispatch, actions, user, history, loading, socket, pepProject
</div> </div>
{/* 右边 */} {/* 右边 */}
{exhibition.current?.overall?.find(v => v.key == 'dynamic' || v.key == 'tool') {exhibition.current?.overall_new?.find(v => v.key == 'dynamic' || v.key == 'tool')
&& <div style={{ width: 415, marginLeft: 20 }}> && <div style={{ width: 415, marginLeft: 20 }}>
{/* 最新动态 */} {/* 最新动态 */}
{exhibition.current?.overall?.find(v => v.key == 'dynamic') {exhibition.current?.overall_new?.find(v => v.key == 'dynamic')
&& <div style={{ width: 415, background: '#FFFFFF', marginBottom: 20, boxShadow: '0px 0px 12px 2px rgba(220,222,224,0.2)', borderRadius: 2, paddingTop: 20, paddingLeft: 21, height: 639, }}> && <div style={{ width: 415, background: '#FFFFFF', marginBottom: 20, boxShadow: '0px 0px 12px 2px rgba(220,222,224,0.2)', borderRadius: 2, paddingTop: 20, paddingLeft: 21, height: 639, }}>
<div style={{ display: 'flex', alignItems: 'center', justifyContent: 'space-between' }}> <div style={{ display: 'flex', alignItems: 'center', justifyContent: 'space-between' }}>
<div style={{ display: 'flex', alignItems: 'center' }}> <div style={{ display: 'flex', alignItems: 'center' }}>
@ -1260,7 +1260,7 @@ const Control = ({ dispatch, actions, user, history, loading, socket, pepProject
</div> </div>
</div>} </div>}
{/* 我常用的工具 */} {/* 我常用的工具 */}
{exhibition.current?.overall?.find(v => v.key == 'tool') ? {exhibition.current?.overall_new?.find(v => v.key == 'tool') ?
<div style={{ background: '#FFFFFF', boxShadow: '0px 0px 12px 2px rgba(220,222,224,0.2)', borderRadius: 2, padding: 20 }}> <div style={{ background: '#FFFFFF', boxShadow: '0px 0px 12px 2px rgba(220,222,224,0.2)', borderRadius: 2, padding: 20 }}>
<div style={{ display: 'flex', alignItems: 'center', justifyContent: 'space-between' }}> <div style={{ display: 'flex', alignItems: 'center', justifyContent: 'space-between' }}>
<div style={{ display: 'flex', alignItems: 'center' }}> <div style={{ display: 'flex', alignItems: 'center' }}>

9
web/client/src/sections/install/containers/AbnRecognize.jsx

@ -10,7 +10,7 @@ import Interrupt from './interrupt'
const AbnRecognize = (props) => { const AbnRecognize = (props) => {
// const {abnCompareData}=props // const {abnCompareData}=props
const {calcMethod,abnCompareData,factorId,structId,strunctChange,itName,sensorId,project}=props const {calcMethod,abnCompareData,factorId,structId,strunctChange,itName,sensorId,project,limits,query,changeQuery,limitChange}=props
// let originalData = [''], calcArray = [], key, itemName, start, end; // let originalData = [''], calcArray = [], key, itemName, start, end;
// let stationsData = []; // let stationsData = [];
// if (abnCompareData &&calcMethod == abnCompareData.method) { // if (abnCompareData &&calcMethod == abnCompareData.method) {
@ -56,12 +56,11 @@ const AbnRecognize = (props) => {
// } // }
// } // }
const renderContent=()=> { const renderContent=()=> {
const SubContent = { const SubContent = {
'interrupt': <Interrupt project={project} sensorId={sensorId} structId={structId} factorId={factorId} />, 'interrupt': <Interrupt limitChange={limitChange} query={query} changeQuery={changeQuery} limits={limits} project={project} sensorId={sensorId} structId={structId} factorId={factorId} />,
'burr': <Burr project={project} sensorId={sensorId} structId={structId} factorId={factorId} itName={itName} />, 'burr': <Burr limitChange={limitChange} query={query} changeQuery={changeQuery} limits={limits} project={project} sensorId={sensorId} structId={structId} factorId={factorId} itName={itName} />,
'trend': <Trend project={project} sensorId={sensorId} structId={structId} factorId={factorId} itName={itName}/>, 'trend': <Trend limitChange={limitChange} query={query} changeQuery={changeQuery} limits={limits} project={project} sensorId={sensorId} structId={structId} factorId={factorId} itName={itName}/>,
}; };
return SubContent[calcMethod]; return SubContent[calcMethod];
} }

57
web/client/src/sections/install/containers/burr.jsx

@ -2,12 +2,12 @@
import React, { useState,useRef } from 'react'; import React, { useState,useRef } from 'react';
import { connect } from 'react-redux'; import { connect } from 'react-redux';
import { Row, Col, Button, Table, Card, Popconfirm, Tag,Notification, Form } from '@douyinfe/semi-ui'; import { Row, Col, Button, Table, Card, Popconfirm, Tag,Notification, Form,Pagination } from '@douyinfe/semi-ui';
import BurrModal from '../components/burrModal'; import BurrModal from '../components/burrModal';
import { useEffect } from 'react'; import { useEffect } from 'react';
const Burr = (props) => { const Burr = (props) => {
const {factorId,abnParam,structId,dispatch,actions,itName,sensorId,project}=props const {factorId,abnParam,structId,dispatch,actions,itName,sensorId,project,limits,query,changeQuery}=props
const form = useRef() const form = useRef()
const [selectedRowKeys, setSelectedRowKeys] = useState([]) const [selectedRowKeys, setSelectedRowKeys] = useState([])
const [filterFunc, setFilterFunc] = useState({}) const [filterFunc, setFilterFunc] = useState({})
@ -33,7 +33,12 @@ const Burr = (props) => {
dispatch(install.deleteAbnParams(e)).then(res=>{ dispatch(install.deleteAbnParams(e)).then(res=>{
if(res.success){ if(res.success){
const id = [factorId, -1].join(',') const id = [factorId, -1].join(',')
dispatch(install.getAbnParamList({ factorId: id })) changeQuery(10,0)
dispatch(install.getAbnParamList({ factorId: id,limit:10, page: 0,type:2})).then(rs=>{
if(rs.success){
limitChange(rs.payload.data.count)
}
})
} }
}) })
}; };
@ -62,7 +67,12 @@ const Burr = (props) => {
dispatch(install.batchCfgAbnParams(ids,data)).then(res=>{ dispatch(install.batchCfgAbnParams(ids,data)).then(res=>{
if(res.success){ if(res.success){
const id = [factorId, -1].join(',') const id = [factorId, -1].join(',')
dispatch(install.getAbnParamList({ factorId: id })) changeQuery(10,0)
dispatch(install.getAbnParamList({ factorId: id,limit:10, page: 0,type:2})).then(rs=>{
if(rs.success){
limitChange(rs.payload.data.count)
}
})
} }
}) })
} }
@ -74,7 +84,12 @@ const Burr = (props) => {
dispatch(install.deleteAbnParams(ids)).then(res=>{ dispatch(install.deleteAbnParams(ids)).then(res=>{
if(res.success){ if(res.success){
const id = [factorId, -1].join(',') const id = [factorId, -1].join(',')
dispatch(install.getAbnParamList({ factorId: id })) changeQuery(10,0)
dispatch(install.getAbnParamList({ factorId: id,limit:10, page: 0,type:2})).then(rs=>{
if(rs.success){
limitChange(rs.payload.data.count)
}
})
} }
}) })
@ -102,7 +117,12 @@ const Burr = (props) => {
dispatch(install.batchCfgAbnParams(ids,data)).then(res=>{ dispatch(install.batchCfgAbnParams(ids,data)).then(res=>{
if(res.success){ if(res.success){
const id = [factorId, -1].join(',') const id = [factorId, -1].join(',')
dispatch(install.getAbnParamList({ factorId: id })) changeQuery(10,0)
dispatch(install.getAbnParamList({ factorId: id,limit:10, page:0,type:2})).then(rs=>{
if(rs.success){
limitChange(rs.payload.data.count)
}
})
} }
}) })
} else if (dataSource.length != 0) { } else if (dataSource.length != 0) {
@ -236,7 +256,28 @@ const Burr = (props) => {
</Col> </Col>
</Row> </Row>
</Form> </Form>
<Table rowSelection={rowSelection} columns={columns} dataSource={tmpds} /> <Table rowSelection={rowSelection} columns={columns} dataSource={tmpds} pagination={false}/>
<div
style={{
display: "flex",
justifyContent: "flex-end",
padding: "20px 20px",
}}
>
<span style={{ lineHeight: "30px", fontSize: 13, color: 'rgba(0,90,189,0.8)' }}>
{limits}条信息
</span>
<Pagination
total={limits}
showSizeChanger
currentPage={query.page + 1}
pageSizeOpts={[10, 20, 30, 40]}
onChange={(currentPage, pageSize) => {
changeQuery( pageSize, currentPage - 1)
page.current = currentPage - 1
}}
/>
</div>
{modalVisible ? <BurrModal {modalVisible ? <BurrModal
project={project} project={project}
structId={structId} structId={structId}
@ -261,7 +302,7 @@ function mapStateToProps(state) {
return { return {
isRequesting: false,// isRequesting: false,//
abnParam: abnParam?.data||[], abnParam: abnParam?.data?.rows || [],
actions:global.actions actions:global.actions
} }
} }

43
web/client/src/sections/install/containers/cacl.jsx

@ -32,6 +32,9 @@ const Calc = (props) => {
const [sensorId, setSensorId] = useState([])//id' const [sensorId, setSensorId] = useState([])//id'
const [itemId, setItemId] = useState(null)// const [itemId, setItemId] = useState(null)//
const [itemName, setItemName] = useState('')//name const [itemName, setItemName] = useState('')//name
const [query, setQuery] = useState({ limit: 10, page: 0 }); //
const [limits,setLimits]=useState(0)
// const [methodValue,setMethodValue]=useState(1)//
const form = useRef() const form = useRef()
const form2 = useRef() const form2 = useRef()
const method = { const method = {
@ -44,13 +47,23 @@ const Calc = (props) => {
// getData() // getData()
dispatch(install.getAbnMethods()) dispatch(install.getAbnMethods())
}, []) }, [])
console.log('factore111',factorId) //
const pageChange=(arg1,arg2)=>{
setQuery( {limit: arg1, page:arg2 })
}
const limitChange=(arg)=>{
setLimits(arg)
}
useEffect(() => { useEffect(() => {
if(project&&factorId){ if(project&&factorId){
const id = [factorId, -1].join(',') const id = [factorId, -1].join(',')
dispatch(install.getAbnParamList({ factorId: id })) dispatch(install.getAbnParamList({ factorId: id,limit:query.limit, page: query.page,type:method[methodType]})).then(rs=>{
if(rs.success){
setLimits(rs.payload.data.count)
}
})
} }
}, [factorId,project]) }, [factorId,project,methodType,query])
// //
useEffect(() => { useEffect(() => {
@ -114,11 +127,11 @@ const Calc = (props) => {
let seStaName = sensorList.find(a => a.value == selectIds[i]).label let seStaName = sensorList.find(a => a.value == selectIds[i]).label
let cfg let cfg
if (methodType == "interrupt") { if (methodType == "interrupt") {
cfg = abnParam.find(a => a.abnType == 1 && a.factorId == factorId cfg = abnParam?.find(a => a.abnType == 1 && a.factorId == factorId
&& a.sensorId == project+':'+ selectIds[i]) && a.sensorId == project+':'+ selectIds[i])
} else { } else {
let type = methodType == "burr" ? 2 : 3 let type = methodType == "burr" ? 2 : 3
cfg = abnParam.find(a => a.abnType == type && a.factorId == factorId cfg = abnParam?.find(a => a.abnType == type && a.factorId == factorId
&& a.sensorId ==project+':'+ selectIds[i]) && a.sensorId ==project+':'+ selectIds[i])
} }
if (!cfg) { if (!cfg) {
@ -140,7 +153,6 @@ const Calc = (props) => {
form2.current.validate().then(res => { form2.current.validate().then(res => {
if (sensorId.length != 0) { if (sensorId.length != 0) {
let ids = getStationstoSave() let ids = getStationstoSave()
console.log('xx111',ids)
if (ids.toSave.length != 0) { if (ids.toSave.length != 0) {
let paramJson = getJson(res) let paramJson = getJson(res)
let data = { let data = {
@ -170,7 +182,11 @@ const Calc = (props) => {
dispatch(install.addAbnParam(pushData)).then(res => { dispatch(install.addAbnParam(pushData)).then(res => {
if (res.success) { if (res.success) {
const id = [factorId, -1].join(',') const id = [factorId, -1].join(',')
dispatch(install.getAbnParamList({ factorId: id })) dispatch(install.getAbnParamList({ factorId: id,limit:query.limit, page: query.page,type:method[methodType]})).then(rs=>{
if(rs.success){
setLimits(rs.payload.data.count)
}
})
} }
}) })
if (ids.notToSave.length != 0) { if (ids.notToSave.length != 0) {
@ -315,6 +331,7 @@ const Calc = (props) => {
) )
} }
const changeMethod = (value) => { const changeMethod = (value) => {
setQuery({ limit: 10, page: 0 })
setMethodType(value) setMethodType(value)
} }
const clearFactorAndSensor = () => { const clearFactorAndSensor = () => {
@ -325,7 +342,10 @@ const Calc = (props) => {
setStructId(value) setStructId(value)
clearFactorAndSensor() clearFactorAndSensor()
} }
// const methodChange=(e)=>{
// console.log('methodChange',e)
// setMethodValue(e)
// }
const renderParamsConfig = () => { const renderParamsConfig = () => {
switch (methodType) { switch (methodType) {
@ -439,7 +459,7 @@ const Calc = (props) => {
<Form.Select showSearch filter label="异常识别算法" field="method" onChange={changeMethod} <Form.Select showSearch filter label="异常识别算法" field="method" onChange={changeMethod}
placeholder="请选择异常识别算法" style={{ textAlign: 'left', width: 127 }} > placeholder="请选择异常识别算法" style={{ textAlign: 'left', width: 127 }} >
{abnMethods?.map(item => { {abnMethods?.map(item => {
return <Form.Select.Option value={item.name} label={item.des}></Form.Select.Option>; return <Form.Select.Option value={item.name} label={item.des} ></Form.Select.Option>;
})} })}
</Form.Select> </Form.Select>
</Col> </Col>
@ -464,7 +484,7 @@ const Calc = (props) => {
</Row> </Row>
</Form> </Form>
<AbnRecognize project={project} sensorId={sensorId} calcMethod={methodType} factorId={factorId} structId={structId} itName={itemName} /> <AbnRecognize limitChange={limitChange} query={query} changeQuery={pageChange} limits={limits} project={project} sensorId={sensorId} calcMethod={methodType} factorId={factorId} structId={structId} itName={itemName} />
</div> </div>
</div> </div>
@ -484,13 +504,14 @@ const Calc = (props) => {
function mapStateToProps(state) { function mapStateToProps(state) {
const { auth, global, OrganizationDeps, abnMethods, abnParam } = state; const { auth, global, OrganizationDeps, abnMethods, abnParam } = state;
return { return {
loading: OrganizationDeps.isRequesting, loading: OrganizationDeps.isRequesting,
user: auth.user, user: auth.user,
actions: global.actions, actions: global.actions,
pepProjectId: global.pepProjectId, pepProjectId: global.pepProjectId,
abnMethods: abnMethods?.data || [], abnMethods: abnMethods?.data || [],
abnParam: abnParam?.data || [] abnParam: abnParam?.data?.rows || []
}; };
} }
export default connect(mapStateToProps)(Calc); export default connect(mapStateToProps)(Calc);

57
web/client/src/sections/install/containers/interrupt.jsx

@ -2,13 +2,13 @@
import React, { useRef, useState, useEffect } from 'react'; import React, { useRef, useState, useEffect } from 'react';
import { connect } from 'react-redux'; import { connect } from 'react-redux';
import { Row, Col, Button, Table, Card, Popconfirm, Tag, Notification, Form } from '@douyinfe/semi-ui'; import { Row, Col, Button, Table, Card, Popconfirm, Tag, Notification, Form,Pagination } from '@douyinfe/semi-ui';
import InterruptModal from '../components/interruptModal'; import InterruptModal from '../components/interruptModal';
import '../style.less' import '../style.less'
const Interrupt = (props) => { const Interrupt = (props) => {
const {dispatch, abnParam,structId,factorId,actions,sensorId,project} = props const {dispatch, abnParam,structId,factorId,actions,sensorId,project,limits,query,changeQuery,limitChange} = props
const form = useRef() const form = useRef()
const [selectedRowKeys, setSelectedRowKeys] = useState([]) const [selectedRowKeys, setSelectedRowKeys] = useState([])
const [filterFunc, setFilterFunc] = useState({}) const [filterFunc, setFilterFunc] = useState({})
@ -31,7 +31,12 @@ const Interrupt = (props) => {
dispatch(install.deleteAbnParams(e)).then(res=>{ dispatch(install.deleteAbnParams(e)).then(res=>{
if(res.success){ if(res.success){
const id = [factorId, -1].join(',') const id = [factorId, -1].join(',')
dispatch(install.getAbnParamList({ factorId: id })) changeQuery(10,0)
dispatch(install.getAbnParamList({ factorId: id,limit:10, page: 0,type:1})).then(rs=>{
if(rs.success){
limitChange(rs.payload.data.count)
}
})
} }
}) })
} }
@ -59,7 +64,12 @@ const Interrupt = (props) => {
dispatch(install.batchCfgAbnParams(ids,data)).then(res=>{ dispatch(install.batchCfgAbnParams(ids,data)).then(res=>{
if(res.success){ if(res.success){
const id = [factorId, -1].join(',') const id = [factorId, -1].join(',')
dispatch(install.getAbnParamList({ factorId: id })) changeQuery(10,0)
dispatch(install.getAbnParamList({ factorId: id,limit:10, page: 0,type:1})).then(rs=>{
if(rs.success){
limitChange(rs.payload.data.count)
}
})
} }
}) })
@ -72,7 +82,12 @@ const Interrupt = (props) => {
dispatch(install.deleteAbnParams(ids)).then(res=>{ dispatch(install.deleteAbnParams(ids)).then(res=>{
if(res.success){ if(res.success){
const id = [factorId, -1].join(',') const id = [factorId, -1].join(',')
dispatch(install.getAbnParamList({ factorId: id })) changeQuery(10,0)
dispatch(install.getAbnParamList({ factorId: id,limit:10, page: 0,type:1})).then(rs=>{
if(rs.success){
limitChange(rs.payload.data.count)
}
})
} }
}) })
} else { } else {
@ -96,7 +111,12 @@ const Interrupt = (props) => {
dispatch(install.batchCfgAbnParams(ids,data)).then(res=>{ dispatch(install.batchCfgAbnParams(ids,data)).then(res=>{
if(res.success){ if(res.success){
const id = [factorId, -1].join(',') const id = [factorId, -1].join(',')
dispatch(install.getAbnParamList({ factorId: id })) changeQuery(10,0)
dispatch(install.getAbnParamList({ factorId: id,limit:10, page:0,type:1})).then(rs=>{
if(rs.success){
limitChange(rs.payload.data.count)
}
})
} }
}) })
} else if (dataSource.length != 0) { } else if (dataSource.length != 0) {
@ -229,7 +249,28 @@ const Interrupt = (props) => {
</Col> </Col>
</Row> </Row>
</Form> </Form>
<Table rowSelection={rowSelection} columns={columns} dataSource={tmpds} /> <Table rowSelection={rowSelection} columns={columns} dataSource={tmpds} pagination={false}/>
<div
style={{
display: "flex",
justifyContent: "flex-end",
padding: "20px 20px",
}}
>
<span style={{ lineHeight: "30px", fontSize: 13, color: 'rgba(0,90,189,0.8)' }}>
{limits}条信息
</span>
<Pagination
total={limits}
showSizeChanger
currentPage={query.page + 1}
pageSizeOpts={[10, 20, 30, 40]}
onChange={(currentPage, pageSize) => {
changeQuery( pageSize, currentPage - 1)
page.current = currentPage - 1
}}
/>
</div>
{modalVisible ? <InterruptModal {modalVisible ? <InterruptModal
structId={structId} structId={structId}
visible={true} visible={true}
@ -260,7 +301,7 @@ function mapStateToProps(state) {
return { return {
isRequesting: false,// isRequesting: false,//
abnParam: abnParam?.data || [], abnParam: abnParam?.data?.rows || [],
actions:global.actions, actions:global.actions,
} }
} }

38
web/client/src/sections/install/containers/roles.jsx

@ -1,6 +1,6 @@
import React, { useEffect, useState, useRef } from 'react'; import React, { useEffect, useState, useRef } from 'react';
import { connect } from 'react-redux'; import { connect } from 'react-redux';
import { Skeleton, Table, RadioGroup, Radio, Button, Pagination, Popconfirm, Tooltip } from '@douyinfe/semi-ui'; import { Skeleton, Table, RadioGroup, Radio, Button, Pagination, Popconfirm, Tooltip,Input } from '@douyinfe/semi-ui';
import { SkeletonScreen, } from "$components"; import { SkeletonScreen, } from "$components";
import AdminModal from '../components/adminModal'; import AdminModal from '../components/adminModal';
import MemberModal from '../components/memberModal'; import MemberModal from '../components/memberModal';
@ -371,13 +371,14 @@ const Roles = (props) => {
}, },
}, },
]) ])
// const [data, setdata] = useState([])// // const [data, setData] = useState([])//
const tableData = useRef([]); // const tableData = useRef([]); //
const page = useRef(query.page);// const page = useRef(query.page);//
const [limits, setLimits] = useState()// const [limits, setLimits] = useState()//
const mylimits = useRef(); // const mylimits = useRef(); //
const [pepList, setPepList] = useState([])// const [pepList, setPepList] = useState([])//
const [pomsList, setPomsList] = useState([])// const [pomsList, setPomsList] = useState([])//
const [keywords,setKeywords]=useState('')
const userAdmin = user?.pomsUserInfo?.role.includes('admin') // const userAdmin = user?.pomsUserInfo?.role.includes('admin') //
useEffect(() => { useEffect(() => {
@ -397,7 +398,8 @@ const Roles = (props) => {
let searchData = { ...query, role: roleChoose } let searchData = { ...query, role: roleChoose }
dispatch(install.getOrganizationUser(searchData)).then((res) => {// dispatch(install.getOrganizationUser(searchData)).then((res) => {//
if (res.success) { if (res.success) {
tableData.current = res.payload.data.users.rows; tableData.current = res.payload.data.users.rows
// setData(res.payload.data.users.rows)
let notCreatedArr = [] let notCreatedArr = []
let notCreatedNum = 5 - res.payload.data.admin.length let notCreatedNum = 5 - res.payload.data.admin.length
for (let i = 0; i < notCreatedNum; i++) { for (let i = 0; i < notCreatedNum; i++) {
@ -425,6 +427,28 @@ const Roles = (props) => {
function roleOnChange (e) {// function roleOnChange (e) {//
setRoleChoose(e.target.value); setRoleChoose(e.target.value);
} }
const handleChange = (value) => {
setKeywords(value)
}
const searchHanlder = () => {
let searchData = { ...query, limit: Number(10), page: 0 , role: roleChoose,keywords }
dispatch(install.getOrganizationUser(searchData)).then((res) => {//
if (res.success) {
tableData.current = res.payload.data.users.rows
// setData(res.payload.data.users.rows)
let notCreatedArr = []
let notCreatedNum = 5 - res.payload.data.admin.length
for (let i = 0; i < notCreatedNum; i++) {
notCreatedArr.push('')
}
if (userAdmin) notCreatedArr = []
setRoleAssignment(res.payload.data.admin.concat(notCreatedArr))
setLimits(res.payload.data.users.count)
mylimits.current = res.payload.data.users.rows.length
}
})
}
return ( return (
<> <>
<div style={{ background: '#FFFFFF', margin: '8px 12px', padding: '20px 20px 0px 20px' }}> <div style={{ background: '#FFFFFF', margin: '8px 12px', padding: '20px 20px 0px 20px' }}>
@ -552,7 +576,7 @@ const Roles = (props) => {
<div style={{ marginLeft: 6, fontSize: 12, color: '#969799', fontFamily: "DINExp", }}>MANAGEMENT OF MEMBERS</div> <div style={{ marginLeft: 6, fontSize: 12, color: '#969799', fontFamily: "DINExp", }}>MANAGEMENT OF MEMBERS</div>
</div> </div>
<div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center', marginBottom: 20 }}> <div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center', marginBottom: 20 }}>
<div style={{ fontSize: 12, color: '#8B8B8B' }}>平台有4种类型的成员角色分别是数据分析师售后运维资源管理者和客户服务每名项目成员可拥有多种成员角色</div> <div style={{ fontSize: 12, color: '#8B8B8B' }}>平台有5种类型的成员角色分别是数据分析师售后运维资源管理者客户服务和设备维护每名项目成员可拥有多种成员角色</div>
<div className='roleRadio' style={{ display: 'flex', alignItems: 'center' }}> <div className='roleRadio' style={{ display: 'flex', alignItems: 'center' }}>
<div> <div>
<RadioGroup onChange={roleOnChange} value={roleChoose} aria-label="单选组合示例" name="demo-radio-group"> <RadioGroup onChange={roleOnChange} value={roleChoose} aria-label="单选组合示例" name="demo-radio-group">
@ -564,6 +588,9 @@ const Roles = (props) => {
<Radio value='firmware_upgrade'>设备维护</Radio> <Radio value='firmware_upgrade'>设备维护</Radio>
</RadioGroup> </RadioGroup>
</div> </div>
<div style={{ display: 'flex', alignItems: 'center',marginLeft:10 }}><Input style={{width: 200,height: 32, borderRadius: 2, marginRight: 10, }} placeholder='请输入人员姓名' onChange={handleChange}/>
<Button onClick={searchHanlder} theme="solid">查询人员</Button></div>
<div> <div>
<Button <Button
theme="solid" theme="solid"
@ -572,7 +599,7 @@ const Roles = (props) => {
width: 108, width: 108,
height: 32, height: 32,
borderRadius: 2, borderRadius: 2,
marginLeft: 40 marginLeft: 10
}} }}
onClick={() => { onClick={() => {
setEditObj({}) setEditObj({})
@ -584,6 +611,7 @@ const Roles = (props) => {
> >
添加成员 添加成员
</Button> </Button>
</div> </div>
</div> </div>
</div> </div>

11
web/client/src/sections/install/containers/system.jsx

@ -150,7 +150,7 @@ const Example = (props) => {
title: '安心云项目名称', title: '安心云项目名称',
dataIndex: "anxinProject", dataIndex: "anxinProject",
key: 'anxinProject', key: 'anxinProject',
width: 400, width: 300,
render: (_, row) => { render: (_, row) => {
let anxinerror = false let anxinerror = false
let anxinerrorArr = [] let anxinerrorArr = []
@ -225,6 +225,15 @@ const Example = (props) => {
) )
} }
}, },
{
title: '客户等级',
dataIndex: "customerLevel",
key: 'customerLevel',
// render: (_, row) => {
// let data = { wisdom: '', monitor: '', other: '' }
// return data[row.mappingClass]
// }
},
{ {
title: '映射类型', title: '映射类型',
dataIndex: "mappingClass", dataIndex: "mappingClass",

57
web/client/src/sections/install/containers/trend.jsx

@ -2,14 +2,14 @@
import React, { Component, useRef,useState } from 'react'; import React, { Component, useRef,useState } from 'react';
import { connect } from 'react-redux'; import { connect } from 'react-redux';
import { Row, Col, Button, Table, Card, Popconfirm, Tag, Notification, Form, Select } from '@douyinfe/semi-ui' import { Row, Col, Button, Table, Card, Popconfirm, Tag, Notification, Form, Select,Pagination } from '@douyinfe/semi-ui'
import {IconPlus} from "@douyinfe/semi-icons" import {IconPlus} from "@douyinfe/semi-icons"
import TrendModal from '../components/TrendModal'; import TrendModal from '../components/TrendModal';
const Trend = (props) => { const Trend = (props) => {
const { abnParam, factorId,itName,actions,dispatch,sensorId,project } = props const { abnParam, factorId,itName,actions,dispatch,sensorId,project,limits,query,changeQuery,limitChange } = props
const form = useRef() const form = useRef()
const [selectedRowKeys, setSelectedRowKeys] = useState([]) const [selectedRowKeys, setSelectedRowKeys] = useState([])
const [filterFunc, setFilterFunc] = useState({}) const [filterFunc, setFilterFunc] = useState({})
@ -39,7 +39,12 @@ const Trend = (props) => {
dispatch(install.deleteAbnParams(e)).then(res=>{ dispatch(install.deleteAbnParams(e)).then(res=>{
if(res.success){ if(res.success){
const id = [factorId, -1].join(',') const id = [factorId, -1].join(',')
dispatch(install.getAbnParamList({ factorId: id })) changeQuery(10,0)
dispatch(install.getAbnParamList({ factorId: id,limit:10, page: 0,type:3})).then(rs=>{
if(rs.success){
limitChange(rs.payload.data.count)
}
})
} }
}) })
} }
@ -68,7 +73,12 @@ const Trend = (props) => {
dispatch(install.batchCfgAbnParams(ids,data)).then(res=>{ dispatch(install.batchCfgAbnParams(ids,data)).then(res=>{
if(res.success){ if(res.success){
const id = [factorId, -1].join(',') const id = [factorId, -1].join(',')
dispatch(install.getAbnParamList({ factorId: id })) changeQuery(10,0)
dispatch(install.getAbnParamList({ factorId: id,limit:10, page: 0,type:3})).then(rs=>{
if(rs.success){
limitChange(rs.payload.data.count)
}
})
} }
}) })
} }
@ -81,7 +91,12 @@ const Trend = (props) => {
dispatch(install.deleteAbnParams(ids)).then(res=>{ dispatch(install.deleteAbnParams(ids)).then(res=>{
if(res.success){ if(res.success){
const id = [factorId, -1].join(',') const id = [factorId, -1].join(',')
dispatch(install.getAbnParamList({ factorId: id })) changeQuery(10,0)
dispatch(install.getAbnParamList({ factorId: id,limit:10, page: 0,type:3})).then(rs=>{
if(rs.success){
limitChange(rs.payload.data.count)
}
})
} }
}) })
} else { } else {
@ -112,7 +127,12 @@ const Trend = (props) => {
dispatch(install.batchCfgAbnParams(ids,data)).then(res=>{ dispatch(install.batchCfgAbnParams(ids,data)).then(res=>{
if(res.success){ if(res.success){
const id = [factorId, -1].join(',') const id = [factorId, -1].join(',')
dispatch(install.getAbnParamList({ factorId: id })) changeQuery(10,0)
dispatch(install.getAbnParamList({ factorId: id,limit:10, page: 0,type:3})).then(rs=>{
if(rs.success){
limitChange(rs.payload.data.count)
}
})
} }
}) })
} else if (dataSource.length != 0) { } else if (dataSource.length != 0) {
@ -399,7 +419,28 @@ const Trend = (props) => {
</Col> </Col>
</Row> : ''} </Row> : ''}
</Form> </Form>
<Table rowSelection={rowSelection} columns={columns} dataSource={tmpds} /> <Table rowSelection={rowSelection} columns={columns} dataSource={tmpds} pagination={false}/>
<div
style={{
display: "flex",
justifyContent: "flex-end",
padding: "20px 20px",
}}
>
<span style={{ lineHeight: "30px", fontSize: 13, color: 'rgba(0,90,189,0.8)' }}>
{limits}条信息
</span>
<Pagination
total={limits}
showSizeChanger
currentPage={query.page + 1}
pageSizeOpts={[10, 20, 30, 40]}
onChange={(currentPage, pageSize) => {
changeQuery( pageSize, currentPage - 1)
page.current = currentPage - 1
}}
/>
</div>
{modalVisible ? <TrendModal {modalVisible ? <TrendModal
// structId={structId} // structId={structId}
visible={true} visible={true}
@ -420,7 +461,7 @@ function mapStateToProps(state) {
return { return {
isRequesting: false,// isRequesting: false,//
abnParam: abnParam?.data||[], abnParam: abnParam?.data?.rows || [],
actions:global.actions actions:global.actions
} }
} }

2
web/client/src/sections/install/style.less

@ -1,6 +1,6 @@
.roleRadio{ .roleRadio{
.semi-radio{ .semi-radio{
margin-right: 40px; // margin-right: 40px;
font-size: 13px; font-size: 13px;
} }
} }

2
web/client/src/sections/problem/actions/problem.jsx

@ -72,7 +72,7 @@ export function getAlarmDataGroup (query) { //获取数据告警分类
actionType: 'GET_ALARM_DATA_GROUP', actionType: 'GET_ALARM_DATA_GROUP',
url: `${ApiTable.getAlarmDataGroup}`, url: `${ApiTable.getAlarmDataGroup}`,
msg: { option: '获取数据告警分类' }, msg: { option: '获取数据告警分类' },
reducer: { name: '' } reducer: { name: 'alarmDataGroup' }
}); });
} }

29
web/client/src/sections/problem/components/tableData.jsx

@ -4,7 +4,7 @@ import { Button, Form, Modal, Skeleton, Pagination, Table, Tooltip, Toast } from
import { SkeletonScreen, } from "$components"; import { SkeletonScreen, } from "$components";
import moment from "moment"; import moment from "moment";
const TableData = ({ route, dispatch, actions, collectData, setSetup, exhibition, pepProjectId, const TableData = ({alarmDataGroup, route, dispatch, actions, collectData, setSetup, exhibition, pepProjectId,
selected, setSelected, setIfBulk, setConfirm, genre, setGenre, query, setQuery, tableData, setTableData, location, user, statusId, setStatusId }) => { selected, setSelected, setIfBulk, setConfirm, genre, setGenre, query, setQuery, tableData, setTableData, location, user, statusId, setStatusId }) => {
const { problem } = actions const { problem } = actions
@ -82,7 +82,7 @@ const TableData = ({ route, dispatch, actions, collectData, setSetup, exhibition
break; break;
default: default:
if (genre?.length > 0) { if (genre?.length > 0) {
dispatch(problem.getAlarmDataList({ ...query, ...search.current, groupId: groupId.current.map(v => v.id).join(), pepProjectId: pepProjectId })).then((res) => { dispatch(problem.getAlarmDataList({...(route === 'deviceAbnormal' ? { timestamps: moment().valueOf() } : {}), ...query, ...search.current, groupId: groupId.current.map(v => v.id).join(), pepProjectId: pepProjectId })).then((res) => {
if (res.success) { if (res.success) {
setCount(res.payload.data?.count || 0) setCount(res.payload.data?.count || 0)
let tableDatas = res.payload.data?.rows?.map(v => ({ let tableDatas = res.payload.data?.rows?.map(v => ({
@ -124,13 +124,13 @@ const TableData = ({ route, dispatch, actions, collectData, setSetup, exhibition
api.current?.setValues({ ...location, state: 'new' }) api.current?.setValues({ ...location, state: 'new' })
} }
if (route !== 'videoAbnormal' && route !== 'useAbnormal') { if (route !== 'videoAbnormal' && route !== 'useAbnormal') {
dispatch(problem.getAlarmDataGroup()).then((res) => { // dispatch(problem.getAlarmDataGroup()).then((res) => {
if (res.success) { // if (res.success) {
let data let data
if (route == 'dataLnterrupt') data = res.payload.data?.filter(v => v.desc == '数据中断') if (route == 'dataLnterrupt') data = alarmDataGroup?.filter(v => v.desc == '数据中断')
if (route == 'dataAbnormal') data = res.payload.data?.filter(v => v.desc == '数据异常') if (route == 'dataAbnormal') data = alarmDataGroup?.filter(v => v.desc == '数据异常')
if (route == 'strategyHit') data = res.payload.data?.filter(v => v.desc == '策略命中') if (route == 'strategyHit') data = alarmDataGroup?.filter(v => v.desc == '策略命中')
if (route == 'deviceAbnormal') data = res.payload.data?.filter(v => v.desc == '掉线' || v.desc == '不活跃') if (route == 'deviceAbnormal') data = alarmDataGroup?.filter(v => v.desc == '掉线' || v.desc == '不活跃')
groupId.current = data groupId.current = data
let genreData = [] let genreData = []
data?.map(v => { data?.map(v => {
@ -139,8 +139,8 @@ const TableData = ({ route, dispatch, actions, collectData, setSetup, exhibition
}) })
}) })
setGenre(genreData) setGenre(genreData)
} // }
}) // })
} }
if (route == 'useAbnormal') { if (route == 'useAbnormal') {
setGenre({ element: "元素异常", apiError: "接口报错 ", timeout: "加载超时" }) setGenre({ element: "元素异常", apiError: "接口报错 ", timeout: "加载超时" })
@ -158,8 +158,7 @@ const TableData = ({ route, dispatch, actions, collectData, setSetup, exhibition
} }
}) })
} }
}, []) }, [route])
const handleExport = () => { const handleExport = () => {
let url = '' let url = ''
let { keywordTarget, keyword = '', errType = '', state = '', kindId = '', statusId = '', groupUnitId = '', confirmState = '', onlineState = '', sustainTimeStart = '', sustainTimeEnd = '' } = search.current let { keywordTarget, keyword = '', errType = '', state = '', kindId = '', statusId = '', groupUnitId = '', confirmState = '', onlineState = '', sustainTimeStart = '', sustainTimeEnd = '' } = search.current
@ -211,7 +210,7 @@ const TableData = ({ route, dispatch, actions, collectData, setSetup, exhibition
}) })
break; break;
default: default:
dispatch(problem.getAlarmDataList({ ...query, ...search.current, limit: 1, sustainTimeStart, sustainTimeEnd, groupId: groupId.current.map(v => v.id).join(), pepProjectId: pepProjectId })).then((res) => { dispatch(problem.getAlarmDataList({...(route === 'deviceAbnormal' ? { timestamps: moment().valueOf() } : {}), ...query, ...search.current, limit: 1, sustainTimeStart, sustainTimeEnd, groupId: groupId.current.map(v => v.id).join(), pepProjectId: pepProjectId })).then((res) => {
if (res.success) { if (res.success) {
if (res.payload.data.count) { if (res.payload.data.count) {
let groups = { let groups = {
@ -379,7 +378,6 @@ const TableData = ({ route, dispatch, actions, collectData, setSetup, exhibition
placeholder={SkeletonScreen()} placeholder={SkeletonScreen()}
> >
{(() => { {(() => {
console.log(tableData);
console.log((route == 'useAbnormal' || route == 'videoAbnormal') ? console.log((route == 'useAbnormal' || route == 'videoAbnormal') ?
(tableData?.slice(query.page * query.limit, (query.page + 1) * query.limit) || []) (tableData?.slice(query.page * query.limit, (query.page + 1) * query.limit) || [])
: tableData); : tableData);
@ -481,7 +479,7 @@ const TableData = ({ route, dispatch, actions, collectData, setSetup, exhibition
function mapStateToProps (state) { function mapStateToProps (state) {
const { auth, global, members } = state; const { auth, global, members,alarmDataGroup } = state;
// console.log(global); // console.log(global);
return { return {
user: auth.user, user: auth.user,
@ -489,6 +487,7 @@ function mapStateToProps (state) {
global: global, global: global,
pepProjectId: global.pepProjectId, pepProjectId: global.pepProjectId,
// members: members, // members: members,
alarmDataGroup:alarmDataGroup.data||[]
}; };
} }
export default connect(mapStateToProps)(TableData); export default connect(mapStateToProps)(TableData);

2
web/client/src/sections/problem/containers/dataAlarm.jsx

@ -46,7 +46,6 @@ const DataAlarm = (props) => {
const statistic = { dataLnterrupt: '数据中断统计', dataAbnormal: '数据异常统计', strategyHit: '策略命中统计', videoAbnormal: '视频异常统计', useAbnormal: '应用半自动化巡检', deviceAbnormal: '设备异常统计' } const statistic = { dataLnterrupt: '数据中断统计', dataAbnormal: '数据异常统计', strategyHit: '策略命中统计', videoAbnormal: '视频异常统计', useAbnormal: '应用半自动化巡检', deviceAbnormal: '设备异常统计' }
useEffect(() => { useEffect(() => {
if (route) { if (route) {
// //
let data = columns[route] let data = columns[route]
@ -408,7 +407,6 @@ const DataAlarm = (props) => {
}) })
return confirmItems; return confirmItems;
} }
return ( return (
// route=='dataLnterrupt'|| route=='dataAbnormal'|| route=='strategyHit'? // route=='dataLnterrupt'|| route=='dataAbnormal'|| route=='strategyHit'?
<div style={{ minWidth: 1000 }}> <div style={{ minWidth: 1000 }}>

16
web/client/src/sections/projectGroup/actions/group.js

@ -135,3 +135,19 @@ export function getWorkOrdersRepairRank (query) {
}); });
} }
export function getWorkOrdersAvgTimes (query) {
return (dispatch) => basicAction({
type: "get",
dispatch: dispatch,
query,
actionType: "GET_WORK_ORDERS_AVG_TIMES",
url: `${ApiTable.getWorkOrdersAvgTimes}`,
msg: { error: "获取工单修复平均时长" },
reducer: {
name: "workOrdersAvgTimes",
params: { noClear: true }
},
});
}

368
web/client/src/sections/projectGroup/containers/bigscreen.jsx

@ -1,5 +1,6 @@
import React, { useEffect, useRef, useState } from 'react'; import React, { useEffect, useRef, useState } from 'react';
import { Skeleton, Button, Pagination, Select, Popconfirm, Table, Tooltip } from '@douyinfe/semi-ui'; import { Skeleton, Button, Pagination, Select, Popconfirm, Table, Tooltip,Tabs,TabPane} from '@douyinfe/semi-ui';
import { IconChevronUpDown,IconChevronUp,IconChevronDown } from '@douyinfe/semi-icons'
import { connect } from 'react-redux'; import { connect } from 'react-redux';
import { push } from 'react-router-redux'; import { push } from 'react-router-redux';
import Header from '../components/header'; import Header from '../components/header';
@ -15,7 +16,7 @@ let interrupt
let repair let repair
let overviewScrollbar; let overviewScrollbar;
const Bigscreen = (props) => { const Bigscreen = (props) => {
const { dispatch, actions, user, match, history, clientHeight, groupStatisticOnline, pomsProjectBasicAll,...restProps } = props const { dispatch, actions, user, match, history, clientHeight, groupStatisticOnline, pomsProjectBasicAll, ...restProps } = props
const [InterruptRank, setInterruptRank] = useState([]) const [InterruptRank, setInterruptRank] = useState([])
const [online, setOnline] = useState([]) const [online, setOnline] = useState([])
@ -25,13 +26,15 @@ const Bigscreen = (props) => {
const [proportion, setProportion] = useState([]) const [proportion, setProportion] = useState([])
const [formatter, setFormatter] = useState({}) const [formatter, setFormatter] = useState({})
const [groupDetail, setGroupDetail] = useState({}) const [groupDetail, setGroupDetail] = useState({})
const [allProjects,setAllProjects]=useState([]) const [allProjects, setAllProjects] = useState([])
const [alarmData, setAlarmData] = useState()// const [alarmData, setAlarmData] = useState()//
const [biggest, setBiggest] = useState()// const [biggest, setBiggest] = useState()//
const [mockData, setMockData] = useState()// const [mockData, setMockData] = useState()//
const [xData, setXData] = useState([])// const [xData, setXData] = useState([])//
const self = useRef({ myChart: null }); const self = useRef({ myChart: null });
const [state, setState] = useState(0)
const [interruptData,setInterruptData]=useState([])
const [avgTmes,setAvgTimes]=useState([])//
// const [queryUserId, setQueryUserId] = useState('') // const [queryUserId, setQueryUserId] = useState('')
useEffect(() => { useEffect(() => {
@ -143,25 +146,37 @@ const Bigscreen = (props) => {
useEffect(() => { useEffect(() => {
if(groupDetail?.pomsProjectIds&&groupDetail?.pomsProjectIds.length&&allProjects&&allProjects.length){ if (groupDetail?.pomsProjectIds && groupDetail?.pomsProjectIds.length && allProjects && allProjects.length) {
const query=groupDetail?.pomsProjectIds+'' const query = groupDetail?.pomsProjectIds + ''
dispatch(actions.projectGroup.getProjectWorkOrders({projectIds:query})).then(res=>{ dispatch(actions.projectGroup.getProjectWorkOrders({ projectIds: query })).then(res => {
if(res.success){ if (res.success) {
setProportion([...res.payload.data?.slice(0, 3)?.map(v => ({ name: allProjects?.find(item=>item.value===v.projectId)?.label, value: Number(v.count) })), setProportion([...res.payload.data?.slice(0, 3)?.map(v => ({ name: allProjects?.find(item => item.value === v.projectId)?.label, value: Number(v.count) })),
{ name: '其它', value: res.payload.data&&res.payload.data.length>3?res.payload.data?.slice(3)?.reduce((p,c)=>{ {
return p+Number(c.count) name: '其它', value: res.payload.data && res.payload.data.length > 3 ? res.payload.data?.slice(3)?.reduce((p, c) => {
},0):0 }]) return p + Number(c.count)
}, 0) : 0
}])
} }
}) })
dispatch(actions.projectGroup.getWorkOrdersRepairRank({projectIds:query})).then(res=>{ dispatch(actions.projectGroup.getWorkOrdersRepairRank({ projectIds: query })).then(res => {
if(res.success){ if (res.success) {
setGroupProject(res.payload.data?.slice(0, 10).map(v => ({name:v.formname,startTime:moment(v?.startTime).format('YYYY-MM-DD'),duration:moment(v?.endTime).add(8, 'hours').diff(v?.startTime,'hours') })) || []) setGroupProject(res.payload.data?.slice(0, 10).map(v => ({ name: v.formname, startTime: moment(v?.startTime).format('YYYY-MM-DD'), duration: moment(v?.endTime).add(8, 'hours').diff(v?.startTime, 'hours') })) || [])
} }
}) })
//
dispatch(actions.projectGroup.getWorkOrdersAvgTimes({ projectIds: query })).then(res=>{
if (res.success) {
const data=res.payload.data?.map(v=>{
return {projectName:allProjects?.find(item => item.value == v.project_id)?.label,
avgTime: Math.ceil(v.avgTime / 60 / 60),
project_id:v.project_id
}
})
setAvgTimes(data)
}
})
} }
},[groupDetail,allProjects]) }, [groupDetail, allProjects])
let statisticOnline = (groupId) => { let statisticOnline = (groupId) => {
dispatch(actions.projectGroup.groupStatisticOnline({ groupId })).then(res => { dispatch(actions.projectGroup.groupStatisticOnline({ groupId })).then(res => {
if (res.success) { if (res.success) {
@ -171,8 +186,9 @@ const Bigscreen = (props) => {
Interrupt.push({ name: v.name, ...v.offline }) Interrupt.push({ name: v.name, ...v.offline })
} }
}) })
Interrupt = Interrupt?.sort((a, b) => b.offline - a.offline) Interrupt = Interrupt?.sort((a, b) =>a.offnum/a.totnum- b.offnum/b.totnum)
setInterruptRank(Interrupt) setInterruptRank(Interrupt)
setInterruptData(Interrupt)
setOnline(res.payload.data?.slice(0, 10) || []) setOnline(res.payload.data?.slice(0, 10) || [])
setValue(res.payload.data?.map(v => v.id)?.slice(0, 10) || []) setValue(res.payload.data?.map(v => v.id)?.slice(0, 10) || [])
} }
@ -191,8 +207,41 @@ const Bigscreen = (props) => {
timeRequest(groupId) timeRequest(groupId)
}, 1000 * 60 * (minuteDifference + 1 || 61)); }, 1000 * 60 * (minuteDifference + 1 || 61));
} }
//
const topClick=(e)=>{
let data=[]
interruptData.map(v=>{data.push(v)})
switch (e) {
case 'perBottom':
setInterruptRank(data.sort((a, b) => b.offnum/b.totnum-a.offnum/a.totnum))
setState(1)
break;
case 'perTop':
setInterruptRank(data.sort((a, b) => a.offnum/a.totnum - b.offnum/b.totnum))
setState(0)
break;
case 'timeBottom':
setInterruptRank(data.sort((a, b) => b.offline-a.offline ))
setState(3)
break;
case 'timeTop':
setInterruptRank(data.sort((a, b) => a.offline - b.offline ))
setState(2)
break;
case 'countBottom':
setInterruptRank(data.sort((a, b) => b.totnum-a.totnum ))
setState(5)
break;
case 'countTop':
setInterruptRank(data.sort((a, b) => a.totnum-b.totnum ))
setState(4)
break;
default:
return
}
}
// console.log('sortOrder',sortOrder)
useEffect(() => { useEffect(() => {
let count = 0; let count = 0;
let currentIndex = -1; let currentIndex = -1;
@ -235,7 +284,92 @@ const Bigscreen = (props) => {
<Body> <Body>
<div style={{ width: "100%", height: '100%' }}> <div style={{ width: "100%", height: '100%' }}>
<div style={{ width: '100%', height: "45%", display: 'flex' }}> <div style={{ width: '100%', height: "45%", display: 'flex' }}>
<div style={{ width: "calc(50% - 8px)", height: "100%", marginRight: 16, display: 'flex' }}> <Card title='数据在线率' tooltipContent='在线率计算:设备存活/总设备(存活判断:普通设备2h以内有实时数据,GNSS设备8h以内有实时数据)' style={{ width: "calc(50% - 8px)", height: "100%", }}>
<div style={{ height: '100%', position: 'relative' }}>
{/* <div > */}
<Select
showClear
filter
value={value}
multiple={true}
maxTagCount={1}
style={{ width: 300, position: 'absolute', top: 0, right: 0, zIndex: 99 }}
optionList={groupStatisticOnline?.map(v => ({ value: v.id, label: v.name })) || []}
onChange={v => {
setValue(v)
setOnline(groupStatisticOnline?.filter(s => v.includes(s.id)))
}}
/>
{/* </div> */}
<ReactECharts
option={{
title: {
// text: v.name,
},
grid: {
left: 27,
right: 10,
bottom: 20,
},
tooltip: {
trigger: 'axis',
formatter: function (params) {
//
// console.log(params);
let title = params[0].data[0] + '<br/>' + '<br/>'
params.forEach(v => {
let find = online?.find(s => s.name == v.seriesName)?.online?.find(d => moment(d.collect_time).format('YYYY-MM-DD HH') == v.data[0]) || {}
title = title + v.seriesName + ":" + "&nbsp" + "&nbsp" + v.data[1] + "%" + "(" + find?.online + "/" + find?.total + ")" + '<br/>'
})
return title
}
},
xAxis: {
type: 'time',
// name: "",
boundaryGap: false,
minInterval: 1000 * 60 * 60,
},
dataZoom:[
{
show: true,
realtime: true,
start: 0,
end: 100
},
{
type: 'inside',
realtime: true,
start: 0,
end: 100
}
],
yAxis: {
type: 'value',
name: "单位%",
areaStyle: {
color: '#FFF',
},
},
series: online?.map(v => ({
type: 'line',
name: v.name,
smooth: true,
areaStyle: {
color: '#0e9cff26',
},
data: v.online?.map(f => [moment(f.collect_time).format('YYYY-MM-DD HH'), f.rate.toFixed(1)]) || []
})) || []
}}
notMerge={true}
lazyUpdate={true}
style={{ width: "100%", height: "100%" }}
theme={'ReactEChart'}
/>
</div>
</Card>
<div style={{ width: "calc(50% - 8px)", height: "100%", marginLeft: 16, display: 'flex' }}>
<Card title='项目工单占比' tooltipContent='项目工单占比:一个月内项目发起工单修复的次数占比。' style={{ width: "calc(50% - 8px)", height: "100%", marginRight: 16 }}> <Card title='项目工单占比' tooltipContent='项目工单占比:一个月内项目发起工单修复的次数占比。' style={{ width: "calc(50% - 8px)", height: "100%", marginRight: 16 }}>
<div style={{ height: '100%', position: 'relative' }}> <div style={{ height: '100%', position: 'relative' }}>
<div style={{ height: clientHeight * 0.55 - 300, display: 'flex', justifyContent: "center", position: 'relative' }}> <div style={{ height: clientHeight * 0.55 - 300, display: 'flex', justifyContent: "center", position: 'relative' }}>
@ -315,15 +449,18 @@ const Bigscreen = (props) => {
</div> </div>
</Card> </Card>
<Card title='修复排名' tooltipContent='修复时间排名:一个月内,计算每个工单的修复时间' style={{ width: "calc(50% - 8px)", height: "100%" }}> <Card title='修复排名' style={{ width: "calc(50% - 8px)", height: "100%" }} tooltipContent='修复时间排名:一个月内,计算每个工单的修复时间'>
<Tabs type="line">
<TabPane tab="修复排名" itemKey="1">
<div style={{ height: '100%', fontFamily: 'SourceHanSansCN-Regular', fontWeight: 400, fontSize: 14, }}> <div style={{ height: '100%', fontFamily: 'SourceHanSansCN-Regular', fontWeight: 400, fontSize: 14, }}>
<div style={{ display: "flex", background: '#F6F9FF', height: 40, alignItems: 'center' }}> <div style={{ display: "flex", background: '#F6F9FF', height: 40, alignItems: 'center' }}>
<div style={{ textAlign: 'center', width: '25%' }}>序号</div> <div style={{ textAlign: 'center', width: '25%' }}>序号</div>
<div style={{ textAlign: 'center', width: '49%' }}>工单名称</div> <div style={{ textAlign: 'center', width: '49%' }}>工单名称</div>
<div style={{ textAlign: 'center', width: '25%' }}>修复时长</div> <div style={{ textAlign: 'center', width: '25%' }}>修复时长</div>
</div> </div>
<div id="repair" style={{ position: 'relative', height: clientHeight * 0.55 - 220 }}> <div id="repair" style={{ position: 'relative', height: clientHeight * 0.55 - 220 - 52 }}>
<AutoRollComponent content={<> {groupProject?.map((c, index) => { <AutoRollComponent content={<> {groupProject?.map((c, index) => {
return index < 10 ? <div style={{ display: "flex", background: index % 2 == 1 ? "#F6F9FF" : '', padding: 6, height: 50, alignItems: 'center' }}> return index < 10 ? <div style={{ display: "flex", background: index % 2 == 1 ? "#F6F9FF" : '', padding: 6, height: 50, alignItems: 'center' }}>
<div style={{ textAlign: 'center', width: '25%', fontFamily: 'SourceHanSansCN-Regular', color: '#2C66F3', fontWeight: 400 }}> <div style={{ textAlign: 'center', width: '25%', fontFamily: 'SourceHanSansCN-Regular', color: '#2C66F3', fontWeight: 400 }}>
NO.{index + 1}</div> NO.{index + 1}</div>
@ -332,31 +469,16 @@ const Bigscreen = (props) => {
<div style={{ textAlign: 'center', width: '25%', fontFamily: 'SourceHanSansCN-Regular', fontWeight: 400 }}> <div style={{ textAlign: 'center', width: '25%', fontFamily: 'SourceHanSansCN-Regular', fontWeight: 400 }}>
{c.duration}h</div> {c.duration}h</div>
</div> : <></> </div> : <></>
})}</>} containerStyle={{ position: "relative", height: "95%", }} })}</>} containerStyle={{ position: "relative", height: "95%", }}
divHeight={"100%"} divId={"rank"} /> divHeight={"100%"} divId={"rank"} />
</div> </div>
</div> </div>
</Card> </TabPane>
</div> <TabPane tab="项目统计" itemKey="2">
<Card title='数据在线率' tooltipContent='在线率计算:设备存活/总设备(存活判断:普通设备2h以内有实时数据,GNSS设备8h以内有实时数据)' style={{ width: "calc(50% - 8px)", height: "100%", }}> <div style={{ height: clientHeight * 0.55 - 220 - 52, fontFamily: 'SourceHanSansCN-Regular', fontSize: 14,width:'100%' }}>
<div style={{ height: '100%', position: 'relative' }}>
{/* <div > */} <ReactECharts
<Select
showClear
filter
value={value}
multiple={true}
maxTagCount={1}
style={{ width: 300, position: 'absolute', top: 0, right: 0, zIndex: 99 }}
optionList={groupStatisticOnline?.map(v => ({ value: v.id, label: v.name })) || []}
onChange={v => {
setValue(v)
setOnline(groupStatisticOnline?.filter(s => v.includes(s.id)))
}}
/>
{/* </div> */}
<ReactECharts
option={{ option={{
title: { title: {
// text: v.name, // text: v.name,
@ -367,54 +489,100 @@ const Bigscreen = (props) => {
bottom: 20, bottom: 20,
}, },
tooltip: { tooltip: {
trigger: 'axis', // trigger: 'axis',
formatter: function (params) { position: ['5%', '50%'] ,
//
// console.log(params);
let title = params[0].data[0] + '<br/>' + '<br/>'
params.forEach(v => {
let find = online?.find(s => s.name == v.seriesName)?.online?.find(d => moment(d.collect_time).format('YYYY-MM-DD HH') == v.data[0]) || {}
title = title + v.seriesName + ":" + "&nbsp" + "&nbsp" + v.data[1] + "%" + "(" + find?.online + "/" + find?.total + ")" + '<br/>'
})
return title
}
}, },
xAxis: { xAxis: {
type: 'time', show:true,
// name: "", type: 'category',
boundaryGap: false, data: avgTmes?.map(s => s.projectName),
minInterval: 1000 * 60 * 60, axisLabel: {
formatter: function (value) {
//
return value.substring(0, 5) + (value.length > 5 ? '...' : '');
},
},
}, },
yAxis: { yAxis: {
type: 'value', type: 'value',
name: "单位%", name: "单位(小时)",
areaStyle: { // areaStyle: {
color: '#FFF', // color: '#FFF',
}, // },
}, },
series: online?.map(v => ({ series: [
type: 'line', {
name: v.name, type: 'bar',
smooth: true, data: avgTmes?.map(s => s.avgTime),
areaStyle: { }
color: '#0e9cff26', ]
},
data: v.online?.map(f => [moment(f.collect_time).format('YYYY-MM-DD HH'), f.rate.toFixed(1)]) || []
})) || []
}} }}
notMerge={true} // notMerge={true}
lazyUpdate={true} lazyUpdate={true}
style={{ width: "100%", height: "100%" }} style={{ width: "100%", height: "100%" }}
theme={'ReactEChart'} theme={'ReactEChart'}
/> />
</div>
</TabPane>
</Tabs>
</Card>
</div>
</div>
</Card>
</div> </div>
<div style={{ width: '100%', height: "calc(55% - 24px)", display: 'flex', marginTop: 24 }}> <div style={{ width: '100%', height: "calc(55% - 24px)", display: 'flex', marginTop: 24 }}>
<Card title='中断排名' tooltipContent='中断时长:当前时间-最后一条数据时间。中断个数:结构物下中断测点个数/结构物总测点个数。' style={{ width: "calc(50% - 8px)", height: "100%", }}>
<div style={{ height: '100%', fontFamily: 'SourceHanSansCN-Regular', fontWeight: 400, fontSize: 14, }}>
<div style={{ display: "flex", background: '#F6F9FF', height: 40, alignItems: 'center' }}>
<div style={{ textAlign: 'center', width: '33%' }}>结构物</div>
<div style={{ textAlign: 'center', width: '33%', position: 'relative' }}>中断百分比<i class="angle_top" id={state==0?'angleSelected':null} onClick={()=>topClick('perTop')}></i><i id={state==1?'angleSelected':null} class="angle_bottom" onClick={()=>topClick('perBottom')}></i> </div>
<div style={{ textAlign: 'center', width: '33%', position: 'relative' }}>中断时长<i class="angle_top" id={state==2?'angleSelected':null} onClick={()=>topClick('timeTop')}></i><i id={state==3?'angleSelected':null} class="angle_bottom" onClick={()=>topClick('timeBottom')}></i></div>
<div style={{ textAlign: 'center', width: '33%', position: 'relative' }}>中断个数<i class="angle_top" id={state==4?'angleSelected':null} onClick={()=>topClick('countTop')}></i><i id={state==5?'angleSelected':null} class="angle_bottom" onClick={()=>topClick('countBottom')}></i></div>
</div>
<div id="interrupt" style={{ position: 'relative', height: clientHeight * 0.55 - 170 }}>
<AutoRollComponent content={<>
{InterruptRank?.map((c, index) => {
let title
if (c.offline) {
if (c.offline >= 1440 && Math.floor(c.offline / 1440)) title = Math.floor(c.offline / 1440) + "天"
if ((c.offline % 1440) >= 60 && Math.floor(c.offline % 1440 / 60)) {
if (title) {
title = title + Math.floor(c.offline % 1440 / 60) + "时"
} else {
title = Math.floor(c.offline % 1440 / 60) + "时"
}
}
if (c.offline % 1440 % 60) {
if (title) {
title = title + c.offline % 1440 % 60 + "分"
} else {
title = c.offline % 1440 % 60 + "分"
}
}
}
//
const cc = title.split('天')
if (cc.length > 1) {
if (Number(cc[0]) > 200) {
return
}
}
return <div style={{ display: "flex", background: index % 2 == 1 ? "#F6F9FF" : '', height: 40, alignItems: 'center' }}>
<div style={{ textAlign: 'center', width: '33%', fontFamily: 'SourceHanSansCN-Regular', color: '#2C66F3', fontWeight: 400 }}>{c.name}</div>
<div style={{ textAlign: 'center', width: '33%', fontFamily: 'SourceHanSansCN-Regular', color: '#F33B3B', fontWeight: 400 }}>{((c.offnum / c.totnum) * 100).toFixed(2)}%</div>
<div style={{ textAlign: 'center', width: '33%' }}>{title}</div>
<div style={{ textAlign: 'center', width: '33%', fontFamily: 'SourceHanSansCN-Regular', color: '#F33B3B', fontWeight: 400 }}>{c.offnum + '/' + c.totnum}</div>
</div>
})}</>} containerStyle={{ position: "relative", height: "85%", }}
divHeight={"100%"} divId={"interruptchart"} />
</div>
</div>
</Card>
<Card title='告警排名TOP20' tooltipContent='(1)超阈值个数:一周内结构物超阈值告警的个数。(2)手动恢复个数:一个月内超阈值告警手动恢复的个数' style={{ <Card title='告警排名TOP20' tooltipContent='(1)超阈值个数:一周内结构物超阈值告警的个数。(2)手动恢复个数:一个月内超阈值告警手动恢复的个数' style={{
width: "calc(50% - 8px)", height: "100%", marginRight: 16 width: "calc(50% - 8px)", height: "100%", marginLeft: 16
}} > }} >
{alarmData && alarmData.length > 0 ? (<div style={{ height: '100%' }}> {alarmData && alarmData.length > 0 ? (<div style={{ height: '100%' }}>
<div style={{ display: "flex", justifyContent: 'flex-end' }}> <div style={{ display: "flex", justifyContent: 'flex-end' }}>
@ -458,46 +626,6 @@ const Bigscreen = (props) => {
</div> </div>
</div>) : ''} </div>) : ''}
</Card> </Card>
<Card title='中断排名' tooltipContent='中断时长:当前时间-最后一条数据时间。中断个数:结构物下中断测点个数/结构物总测点个数。' style={{ width: "calc(50% - 8px)", height: "100%", }}>
<div style={{ height: '100%', fontFamily: 'SourceHanSansCN-Regular', fontWeight: 400, fontSize: 14, }}>
<div style={{ display: "flex", background: '#F6F9FF', height: 40, alignItems: 'center' }}>
<div style={{ textAlign: 'center', width: '33%' }}>结构物</div>
<div style={{ textAlign: 'center', width: '33%' }}>中断时长</div>
<div style={{ textAlign: 'center', width: '33%' }}>中断个数</div>
</div>
<div id="interrupt" style={{ position: 'relative', height: clientHeight * 0.55 - 170 }}>
<AutoRollComponent content={<>
{InterruptRank?.map((c, index) => {
let title
if (c.offline) {
if (c.offline >= 1440 && Math.floor(c.offline / 1440)) title = Math.floor(c.offline / 1440) + "天"
if ((c.offline % 1440) >= 60 && Math.floor(c.offline % 1440 / 60)) {
if (title) {
title = title + Math.floor(c.offline % 1440 / 60) + "时"
} else {
title = Math.floor(c.offline % 1440 / 60) + "时"
}
}
if (c.offline % 1440 % 60) {
if (title) {
title = title + c.offline % 1440 % 60 + "分"
} else {
title = c.offline % 1440 % 60 + "分"
}
}
}
return <div style={{ display: "flex", background: index % 2 == 1 ? "#F6F9FF" : '', height: 40, alignItems: 'center' }}>
<div style={{ textAlign: 'center', width: '33%', fontFamily: 'SourceHanSansCN-Regular', color: '#2C66F3', fontWeight: 400 }}>{c.name}</div>
<div style={{ textAlign: 'center', width: '33%' }}>{title}</div>
<div style={{ textAlign: 'center', width: '33%', fontFamily: 'SourceHanSansCN-Regular', color: '#F33B3B', fontWeight: 400 }}>{c.offnum + '/' + c.totnum+`(${((c.offnum/c.totnum)*100).toFixed(2)}%)`}</div>
</div>
})}</> } containerStyle={{ position: "relative", height: "85%", }}
divHeight={"100%"} divId={"interruptchart"}/>
</div>
</div>
</Card>
</div> </div>
</div > </div >
@ -506,9 +634,9 @@ const Bigscreen = (props) => {
</div > </div >
) )
} }
function mapStateToProps (state) { function mapStateToProps(state) {
const { auth, global, groupStatisticOnline,pomsProjectBasicAll } = state; const { auth, global, groupStatisticOnline, pomsProjectBasicAll } = state;
return { return {
user: auth.user, user: auth.user,
actions: global.actions, actions: global.actions,

40
web/client/src/sections/projectGroup/style.less

@ -104,6 +104,46 @@
margin-left: 134.48px; margin-left: 134.48px;
} }
.angle_top {
content: '';
width: 0;
height: 0;
display: block;
border-style: solid;
border-width: 0 6px 6px;
// border-color: transparent transparent #5e5e5e;
position: absolute;
transform: rotate(180deg);
bottom: 3px;
right: 62px;
}
.angle_bottom {
content: '';
width: 0;
height: 0;
display: block;
border-style: solid;
border-width: 0 6px 6px;
// border-color: transparent transparent #5e5e5e;
position: absolute;
top: 2px;
right: 62px;
}
.angle_bottom,.angle_top:first-child{
border-color: transparent transparent #5e5e5e;
}
.angle_bottom,.angle_top:nth-child(2){
border-color: transparent transparent #5e5e5e;
}
.angle_bottom,.angle_top:nth-child(3){
border-color: transparent transparent #5e5e5e;
}
#angleSelected {
/* 添加选中时的样式 */
border-color: transparent transparent blue
}

16
web/client/src/sections/service/components/automatic-Modal.jsx

@ -22,7 +22,6 @@ const AutomaticModal = ({ actions, dispatch, apiRoot, qiniuUrl, visible, eidtDat
useEffect(async () => { useEffect(async () => {
if (eidtData?.id) { if (eidtData?.id) {
console.log(eidtData);
setProjectId(eidtData?.projectId) setProjectId(eidtData?.projectId)
setStructId(eidtData?.structId) setStructId(eidtData?.structId)
setFactorId(eidtData?.factors?.map(s => s.codeName) || []) setFactorId(eidtData?.factors?.map(s => s.codeName) || [])
@ -63,6 +62,7 @@ const AutomaticModal = ({ actions, dispatch, apiRoot, qiniuUrl, visible, eidtDat
projectName: v.projectName, projectName: v.projectName,
reportType: v.reportType, reportType: v.reportType,
reportPicPath: v.reportPicPath[0]?.response?.url, reportPicPath: v.reportPicPath[0]?.response?.url,
overview: v.overview[0]?.response?.url,
framer: v.framer, framer: v.framer,
auditor: v.auditor, auditor: v.auditor,
ratifier: v.ratifier, ratifier: v.ratifier,
@ -139,7 +139,7 @@ const AutomaticModal = ({ actions, dispatch, apiRoot, qiniuUrl, visible, eidtDat
> >
<Form.Input field="reportName" label='报表名称' style={{ width: 300 }} placeholder="请输入报表名称" showClear <Form.Input field="reportName" label='报表名称' style={{ width: 300 }} placeholder="请输入报表名称" showClear
initValue={eidtData?.reportName || ""} initValue={eidtData?.reportName || ""}
rules={[{ required: true, message: "请输入报表名称,15字以内", max: 15 }]} // rules={[{ required: true, message: ",15", max: 15 }]}
/> />
<Form.Select label="所属项目" field="projectId" placeholder="请选择项目" showClear style={{ width: 300 }} filter <Form.Select label="所属项目" field="projectId" placeholder="请选择项目" showClear style={{ width: 300 }} filter
initValue={eidtData?.projectId || ""} initValue={eidtData?.projectId || ""}
@ -169,7 +169,17 @@ const AutomaticModal = ({ actions, dispatch, apiRoot, qiniuUrl, visible, eidtDat
/> />
<Form.Upload label="首页图片" field="reportPicPath" style={{ display: 'inline-block', }} <Form.Upload label="首页图片" field="reportPicPath" style={{ display: 'inline-block', }}
initValue={eidtData?.reportPicPath && [{ url: `/_file-server/${eidtData?.reportPicPath?.slice(qiniuUrl.length + 1)}`, name: eidtData.reportPicPath?.split('/')?.pop(), status: 'success', preview: ['png', 'jpg', 'jpeg'].includes(eidtData.reportPicPath?.split('.')?.pop()?.replace('.', '')) }] || null} initValue={eidtData?.reportPicPath && [{ url: `/_file-server/${eidtData?.reportPicPath?.slice(qiniuUrl.length + 1)}`, name: eidtData.reportPicPath?.split('/')?.pop(), status: 'success', preview: ['png', 'jpg', 'jpeg'].includes(eidtData.reportPicPath?.split('.')?.pop()?.replace('.', '')) }] || null}
rules={[{ required: true, message: "请上传首页图片" }]} // rules={[{ required: true, message: "" }]}
action={`${apiRoot}/attachments/p`}
accept={'.txt, .doc, .docx, .xls, .xlsx, .pdf, .png, .jpg, .rar, .zip'}
limit={1} maxSize={5120}
>
<Button icon={<IconUpload />} theme="light">
文件上传
</Button>
</Form.Upload>
<Form.Upload label="项目概况" field="overview" style={{ display: 'inline-block', }}
initValue={eidtData?.overview && [{ url: `/_file-server/${eidtData?.overview?.slice(qiniuUrl.length + 1)}`, name: eidtData.overview?.split('/')?.pop(), status: 'success', preview: ['png', 'jpg', 'jpeg'].includes(eidtData.reportPicPath?.split('.')?.pop()?.replace('.', '')) }] || null}
action={`${apiRoot}/attachments/p`} action={`${apiRoot}/attachments/p`}
accept={'.txt, .doc, .docx, .xls, .xlsx, .pdf, .png, .jpg, .rar, .zip'} accept={'.txt, .doc, .docx, .xls, .xlsx, .pdf, .png, .jpg, .rar, .zip'}
limit={1} maxSize={5120} limit={1} maxSize={5120}

4
web/client/src/sections/workOrder/containers/initiated.jsx

@ -16,6 +16,7 @@ const Rest = (props) => {
const [workflowModalType, setWorkflowModalType] = useState('') const [workflowModalType, setWorkflowModalType] = useState('')
const [checkProcessInstanceId, setCheckProcessInstanceId] = useState(null) const [checkProcessInstanceId, setCheckProcessInstanceId] = useState(null)
const [params, setParams] = useState({}) const [params, setParams] = useState({})
const [page,setPage]=useState(1)//
useEffect(() => { useEffect(() => {
backlogData() backlogData()
if (!pomsProjectBasicAll.length) { if (!pomsProjectBasicAll.length) {
@ -194,7 +195,7 @@ const Rest = (props) => {
}) })
.then(res => { .then(res => {
setLoading(false) setLoading(false)
backlogData() backlogData({limit:query.limit,page})
Toast.success({ content: '撤销流程成功', duration: 1, }) Toast.success({ content: '撤销流程成功', duration: 1, })
}, error => { }, error => {
Toast.error({ content: '撤销流程失败', duration: 1, }) Toast.error({ content: '撤销流程失败', duration: 1, })
@ -309,6 +310,7 @@ const Rest = (props) => {
currentPage={query.offset + 1} currentPage={query.offset + 1}
pageSizeOpts={[10, 20, 30, 40]} pageSizeOpts={[10, 20, 30, 40]}
onChange={(currentPage, pageSize) => { onChange={(currentPage, pageSize) => {
setPage(currentPage)
setQuery({ limit: pageSize, offset: currentPage - 1 }); setQuery({ limit: pageSize, offset: currentPage - 1 });
backlogData({ ...params, limit: pageSize, offset: currentPage - 1 }) backlogData({ ...params, limit: pageSize, offset: currentPage - 1 })
}} }}

2
web/client/src/utils/webapi.js

@ -188,7 +188,7 @@ export const ApiTable = {
deleteAbnParams: 'delete/abnormal/params/{id}',//删除配置 deleteAbnParams: 'delete/abnormal/params/{id}',//删除配置
editAbnParams: 'edit/abnormal/params/{id}',//修改配置 editAbnParams: 'edit/abnormal/params/{id}',//修改配置
getAbnTaskResult: 'struct/{structId}/abnTask/result/{start}/{end}',// getAbnTaskResult: 'struct/{structId}/abnTask/result/{start}/{end}',//
getWorkOrdersAvgTimes:'project/workOrders/avgTime'
}; };
// 项企的接口 // 项企的接口

Loading…
Cancel
Save