'use strict'; const moment = require('moment') async function edit (ctx) { const transaction = await ctx.fs.dc.orm.transaction(); try { const sequelize = ctx.fs.dc.orm; const { models } = ctx.fs.dc; const { userId } = ctx.fs.api const data = ctx.request.body const timeNow = moment() const { mirrorId, tree = [], filterGroup = [] } = data let mirrorId_ = mirrorId if (mirrorId_) { let upData = { template: data.template, updateTime: timeNow.format(), title: data.title, showHeader: Boolean(data.showHeader), } if (data.publish) { upData.publish = true upData.publishTime = timeNow.format() } await models.Mirror.update(upData, { where: { id: mirrorId_ }, transaction }) // 除 Mirror 外的信息全删除并重建 await models.MirrorCamera.destroy({ where: { mirrorId: mirrorId_ }, transaction }) await sequelize.query('DELETE FROM mirror_filter WHERE group_id IN (SELECT id FROM mirror_filter_group WHERE mirror_id=?)', { replacements: [mirrorId_], transaction }) await models.MirrorFilterGroup.destroy({ where: { mirrorId: mirrorId_ }, transaction }) await models.MirrorTree.destroy({ where: { mirrorId: mirrorId_ }, transaction }) } else { // 创建 镜像信息 let createData = { template: data.template, createUser: userId, createTime: timeNow.format(), title: data.title, showHeader: Boolean(data.showHeader), publish: false, mid: timeNow.format(`ssmmHHDDMMYY${Math.floor(Math.random() * 89 + 10)}`) } if (data.publish) { createData.publish = true createData.publishTime = timeNow.format() } const mirrorCreateRes = await models.Mirror.create(createData, { transaction }) mirrorId_ = mirrorCreateRes.id } let cameraStorage = {} const dealTree = async (child, lastNodeStorageId, level) => { // 递归 tree 获得扁平信息 let curLevel = level for (let c of child) { if (c.cameraId) { // 摄像头节点为末端节点 // 不创建节点 if (cameraStorage[c.cameraId]) { cameraStorage[c.cameraId].treeIds.push(lastNodeStorageId) } else { cameraStorage[c.cameraId] = { treeIds: [lastNodeStorageId], filterIds: [] } } } else { const treeStorageRes = await models.MirrorTree.create({ name: c.label, level: curLevel, dependence: lastNodeStorageId, mirrorId: mirrorId_ }, { transaction }) if (c.children) { await dealTree(c.children, treeStorageRes.id, curLevel + 1) } } } } await dealTree(tree, null, 1) for (let g of filterGroup) { // 遍历创建筛选分组 const filterGroupStorageRes = await models.MirrorFilterGroup.create({ name: g.name, forbidden: g.forbidden, mirrorId: mirrorId_ }, { transaction }) if (g.filters) { for (let f of g.filters) { // 遍历创建筛选项 const filterStorageRes = await models.MirrorFilter.create({ name: f.name, groupId: filterGroupStorageRes.id }, { transaction }) for (let cid of f.cameraIds) { if (cameraStorage[cid]) { cameraStorage[cid].filterIds.push(filterStorageRes.id) } } } } } let bulkCreateCameraD = [] for (let cid in cameraStorage) { bulkCreateCameraD.push({ cameraId: cid, ...cameraStorage[cid], mirrorId: mirrorId_ }) } if (bulkCreateCameraD.length) { await models.MirrorCamera.bulkCreate(bulkCreateCameraD, { transaction }) } await transaction.commit(); ctx.status = 204; } catch (error) { await transaction.rollback(); ctx.fs.logger.error(`path: ${ctx.path}, error: ${error}`); ctx.status = 400; ctx.body = { message: typeof error == 'string' ? error : undefined } } } async function refreshId (ctx) { try { const { models } = ctx.fs.dc; const { mirrorId } = ctx.params if (!mirrorId) throw '更新镜像服务ID失败'; const nextId = moment().format(`ssmmHHDDMMYY${Math.floor(Math.random() * 89 + 10)}`) await models.Mirror.update({ mid: nextId }, { where: { id: mirrorId } }) ctx.status = 200; ctx.body = { mid: nextId } } catch (error) { ctx.fs.logger.error(`path: ${ctx.path}, error: error`); ctx.status = 400; ctx.body = { message: typeof error == 'string' ? error : undefined } } } async function list (ctx) { try { const { models } = ctx.fs.dc; const { userId, token } = ctx.fs.api let startTime = moment() const mirrorRes = await models.Mirror.findAll({ attributes: { exclude: ['showHeader'] }, where: {}, order: [['id', 'DESC']] }) console.log(`S1 = ${moment().diff(startTime, 'milliseconds')}`); let createUserIds = new Set() for (let c of mirrorRes) { createUserIds.add(c.dataValues.createUser) } console.log(`S1 = ${moment().diff(startTime, 'milliseconds')}`); // 查对应创建者信息 const corUsers = await ctx.app.fs.authRequest.get(`user/${[...createUserIds].join(',') || -1}/message`, { query: { token } }) console.log(`S3 = ${moment().diff(startTime, 'milliseconds')}`); for (let { dataValues: mirror } of mirrorRes) { const corUser = corUsers.find(u => u.id == mirror.createUser) mirror.createUser = corUser ? corUser.username : '' } console.log(`S4 = ${moment().diff(startTime, 'milliseconds')}`); ctx.status = 200; ctx.body = mirrorRes } catch (error) { ctx.fs.logger.error(`path: ${ctx.path}, error: ${error}`); ctx.status = 400; ctx.body = { message: typeof error == 'string' ? error : undefined } } } async function get (ctx) { try { // 下次这样的关关联联要用数据库关联 !!! // 不然逻辑好绕啊 const { models } = ctx.fs.dc; const { userId } = ctx.fs.api const { mid } = ctx.params const { check } = ctx.query // 查当前镜像的全部信息 const mirrorRes = await models.Mirror.findOne({ attributes: { exclude: ['createUser'] }, order: [['id', 'ASC']], where: { mid: mid }, include: [{ model: models.MirrorTree, required: false }, { model: models.MirrorFilterGroup, attributes: { exclude: ['mirrorId'] }, required: false, include: [{ model: models.MirrorFilter, attributes: { exclude: ['groupId'] }, required: false }] }, { model: models.MirrorCamera, required: false, include: { model: models.Camera, attributes: { exclude: ['rtmp', 'venderId', 'createTime', 'recycleTime', 'delete', 'createUserId', 'nvrId', 'kindId', 'yingshiSecretId', 'gbId'] }, include: [{ model: models.SecretYingshi, attributes: ['token'] }, { model: models.GbCamera, attributes: ['id', 'online', 'playUrl',], required: false }, { model: models.CameraRemark, attributes: ['remark'], order: [ ['id', 'DESC'] ], }] } }] }) let returnData if (mirrorRes) { if (check && !mirrorRes.publish) { throw '尚未发布' } const { mirrorCameras, mirrorFilterGroups, mirrorTrees } = mirrorRes.dataValues returnData = { ...mirrorRes.dataValues, tree: [], filterGroup: [] } // 反向构建出树节点 const buildTree = (treeNodes = [], lastLevelKey = '') => { const nextKeyPre = lastLevelKey ? lastLevelKey + '-' : lastLevelKey treeNodes.forEach((tn, index) => { const curKey = nextKeyPre + index let child = JSON.parse(JSON.stringify(mirrorTrees.filter(mt => mt.dependence == tn.id))) let cameras = mirrorCameras.filter(mc => mc.treeIds.includes(tn.id)) if (cameras.length) { // 有摄像头 向下再创建一级节点 tn.children = cameras.map((c, cIndex) => { return { label: c.dataValues.camera.name, key: curKey + '-' + cIndex, cameraId: c.dataValues.cameraId, camera: c.dataValues.camera } }) } else { tn.children = child buildTree(child, curKey) } tn.label = tn.name tn.key = curKey delete tn.name delete tn.level delete tn.dependence delete tn.mirrorId }) } let tree = JSON.parse(JSON.stringify(mirrorTrees.filter(t => t.level == 1))) buildTree(tree) returnData.tree = tree // 构建筛选分组及筛选项 for (let { dataValues: g } of mirrorFilterGroups) { for (let { dataValues: f } of g.mirrorFilters) { f.cameraIds = (mirrorCameras.filter(mc => mc.filterIds.includes(f.id)) || []).map(mc => mc.cameraId) } g.filters = g.mirrorFilters delete g.mirrorFilters } returnData.filterGroup = mirrorFilterGroups delete returnData.mirrorCameras delete returnData.mirrorFilterGroups delete returnData.mirrorTrees } else { throw '没有查询到对应的镜像服务' } ctx.status = 200; ctx.body = returnData } catch (error) { ctx.fs.logger.error(`path: ${ctx.path}, error: ${error}`); ctx.status = 400; ctx.body = { message: typeof error == 'string' ? error : undefined } } } async function del (ctx) { const transaction = await ctx.fs.dc.orm.transaction(); try { const { models } = ctx.fs.dc; const { userId } = ctx.fs.api const { mirrorId } = ctx.params if (!mirrorId) throw '镜像服务删除失败'; const sequelize = ctx.fs.dc.orm; // 除 Mirror 外的信息全删除并重建 await models.MirrorCamera.destroy({ where: { mirrorId: mirrorId }, transaction }) await sequelize.query('DELETE FROM mirror_filter WHERE group_id IN (SELECT id FROM mirror_filter_group WHERE mirror_id=?)', { replacements: [mirrorId], transaction }) await models.MirrorFilterGroup.destroy({ where: { mirrorId: mirrorId }, transaction }) await models.MirrorTree.destroy({ where: { mirrorId: mirrorId }, transaction }) await models.Mirror.destroy({ where: { id: mirrorId }, transaction }) await transaction.commit(); ctx.status = 204; } catch (error) { await transaction.rollback(); ctx.fs.logger.error(`path: ${ctx.path}, error: ${error}`); ctx.status = 400; ctx.body = { message: typeof error == 'string' ? error : undefined } } } async function publish (ctx) { try { const { models } = ctx.fs.dc; const { userId } = ctx.fs.api const { mirrorId } = ctx.params if (!mirrorId) throw '发布镜像服务失败'; await models.Mirror.update({ publish: true, publishTime: moment().format() }, { where: { id: mirrorId } }) 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 } } } async function copy (ctx) { const transaction = await ctx.fs.dc.orm.transaction(); try { const { models } = ctx.fs.dc; const { userId } = ctx.fs.api const { mirrorId } = ctx.params const timeNow = moment() // 查当前镜像的全部信息 const mirrorRes = await models.Mirror.findOne({ attributes: { exclude: ['createUser'] }, order: [['id', 'ASC']], where: { id: mirrorId }, include: [{ model: models.MirrorTree, required: false }, { model: models.MirrorFilterGroup, required: false, include: [{ model: models.MirrorFilter, required: false }] }, { model: models.MirrorCamera, required: false, }] }) if (mirrorRes) { const { mirrorCameras, mirrorFilterGroups, mirrorTrees } = mirrorRes.dataValues const newMirrorRes = await models.Mirror.create({ template: mirrorRes.template, createUser: userId, createTime: timeNow.format(), title: mirrorRes.title + '-副本', showHeader: mirrorRes.showHeader, publish: mirrorRes.publish, mid: timeNow.format(`ssmmHHDDMMYY${Math.floor(Math.random() * 89 + 10)}`) }, { transaction }) const newMirrorId = newMirrorRes.id let cameraStorage = {} // 重新存一遍树节点 const storageTree = async (node, lastNodeStorageId) => { for (let n of node) { // 创建新节点 const newTreeNodeStorageRes = await models.MirrorTree.create({ name: n.name, level: n.level, dependence: lastNodeStorageId, mirrorId: newMirrorId }, { transaction }) // 筛选老节点所下辖的摄像头 let corCamera = mirrorCameras.filter((mc) => mc.treeIds.includes(n.id)) for (let c of corCamera) { // 为摄像头存新的节点id if (cameraStorage[c.cameraId]) { cameraStorage[c.cameraId].treeIds.push(newTreeNodeStorageRes.id) } else { cameraStorage[c.cameraId] = { treeIds: [newTreeNodeStorageRes.id], filterIds: [] } } } const nextNode = mirrorTrees.filter(mt => mt.dependence == n.id) if (nextNode.length) { await storageTree(nextNode) } } } let treeLevelOne = mirrorTrees.filter(mt => mt.level == 1) await storageTree(treeLevelOne, null) // 重新存一遍筛选分组、筛选项 for (let { dataValues: g } of mirrorFilterGroups) { const newGroupStorageRes = await models.MirrorFilterGroup.create({ name: g.name, forbidden: g.forbidden, mirrorId: newMirrorId }, { transaction }) for (let { dataValues: f } of g.mirrorFilters) { const newFilterStorageRes = await models.MirrorFilter.create({ name: f.name, groupId: newGroupStorageRes.id }, { transaction }) let corCamera = mirrorCameras.filter((mc) => mc.filterIds.includes(f.id)) for (let c of corCamera) { // 为摄像头存新的节点id if (cameraStorage[c.cameraId]) { cameraStorage[c.cameraId].filterIds.push(newFilterStorageRes.id) } } } } let bulkCreateCameraD = [] for (let cid in cameraStorage) { bulkCreateCameraD.push({ cameraId: cid, ...cameraStorage[cid], mirrorId: newMirrorId }) } if (bulkCreateCameraD.length) { await models.MirrorCamera.bulkCreate(bulkCreateCameraD, { transaction }) } } await transaction.commit(); ctx.status = 204; } catch (error) { await transaction.rollback(); ctx.fs.logger.error(`path: ${ctx.path}, error: ${error}`); ctx.status = 400; ctx.body = { message: typeof error == 'string' ? error : undefined } } } module.exports = { edit, refreshId, list, get, del, publish, copy, };