diff --git a/code/VideoAccess-VCMP/api/.vscode/launch.json b/code/VideoAccess-VCMP/api/.vscode/launch.json index 5bef1ea..18a127d 100644 --- a/code/VideoAccess-VCMP/api/.vscode/launch.json +++ b/code/VideoAccess-VCMP/api/.vscode/launch.json @@ -17,7 +17,10 @@ "-f http://localhost:4000", "-g postgres://postgres:123@10.8.30.32:5432/video_access", "--redisHost 127.0.0.1", - "--redisPort 6379" + "--redisPort 6379", + "--axyApiUrl http://127.0.0.1:4100", + "--godUrl https://restapi.amap.com/v3", + "--godKey 21c2d970e1646bb9a795900dd00093ce" ] }, { diff --git a/code/VideoAccess-VCMP/api/app/lib/controllers/camera/index.js b/code/VideoAccess-VCMP/api/app/lib/controllers/camera/index.js new file mode 100644 index 0000000..589f324 --- /dev/null +++ b/code/VideoAccess-VCMP/api/app/lib/controllers/camera/index.js @@ -0,0 +1,159 @@ +'use strict'; + +async function getCameraProject (ctx, next) { + try { + const models = ctx.fs.dc.models; + const { limit, page, orderBy, orderDirection, keyword, abilityId, type, venderId } = ctx.query + const { userId, token } = ctx.fs.api + + let findOption = { + attributes: { exclude: ['delete', 'recycleTime',] }, + where: { + createUserId: userId, + recycleTime: null, + delete: false + }, + order: [ + [orderBy || 'id', orderDirection || 'DESC'] + ], + include: [{ + model: models.CameraAbility + }, { + model: models.CameraKind + }] + } + if (limit) { + findOption.limit = limit + } + if (page && limit) { + findOption.offset = page * limit + } + if (keyword) { + findOption.where.$or = [{ + name: { $like: `%${keyword}%` } + }, { + serialNo: { $like: `%${keyword}%` } + }] + } + if (type) { + findOption.where.type = type + } + if (abilityId) { + findOption.where.abilityId = abilityId + } + if (venderId) { + findOption.where.venderId = venderId + } + + const cameraRes = await models.Camera.findAll(findOption) + const total = await models.Camera.count({ + where: findOption.where + }) + + // 查在安心云绑定的数据 + const cameraIds = cameraRes.map(c => { + return c.dataValues.id + }) + const axbindCameraRes = await ctx.app.fs.axyRequest.get('vcmp/camera/project', { query: { token, cameraId: cameraIds.join(',') } }) + + for (let { dataValues: camera } of cameraRes) { + const corBindCamera = axbindCameraRes.find(b => b.cameraId == camera.id) + if (corBindCamera) { + camera.station = corBindCamera.stations + } else { + camera.station = [] + } + } + + ctx.status = 200; + ctx.body = { + total: total, + data: cameraRes + } + } catch (error) { + ctx.fs.logger.error(`path: ${ctx.path}, error: ${error}`); + ctx.status = 400; + ctx.body = {} + } +} + +async function getCamera (ctx) { + try { + const { models } = ctx.fs.dc; + const { cameraId } = ctx.query + + const cameraRes = await models.Camera.findAll({ + attributes: { exclude: ['delete', 'recycleTime',] }, + where: { + id: { $in: cameraId.split(',') } + }, + include: [{ + model: models.CameraAbility + }, { + model: models.CameraKind + }, { + model: models.Vender + }] + }) + + ctx.status = 200; + ctx.body = cameraRes + } catch (error) { + ctx.fs.logger.error(`path: ${ctx.path}, error: ${error}`); + ctx.status = 400; + ctx.body = {} + } +} + +async function banned (ctx) { + try { + const { models } = ctx.fs.dc; + const data = ctx.request.body; + + // 向视频服务发送通知 + + // 库记录 + await models.Camera.update({ + forbidden: data.forbidden + }, { + where: { + id: data.cameraId + } + }) + + ctx.status = 204; + } catch (error) { + ctx.fs.logger.error(`path: ${ctx.path}, error: ${error}`); + ctx.status = 400; + ctx.body = {} + } +} + +async function del (ctx) { + try { + const { models } = ctx.fs.dc; + const { cameraId } = ctx.query + const { token } = ctx.fs.api + + await models.cameraId.destroy({ + where: { + id: cameraId + } + }) + + await ctx.app.fs.axyRequest.delete('vcmp/camera/project', { query: { token, cameraId: cameraId.join(',') } }) + + ctx.status = 204; + } catch (error) { + ctx.fs.logger.error(`path: ${ctx.path}, error: ${error}`); + ctx.status = 400; + ctx.body = {} + } +} + +module.exports = { + getCameraProject, + getCamera, + banned, + del, +}; \ No newline at end of file diff --git a/code/VideoAccess-VCMP/api/app/lib/controllers/nvr/index.js b/code/VideoAccess-VCMP/api/app/lib/controllers/nvr/index.js index 56b58ba..d216756 100644 --- a/code/VideoAccess-VCMP/api/app/lib/controllers/nvr/index.js +++ b/code/VideoAccess-VCMP/api/app/lib/controllers/nvr/index.js @@ -2,103 +2,134 @@ const moment = require('moment') async function edit (ctx, next) { - const transaction = await ctx.fs.dc.orm.transaction(); - try { - const models = ctx.fs.dc.models; - const { userId } = ctx.fs.api - const data = ctx.request.body; + const transaction = await ctx.fs.dc.orm.transaction(); + try { + const models = ctx.fs.dc.models; + const { userId } = ctx.fs.api + const data = ctx.request.body; - // 或取其他服务信息 - const nvrData = { - channelCount: 8, - port: 8080, - } + // 或取其他服务信息 + const nvrData = { + channelCount: 8, + port: 8080, + } - if (data.id) { - // 修改 - const storageData = Object.assign({}, data, nvrData) - await models.Nvr.update(storageData, { - where: { - id: data.id - }, - transaction - }) - } else { - // 添加 - const storageData = Object.assign({}, data, nvrData, { - createTime: moment().format(), - createUserId: userId, - delete: false, - }) - await models.Nvr.create(storageData, { transaction }) - } + if (data.id) { + // 修改 + const storageData = Object.assign({}, data, nvrData) + await models.Nvr.update(storageData, { + where: { + id: data.id + }, + transaction + }) + } else { + // 添加 + const storageData = Object.assign({}, data, nvrData, { + createTime: moment().format(), + createUserId: userId, + delete: false, + }) + await models.Nvr.create(storageData, { 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 = {} - } + 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 = {} + } } async function get (ctx) { - const models = ctx.fs.dc.models; - try { - const { limit, page, orderBy, orderDirection } = ctx.query - let findOption = { - attributes: { exclude: ['delete'] }, - where: { - delete: false, - }, - order: [ - [orderBy || 'id', orderDirection || 'DESC'] - ] - } - if (limit) { - findOption.limit = limit - } - if (page && limit) { - findOption.offset = page * limit - } + const models = ctx.fs.dc.models; + try { + const { userId, token } = ctx.fs.api + const { limit, page, orderBy, orderDirection, keyword, venderId } = ctx.query + let findOption = { + attributes: { exclude: ['delete'] }, + where: { + createUserId: userId, + delete: false, + }, + order: [ + [orderBy || 'id', orderDirection || 'DESC'] + ] + } + if (limit) { + findOption.limit = limit + } + if (page && limit) { + findOption.offset = page * limit + } + if (keyword) { + findOption.where.name = { $like: `%${keyword}%` } + } + if (venderId) { + findOption.where.venderId = venderId + } - const res = await models.Nvr.findAll(findOption) - const total = await models.Nvr.count() + const res = await models.Nvr.findAll(findOption) + const total = await models.Nvr.count({ + where: findOption.where + }) - ctx.status = 200; - ctx.body = { - total: total, - data: res - } - } catch (error) { - ctx.fs.logger.error(`path: ${ctx.path}, error: ${error}`); - ctx.status = 400; - ctx.body = {} - } + ctx.status = 200; + ctx.body = { + total: total, + data: res + } + } catch (error) { + ctx.fs.logger.error(`path: ${ctx.path}, error: ${error}`); + ctx.status = 400; + ctx.body = {} + } } async function del (ctx, next) { - try { - const models = ctx.fs.dc.models; - const { nvrId } = ctx.params + const transaction = await ctx.fs.dc.orm.transaction(); + try { + const models = ctx.fs.dc.models; + const { userId, token } = ctx.fs.api + const { nvrId } = ctx.params - await models.Nvr.destroy({ - where: { - id: nvrId - } - }) + await models.Nvr.destroy({ + where: { + id: nvrId + }, + transaction + }) + + const cameraRes = await models.Camera.findAll({ + where: { + nvrId + } + }) + + const cameraIds = cameraRes.map(c => c.id) + + await models.Camera.destroy({ + where: { + nvrId, + } + }) + + await ctx.app.fs.axyRequest.delete('vcmp/camera/project', { query: { token, cameraId: cameraIds.join(',') } }) - ctx.status = 204; - } catch (error) { - ctx.fs.logger.error(`path: ${ctx.path}, error: ${error}`); - ctx.status = 400; - ctx.body = {} - } + 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 = {} + } } module.exports = { - edit, - get, - del, + edit, + get, + del, }; \ No newline at end of file diff --git a/code/VideoAccess-VCMP/api/app/lib/index.js b/code/VideoAccess-VCMP/api/app/lib/index.js index 96b161e..0ad68f8 100644 --- a/code/VideoAccess-VCMP/api/app/lib/index.js +++ b/code/VideoAccess-VCMP/api/app/lib/index.js @@ -3,9 +3,9 @@ const routes = require('./routes'); const redisConnect = require('./service/redis') const socketConect = require('./service/socket') +const paasRequest = require('./service/paasRequest'); const authenticator = require('./middlewares/authenticator'); // const apiLog = require('./middlewares/api-log'); -const businessRest = require('./middlewares/business-rest'); module.exports.entry = function (app, router, opts) { app.fs.logger.log('info', '[FS-AUTH]', 'Inject auth and api mv into router.'); @@ -18,8 +18,12 @@ module.exports.entry = function (app, router, opts) { redisConnect(app, opts) socketConect(app, opts) + // 实例其他平台请求方法 + paasRequest(app, opts) + router.use(authenticator(app, opts)); - // router.use(businessRest(app, router, opts)); + + // 日志记录 // router.use(apiLog(app, opts)); router = routes(app, router, opts); diff --git a/code/VideoAccess-VCMP/api/app/lib/middlewares/api-log.js b/code/VideoAccess-VCMP/api/app/lib/middlewares/api-log.js index 12d256c..fb17f66 100644 --- a/code/VideoAccess-VCMP/api/app/lib/middlewares/api-log.js +++ b/code/VideoAccess-VCMP/api/app/lib/middlewares/api-log.js @@ -71,7 +71,7 @@ function factory(app, opts) { partition: 0 }]; - await sendToEsAsync(producer, payloads); + // await sendToEsAsync(producer, payloads); } catch (e) { ctx.fs.logger.error(`日志记录失败: ${e}`); diff --git a/code/VideoAccess-VCMP/api/app/lib/middlewares/authenticator.js b/code/VideoAccess-VCMP/api/app/lib/middlewares/authenticator.js index 8399456..53e8c5b 100644 --- a/code/VideoAccess-VCMP/api/app/lib/middlewares/authenticator.js +++ b/code/VideoAccess-VCMP/api/app/lib/middlewares/authenticator.js @@ -94,7 +94,6 @@ let isResourceAvailable = function (resources, options) { let authCode = null; // authorize user by authorization attribute const { authAttr, method, path } = options; - console.log(resources, options) for (let prop in authAttr) { let keys = []; let re = pathToRegexp(prop.replace(/\:[A-Za-z_\-]+\b/g, '(\\d+)'), keys); diff --git a/code/VideoAccess-VCMP/api/app/lib/middlewares/business-rest.js b/code/VideoAccess-VCMP/api/app/lib/middlewares/business-rest.js deleted file mode 100644 index d9542aa..0000000 --- a/code/VideoAccess-VCMP/api/app/lib/middlewares/business-rest.js +++ /dev/null @@ -1,50 +0,0 @@ -'use strict'; - - const request = require('superagent'); -const buildUrl = (url,token) => { - let connector = url.indexOf('?') === -1 ? '?' : '&'; - return `${url}${connector}token=${token}`; -}; - - function factory(app, router, opts) { - return async function (ctx, next) { - - const token = ctx.fs.api.token; - - //console.log(username,password) - const req = { - get: (url, query) => { - return request - .get(buildUrl(url,token)) - .query(query) - }, - post: (url, data, query) => { - return request - .post(buildUrl(url,token)) - .query(query) - //.set('Content-Type', 'application/json') - .send(data); - }, - - put: (url, data) => { - return request - .put(buildUrl(url,token)) - //.set('Content-Type', 'application/json') - .send(data); - }, - - delete: (url) => { - return request - .del(buildUrl(url,token)) - }, - }; - - app.business = app.business || {}; - app.business.request = req; - - await next(); - }; - } - - module.exports = factory; - \ No newline at end of file diff --git a/code/VideoAccess-VCMP/api/app/lib/models/camera.js b/code/VideoAccess-VCMP/api/app/lib/models/camera.js index 233e2e4..cbdcedb 100644 --- a/code/VideoAccess-VCMP/api/app/lib/models/camera.js +++ b/code/VideoAccess-VCMP/api/app/lib/models/camera.js @@ -2,256 +2,265 @@ 'use strict'; module.exports = dc => { - const DataTypes = dc.ORM; - const sequelize = dc.orm; - const Camera = sequelize.define("camera", { - id: { - type: DataTypes.INTEGER, - allowNull: false, - defaultValue: null, - comment: null, - primaryKey: true, - field: "id", - autoIncrement: true, - unique: "camera_id_uindex" - }, - type: { - type: DataTypes.STRING, - allowNull: false, - defaultValue: null, - comment: "设备类型:yingshi - 萤石;nvr - NVR摄像头;ipc - IPC 网络摄像头;cascade - 级联摄像头", - primaryKey: false, - field: "type", - autoIncrement: false - }, - name: { - type: DataTypes.STRING, - allowNull: true, - defaultValue: null, - comment: "设备名称/安装位置", - primaryKey: false, - field: "name", - autoIncrement: false - }, - channelName: { - type: DataTypes.STRING, - allowNull: true, - defaultValue: null, - comment: "通道名称", - primaryKey: false, - field: "channel_name", - autoIncrement: false - }, - externalDomain: { - type: DataTypes.STRING, - allowNull: true, - defaultValue: null, - comment: "外域名称", - primaryKey: false, - field: "external_domain", - autoIncrement: false - }, - rtmp: { - type: DataTypes.STRING, - allowNull: true, - defaultValue: null, - comment: null, - primaryKey: false, - field: "rtmp", - autoIncrement: false - }, - serialNo: { - type: DataTypes.STRING, - allowNull: true, - defaultValue: null, - comment: "设备编号", - primaryKey: false, - field: "serial_no", - autoIncrement: false - }, - cloudControl: { - type: DataTypes.BOOLEAN, - allowNull: true, - defaultValue: null, - comment: "云台控制", - primaryKey: false, - field: "cloud_control", - autoIncrement: false - }, - highDefinition: { - type: DataTypes.BOOLEAN, - allowNull: true, - defaultValue: null, - comment: "高清支持", - primaryKey: false, - field: "high_definition", - autoIncrement: false - }, - voice: { - type: DataTypes.BOOLEAN, - allowNull: true, - defaultValue: null, - comment: "语音对讲支持", - primaryKey: false, - field: "voice", - autoIncrement: false - }, - memoryCard: { - type: DataTypes.STRING, - allowNull: true, - defaultValue: null, - comment: "内存卡容量", - primaryKey: false, - field: "memory_card", - autoIncrement: false - }, - venderId: { - type: DataTypes.INTEGER, - allowNull: true, - defaultValue: null, - comment: "设备厂商id", - primaryKey: false, - field: "vender_id", - autoIncrement: false, - references: { - key: "id", - model: "vender" + const DataTypes = dc.ORM; + const sequelize = dc.orm; + const Camera = sequelize.define("camera", { + id: { + type: DataTypes.INTEGER, + allowNull: false, + defaultValue: null, + comment: null, + primaryKey: true, + field: "id", + autoIncrement: true, + unique: "camera_id_uindex" + }, + type: { + type: DataTypes.STRING, + allowNull: false, + defaultValue: null, + comment: "设备类型:yingshi - 萤石;nvr - NVR摄像头;ipc - IPC 网络摄像头;cascade - 级联摄像头", + primaryKey: false, + field: "type", + autoIncrement: false + }, + name: { + type: DataTypes.STRING, + allowNull: true, + defaultValue: null, + comment: "设备名称/安装位置", + primaryKey: false, + field: "name", + autoIncrement: false + }, + channelName: { + type: DataTypes.STRING, + allowNull: true, + defaultValue: null, + comment: "通道名称", + primaryKey: false, + field: "channel_name", + autoIncrement: false + }, + externalDomain: { + type: DataTypes.STRING, + allowNull: true, + defaultValue: null, + comment: "外域名称", + primaryKey: false, + field: "external_domain", + autoIncrement: false + }, + rtmp: { + type: DataTypes.STRING, + allowNull: true, + defaultValue: null, + comment: null, + primaryKey: false, + field: "rtmp", + autoIncrement: false + }, + serialNo: { + type: DataTypes.STRING, + allowNull: true, + defaultValue: null, + comment: "设备编号", + primaryKey: false, + field: "serial_no", + autoIncrement: false + }, + cloudControl: { + type: DataTypes.BOOLEAN, + allowNull: true, + defaultValue: null, + comment: "云台控制", + primaryKey: false, + field: "cloud_control", + autoIncrement: false + }, + highDefinition: { + type: DataTypes.BOOLEAN, + allowNull: true, + defaultValue: null, + comment: "高清支持", + primaryKey: false, + field: "high_definition", + autoIncrement: false + }, + voice: { + type: DataTypes.BOOLEAN, + allowNull: true, + defaultValue: null, + comment: "语音对讲支持", + primaryKey: false, + field: "voice", + autoIncrement: false + }, + memoryCard: { + type: DataTypes.STRING, + allowNull: true, + defaultValue: null, + comment: "内存卡容量", + primaryKey: false, + field: "memory_card", + autoIncrement: false + }, + venderId: { + type: DataTypes.INTEGER, + allowNull: true, + defaultValue: null, + comment: "设备厂商id", + primaryKey: false, + field: "vender_id", + autoIncrement: false, + references: { + key: "id", + model: "vender" + } + }, + cascadeType: { + type: DataTypes.STRING, + allowNull: true, + defaultValue: null, + comment: "级联方式:up - 上级联;down - 下级联", + primaryKey: false, + field: "cascade_type", + autoIncrement: false + }, + sip: { + type: DataTypes.STRING, + allowNull: true, + defaultValue: null, + comment: null, + primaryKey: false, + field: "sip", + autoIncrement: false + }, + longitude: { + type: DataTypes.DOUBLE, + allowNull: true, + defaultValue: null, + comment: "经度", + primaryKey: false, + field: "longitude", + autoIncrement: false + }, + latitude: { + type: DataTypes.DOUBLE, + allowNull: true, + defaultValue: null, + comment: "维度", + primaryKey: false, + field: "latitude", + autoIncrement: false + }, + forbidden: { + type: DataTypes.BOOLEAN, + allowNull: false, + defaultValue: null, + comment: "是否禁用", + primaryKey: false, + field: "forbidden", + autoIncrement: false + }, + createTime: { + type: DataTypes.DATE, + allowNull: false, + defaultValue: null, + comment: null, + primaryKey: false, + field: "create_time", + autoIncrement: false + }, + recycleTime: { + type: DataTypes.DATE, + allowNull: true, + defaultValue: null, + comment: "放入回收站时间", + primaryKey: false, + field: "recycle_time", + autoIncrement: false + }, + delete: { + type: DataTypes.BOOLEAN, + allowNull: false, + defaultValue: null, + comment: "是否彻底删除", + primaryKey: false, + field: "delete", + autoIncrement: false + }, + createUserId: { + type: DataTypes.INTEGER, + allowNull: false, + defaultValue: null, + comment: null, + primaryKey: false, + field: "create_user_id", + autoIncrement: false + }, + nvrId: { + type: DataTypes.INTEGER, + allowNull: true, + defaultValue: null, + comment: null, + primaryKey: false, + field: "nvr_id", + autoIncrement: false, + references: { + key: "id", + model: "nvr" + } + }, + model: { + type: DataTypes.STRING, + allowNull: true, + defaultValue: null, + comment: "型号", + primaryKey: false, + field: "model", + autoIncrement: false + }, + kindId: { + type: DataTypes.INTEGER, + allowNull: true, + defaultValue: null, + comment: null, + primaryKey: false, + field: "kind_id", + autoIncrement: false, + references: { + key: "id", + model: "cameraKind" + } + }, + abilityId: { + type: DataTypes.INTEGER, + allowNull: true, + defaultValue: null, + comment: null, + primaryKey: false, + field: "ability_id", + autoIncrement: false, + references: { + key: "id", + model: "cameraAbility" + } } - }, - cascadeType: { - type: DataTypes.STRING, - allowNull: true, - defaultValue: null, - comment: "级联方式:up - 上级联;down - 下级联", - primaryKey: false, - field: "cascade_type", - autoIncrement: false - }, - sip: { - type: DataTypes.STRING, - allowNull: true, - defaultValue: null, - comment: null, - primaryKey: false, - field: "sip", - autoIncrement: false - }, - longitude: { - type: DataTypes.DOUBLE, - allowNull: true, - defaultValue: null, - comment: "经度", - primaryKey: false, - field: "longitude", - autoIncrement: false - }, - latitude: { - type: DataTypes.DOUBLE, - allowNull: true, - defaultValue: null, - comment: "维度", - primaryKey: false, - field: "latitude", - autoIncrement: false - }, - forbidden: { - type: DataTypes.BOOLEAN, - allowNull: false, - defaultValue: null, - comment: "是否禁用", - primaryKey: false, - field: "forbidden", - autoIncrement: false - }, - createTime: { - type: DataTypes.DATE, - allowNull: false, - defaultValue: null, - comment: null, - primaryKey: false, - field: "create_time", - autoIncrement: false - }, - recycleTime: { - type: DataTypes.DATE, - allowNull: true, - defaultValue: null, - comment: "放入回收站时间", - primaryKey: false, - field: "recycle_time", - autoIncrement: false - }, - delete: { - type: DataTypes.BOOLEAN, - allowNull: false, - defaultValue: null, - comment: "是否彻底删除", - primaryKey: false, - field: "delete", - autoIncrement: false - }, - createUserId: { - type: DataTypes.INTEGER, - allowNull: false, - defaultValue: null, - comment: null, - primaryKey: false, - field: "create_user_id", - autoIncrement: false - }, - nvrId: { - type: DataTypes.INTEGER, - allowNull: true, - defaultValue: null, - comment: null, - primaryKey: false, - field: "nvr_id", - autoIncrement: false, - references: { - key: "id", - model: "nvr" - } - }, - model: { - type: DataTypes.STRING, - allowNull: true, - defaultValue: null, - comment: "型号", - primaryKey: false, - field: "model", - autoIncrement: false - }, - kindId: { - type: DataTypes.INTEGER, - allowNull: true, - defaultValue: null, - comment: null, - primaryKey: false, - field: "kind_id", - autoIncrement: false, - references: { - key: "id", - model: "cameraKind" - } - }, - abilityId: { - type: DataTypes.INTEGER, - allowNull: true, - defaultValue: null, - comment: null, - primaryKey: false, - field: "ability_id", - autoIncrement: false, - references: { - key: "id", - model: "cameraAbility" - } - } - }, { - tableName: "camera", - comment: "", - indexes: [] - }); - dc.models.Camera = Camera; - return Camera; + }, { + tableName: "camera", + comment: "", + indexes: [] + }); + dc.models.Camera = Camera; + + const CameraKind = dc.models.CameraKind; + Camera.belongsTo(CameraKind, { foreignKey: 'kindId', targetKey: 'id' }); + CameraKind.hasMany(Camera, { foreignKey: 'kindId', sourceKey: 'id' }); + + const CameraAbility = dc.models.CameraAbility; + Camera.belongsTo(CameraAbility, { foreignKey: 'abilityId', targetKey: 'id' }); + CameraAbility.hasMany(Camera, { foreignKey: 'abilityId', sourceKey: 'id' }); + + return Camera; }; \ No newline at end of file diff --git a/code/VideoAccess-VCMP/api/app/lib/models/vender.js b/code/VideoAccess-VCMP/api/app/lib/models/vender.js index 92e5474..f74bc23 100644 --- a/code/VideoAccess-VCMP/api/app/lib/models/vender.js +++ b/code/VideoAccess-VCMP/api/app/lib/models/vender.js @@ -29,6 +29,12 @@ module.exports = dc => { comment: "", indexes: [] }); + + const Camera = dc.models.Camera; + Camera.belongsTo(Vender, { foreignKey: 'venderId', targetKey: 'id' }); + Vender.hasMany(Camera, { foreignKey: 'venderId', sourceKey: 'id' }); + dc.models.Vender = Vender; + return Vender; }; \ No newline at end of file diff --git a/code/VideoAccess-VCMP/api/app/lib/routes/camera/index.js b/code/VideoAccess-VCMP/api/app/lib/routes/camera/index.js new file mode 100644 index 0000000..931e683 --- /dev/null +++ b/code/VideoAccess-VCMP/api/app/lib/routes/camera/index.js @@ -0,0 +1,17 @@ +'use strict'; + +const camera = require('../../controllers/camera'); + +module.exports = function (app, router, opts) { + app.fs.api.logAttr['GET/camera/project'] = { content: '获取摄像头列表及项目绑定信息', visible: false }; + router.get('/camera/project', camera.getCameraProject); + + app.fs.api.logAttr['GET/camera'] = { content: '获取摄像头信息', visible: false }; + router.get('/camera', camera.getCamera); + + app.fs.api.logAttr['PUT/camera/banned'] = { content: '禁用摄像头', visible: false }; + router.put('/camera/banned', camera.banned); + + app.fs.api.logAttr['DEL/camera'] = { content: '删除摄像头', visible: false }; + router.delete('/camera', camera.del); +}; diff --git a/code/VideoAccess-VCMP/api/app/lib/service/paasRequest.js b/code/VideoAccess-VCMP/api/app/lib/service/paasRequest.js new file mode 100644 index 0000000..5ab6678 --- /dev/null +++ b/code/VideoAccess-VCMP/api/app/lib/service/paasRequest.js @@ -0,0 +1,66 @@ +'use strict'; +const request = require('superagent') + +class paasRequest { + constructor(root, { query = {} } = {}) { + this.root = root; + this.query = query + } + + #buildUrl = (url) => { + return `${this.root}/${url}`; + } + + #resultHandler = (resolve, reject) => { + return (err, res) => { + if (err) { + reject(err); + } else { + resolve(res.body); + } + }; + } + + get = (url, { query = {}, header = {} } = {}) => { + return new Promise((resolve, reject) => { + request.get(this.#buildUrl(url)).set(header).query(Object.assign(query, this.query)).end(this.#resultHandler(resolve, reject)); + }) + } + + post = (url, { data = {}, query = {}, header = {} } = {}) => { + return new Promise((resolve, reject) => { + request.post(this.#buildUrl(url)).set(header).query(Object.assign(query, this.query)).send(data).end(this.#resultHandler(resolve, reject)); + }) + } + + put = (url, { data = {}, header = {}, query = {}, } = {}) => { + return new Promise((resolve, reject) => { + request.put(this.#buildUrl(url)).set(header).query(Object.assign(query, this.query)).send(data).end(this.#resultHandler(resolve, reject)); + }) + } + + delete = (url, { header = {}, query = {} } = {}) => { + return new Promise((resolve, reject) => { + request.delete(this.#buildUrl(url)).set(header).query(Object.assign(query, this.query)).end(this.#resultHandler(resolve, reject)); + }) + } +} + +function factory (app, opts) { + if (opts.pssaRequest) { + try { + for (let r of opts.pssaRequest) { + if (r.name && r.root) { + app.fs[r.name] = new paasRequest(r.root, { ...(r.params || {}) }) + } else { + throw 'opts.pssaRequest 参数错误!' + } + } + } catch (error) { + console.error(error) + process.exit(-1); + } + } +} + +module.exports = factory; diff --git a/code/VideoAccess-VCMP/api/app/lib/service/redis.js b/code/VideoAccess-VCMP/api/app/lib/service/redis.js index a9b9d52..4fc0ff4 100644 --- a/code/VideoAccess-VCMP/api/app/lib/service/redis.js +++ b/code/VideoAccess-VCMP/api/app/lib/service/redis.js @@ -1,7 +1,6 @@ 'use strict'; // https://github.com/luin/ioredis const redis = require("ioredis") -const moment = require('moment') module.exports = async function factory (app, opts) { let client = new redis(opts.redis.port, opts.redis.host); diff --git a/code/VideoAccess-VCMP/api/config.js b/code/VideoAccess-VCMP/api/config.js index 084a131..149666d 100644 --- a/code/VideoAccess-VCMP/api/config.js +++ b/code/VideoAccess-VCMP/api/config.js @@ -14,6 +14,9 @@ args.option(['f', 'fileHost'], '文件中心本地化存储: WebApi 服务器地 args.option('redisHost', 'redisHost'); args.option('redisPort', 'redisPort'); args.option('redisPswd', 'redisPassword'); +args.option('axyApiUrl', 'axyApiUrl'); // 安心云 api +args.option('godUrl', '高德地图API请求地址'); +args.option('godKey', '高德地图API key'); const flags = args.parse(process.argv); @@ -24,92 +27,108 @@ const IOTA_REDIS_SERVER_HOST = process.env.IOTA_REDIS_SERVER_HOST || flags.redis const IOTA_REDIS_SERVER_PORT = process.env.IOTA_REDIS_SERVER_PORT || flags.redisPort || "6379";//redis 端口 const IOTA_REDIS_SERVER_PWD = process.env.IOTA_REDIS_SERVER_PWD || flags.redisPswd || "";//redis 密码 -if (!IOT_VIDEO_ACCESS_DB || !IOTA_REDIS_SERVER_HOST || !IOTA_REDIS_SERVER_PORT) { - console.log('缺少启动参数,异常退出'); - args.showHelp(); - process.exit(-1); +const AXY_API_URL = process.env.AXY_API_URL || flags.axyApiUrl; +const GOD_URL = process.env.GOD_URL || flags.godUrl || 'https://restapi.amap.com/v3'; +const GOD_KEY = process.env.GOD_KEY || flags.godKey; + +if (!IOT_VIDEO_ACCESS_DB || !IOTA_REDIS_SERVER_HOST || !IOTA_REDIS_SERVER_PORT || !GOD_KEY) { + console.log('缺少启动参数,异常退出'); + args.showHelp(); + process.exit(-1); } const product = { - port: flags.port || 8080, - staticDirs: ['static'], - mws: [ - { - entry: require('@fs/attachment').entry, - opts: { - local: { - origin: IOT_VIDEO_ACCESS_LOCAL_SVR_ORIGIN || `http://localhost:${flags.port || 8080}`, - rootPath: 'static', - childPath: 'upload', - }, - maxSize: 104857600, // 100M - } - }, { - entry: require('./app').entry, - opts: { - exclude: [], // 不做认证的路由,也可以使用 exclude: ["*"] 跳过所有路由 - redis: { - host: IOTA_REDIS_SERVER_HOST, - port: IOTA_REDIS_SERVER_PORT, - pwd: IOTA_REDIS_SERVER_PWD - }, - } - } - ], - dc: { - url: IOT_VIDEO_ACCESS_DB, - opts: { - pool: { - max: 80, - min: 10, - idle: 10000 + port: flags.port || 8080, + staticDirs: ['static'], + mws: [ + { + entry: require('@fs/attachment').entry, + opts: { + local: { + origin: IOT_VIDEO_ACCESS_LOCAL_SVR_ORIGIN || `http://localhost:${flags.port || 8080}`, + rootPath: 'static', + childPath: 'upload', }, - define: { - freezeTableName: true, // 固定表名 - timestamps: false // 不含列 "createAt"/"updateAt"/"DeleteAt" + maxSize: 104857600, // 100M + } + }, { + entry: require('./app').entry, + opts: { + exclude: [], // 不做认证的路由,也可以使用 exclude: ["*"] 跳过所有路由 + redis: { + host: IOTA_REDIS_SERVER_HOST, + port: IOTA_REDIS_SERVER_PORT, + pwd: IOTA_REDIS_SERVER_PWD }, - timezone: '+08:00', - logging: false - }, - models: [require('./app').models] - }, - logger: { - level: 'info', - json: false, - filename: path.join(__dirname, 'log', 'runtime.log'), - colorize: false, - maxsize: 1024 * 1024 * 5, - rotationFormat: false, - zippedArchive: true, - maxFiles: 10, - prettyPrint: true, - label: '', - timestamp: () => moment().format('YYYY-MM-DD HH:mm:ss.SSS'), - eol: os.EOL, - tailable: true, - depth: null, - showLevel: true, - maxRetries: 1 - } + pssaRequest: [{ // name 会作为一个 request 出现在 ctx.app.fs + name: 'axyRequest', + root: AXY_API_URL + }, { + name: 'godRequest', + root: GOD_URL, + params: { + query: { + key: GOD_KEY + } + } + },] + } + } + ], + dc: { + url: IOT_VIDEO_ACCESS_DB, + opts: { + pool: { + max: 80, + min: 10, + idle: 10000 + }, + define: { + freezeTableName: true, // 固定表名 + timestamps: false // 不含列 "createAt"/"updateAt"/"DeleteAt" + }, + timezone: '+08:00', + logging: false + }, + models: [require('./app').models] + }, + logger: { + level: 'info', + json: false, + filename: path.join(__dirname, 'log', 'runtime.log'), + colorize: false, + maxsize: 1024 * 1024 * 5, + rotationFormat: false, + zippedArchive: true, + maxFiles: 10, + prettyPrint: true, + label: '', + timestamp: () => moment().format('YYYY-MM-DD HH:mm:ss.SSS'), + eol: os.EOL, + tailable: true, + depth: null, + showLevel: true, + maxRetries: 1 + } }; const development = { - port: product.port, - staticDirs: product.staticDirs, - mws: product.mws, - dc: product.dc, - logger: product.logger + port: product.port, + staticDirs: product.staticDirs, + mws: product.mws, + dc: product.dc, + logger: product.logger }; if (dev) { - // mws - for (let mw of development.mws) { - // if (mw.opts.exclude) mw.opts.exclude = ['*']; // 使用 ['*'] 跳过所有路由 - } - // logger - development.logger.filename = path.join(__dirname, 'log', 'development.log'); - development.logger.level = 'debug'; - development.dc.opts.logging = console.log; + // mws + for (let mw of development.mws) { + // if (mw.opts.exclude) mw.opts.exclude = ['*']; // 使用 ['*'] 跳过所有路由 + } + // logger + development.logger.filename = path.join(__dirname, 'log', 'development.log'); + development.logger.level = 'debug'; + development.dc.opts.logging = console.log; } module.exports = dev ? development : product; diff --git a/code/VideoAccess-VCMP/web/.vscode/extensions.json b/code/VideoAccess-VCMP/web/.vscode/extensions.json new file mode 100644 index 0000000..0925499 --- /dev/null +++ b/code/VideoAccess-VCMP/web/.vscode/extensions.json @@ -0,0 +1,5 @@ +{ + "recommendations": [ + "formulahendry.code-runner" + ] +} \ No newline at end of file diff --git a/code/VideoAccess-VCMP/web/client/assets/images/background/backGround.png b/code/VideoAccess-VCMP/web/client/assets/images/background/backGround.png index a01c0fe..e89d8f2 100644 Binary files a/code/VideoAccess-VCMP/web/client/assets/images/background/backGround.png and b/code/VideoAccess-VCMP/web/client/assets/images/background/backGround.png differ diff --git a/code/VideoAccess-VCMP/web/client/assets/images/background/camera.png b/code/VideoAccess-VCMP/web/client/assets/images/background/camera.png new file mode 100644 index 0000000..a16166d Binary files /dev/null and b/code/VideoAccess-VCMP/web/client/assets/images/background/camera.png differ diff --git a/code/VideoAccess-VCMP/web/client/assets/images/background/copy1.png b/code/VideoAccess-VCMP/web/client/assets/images/background/copy1.png new file mode 100644 index 0000000..80df7ff Binary files /dev/null and b/code/VideoAccess-VCMP/web/client/assets/images/background/copy1.png differ diff --git a/code/VideoAccess-VCMP/web/client/assets/images/background/copy2.png b/code/VideoAccess-VCMP/web/client/assets/images/background/copy2.png new file mode 100644 index 0000000..77b9867 Binary files /dev/null and b/code/VideoAccess-VCMP/web/client/assets/images/background/copy2.png differ diff --git a/code/VideoAccess-VCMP/web/client/assets/images/background/header.png b/code/VideoAccess-VCMP/web/client/assets/images/background/header.png new file mode 100644 index 0000000..59900ca Binary files /dev/null and b/code/VideoAccess-VCMP/web/client/assets/images/background/header.png differ diff --git a/code/VideoAccess-VCMP/web/client/assets/images/background/logo.png b/code/VideoAccess-VCMP/web/client/assets/images/background/logo.png new file mode 100644 index 0000000..a81edce Binary files /dev/null and b/code/VideoAccess-VCMP/web/client/assets/images/background/logo.png differ diff --git a/code/VideoAccess-VCMP/web/client/assets/images/background/notice.png b/code/VideoAccess-VCMP/web/client/assets/images/background/notice.png new file mode 100644 index 0000000..e00a54f Binary files /dev/null and b/code/VideoAccess-VCMP/web/client/assets/images/background/notice.png differ diff --git a/code/VideoAccess-VCMP/web/client/assets/images/background/projectIcon0.png b/code/VideoAccess-VCMP/web/client/assets/images/background/projectIcon0.png new file mode 100644 index 0000000..837bd5b Binary files /dev/null and b/code/VideoAccess-VCMP/web/client/assets/images/background/projectIcon0.png differ diff --git a/code/VideoAccess-VCMP/web/client/assets/images/background/projectIcon1.png b/code/VideoAccess-VCMP/web/client/assets/images/background/projectIcon1.png new file mode 100644 index 0000000..0999200 Binary files /dev/null and b/code/VideoAccess-VCMP/web/client/assets/images/background/projectIcon1.png differ diff --git a/code/VideoAccess-VCMP/web/client/assets/images/background/projectIcon2.png b/code/VideoAccess-VCMP/web/client/assets/images/background/projectIcon2.png new file mode 100644 index 0000000..ebae1c1 Binary files /dev/null and b/code/VideoAccess-VCMP/web/client/assets/images/background/projectIcon2.png differ diff --git a/code/VideoAccess-VCMP/web/client/assets/images/background/projectIcon3.png b/code/VideoAccess-VCMP/web/client/assets/images/background/projectIcon3.png new file mode 100644 index 0000000..46072ed Binary files /dev/null and b/code/VideoAccess-VCMP/web/client/assets/images/background/projectIcon3.png differ diff --git a/code/VideoAccess-VCMP/web/client/assets/images/background/sewage_camera1.png b/code/VideoAccess-VCMP/web/client/assets/images/background/sewage_camera1.png new file mode 100644 index 0000000..e272df9 Binary files /dev/null and b/code/VideoAccess-VCMP/web/client/assets/images/background/sewage_camera1.png differ diff --git a/code/VideoAccess-VCMP/web/client/assets/images/background/sewage_camera2.png b/code/VideoAccess-VCMP/web/client/assets/images/background/sewage_camera2.png new file mode 100644 index 0000000..67abdbe Binary files /dev/null and b/code/VideoAccess-VCMP/web/client/assets/images/background/sewage_camera2.png differ diff --git a/code/VideoAccess-VCMP/web/client/assets/images/background/store1.png b/code/VideoAccess-VCMP/web/client/assets/images/background/store1.png new file mode 100644 index 0000000..84674e2 Binary files /dev/null and b/code/VideoAccess-VCMP/web/client/assets/images/background/store1.png differ diff --git a/code/VideoAccess-VCMP/web/client/assets/images/background/store2.png b/code/VideoAccess-VCMP/web/client/assets/images/background/store2.png new file mode 100644 index 0000000..1ccdbb9 Binary files /dev/null and b/code/VideoAccess-VCMP/web/client/assets/images/background/store2.png differ diff --git a/code/VideoAccess-VCMP/web/client/assets/images/background/straightline.png b/code/VideoAccess-VCMP/web/client/assets/images/background/straightline.png new file mode 100644 index 0000000..4caca7a Binary files /dev/null and b/code/VideoAccess-VCMP/web/client/assets/images/background/straightline.png differ diff --git a/code/VideoAccess-VCMP/web/client/src/layout/components/header/index.jsx b/code/VideoAccess-VCMP/web/client/src/layout/components/header/index.jsx index 457c815..684980d 100644 --- a/code/VideoAccess-VCMP/web/client/src/layout/components/header/index.jsx +++ b/code/VideoAccess-VCMP/web/client/src/layout/components/header/index.jsx @@ -1,47 +1,85 @@ -'use strict'; -import React from 'react'; -import { connect } from 'react-redux'; -import { Nav } from '@douyinfe/semi-ui'; +"use strict"; +import React from "react"; +import { connect } from "react-redux"; +import { Nav, Avatar, Dropdown } from "@douyinfe/semi-ui"; -const Header = props => { - const { dispatch, history, user, actions, socket } = props +const Header = (props) => { + const { dispatch, history, user, actions, socket } = props; - return ( -
-
-
- 飞尚物联 -
-
- }> - - - -
- - ) + return ( + <> +