Browse Source

项目在线率查询接口

dev
CODE 2 years ago
parent
commit
b016b3effe
  1. 1
      api/.vscode/launch.json
  2. 152
      api/app/lib/controllers/project/group.js
  3. 62
      api/app/lib/models/structure_off.js
  4. 10
      api/app/lib/routes/project/index.js
  5. 8
      api/config.js
  6. 4
      api/sequelize-automate.config.js

1
api/.vscode/launch.json

@ -22,6 +22,7 @@
// "-g postgres://FashionAdmin:123456@10.8.30.156:5432/POMS",
"-k 10.8.30.72:29092,10.8.30.73:29092,10.8.30.74:29092",
"-e http://10.8.30.60:9200",
// "-e http://10.8.30.60:5601",
"--iotaProxy http://10.8.30.157:17007",
"--redisHost localhost",
"--redisPort 6379",

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

@ -103,7 +103,7 @@ async function delGroup (ctx) {
}
}
async function groupStatic (ctx) {
async function groupStatistic (ctx) {
try {
const { models } = ctx.fs.dc;
const { userId } = ctx.fs.api
@ -114,16 +114,11 @@ async function groupStatic (ctx) {
where: {
pomsUserId: userId
}
})
// 获取全部的 poms 项目id 并构建关系
let pomsProjectIds = new Set()
let groupMap = {
}
for (let group of progectGroupList) {
groupMap[group.id] = groupMap[group.id] || {}
for (let projectId of group.pomsProjectIds) {
pomsProjectIds.add(projectId)
}
@ -142,33 +137,151 @@ async function groupStatic (ctx) {
for (let projectId of project.anxinProjectId) {
anxinProjectIds.add(projectId)
}
groupMap[group.id].anxinProjectCount = anxinProjectCount
}
let anxinProjectIdArr = Array.from(anxinProjectIds)
// 统计安心云项目下的结构物个数
const strucCountRes = await clickHouse.anxinyun.query(
// 统计安心云项目下的结构物id
const strucIdRes = await clickHouse.anxinyun.query(
`
SELECT project, COUNT(*) AS count
SELECT *
FROM t_project_structure
WHERE project IN (${[...anxinProjectIdArr].join(',')}, -1)
GROUP BY project
`
).toPromise()
let strucIds = new Set()
for (let struc of strucIdRes) {
strucIds.add(struc.structure)
}
let strucIdArr = Array.from(strucIds)
const deviceOffTimeRes = strucIdArr.length ? await models.StructureOff.findAll({
where: {
structure: { $in: strucIdArr }
}
}) : []
let rslt = []
for (let pg of progectGroupList) {
let anxinProjectCount = 0
for (let projectId of pg.pomsProjectIds) {
if (anxinProjectIdArr.includes(projectId)) {
anxinProjectCount++
}
}
let strucCount = 0
let maxOffLineTime = 0
let anxinProjectCount = groupProjectRes.reduce((count, gp) => {
if (pg.pomsProjectIds.some(id => gp.id == id)) {
// 如果 pg 分组信息 存储的 pomsProjectIds 运维项目id 和 真正的 groupProjectRes 运维项目id 相等
// gp.anxinProjectId 就是对应的 安心云的项目 id 集
count += gp.anxinProjectId.length
//
let strucIdArr_ =
strucIdRes.filter(s => gp.anxinProjectId.includes(s.project))
strucCount += strucIdArr_.length
//
for (let { dataValues: off } of deviceOffTimeRes) {
if (strucIdArr_.some((s) => s.structure == off.structure)) {
if (off.offline > maxOffLineTime) {
maxOffLineTime = off.offline
}
}
}
}
return count
}, 0)
rslt.unshift({
...pg.dataValues,
strucCount,
maxOffLineTime,
anxinProjectCount,
})
}
ctx.status = 200;
ctx.body = []
ctx.body = rslt
} catch (error) {
ctx.fs.logger.error(`path: ${ctx.path}, error: error`);
ctx.status = 400;
ctx.body = {
message: typeof error == 'string' ? error : undefined
}
}
}
async function groupStatisticOnline (ctx) {
try {
const { models } = ctx.fs.dc;
const { userId } = ctx.fs.api
const { groupId } = ctx.query
const sequelize = ctx.fs.dc.orm
const { clickHouse } = ctx.app.fs
const pomsProjectRes = await sequelize.query(`
SELECT project_correlation.anxin_project_id
FROM project_group
JOIN project_correlation
ON project_correlation.id = ANY(project_group.poms_project_ids)
WHERE project_group.id = ${groupId};
`)
const anxinProjectIds = new Set()
for (let pomsProject of (pomsProjectRes[0] || [])) {
for (let pid of pomsProject.anxin_project_id)
anxinProjectIds.add(pid)
}
const strucIdRes = await clickHouse.anxinyun.query(
`
SELECT *
FROM t_project_structure
WHERE project IN (${[...anxinProjectIds].join(',')}, -1)
`
).toPromise()
let strucIds = new Set()
for (let struc of strucIdRes) {
strucIds.add(struc.structure)
}
let strucIdArr = Array.from(strucIds)
const strucRes = strucIdArr.length ? await clickHouse.anxinyun.query(
`
SELECT * FROM t_structure WHERE id IN (${[...strucIdArr].join(',')});
`
).toPromise() : []
const strucOnlineClient = ctx.app.fs.esclient.strucOnline
const onlineRes = await strucOnlineClient.search({
index: strucOnlineClient.config.index,
type: strucOnlineClient.config.type,
body: {
"query": {
"bool": {
"filter": [
{
"range": {
"collect_time": {
"gte": `${moment().subtract(24, 'hours').format('YYYY-MM-DDTHH:mm:ss.SSS')}Z`,
"gte": "2023-08-24T08:00:00.000Z",
}
}
},
{
"terms": {
"structure": strucIdArr,
"structure": [1, 2, 3]
}
}
]
}
},
"sort": [
{
"collect_time": {
"order": "asc"
}
}
]
}
})
ctx.status = 200;
ctx.body = onlineRes.hits.hits;
} catch (error) {
ctx.fs.logger.error(`path: ${ctx.path}, error: error`);
ctx.status = 400;
@ -182,5 +295,6 @@ module.exports = {
groupList,
editGroup,
delGroup,
groupStatic,
groupStatistic,
groupStatisticOnline,
};

62
api/app/lib/models/structure_off.js

@ -0,0 +1,62 @@
/* eslint-disable*/
'use strict';
module.exports = dc => {
const DataTypes = dc.ORM;
const sequelize = dc.orm;
const StructureOff = sequelize.define("structureOff", {
id: {
type: DataTypes.INTEGER,
allowNull: false,
defaultValue: null,
comment: null,
primaryKey: true,
field: "id",
autoIncrement: true,
unique: "t_structure_off_id_uindex"
},
structure: {
type: DataTypes.INTEGER,
allowNull: false,
defaultValue: null,
comment: "结构物id",
primaryKey: false,
field: "structure",
autoIncrement: false
},
offline: {
type: DataTypes.INTEGER,
allowNull: false,
defaultValue: null,
comment: "离线时长(分钟)",
primaryKey: false,
field: "offline",
autoIncrement: false
},
offtime: {
type: DataTypes.STRING,
allowNull: false,
defaultValue: null,
comment: "最后数据时间",
primaryKey: false,
field: "offtime",
autoIncrement: false
},
state: {
type: DataTypes.INTEGER,
allowNull: false,
defaultValue: null,
comment: "数据状态( 0:有效,1:无效)",
primaryKey: false,
field: "state",
autoIncrement: false
}
}, {
tableName: "t_structure_off",
comment: "",
indexes: []
});
dc.models.StructureOff = StructureOff;
return StructureOff;
};

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

@ -40,6 +40,12 @@ module.exports = function (app, router, opts) {
app.fs.api.logAttr['DEL/project/group'] = { content: '删除项目分组', visible: true };
router.delete('/project/group', projectGroup.delGroup);
app.fs.api.logAttr['GET/project/group/static'] = { content: '获取项目分组统计信息', visible: true };
router.get('/project/group/static', projectGroup.groupStatic);
app.fs.api.logAttr['GET/project/group/statistic'] = { content: '获取项目分组统计信息', visible: true };
router.get('/project/group/statistic', projectGroup.groupStatistic);
app.fs.api.logAttr['GET/project/group/statistic'] = { content: '获取项目分组统计信息', visible: true };
router.get('/project/group/statistic', projectGroup.groupStatistic);
app.fs.api.logAttr['GET/project/group/statistic/online'] = { content: '获取项目分组在线率统计信息', visible: true };
router.get('/project/group/statistic/online', projectGroup.groupStatisticOnline);
};

8
api/config.js

@ -124,7 +124,9 @@ const CAIYUN_API = process.env.CAIYUN_API || flags.caiyunApi || 'https://api.cai
const CAIYUN_KEY = process.env.CAIYUN_KEY || flags.caiyunKey || '1l0eNveMANMXEIJI';
// ES
const ES_PLATFORM_NAME = process.env.ES_PLATFORM_NAME || flags.esPlatformName || 'anxinyun';
const ES_PLATFORM_NAME = process.env.ES_PLATFORM_NAME || flags.esPlatformName
|| 'anxincloud'
|| 'anxinyun';
const ANXINCLOUD_ES_NODES_REST = process.env.ANXINCLOUD_ES_NODES_REST || flags.es;
if (
@ -277,10 +279,10 @@ const product = {
]
},
es: {
alarm: {
strucOnline: {
//告警记录
rootURL: ANXINCLOUD_ES_NODES_REST.split(','),
index: `${ES_PLATFORM_NAME}_alarms`,
index: `${ES_PLATFORM_NAME}_online`,
type: flags.esType ? flags.esType : '_doc'
},
}

4
api/sequelize-automate.config.js

@ -33,10 +33,10 @@ module.exports = {
dir: './app/lib/models', // 指定输出 models 文件的目录
typesDir: 'models', // 指定输出 TypeScript 类型定义的文件目录,只有 TypeScript / Midway 等会有类型定义
emptyDir: false, // !!! 谨慎操作 生成 models 之前是否清空 `dir` 以及 `typesDir`
tables: ['project_group'], // 指定生成哪些表的 models,如 ['user', 'user_post'];如果为 null,则忽略改属性
tables: ['t_structure_off'], // 指定生成哪些表的 models,如 ['user', 'user_post'];如果为 null,则忽略改属性
skipTables: [], // 指定跳过哪些表的 models,如 ['user'];如果为 null,则忽略改属性
tsNoCheck: false, // 是否添加 `@ts-nocheck` 注释到 models 文件中
ignorePrefix: [], // 生成的模型名称忽略的前缀,因为 项目中有以下表名是以 t_ 开头的,在实际模型中不需要, 可以添加多个 [ 't_data_', 't_',] ,长度较长的 前缀放前面
ignorePrefix: ['t_'], // 生成的模型名称忽略的前缀,因为 项目中有以下表名是以 t_ 开头的,在实际模型中不需要, 可以添加多个 [ 't_data_', 't_',] ,长度较长的 前缀放前面
attrLength: false, // 在生成模型的字段中 是否生成 如 var(128)这种格式,公司一般使用 String ,则配置为 false
},
}
Loading…
Cancel
Save