diff --git a/api/app/lib/controllers/alarm/data.js b/api/app/lib/controllers/alarm/data.js index af30048..5715085 100644 --- a/api/app/lib/controllers/alarm/data.js +++ b/api/app/lib/controllers/alarm/data.js @@ -46,7 +46,7 @@ async function list (ctx) { const { utils: { judgeSuper, anxinStrucIdRange } } = ctx.app.fs 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({ ctx, pepProjectId, keywordTarget, keyword @@ -100,10 +100,10 @@ async function list (ctx) { let alarmQueryOptionStr = ` FROM alarms - LEFT JOIN ( - SELECT DeviceId, any(Status) AS Status,max(Time) FROM DeviceStatus GROUP BY DeviceId - ) AS DeviceStatus - ON DeviceStatus.DeviceId = alarms.SourceId + ${timestamps?`LEFT JOIN ( + SELECT DeviceId, any(Status) AS Status,max(Time) FROM DeviceStatus GROUP BY DeviceId + ) AS DeviceStatus + ON DeviceStatus.DeviceId = alarms.SourceId`:''} LEFT JOIN ${anxinyun}.t_structure ON ${anxinyun}.t_structure.id = alarms.StructureId LEFT JOIN ${anxinyun}.t_alarm_code @@ -121,7 +121,7 @@ async function list (ctx) { SourceTypeId, AlarmAdviceProblem, AlarmGroup, AlarmGroupUnit, AlarmAdviceProblem, alarms.StructureId AS StructureId, - ${`DeviceStatus.Status AS DeviceStatus,`} + ${timestamps?`DeviceStatus.Status AS DeviceStatus,`:''} ${anxinyun}.t_structure.name AS StructureName, ${anxinyun}.t_structure.longitude AS StructureLongitude, ${anxinyun}.t_structure.latitude AS StructureLatitude, diff --git a/api/app/lib/controllers/dataCacl/index.js b/api/app/lib/controllers/dataCacl/index.js index bd7314b..c7880ff 100644 --- a/api/app/lib/controllers/dataCacl/index.js +++ b/api/app/lib/controllers/dataCacl/index.js @@ -26,16 +26,28 @@ async function findAbnMethods(ctx, next) { } //获取异常参数配置 async function findAbnParamList(ctx) { - const { factorId } = ctx.query + const { factorId,limit,page,keywords,type } = ctx.query const id=factorId.split(',') let rslt = null; let error = { name: 'FindError', message: '异常参数配置获取失败' }; + let abnParamList 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; - let abnParamList = await models.AbnReportParams.findAll({ - where: { factorId:{$in:id} } - }) - rslt = abnParamList.map(s => ({ + abnParamList= await models.AbnReportParams.findAndCountAll(findOption) + rslt = abnParamList.rows.map(s => ({ key: s.id, id: s.id, sensorId: s.sensorId, @@ -56,7 +68,7 @@ async function findAbnParamList(ctx) { ctx.body = error; } else { ctx.status = 200; - ctx.body = rslt; + ctx.body ={count:abnParamList.count,rows:rslt} } } diff --git a/api/app/lib/controllers/monitor/index.js b/api/app/lib/controllers/monitor/index.js index 61038e9..e4ca510 100644 --- a/api/app/lib/controllers/monitor/index.js +++ b/api/app/lib/controllers/monitor/index.js @@ -284,7 +284,6 @@ async function exportMaterialEnterList(ctx, data, columns) { // exportData.push(item) // } const fileName = `${siteName}` + '.xls' - console.log('x11111111',data,fileName,header) const filePath = await simpleExcelDown({ data: data, header, fileName: fileName, needIndexCell: false }) const fileData = fs.readFileSync(filePath) ctx.status = 200 diff --git a/api/app/lib/controllers/organization/index.js b/api/app/lib/controllers/organization/index.js index ee13a95..fb77694 100644 --- a/api/app/lib/controllers/organization/index.js +++ b/api/app/lib/controllers/organization/index.js @@ -1,7 +1,7 @@ 'use strict'; const moment = require('moment') -async function allDeps (ctx) { +async function allDeps(ctx) { try { const models = ctx.fs.dc.models; const { redis } = ctx.app @@ -22,7 +22,7 @@ async function allDeps (ctx) { } } -async function allUsers (ctx) { +async function allUsers(ctx) { try { const { models } = ctx.fs.dc; const { clickHouse } = ctx.app.fs @@ -43,7 +43,7 @@ async function allUsers (ctx) { } } -async function editUser (ctx) { +async function editUser(ctx) { try { const models = ctx.fs.dc.models; 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 { const models = ctx.fs.dc.models; const { pomsUserId } = ctx.params @@ -153,7 +153,7 @@ async function putUser (ctx) { } } -async function delAdmin (ctx) { +async function delAdmin(ctx) { try { const models = ctx.fs.dc.models; const { pomsUserId } = ctx.params @@ -189,13 +189,13 @@ async function delAdmin (ctx) { } } -async function user (ctx) { +async function user(ctx) { try { const models = ctx.fs.dc.models; const { clickHouse } = ctx.app.fs 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'] @@ -222,14 +222,107 @@ async function user (ctx) { findOption.where.role = { $contains: [role] } } if (limit) { - findOption.limit = limit + findOption.limit = 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({ where: { role: { $contains: ['admin'] } @@ -260,7 +353,8 @@ async function user (ctx) { ON department.id=department_user.department WHERE user.id IN (${[...userIds].join(',')},-1) - AND department.delete='0'` + AND department.delete='0' + ` ).toPromise() : [] @@ -285,38 +379,45 @@ async function user (ctx) { `).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)) { - // 用户信息 - const corUsers = userPepRes.filter(up => up.id == u.pepUserId) - 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 + for (let u of userRes.rows.concat(adminRes)) { + // 用户信息 + const corUsers = userPepRes.filter(up => up.id == u.pepUserId) + 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 - }) - } + return returnData + }) + } + + ctx.status = 200 ctx.body = { diff --git a/api/app/lib/controllers/project/group.js b/api/app/lib/controllers/project/group.js index 62f1fc9..0fdf51e 100644 --- a/api/app/lib/controllers/project/group.js +++ b/api/app/lib/controllers/project/group.js @@ -435,114 +435,54 @@ async function groupStatisticOnline (ctx) { // 查在线率 const strucOnlineClient = ctx.app.fs.esclient.strucOnline - // let arr = [1,2,3,4,5,6,7] - // let onlineRes={ - // hits: { - // hits: [] - // } - // } - // if(strucIdArr.length){ - // for(let i = 0;i 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", + let arr = [1,2,3,4,5,6,7] + let onlineRes={ + hits: { + hits: [] + } + } + if(strucIdArr.length){ + for(let i = 0;i pp.id == p.pepProjectId) || {} @@ -161,6 +171,7 @@ async function pomsProject (ctx) { p.dataValues.anxinProject = nextAnxinProject p.dataValues.pepUserName = pepUserName delete p.dataValues.anxinProjectId + p.dataValues.customerLevel=(pepmCustomerLevelRes.find(pp => pp.projectId == p.dataValues.pepProjectId)||{name:'--'}).name } ctx.status = 200; ctx.body = proRes diff --git a/api/app/lib/models/report_automatic.js b/api/app/lib/models/report_automatic.js index f2bf788..88b8029 100644 --- a/api/app/lib/models/report_automatic.js +++ b/api/app/lib/models/report_automatic.js @@ -53,7 +53,7 @@ module.exports = dc => { }, reportPicPath: { type: DataTypes.STRING, - allowNull: false, + allowNull: true, defaultValue: null, comment: "", primaryKey: false, @@ -141,6 +141,15 @@ module.exports = dc => { field: "factors", autoIncrement: false }, + overview: { + type: DataTypes.STRING, + allowNull: true, + defaultValue: null, + comment: "", + primaryKey: false, + field: "overview", + autoIncrement: false + }, }, { tableName: "report_automatic", comment: "", diff --git a/api/app/lib/routes/project/index.js b/api/app/lib/routes/project/index.js index 2d6e46c..c232299 100644 --- a/api/app/lib/routes/project/index.js +++ b/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 }; 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); }; \ No newline at end of file diff --git a/api/app/lib/schedule/alarms_push.js b/api/app/lib/schedule/alarms_push.js index d6276b7..bac1b46 100644 --- a/api/app/lib/schedule/alarms_push.js +++ b/api/app/lib/schedule/alarms_push.js @@ -1503,16 +1503,38 @@ module.exports = function (app, opts) { let alarmHtmlTitle = packageTableTitle(alarmTitleArr) let accumulate = 0 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) => { accumulate += h.rowspan || 0 if (h.projects && h.projects.length) { h.projects.map((x, xi) => { - let flag + //用于设备全部中断做特殊标记 + let problem=0 + let count=0 let showOne1 = (xi == 0) ? true : false if (x.factor && x.factor.length) { - x.factor.map((f, fi) => { + problem+=f.problem + count+=f.devicesLength let showOne2 = (fi == 0) ? true : false if (f.devices && f.devices.length) { f.devices.map((c, ci) => { @@ -1537,7 +1559,7 @@ module.exports = function (app, opts) { break; case 'Structure': if (showOne2 && showOne3 && showOne4) { - tableData += `${x['name'] || ''}` + tableData +=problem==count?`${x['name'](测点数据全部中断) || ''}`: `${x['name'] || ''}` } break; case 'factor': diff --git a/api/app/lib/schedule/workOrder.js b/api/app/lib/schedule/workOrder.js index dd2a6c1..e271a81 100644 --- a/api/app/lib/schedule/workOrder.js +++ b/api/app/lib/schedule/workOrder.js @@ -64,17 +64,15 @@ module.exports = function (app, opts,ctx) { : ''}` ).toPromise() const procinstIds = [...new Set(formRes.map(e => e.procinstId))]; - console.log('formRes1',procinstIds) // 获取流程实例变量 if(formRes && formRes.length > 0){ let procinstsVariables = await request.post(encodeURI(opts.camundarest.host+'/'+opts.camundarest.root+`/engine-rest/history/variable-instance`)) .auth(username, password) .set('Content-Type', 'application/json') .send({processInstanceIdIn: procinstIds}) - console.log('formRes2',procinstsVariables) if(procinstsVariables.body&&procinstsVariables.body.length){ for (let f of formRes) { - const parseData = parseProcessData({ + const parseData =f.formSchema&& parseProcessData({ formSchema: JSON.parse(f.formSchema), formData: JSON.parse(f.formData) }) diff --git a/script/3.9/schema/1.update_report_automatic.sql b/script/3.9/schema/1.update_report_automatic.sql new file mode 100644 index 0000000..7c7a1db --- /dev/null +++ b/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; + diff --git a/web/client/src/layout/components/header/index.jsx b/web/client/src/layout/components/header/index.jsx index 11a5cac..55dc3fc 100644 --- a/web/client/src/layout/components/header/index.jsx +++ b/web/client/src/layout/components/header/index.jsx @@ -13,7 +13,7 @@ import layout from '../../containers/layout'; let newScrollbar; const Header = (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 [pomsName, setPomsName] = useState('全局') const [pepProjectId, setPepProjectId] = useState() @@ -63,7 +63,7 @@ const Header = (props) => { setCount(res.payload.data?.count) } }) - + dispatch(problem.getAlarmDataGroup()) } }, []) diff --git a/web/client/src/sections/control/containers/control.jsx b/web/client/src/sections/control/containers/control.jsx index 7444a20..be2ee11 100644 --- a/web/client/src/sections/control/containers/control.jsx +++ b/web/client/src/sections/control/containers/control.jsx @@ -202,7 +202,8 @@ const Control = ({ dispatch, actions, user, history, loading, socket, pepProject 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 => { localStorage.getItem(v) == null ? localStorage.setItem(v, JSON.stringify(show[v])) @@ -226,14 +227,13 @@ const Control = ({ dispatch, actions, user, history, loading, socket, pepProject }, [pepProjectId]) useEffect(() => { - if (exhibition.current?.overall?.find(v => v.key == 'tool')) { + if (exhibition.current?.overall_new?.find(v => v.key == 'tool')) { consoleToollink() } }, [exhibition.current]) - useEffect(() => { async function concentration2 () { - if (exhibition.current?.overall?.find(v => v.key == 'analyse')) { + if (exhibition.current?.overall_new?.find(v => v.key == 'analyse')) { // 查询BI分析数据-数据 await dispatch(control.getDataAlarmsAggDay({ pepProjectId: pepProjectId })).then(res => { 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() } }, [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() } @@ -580,14 +580,14 @@ const Control = ({ dispatch, actions, user, history, loading, socket, pepProject let Select = { - overall: ['workbench', 'statistical', 'dataAnalyse', 'analyse', 'dynamic', 'tool'], + overall_new: ['workbench', 'statistical', 'dataAnalyse', 'analyse', 'dynamic', 'tool'], workbench: ['project', 'data', 'app', 'device'], statistical: ['milestone', 'personnel', 'DeviceAccess', 'web', 'problem'], analyse: ['dataInterrupt', 'dataAbnormal', 'policyHit', 'videoException', 'appAbnormal', 'deviceAbnormal', 'problemAnalysis'], dynamic: ['discovery', 'notice', 'handle', 'confirm'], } let show = { - overall: ['workbench', 'dataAnalyse'], + overall_new: ['workbench', 'dataAnalyse'], workbench: ['project', 'data', 'app', 'device'], statistical: ['milestone', 'personnel', 'web', 'problem'], analyse: ['dataInterrupt', 'dataAbnormal', 'policyHit', 'videoException', 'appAbnormal', 'deviceAbnormal', 'problemAnalysis'], @@ -662,8 +662,8 @@ const Control = ({ dispatch, actions, user, history, loading, socket, pepProject
{ setSetup(true) - setTableType('overall') - attribute('overall') + setTableType('overall_new') + attribute('overall_new') setSetData(6) }} />
@@ -672,7 +672,7 @@ const Control = ({ dispatch, actions, user, history, loading, socket, pepProject
{/* 左边 */}
v.key == 'dynamic' || v.key == 'tool') ? + width: exhibition.current?.overall_new?.find(v => v.key == 'dynamic' || v.key == 'tool') ? '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') ? <>
@@ -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') && } {/* BI分析模块 */} - {exhibition.current?.overall?.find(v => v.key == 'analyse') ? + {exhibition.current?.overall_new?.find(v => v.key == 'analyse') ?
@@ -1193,10 +1193,10 @@ const Control = ({ dispatch, actions, user, history, loading, socket, pepProject
{/* 右边 */} - {exhibition.current?.overall?.find(v => v.key == 'dynamic' || v.key == 'tool') + {exhibition.current?.overall_new?.find(v => v.key == 'dynamic' || v.key == 'tool') &&
{/* 最新动态 */} - {exhibition.current?.overall?.find(v => v.key == 'dynamic') + {exhibition.current?.overall_new?.find(v => v.key == 'dynamic') &&
@@ -1260,7 +1260,7 @@ const Control = ({ dispatch, actions, user, history, loading, socket, pepProject
} {/* 我常用的工具 */} - {exhibition.current?.overall?.find(v => v.key == 'tool') ? + {exhibition.current?.overall_new?.find(v => v.key == 'tool') ?
diff --git a/web/client/src/sections/install/containers/AbnRecognize.jsx b/web/client/src/sections/install/containers/AbnRecognize.jsx index 0ea7b82..8bb8033 100644 --- a/web/client/src/sections/install/containers/AbnRecognize.jsx +++ b/web/client/src/sections/install/containers/AbnRecognize.jsx @@ -10,7 +10,7 @@ import Interrupt from './interrupt' const AbnRecognize = (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 stationsData = []; // if (abnCompareData &&calcMethod == abnCompareData.method) { @@ -56,12 +56,11 @@ const AbnRecognize = (props) => { // } // } - const renderContent=()=> { const SubContent = { - 'interrupt': , - 'burr': , - 'trend': , + 'interrupt': , + 'burr': , + 'trend': , }; return SubContent[calcMethod]; } diff --git a/web/client/src/sections/install/containers/burr.jsx b/web/client/src/sections/install/containers/burr.jsx index 9f2b715..379eb47 100644 --- a/web/client/src/sections/install/containers/burr.jsx +++ b/web/client/src/sections/install/containers/burr.jsx @@ -2,12 +2,12 @@ import React, { useState,useRef } from 'react'; 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 { useEffect } from 'react'; 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 [selectedRowKeys, setSelectedRowKeys] = useState([]) const [filterFunc, setFilterFunc] = useState({}) @@ -33,7 +33,12 @@ const Burr = (props) => { dispatch(install.deleteAbnParams(e)).then(res=>{ if(res.success){ 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=>{ if(res.success){ 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=>{ if(res.success){ 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=>{ if(res.success){ 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) { @@ -236,7 +256,28 @@ const Burr = (props) => { - +
+
+ + 共{limits}条信息 + + { + changeQuery( pageSize, currentPage - 1) + page.current = currentPage - 1 + }} + /> +
{modalVisible ? { const [sensorId, setSensorId] = useState([])//设备id' const [itemId, setItemId] = useState(null)//监测项索引 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 form2 = useRef() const method = { @@ -44,14 +47,24 @@ const Calc = (props) => { // getData() dispatch(install.getAbnMethods()) }, []) - console.log('factore111',factorId) + //页码改变的回调函数 + const pageChange=(arg1,arg2)=>{ + setQuery( {limit: arg1, page:arg2 }) + } + const limitChange=(arg)=>{ + setLimits(arg) + } useEffect(() => { if(project&&factorId){ 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(() => { setStructList([]) @@ -114,11 +127,11 @@ const Calc = (props) => { let seStaName = sensorList.find(a => a.value == selectIds[i]).label let cfg 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]) } else { 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]) } if (!cfg) { @@ -140,7 +153,6 @@ const Calc = (props) => { form2.current.validate().then(res => { if (sensorId.length != 0) { let ids = getStationstoSave() - console.log('xx111',ids) if (ids.toSave.length != 0) { let paramJson = getJson(res) let data = { @@ -170,7 +182,11 @@ const Calc = (props) => { dispatch(install.addAbnParam(pushData)).then(res => { if (res.success) { 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) { @@ -315,6 +331,7 @@ const Calc = (props) => { ) } const changeMethod = (value) => { + setQuery({ limit: 10, page: 0 }) setMethodType(value) } const clearFactorAndSensor = () => { @@ -325,7 +342,10 @@ const Calc = (props) => { setStructId(value) clearFactorAndSensor() } - + // const methodChange=(e)=>{ + // console.log('methodChange',e) + // setMethodValue(e) + // } const renderParamsConfig = () => { switch (methodType) { @@ -439,7 +459,7 @@ const Calc = (props) => { {abnMethods?.map(item => { - return ; + return ; })} @@ -464,7 +484,7 @@ const Calc = (props) => { - + @@ -484,13 +504,14 @@ const Calc = (props) => { function mapStateToProps(state) { const { auth, global, OrganizationDeps, abnMethods, abnParam } = state; + return { loading: OrganizationDeps.isRequesting, user: auth.user, actions: global.actions, pepProjectId: global.pepProjectId, abnMethods: abnMethods?.data || [], - abnParam: abnParam?.data || [] + abnParam: abnParam?.data?.rows || [] }; } export default connect(mapStateToProps)(Calc); diff --git a/web/client/src/sections/install/containers/interrupt.jsx b/web/client/src/sections/install/containers/interrupt.jsx index aada9a2..7118512 100644 --- a/web/client/src/sections/install/containers/interrupt.jsx +++ b/web/client/src/sections/install/containers/interrupt.jsx @@ -2,13 +2,13 @@ import React, { useRef, useState, useEffect } from 'react'; 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 '../style.less' 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 [selectedRowKeys, setSelectedRowKeys] = useState([]) const [filterFunc, setFilterFunc] = useState({}) @@ -31,7 +31,12 @@ const Interrupt = (props) => { dispatch(install.deleteAbnParams(e)).then(res=>{ if(res.success){ 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=>{ if(res.success){ 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=>{ if(res.success){ 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 { @@ -96,7 +111,12 @@ const Interrupt = (props) => { dispatch(install.batchCfgAbnParams(ids,data)).then(res=>{ if(res.success){ 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) { @@ -229,7 +249,28 @@ const Interrupt = (props) => { -
+
+
+ + 共{limits}条信息 + + { + changeQuery( pageSize, currentPage - 1) + page.current = currentPage - 1 + }} + /> +
{modalVisible ? { }, }, ]) - // const [data, setdata] = useState([])//表格数据 + // const [data, setData] = useState([])//表格数据 const tableData = useRef([]); //表格数据 const page = useRef(query.page);//哪一页 const [limits, setLimits] = useState()//每页实际条数 const mylimits = useRef(); //每页实际条数 const [pepList, setPepList] = useState([])//角色分配 const [pomsList, setPomsList] = useState([])//已绑定项目列表 + const [keywords,setKeywords]=useState('') const userAdmin = user?.pomsUserInfo?.role.includes('admin') //判断当前用户是否为管理员 useEffect(() => { @@ -397,7 +398,8 @@ const Roles = (props) => { let searchData = { ...query, role: roleChoose } dispatch(install.getOrganizationUser(searchData)).then((res) => {//获取成员列表 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 notCreatedNum = 5 - res.payload.data.admin.length for (let i = 0; i < notCreatedNum; i++) { @@ -425,6 +427,28 @@ const Roles = (props) => { function roleOnChange (e) {//角色选择 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 ( <>
@@ -552,7 +576,7 @@ const Roles = (props) => {
MANAGEMENT OF MEMBERS
-
平台有4种类型的成员角色,分别是数据分析师、售后运维、资源管理者和客户服务,每名项目成员可拥有多种成员角色;
+
平台有5种类型的成员角色,分别是数据分析师、售后运维、资源管理者、客户服务和设备维护,每名项目成员可拥有多种成员角色;
@@ -564,6 +588,9 @@ const Roles = (props) => { 设备维护
+ +
+
+
diff --git a/web/client/src/sections/install/containers/system.jsx b/web/client/src/sections/install/containers/system.jsx index b0caa78..02178be 100644 --- a/web/client/src/sections/install/containers/system.jsx +++ b/web/client/src/sections/install/containers/system.jsx @@ -150,7 +150,7 @@ const Example = (props) => { title: '安心云项目名称', dataIndex: "anxinProject", key: 'anxinProject', - width: 400, + width: 300, render: (_, row) => { let anxinerror = false 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: '映射类型', dataIndex: "mappingClass", diff --git a/web/client/src/sections/install/containers/trend.jsx b/web/client/src/sections/install/containers/trend.jsx index ec2dd2e..c04f395 100644 --- a/web/client/src/sections/install/containers/trend.jsx +++ b/web/client/src/sections/install/containers/trend.jsx @@ -2,14 +2,14 @@ import React, { Component, useRef,useState } from 'react'; 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 TrendModal from '../components/TrendModal'; 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 [selectedRowKeys, setSelectedRowKeys] = useState([]) const [filterFunc, setFilterFunc] = useState({}) @@ -39,7 +39,12 @@ const Trend = (props) => { dispatch(install.deleteAbnParams(e)).then(res=>{ if(res.success){ 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=>{ if(res.success){ 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=>{ if(res.success){ 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 { @@ -112,7 +127,12 @@ const Trend = (props) => { dispatch(install.batchCfgAbnParams(ids,data)).then(res=>{ if(res.success){ 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) { @@ -399,7 +419,28 @@ const Trend = (props) => { : ''} -
+
+
+ + 共{limits}条信息 + + { + changeQuery( pageSize, currentPage - 1) + page.current = currentPage - 1 + }} + /> +
{modalVisible ? { const { problem } = actions @@ -82,7 +82,7 @@ const TableData = ({ route, dispatch, actions, collectData, setSetup, exhibition break; default: 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) { setCount(res.payload.data?.count || 0) 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' }) } if (route !== 'videoAbnormal' && route !== 'useAbnormal') { - dispatch(problem.getAlarmDataGroup()).then((res) => { - if (res.success) { + // dispatch(problem.getAlarmDataGroup()).then((res) => { + // if (res.success) { let data - if (route == 'dataLnterrupt') data = res.payload.data?.filter(v => v.desc == '数据中断') - if (route == 'dataAbnormal') data = res.payload.data?.filter(v => v.desc == '数据异常') - if (route == 'strategyHit') data = res.payload.data?.filter(v => v.desc == '策略命中') - if (route == 'deviceAbnormal') data = res.payload.data?.filter(v => v.desc == '掉线' || v.desc == '不活跃') + if (route == 'dataLnterrupt') data = alarmDataGroup?.filter(v => v.desc == '数据中断') + if (route == 'dataAbnormal') data = alarmDataGroup?.filter(v => v.desc == '数据异常') + if (route == 'strategyHit') data = alarmDataGroup?.filter(v => v.desc == '策略命中') + if (route == 'deviceAbnormal') data = alarmDataGroup?.filter(v => v.desc == '掉线' || v.desc == '不活跃') groupId.current = data let genreData = [] data?.map(v => { @@ -139,8 +139,8 @@ const TableData = ({ route, dispatch, actions, collectData, setSetup, exhibition }) }) setGenre(genreData) - } - }) + // } + // }) } if (route == 'useAbnormal') { setGenre({ element: "元素异常", apiError: "接口报错 ", timeout: "加载超时" }) @@ -158,8 +158,7 @@ const TableData = ({ route, dispatch, actions, collectData, setSetup, exhibition } }) } - }, []) - + }, [route]) const handleExport = () => { let url = '' 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; 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.payload.data.count) { let groups = { @@ -379,7 +378,6 @@ const TableData = ({ route, dispatch, actions, collectData, setSetup, exhibition placeholder={SkeletonScreen()} > {(() => { - console.log(tableData); console.log((route == 'useAbnormal' || route == 'videoAbnormal') ? (tableData?.slice(query.page * query.limit, (query.page + 1) * query.limit) || []) : tableData); @@ -481,7 +479,7 @@ const TableData = ({ route, dispatch, actions, collectData, setSetup, exhibition function mapStateToProps (state) { - const { auth, global, members } = state; + const { auth, global, members,alarmDataGroup } = state; // console.log(global); return { user: auth.user, @@ -489,6 +487,7 @@ function mapStateToProps (state) { global: global, pepProjectId: global.pepProjectId, // members: members, + alarmDataGroup:alarmDataGroup.data||[] }; } export default connect(mapStateToProps)(TableData); diff --git a/web/client/src/sections/problem/containers/dataAlarm.jsx b/web/client/src/sections/problem/containers/dataAlarm.jsx index daff70d..ebe0af6 100644 --- a/web/client/src/sections/problem/containers/dataAlarm.jsx +++ b/web/client/src/sections/problem/containers/dataAlarm.jsx @@ -46,7 +46,6 @@ const DataAlarm = (props) => { const statistic = { dataLnterrupt: '数据中断统计', dataAbnormal: '数据异常统计', strategyHit: '策略命中统计', videoAbnormal: '视频异常统计', useAbnormal: '应用半自动化巡检', deviceAbnormal: '设备异常统计' } useEffect(() => { - if (route) { //初始化表格显示设置 let data = columns[route] @@ -408,7 +407,6 @@ const DataAlarm = (props) => { }) return confirmItems; } - return ( // route=='dataLnterrupt'|| route=='dataAbnormal'|| route=='strategyHit'?
diff --git a/web/client/src/sections/projectGroup/actions/group.js b/web/client/src/sections/projectGroup/actions/group.js index 928b428..764b3dc 100644 --- a/web/client/src/sections/projectGroup/actions/group.js +++ b/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 } + }, + }); +} + diff --git a/web/client/src/sections/projectGroup/containers/bigscreen.jsx b/web/client/src/sections/projectGroup/containers/bigscreen.jsx index 7b5d530..ba7b8e9 100644 --- a/web/client/src/sections/projectGroup/containers/bigscreen.jsx +++ b/web/client/src/sections/projectGroup/containers/bigscreen.jsx @@ -1,5 +1,6 @@ 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 { push } from 'react-router-redux'; import Header from '../components/header'; @@ -15,7 +16,7 @@ let interrupt let repair let overviewScrollbar; 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 [online, setOnline] = useState([]) @@ -25,13 +26,15 @@ const Bigscreen = (props) => { const [proportion, setProportion] = useState([]) const [formatter, setFormatter] = useState({}) const [groupDetail, setGroupDetail] = useState({}) - const [allProjects,setAllProjects]=useState([]) + const [allProjects, setAllProjects] = useState([]) const [alarmData, setAlarmData] = useState()//第三项之后的数据 const [biggest, setBiggest] = useState()//最大的刻度值 const [mockData, setMockData] = useState()//所有的告警数据 const [xData, setXData] = useState([])//横坐标 const self = useRef({ myChart: null }); - + const [state, setState] = useState(0) + const [interruptData,setInterruptData]=useState([]) + const [avgTmes,setAvgTimes]=useState([])//平均修复时长数组 // const [queryUserId, setQueryUserId] = useState('') useEffect(() => { @@ -65,12 +68,12 @@ const Bigscreen = (props) => { dispatch(actions.projectGroup.getProjectGroupDetail(groupId_)).then(res => { if (res.success) { - setGroupDetail(res.payload.data) + setGroupDetail(res.payload.data) } }) dispatch(actions.workOrder.getPomsProjectBasicAll()).then(res => { if (res.success) { - setAllProjects(res.payload.data) + setAllProjects(res.payload.data) } }) @@ -89,7 +92,7 @@ const Bigscreen = (props) => { suppressScrollX: true, }); } - + }, []) useEffect(() => { @@ -143,25 +146,37 @@ const Bigscreen = (props) => { useEffect(() => { - if(groupDetail?.pomsProjectIds&&groupDetail?.pomsProjectIds.length&&allProjects&&allProjects.length){ - const query=groupDetail?.pomsProjectIds+'' - dispatch(actions.projectGroup.getProjectWorkOrders({projectIds:query})).then(res=>{ - 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) })), - { name: '其它', value: res.payload.data&&res.payload.data.length>3?res.payload.data?.slice(3)?.reduce((p,c)=>{ - return p+Number(c.count) - },0):0 }]) + if (groupDetail?.pomsProjectIds && groupDetail?.pomsProjectIds.length && allProjects && allProjects.length) { + const query = groupDetail?.pomsProjectIds + '' + dispatch(actions.projectGroup.getProjectWorkOrders({ projectIds: query })).then(res => { + 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) })), + { + name: '其它', value: res.payload.data && res.payload.data.length > 3 ? res.payload.data?.slice(3)?.reduce((p, c) => { + return p + Number(c.count) + }, 0) : 0 + }]) } }) - dispatch(actions.projectGroup.getWorkOrdersRepairRank({projectIds:query})).then(res=>{ - 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') })) || []) + dispatch(actions.projectGroup.getWorkOrdersRepairRank({ projectIds: query })).then(res => { + 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') })) || []) } }) - + //修复平均时长 + 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) => { dispatch(actions.projectGroup.groupStatisticOnline({ groupId })).then(res => { if (res.success) { @@ -171,8 +186,9 @@ const Bigscreen = (props) => { 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) + setInterruptData(Interrupt) setOnline(res.payload.data?.slice(0, 10) || []) setValue(res.payload.data?.map(v => v.id)?.slice(0, 10) || []) } @@ -191,8 +207,41 @@ const Bigscreen = (props) => { timeRequest(groupId) }, 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(() => { let count = 0; let currentIndex = -1; @@ -230,12 +279,97 @@ const Bigscreen = (props) => { }, [proportion]); return (
- +
-
+ +
+ {/*
*/} + ({ value: v.id, label: v.name })) || []} - onChange={v => { - setValue(v) - setOnline(groupStatisticOnline?.filter(s => v.includes(s.id))) - }} - /> - {/*
*/} - + +
+ + { bottom: 20, }, tooltip: { - trigger: 'axis', - formatter: function (params) { - // 自定义提示框内容 - // console.log(params); - let title = params[0].data[0] + '
' + '
' - 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 + ":" + " " + " " + v.data[1] + "%" + "(" + find?.online + "/" + find?.total + ")" + '
' - }) - return title - } + // trigger: 'axis', + position: ['5%', '50%'] , + }, xAxis: { - type: 'time', - // name: "时间", - boundaryGap: false, - minInterval: 1000 * 60 * 60, + show:true, + type: 'category', + data: avgTmes?.map(s => s.projectName), + axisLabel: { + formatter: function (value) { + // 控制显示前五个字符,其余用省略号代替 + return value.substring(0, 5) + (value.length > 5 ? '...' : ''); + }, + }, }, yAxis: { type: 'value', - name: "单位%", - areaStyle: { - color: '#FFF', - }, + 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)]) || [] - })) || [] + series: [ + { + type: 'bar', + data: avgTmes?.map(s => s.avgTime), + } + ] }} - notMerge={true} + // notMerge={true} lazyUpdate={true} style={{ width: "100%", height: "100%" }} theme={'ReactEChart'} /> - -
- +
+ + +
+ +
+
+ + +
+
+
结构物
+
中断百分比topClick('perTop')}>topClick('perBottom')}>
+
中断时长topClick('timeTop')}>topClick('timeBottom')}>
+
中断个数topClick('countTop')}>topClick('countBottom')}>
+
+
+ + {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
+
{c.name}
+
{((c.offnum / c.totnum) * 100).toFixed(2)}%
+
{title}
+
{c.offnum + '/' + c.totnum}
+
+ })}} containerStyle={{ position: "relative", height: "85%", }} + divHeight={"100%"} divId={"interruptchart"} /> +
+
+
{alarmData && alarmData.length > 0 ? (
@@ -458,46 +626,6 @@ const Bigscreen = (props) => {
) : ''}
- -
-
-
结构物
-
中断时长
-
中断个数
-
-
- - {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
-
{c.name}
-
{title}
-
{c.offnum + '/' + c.totnum+`(${((c.offnum/c.totnum)*100).toFixed(2)}%)`}
-
- })} } containerStyle={{ position: "relative", height: "85%", }} - divHeight={"100%"} divId={"interruptchart"}/> -
-
-
@@ -506,9 +634,9 @@ const Bigscreen = (props) => {
) } -function mapStateToProps (state) { - - const { auth, global, groupStatisticOnline,pomsProjectBasicAll } = state; +function mapStateToProps(state) { + + const { auth, global, groupStatisticOnline, pomsProjectBasicAll } = state; return { user: auth.user, actions: global.actions, diff --git a/web/client/src/sections/projectGroup/style.less b/web/client/src/sections/projectGroup/style.less index e15137d..c92673a 100644 --- a/web/client/src/sections/projectGroup/style.less +++ b/web/client/src/sections/projectGroup/style.less @@ -104,6 +104,46 @@ 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 + + } \ No newline at end of file diff --git a/web/client/src/sections/service/components/automatic-Modal.jsx b/web/client/src/sections/service/components/automatic-Modal.jsx index 8304b8d..8f8b497 100644 --- a/web/client/src/sections/service/components/automatic-Modal.jsx +++ b/web/client/src/sections/service/components/automatic-Modal.jsx @@ -22,7 +22,6 @@ const AutomaticModal = ({ actions, dispatch, apiRoot, qiniuUrl, visible, eidtDat useEffect(async () => { if (eidtData?.id) { - console.log(eidtData); setProjectId(eidtData?.projectId) setStructId(eidtData?.structId) setFactorId(eidtData?.factors?.map(s => s.codeName) || []) @@ -63,6 +62,7 @@ const AutomaticModal = ({ actions, dispatch, apiRoot, qiniuUrl, visible, eidtDat projectName: v.projectName, reportType: v.reportType, reportPicPath: v.reportPicPath[0]?.response?.url, + overview: v.overview[0]?.response?.url, framer: v.framer, auditor: v.auditor, ratifier: v.ratifier, @@ -139,7 +139,7 @@ const AutomaticModal = ({ actions, dispatch, apiRoot, qiniuUrl, visible, eidtDat > + + + { const [workflowModalType, setWorkflowModalType] = useState('') const [checkProcessInstanceId, setCheckProcessInstanceId] = useState(null) const [params, setParams] = useState({}) + const [page,setPage]=useState(1)//当前页 useEffect(() => { backlogData() if (!pomsProjectBasicAll.length) { @@ -194,7 +195,7 @@ const Rest = (props) => { }) .then(res => { setLoading(false) - backlogData() + backlogData({limit:query.limit,page}) Toast.success({ content: '撤销流程成功', duration: 1, }) }, error => { Toast.error({ content: '撤销流程失败', duration: 1, }) @@ -309,6 +310,7 @@ const Rest = (props) => { currentPage={query.offset + 1} pageSizeOpts={[10, 20, 30, 40]} onChange={(currentPage, pageSize) => { + setPage(currentPage) setQuery({ limit: pageSize, offset: currentPage - 1 }); backlogData({ ...params, limit: pageSize, offset: currentPage - 1 }) }} diff --git a/web/client/src/utils/webapi.js b/web/client/src/utils/webapi.js index 938e776..e9a431a 100644 --- a/web/client/src/utils/webapi.js +++ b/web/client/src/utils/webapi.js @@ -188,7 +188,7 @@ export const ApiTable = { deleteAbnParams: 'delete/abnormal/params/{id}',//删除配置 editAbnParams: 'edit/abnormal/params/{id}',//修改配置 getAbnTaskResult: 'struct/{structId}/abnTask/result/{start}/{end}',// - + getWorkOrdersAvgTimes:'project/workOrders/avgTime' }; // 项企的接口