diff --git a/api/.vscode/launch.json b/api/.vscode/launch.json index 08a8a22..0e17253 100644 --- a/api/.vscode/launch.json +++ b/api/.vscode/launch.json @@ -22,6 +22,8 @@ "-d postgres/example/10.8.30.160/30432", "-w https://smartwater.anxinyun.cn", "-a https://smartworksafety.anxinyun.cn", + "--yingshiKey 5d16a667e1c2423d9d0d634f781810b4", + "--yingshiSecret 0cc4e1ec4e6a53ea3dabeb09cd5f468b", "--tf http://91mogo.com/onecity/v5", "--axyApi https://openapi.anxinyun.cn/api/v1", "--axyPumpProject 1a271f12-52f2-4d16-8dad-ec0c92d3e0cc/03bzzdh/123456", // 泵站 diff --git a/api/app/lib/controllers/superScreen/fire.js b/api/app/lib/controllers/superScreen/fire.js index f39a986..9a11675 100644 --- a/api/app/lib/controllers/superScreen/fire.js +++ b/api/app/lib/controllers/superScreen/fire.js @@ -1,110 +1,262 @@ 'use strict'; -const request = require("superagent"); + +const request = require('superagent'); + const moment = require("moment"); -function getFireAlarmList(opts) { - return async function (ctx, next) { - const models = ctx.fs.dc.models; - let errMsg = { message: '获取消防告警失败' } - try { - const res = await models.FireAlarm.findAll(); - ctx.status = 200; - ctx.body = res; - } catch (error) { - ctx.fs.logger.error(`path: ${ctx.path}, error: ${error}`); - ctx.status = 400; - ctx.body = errMsg - } - } + +function getFireAlarmList (opts) { + return async function (ctx, next) { + const models = ctx.fs.dc.models; + let errMsg = { message: '获取消防告警失败' } + try { + const res = await models.FireAlarm.findAll(); + ctx.status = 200; + ctx.body = res; + } catch (error) { + ctx.fs.logger.error(`path: ${ctx.path}, error: ${error}`); + ctx.status = 400; + ctx.body = errMsg + } + } } // 新增消防告警 -function addAlarm(opts) { - return async function (ctx, next) { - const models = ctx.fs.dc.models; - try { - const body = ctx.request.body - await models.FireAlarm.create(body) - - ctx.status = 204; - ctx.body = { message: '新建消防告警成功' } - } catch (error) { - ctx.fs.logger.error(`path: ${ctx.path}, error: ${error}`); - ctx.status = 400; - ctx.body = { message: '新建消防告警失败' } - } - } +function addAlarm (opts) { + return async function (ctx, next) { + const models = ctx.fs.dc.models; + try { + const body = ctx.request.body + await models.FireAlarm.create(body) + + ctx.status = 204; + ctx.body = { message: '新建消防告警成功' } + } catch (error) { + ctx.fs.logger.error(`path: ${ctx.path}, error: ${error}`); + ctx.status = 400; + ctx.body = { message: '新建消防告警失败' } + } + } } // 修改消防告警 -function updateAlarm(opts) { - return async function (ctx, next) { - try { - const models = ctx.fs.dc.models; - const { id } = ctx.params; - const body = ctx.request.body; - await models.FireAlarm.update( - body, - { where: { id: id, } } - ) - ctx.status = 204; - ctx.body = { message: '修改消防告警成功' } - - } catch (error) { - ctx.fs.logger.error(`path: ${ctx.path}, error: ${error}`); - ctx.status = 400; - ctx.body = { message: '修改消防告警失败' } - } - } +function updateAlarm (opts) { + return async function (ctx, next) { + try { + const models = ctx.fs.dc.models; + const { id } = ctx.params; + const body = ctx.request.body; + await models.FireAlarm.update( + body, + { where: { id: id, } } + ) + ctx.status = 204; + ctx.body = { message: '修改消防告警成功' } + + } catch (error) { + ctx.fs.logger.error(`path: ${ctx.path}, error: ${error}`); + ctx.status = 400; + ctx.body = { message: '修改消防告警失败' } + } + } } + +function videoList (opts) { + return async function (ctx) { + try { + const { models, } = ctx.fs.dc; + const { app, yingshiTokenRes } = ctx + + let yingshiToken = '' + if (yingshiTokenRes && yingshiTokenRes.token && yingshiTokenRes.expire && moment().isBefore(moment(yingshiTokenRes.expire))) { + yingshiToken = yingshiTokenRes.token + } else { + const tokenRes = await app.fs.yingshiRequest.post(`lapp/token/get`, { + query: { + appKey: opts.yingshiKey, + appSecret: opts.yingshiSecret + } + }) + if (tokenRes.code == 200 && tokenRes.data) { + const { accessToken, expireTime } = tokenRes.data + + ctx.yingshiTokenRes = { + token: accessToken, + expire: expireTime + } + yingshiToken = accessToken + } else { + throw '未能获取进行萤石鉴权' + } + } + + // const deviceRes = await app.fs.yingshiRequest.post(`lapp/device/list`, { + // query: { + // accessToken: yingshiToken, + // } + // }) + + ctx.status = 200; + + let deviceRes_ = [{ + deviceName: '楼前大桥', + deviceSerial: 'L48947105', + }, { + deviceName: '滁北大桥', + deviceSerial: 'L48947108', + }, { + deviceName: '新联桥', + deviceSerial: 'L48947110', + }, { + deviceName: '湾庄线', + deviceSerial: 'L48947112', + }, { + deviceName: '新土线', + deviceSerial: 'AA9943808', + }, { + deviceName: '东文大桥', + deviceSerial: 'L48947087', + }, { + deviceName: '莲姚线', + deviceSerial: 'L48947082', + }, { + deviceName: '荷漳公路', + deviceSerial: 'L48947109', + }, { + deviceName: '新武大桥', + deviceSerial: 'L48947086', + },] + + const deviceState = await Promise.all(deviceRes_.map(d => { + return app.fs.yingshiRequest.post(`lapp/device/info`, { + query: { + accessToken: yingshiToken, + deviceSerial: d.deviceSerial + } + }) + })) + + for (let d of deviceRes_) { + let corState = deviceState.find(item => item.code == 200 && item.data && item.data.deviceSerial == d.deviceSerial) + if (corState) { + d.status = corState.data.status + } else { + d.status = 0 + } + d.token = yingshiToken + } + + ctx.body = deviceRes_ + // || + // (deviceRes.data || []).map(item => { + // return { + // ...item, + // token: yingshiToken, + // } + // }) + } catch (error) { + ctx.fs.logger.error(`path: ${ctx.path}, error: error`); + ctx.status = 400; + ctx.body = { + message: typeof error == 'string' ? error : undefined + } + } + } +} + + +function getDetails (opts) { + return async function (ctx) { + try { + const res = await request.get('https://jiaotong.baidu.com/trafficindex/city/details/?cityCode=163') + + ctx.status = 200 + ctx.body = res.body || {} + + } catch (error) { + ctx.fs.logger.error(`path: ${ctx.path}, error: error`); + ctx.status = 400; + ctx.body = { + message: '获取南昌市道路数据失败' + } + } + } +} + + // 获取消防设备 -function getFireDevice(opts) { - return async function (ctx, next) { - let rslt = {}; - try { - let url = `${opts.tfApi}/device/alarm/statistic?_timeStamp=${new Date().getTime()}`; - const res = (await request.get(url).set("X-API-TOKEN", "9911510d-9dae-438d-9b6e-0545ef003c58")).body.data; - rslt = res.items; - ctx.status = 200; - ctx.body = rslt; - } catch (error) { - ctx.fs.logger.error(`path: ${ctx.path}, error: ${error}`); - ctx.status = 400; - ctx.body = { message: '获取消防设备失败' } - } - } +function getFireDevice (opts) { + return async function (ctx, next) { + let rslt = {}; + try { + let url = `${opts.tfApi}/device/alarm/statistic?_timeStamp=${new Date().getTime()}`; + const res = (await request.get(url).set("X-API-TOKEN", "9911510d-9dae-438d-9b6e-0545ef003c58")).body.data; + rslt = res.items; + ctx.status = 200; + ctx.body = rslt; + } catch (error) { + ctx.fs.logger.error(`path: ${ctx.path}, error: ${error}`); + ctx.status = 400; + ctx.body = { message: '获取消防设备失败' } + } + } } // 获取火情趋势 -function getFireTrend(opts) { - return async function (ctx, next) { - let rslt = []; - try { - let url = `${opts.tfApi}/alarms/trend?key=1`; - const res = (await request.get(url).set("X-API-TOKEN", "9911510d-9dae-438d-9b6e-0545ef003c58")).body.data; - let start = moment().add(-6, 'day').startOf('day').valueOf(); - let end = moment().endOf('day').valueOf(); - res.map(item => { - const time = moment(item.time).valueOf(); - if (time >= start && time <= end) { - rslt.push({ time: item.time, count: item.val }) - } - }) - ctx.status = 200; - ctx.body = rslt; - } catch (error) { - ctx.fs.logger.error(`path: ${ctx.path}, error: ${error}`); - ctx.status = 400; - ctx.body = { message: '获取火情趋势失败' } - } - } +function getFireTrend (opts) { + return async function (ctx, next) { + let rslt = []; + try { + let url = `${opts.tfApi}/alarms/trend?key=1`; + const res = (await request.get(url).set("X-API-TOKEN", "9911510d-9dae-438d-9b6e-0545ef003c58")).body.data; + let start = moment().add(-6, 'day').startOf('day').valueOf(); + let end = moment().endOf('day').valueOf(); + res.map(item => { + const time = moment(item.time).valueOf(); + if (time >= start && time <= end) { + rslt.push({ time: item.time, count: item.val }) + } + }) + ctx.status = 200; + ctx.body = rslt; + } catch (error) { + ctx.fs.logger.error(`path: ${ctx.path}, error: ${error}`); + ctx.status = 400; + ctx.body = { message: '获取火情趋势失败' } + } + } +} + + +function getSurroundingConditions (opts) { + return async function (ctx) { + try { + + const { app, yingshiTokenRes } = ctx + const { center } = ctx.query; + const res = await app.fs.baiDu.get('/traffic/v1/around', { ak: opts.baiduAK, radius: 1000, center: center }) + + ctx.status = 200 + ctx.body = res.body || {} + + } catch (error) { + ctx.fs.logger.error(`path: ${ctx.path}, error: error`); + ctx.status = 400; + ctx.body = { + message: '获取南昌市道路数据失败' + } + } + } } module.exports = { - addAlarm, - updateAlarm, - getFireAlarmList, - getFireDevice, - getFireTrend + addAlarm, + updateAlarm, + getFireAlarmList, + getFireDevice, + getFireTrend, + videoList, + getDetails, + getSurroundingConditions } \ No newline at end of file diff --git a/api/app/lib/middlewares/authenticator.js b/api/app/lib/middlewares/authenticator.js index 43a5531..11d2978 100644 --- a/api/app/lib/middlewares/authenticator.js +++ b/api/app/lib/middlewares/authenticator.js @@ -8,42 +8,42 @@ const util = require('util'); const moment = require('moment'); class ExcludesUrls { - constructor(opts) { - this.allUrls = undefined; - this.reload(opts); - } + constructor(opts) { + this.allUrls = undefined; + this.reload(opts); + } - sanitizePath (path) { - if (!path) return '/'; - const p = '/' + path.replace(/^\/+/i, '').replace(/\/+$/, '').replace(/\/{2,}/, '/'); - return p; - } + sanitizePath (path) { + if (!path) return '/'; + const p = '/' + path.replace(/^\/+/i, '').replace(/\/+$/, '').replace(/\/{2,}/, '/'); + return p; + } - reload (opts) { - // load all url - if (!this.allUrls) { - this.allUrls = opts; - let that = this; - this.allUrls.forEach(function (url, i, arr) { - if (typeof url === "string") { - url = { p: url, o: '*' }; - arr[i] = url; - } - const keys = []; - let eachPath = url.p; - url.p = (!eachPath || eachPath === '(.*)' || util.isRegExp(eachPath)) ? eachPath : that.sanitizePath(eachPath); - url.pregexp = pathToRegexp(eachPath, keys); - }); - } - } + reload (opts) { + // load all url + if (!this.allUrls) { + this.allUrls = opts; + let that = this; + this.allUrls.forEach(function (url, i, arr) { + if (typeof url === "string") { + url = { p: url, o: '*' }; + arr[i] = url; + } + const keys = []; + let eachPath = url.p; + url.p = (!eachPath || eachPath === '(.*)' || util.isRegExp(eachPath)) ? eachPath : that.sanitizePath(eachPath); + url.pregexp = pathToRegexp(eachPath, keys); + }); + } + } - isExcluded (path, method) { - return this.allUrls.some(function (url) { - return !url.auth - && url.pregexp.test(path) - && (url.o === '*' || url.o.indexOf(method) !== -1); - }); - } + isExcluded (path, method) { + return this.allUrls.some(function (url) { + return !url.auth + && url.pregexp.test(path) + && (url.o === '*' || url.o.indexOf(method) !== -1); + }); + } } /** @@ -53,106 +53,109 @@ class ExcludesUrls { * @param {*} method 当前request的method */ let isPathExcluded = function (opts, path, method) { - let excludeAll = Boolean(opts.exclude && opts.exclude.length && opts.exclude[0] == '*'); - let excludes = null; - if (!excludeAll) { - let excludeOpts = opts.exclude || []; - excludeOpts.push({ p: '/login', o: 'POST' }); - excludeOpts.push({ p: '/logout', o: 'PUT' }); - excludeOpts.push({ p: '/water/realstate', o: 'GET' }); - excludeOpts.push({ p: '/water/emergency', o: 'GET' }); - excludeOpts.push({ p: '/fire/alarm', o: 'GET' }); - excludeOpts.push({ p: '/fire/alarm', o: 'POST' }); - excludeOpts.push({ p: '/fire/alarm/:id', o: 'PUT' }); - excludeOpts.push({ p: '/fire/device', o: 'GET' }); - excludeOpts.push({ p: '/fire/trend', o: 'GET' }); - excludeOpts.push({ p: '/pumpStatus/:structId', o: 'GET' }); - - excludes = new ExcludesUrls(excludeOpts); - } - let excluded = excludeAll || excludes.isExcluded(path, method); - return excluded; + let excludeAll = Boolean(opts.exclude && opts.exclude.length && opts.exclude[0] == '*'); + let excludes = null; + if (!excludeAll) { + let excludeOpts = opts.exclude || []; + excludeOpts.push({ p: '/login', o: 'POST' }); + excludeOpts.push({ p: '/logout', o: 'PUT' }); + excludeOpts.push({ p: '/water/realstate', o: 'GET' }); + excludeOpts.push({ p: '/water/emergency', o: 'GET' }); + excludeOpts.push({ p: '/videoCenter/list', o: 'GET' }); + excludeOpts.push({ p: '/trafficindex/city/details', o: 'GET' }); + excludeOpts.push({ p: '/traffic/v1/around', o: 'GET' }); + excludeOpts.push({ p: '/fire/alarm', o: 'GET' }); + excludeOpts.push({ p: '/fire/alarm', o: 'POST' }); + excludeOpts.push({ p: '/fire/alarm/:id', o: 'PUT' }); + excludeOpts.push({ p: '/fire/device', o: 'GET' }); + excludeOpts.push({ p: '/fire/trend', o: 'GET' }); + excludeOpts.push({ p: '/pumpStatus/:structId', o: 'GET' }); + + excludes = new ExcludesUrls(excludeOpts); + } + let excluded = excludeAll || excludes.isExcluded(path, method); + return excluded; }; let authorizeToken = async function (ctx, token) { - let rslt = null; - const tokenFormatRegexp = /^(\{{0,1}([0-9a-fA-F]){8}-([0-9a-fA-F]){4}-([0-9a-fA-F]){4}-([0-9a-fA-F]){4}-([0-9a-fA-F]){12}\}{0,1})$/g; - if (token && tokenFormatRegexp.test(token)) { - try { + let rslt = null; + const tokenFormatRegexp = /^(\{{0,1}([0-9a-fA-F]){8}-([0-9a-fA-F]){4}-([0-9a-fA-F]){4}-([0-9a-fA-F]){4}-([0-9a-fA-F]){12}\}{0,1})$/g; + if (token && tokenFormatRegexp.test(token)) { + try { - const authorizeRes = await ctx.fs.dc.models.UserToken.findOne({ - where: { - token: token - } - }) - const { userInfo, expired } = authorizeRes; - - if (expired && moment().valueOf() <= moment(expired).valueOf()) { - rslt = { - 'authorized': userInfo.authorized, - 'resources': (userInfo || {}).resources || [], - }; - ctx.fs.api.userId = userInfo.id; - ctx.fs.api.userInfo = userInfo; - ctx.fs.api.token = token; + const authorizeRes = await ctx.fs.dc.models.UserToken.findOne({ + where: { + token: token } - } catch (err) { - const { error } = err.response || {}; - ctx.fs.logger.log('[anxinyun]', '[AUTH] failed', (error || {}).message || `cannot GET /users/${token}`); - } - } - return rslt; + }) + const { userInfo, expired } = authorizeRes; + + if (expired && moment().valueOf() <= moment(expired).valueOf()) { + rslt = { + 'authorized': userInfo.authorized, + 'resources': (userInfo || {}).resources || [], + }; + ctx.fs.api.userId = userInfo.id; + ctx.fs.api.userInfo = userInfo; + ctx.fs.api.token = token; + } + } catch (err) { + const { error } = err.response || {}; + ctx.fs.logger.log('[anxinyun]', '[AUTH] failed', (error || {}).message || `cannot GET /users/${token}`); + } + } + return rslt; }; let isResourceAvailable = function (resources, options) { - let authCode = null; - // authorize user by authorization attribute - const { authAttr, method, path } = options; - for (let prop in authAttr) { - let keys = []; - let re = pathToRegexp(prop.replace(/\:[A-Za-z_\-]+\b/g, '(\\d+)'), keys); - if (re.test(`${method}${path}`)) { - authCode = authAttr[prop]; - break; - } - } - return !authCode || (resources || []).some(code => code === authCode); + let authCode = null; + // authorize user by authorization attribute + const { authAttr, method, path } = options; + for (let prop in authAttr) { + let keys = []; + let re = pathToRegexp(prop.replace(/\:[A-Za-z_\-]+\b/g, '(\\d+)'), keys); + if (re.test(`${method}${path}`)) { + authCode = authAttr[prop]; + break; + } + } + return !authCode || (resources || []).some(code => code === authCode); }; function factory (app, opts) { - return async function auth (ctx, next) { - const { path, method, header, query } = ctx; - ctx.fs.logger.log('[AUTH] start', path, method); - ctx.fs.api = ctx.fs.api || {}; - ctx.fs.port = opts.port; - ctx.redis = app.redis; - ctx.redisTools = app.redisTools; - let error = null; - if (path) { - if (!isPathExcluded(opts, path, method)) { - const user = await authorizeToken(ctx, header.token || query.token); - if (user && user.authorized) { - // if (!isResourceAvailable(user.resources, { authAttr: app.fs.auth.authAttr, path, method })) { - // error = { status: 403, name: 'Forbidden' } - // } else { - // error = { status: 401, name: 'Unauthorized' } - // } - } else { - error = { status: 401, name: 'Unauthorized' } - } + return async function auth (ctx, next) { + const { path, method, header, query } = ctx; + ctx.fs.logger.log('[AUTH] start', path, method); + ctx.fs.api = ctx.fs.api || {}; + ctx.fs.port = opts.port; + ctx.redis = app.redis; + ctx.redisTools = app.redisTools; + let error = null; + if (path) { + if (!isPathExcluded(opts, path, method)) { + const user = await authorizeToken(ctx, header.token || query.token); + if (user && user.authorized) { + // if (!isResourceAvailable(user.resources, { authAttr: app.fs.auth.authAttr, path, method })) { + // error = { status: 403, name: 'Forbidden' } + // } else { + // error = { status: 401, name: 'Unauthorized' } + // } + } else { + error = { status: 401, name: 'Unauthorized' } } - } else { - error = { status: 401, name: 'Unauthorized' }; - } - if (error) { - ctx.fs.logger.log('[AUTH] failed', path, method); - ctx.status = error.status; - ctx.body = error.name; - } else { - ctx.fs.logger.log('[AUTH] passed', path, method); - await next(); - } - } + } + } else { + error = { status: 401, name: 'Unauthorized' }; + } + if (error) { + ctx.fs.logger.log('[AUTH] failed', path, method); + ctx.status = error.status; + ctx.body = error.name; + } else { + ctx.fs.logger.log('[AUTH] passed', path, method); + await next(); + } + } } module.exports = factory; diff --git a/api/app/lib/routes/superScreen/fire.js b/api/app/lib/routes/superScreen/fire.js index dfa6c17..63a7903 100644 --- a/api/app/lib/routes/superScreen/fire.js +++ b/api/app/lib/routes/superScreen/fire.js @@ -16,6 +16,15 @@ module.exports = function (app, router, opts, AuthCode) { app.fs.api.logAttr['PUT/fire/alarm/:id'] = { content: '修改消防告警状态', visible: true }; router.put('/fire/alarm/:id', fire.updateAlarm(opts)); + app.fs.api.logAttr['GET/videoCenter/list'] = { content: '获取萤石设备列表', visible: true }; + router.get('/videoCenter/list', fire.videoList(opts)); + + app.fs.api.logAttr['GET/trafficindex/city/detailst'] = { content: '获取南昌市道路数据', visible: true }; + router.get('/trafficindex/city/details', fire.getDetails(opts)); + + app.fs.api.logAttr['GET/traffic/v1/around'] = { content: '获取周边路况数据失败', visible: true }; + router.get('/traffic/v1/around', fire.getSurroundingConditions(opts)); + //获取消防设备 app.fs.api.logAttr['GET/fire/device'] = { content: '获取消防设备', visible: true }; router.get('/fire/device', fire.getFireDevice(opts)); @@ -23,4 +32,5 @@ module.exports = function (app, router, opts, AuthCode) { //获取火情趋势 app.fs.api.logAttr['GET/fire/trend'] = { content: '获取火情趋势', visible: true }; router.get('/fire/trend', fire.getFireTrend(opts)); + }; diff --git a/api/config.js b/api/config.js index 3c16ac2..714d054 100644 --- a/api/config.js +++ b/api/config.js @@ -1,4 +1,4 @@ -'use strict'; +'use strict'; /*jslint node:true*/ const path = require('path'); const os = require('os'); @@ -19,6 +19,9 @@ args.option('tf', '消防第三方接口 THIRD_FIRECONTROL'); args.option('axyApi', "安心云api"); args.option('axyPumpProject', '安心云泵站项目信息'); +args.option('yingshiKey', '萤石 KEY') +args.option('yingshiSecret', '萤石 SECRET') + const flags = args.parse(process.argv); const DB = process.env.GDRC_DB || flags.pg; @@ -32,136 +35,153 @@ const QINIU_SK = process.env.ANXINCLOUD_QINIU_SECRETKEY || flags.qnsk; const BACKUPS_URL = process.env.BACKUPS_URL || flags.backups; const KUBESPHERE_URL = process.env.KUBESPHERE_URL || flags.kubesphere; const DATABASE_CONFIG = process.env.DATABASE_HOST || flags.dbconfig;//同步数据库配置 - const WATER_URL = process.env.WATER_URL || flags.water; const WORKSAFETY_URL = process.env.WORKSAFETY_URL || flags.worksafety; const THIRD_FIRECONTROL = process.env.THIRD_FIRECONTROL || flags.tf; const AXY_API_URL = process.env.AXY_API_URL || flags.axyApi; const AXY_PUMP_PROJECT = process.env.AXY_PUMP_PROJECT || flags.axyPumpProject; +const YINGSHI_KEY = process.env.YINGSHI_KEY || flags.yingshiKey; +const YINGSHI_SECRET = process.env.YINGSHI_SECRET || flags.yingshiSecret; +// 萤石服务的地址 +const YINGSHI_URL = process.env.YINGSHI_URL || flags.yingshiUrl || 'https://open.ys7.com/api'; + +const BAIDU_API = process.env.BAIDU_API || flags.baiDu || 'https://api.map.baidu.com'; +const BAIDU_AK = process.env.BAIDU_AK || flags.baiDuAk || 'AeSOcqC282tdSUVOfYxe68nEcNF1CTj7'; + if (!DB || !BACKUPS_URL || !KUBESPHERE_URL || !DATABASE_CONFIG || !WATER_URL || !WORKSAFETY_URL || !THIRD_FIRECONTROL || !AXY_API_URL || !AXY_PUMP_PROJECT) { - console.log('缺少启动参数,异常退出'); - args.showHelp(); - process.exit(-1); + console.log('缺少启动参数,异常退出'); + args.showHelp(); + process.exit(-1); } const product = { - port: flags.port || 8080, - staticDirs: ['static'], - mws: [ - { - entry: require('@fs/attachment').entry, - opts: { - qiniu: { - domain: QINIU_DOMAIN_QNDMN_RESOURCE, - bucket: QINIU_BUCKET_RESOURCE, - accessKey: QINIU_AK, - secretKey: QINIU_SK - }, - maxSize: 104857600, // 100M - } - }, { - entry: require('./app').entry, - opts: { - dev, - exclude: [ - // "*" - ], // 不做认证的路由,也可以使用 exclude: ["*"] 跳过所有路由 - - sms: { - ///阿里云-安心云 - accessKey: 'LTAI5tAFdjz7j38aNF2C9Qe8', - accessSecret: '1trYkmiqfBtvZL6BxkNH2uQcQQPs0S' - }, - email: { - enabled: true, - host: 'smtp.exmail.qq.com', - port: 465, - sender: { - name: '政务数据资源中心', - address: 'fsiot@free-sun.com.cn', - password: 'Fs2689' - } - }, - pssaRequest: [], - backupsUrl: BACKUPS_URL, - k8s: KUBESPHERE_URL, - dbConfig: DATABASE_CONFIG, - tfApi: THIRD_FIRECONTROL, - axyPumpProject: AXY_PUMP_PROJECT, - pssaRequest: [{// name 会作为一个 request 出现在 ctx.app.fs - name: 'anxinyun', - root: AXY_API_URL - }], - } - }, { - entry: require('./app/lib/middlewares/proxy').entry, - opts: { - host: WATER_URL, - match: /\/_water\//, - } - }, { - entry: require('./app/lib/middlewares/proxy').entry, - opts: { - host: WORKSAFETY_URL, - match: /\/_worksafety\//, - } - } - ], - dc: { - url: DB, - opts: { - pool: { - max: 80, - min: 10, - idle: 10000 + port: flags.port || 8080, + staticDirs: ['static'], + mws: [ + { + entry: require('@fs/attachment').entry, + opts: { + qiniu: { + domain: QINIU_DOMAIN_QNDMN_RESOURCE, + bucket: QINIU_BUCKET_RESOURCE, + accessKey: QINIU_AK, + secretKey: QINIU_SK + }, + maxSize: 104857600, // 100M + } + }, { + entry: require('./app').entry, + opts: { + dev, + yingshiKey: YINGSHI_KEY, + yingshiSecret: YINGSHI_SECRET, + baiduAK: BAIDU_AK, + exclude: [ + // "*" + ], // 不做认证的路由,也可以使用 exclude: ["*"] 跳过所有路由 + sms: { + ///阿里云-安心云 + accessKey: 'LTAI5tAFdjz7j38aNF2C9Qe8', + accessSecret: '1trYkmiqfBtvZL6BxkNH2uQcQQPs0S' + }, + email: { + enabled: true, + host: 'smtp.exmail.qq.com', + port: 465, + sender: { + name: '政务数据资源中心', + address: 'fsiot@free-sun.com.cn', + password: 'Fs2689' + } }, - define: { - freezeTableName: true, // 固定表名 - timestamps: false // 不含列 "createAt"/"updateAt"/"DeleteAt" + backupsUrl: BACKUPS_URL, + k8s: KUBESPHERE_URL, + dbConfig: DATABASE_CONFIG, + tfApi: THIRD_FIRECONTROL, + axyPumpProject: AXY_PUMP_PROJECT, + pssaRequest: [{// name 会作为一个 request 出现在 ctx.app.fs + name: 'anxinyun', + root: AXY_API_URL + }, { + name: 'yingshiRequest', + root: YINGSHI_URL, + params: {} }, - 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 - } + { + name: 'baiDu', + root: BAIDU_API, + params: {} + },], + } + }, { + entry: require('./app/lib/middlewares/proxy').entry, + opts: { + host: WATER_URL, + match: /\/_water\//, + } + }, { + entry: require('./app/lib/middlewares/proxy').entry, + opts: { + host: WORKSAFETY_URL, + match: /\/_worksafety\//, + } + } + ], + dc: { + url: 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; +module.exports = dev ? development : product; \ No newline at end of file diff --git a/super-screen/client/assets/images/homepage/bigscreen/background_n.png b/super-screen/client/assets/images/homepage/bigscreen/background_n.png new file mode 100644 index 0000000..0834818 Binary files /dev/null and b/super-screen/client/assets/images/homepage/bigscreen/background_n.png differ diff --git a/super-screen/client/assets/images/homepage/bigscreen/blue.png b/super-screen/client/assets/images/homepage/bigscreen/blue.png new file mode 100644 index 0000000..d9cc7cd Binary files /dev/null and b/super-screen/client/assets/images/homepage/bigscreen/blue.png differ diff --git a/super-screen/client/assets/images/homepage/bigscreen/dateDook.png b/super-screen/client/assets/images/homepage/bigscreen/dateDook.png new file mode 100644 index 0000000..e49d725 Binary files /dev/null and b/super-screen/client/assets/images/homepage/bigscreen/dateDook.png differ diff --git a/super-screen/client/assets/images/homepage/bigscreen/green.png b/super-screen/client/assets/images/homepage/bigscreen/green.png new file mode 100644 index 0000000..d6953f6 Binary files /dev/null and b/super-screen/client/assets/images/homepage/bigscreen/green.png differ diff --git a/super-screen/client/assets/images/homepage/bigscreen/red.png b/super-screen/client/assets/images/homepage/bigscreen/red.png new file mode 100644 index 0000000..e938cbb Binary files /dev/null and b/super-screen/client/assets/images/homepage/bigscreen/red.png differ diff --git a/super-screen/client/assets/images/homepage/bigscreen/seniority.png b/super-screen/client/assets/images/homepage/bigscreen/seniority.png new file mode 100644 index 0000000..3914201 Binary files /dev/null and b/super-screen/client/assets/images/homepage/bigscreen/seniority.png differ diff --git a/super-screen/client/src/components/index.js b/super-screen/client/src/components/index.js index a326c9d..25cfd96 100644 --- a/super-screen/client/src/components/index.js +++ b/super-screen/client/src/components/index.js @@ -6,6 +6,7 @@ import Uploads from './Uploads'; import NoResource from './no-resource'; import ExportAndImport from './export'; import ButtonGroup from './buttonGroup'; +import YSIframePlayer from './ysPlayerIframe'; import UploadLocal from './UploadLocal'; import Box from './public/table-card'; import CarouselList from './public/carousel-list'; @@ -19,6 +20,7 @@ export { ExportAndImport, ButtonGroup, UploadLocal, + YSIframePlayer, Box, CarouselList, NoData, diff --git a/super-screen/client/src/components/public/index.less b/super-screen/client/src/components/public/index.less index 0ebd58b..c71a66e 100644 --- a/super-screen/client/src/components/public/index.less +++ b/super-screen/client/src/components/public/index.less @@ -1,125 +1,134 @@ .opcityBackground { - background-color: rgba(8, 27, 55, 0.6); + background-color: rgba(8, 27, 55, 0.6); } .card-title { - height: 31px; - font-family: YouSheBiaoTiHei; - font-size: 24px; - color: #FFFFFF; - letter-spacing: 2px; - padding-left: 15px; + height: 31px; + font-family: YouSheBiaoTiHei; + font-size: 24px; + color: #ffffff; + letter-spacing: 2px; + padding-left: 15px; } /* 滚动列表 */ .scroll-board { - width: 533px; - height: 220px; - margin-top: 10px; - margin-left: 6px; - - .header { - height: 30px; - border-top: 1px solid #0047ba; - border-bottom: 1px solid #0047ba; - - .header-item { - // background: rgba(12, 49, 110, 0.3); - margin-right: 10px; - } - } - - .rows { - .row-item { - font-size: 16px; - } - - .row-item:hover { - background: linear-gradient(270deg, rgba(17, 183, 247, 0) 0%, rgba(17, 183, 247, 0.85) 100%); - color: #9ac8fc; - } - } + width: 533px; + height: 220px; + margin-top: 10px; + margin-left: 6px; + + .header { + height: 30px; + border-top: 1px solid #0047ba; + border-bottom: 1px solid #0047ba; + + .header-item { + // background: rgba(12, 49, 110, 0.3); + margin-right: 10px; + } + } + + .rows { + .row-item { + font-size: 16px; + } + + .row-item:hover { + background: linear-gradient( + 270deg, + rgba(17, 183, 247, 0) 0%, + rgba(17, 183, 247, 0.85) 100% + ); + color: #9ac8fc; + } + } } .scroll-board-multi { - padding: 5px 0px 5px; - color: rgba(204, 228, 255, 1) !important; - - .header { - display: flex; - flex-direction: row; - font-size: 12px !important; - color: rgba(204, 228, 255, 1) !important; - // border-bottom: 1px solid #124C79 !important; - } - - .rows { - color: rgba(204, 228, 255, 1) !important; - - .row-item { - border-bottom: 1px solid #124C79 !important; - } - - .row-item:hover { - background: linear-gradient(270deg, rgba(17, 183, 247, 0) 0%, rgba(17, 183, 247, 0.85) 100%); - color: #9ac8fc; - } - } + padding: 5px 0px 5px; + color: rgba(204, 228, 255, 1) !important; + + .header { + display: flex; + flex-direction: row; + font-size: 12px !important; + color: rgba(204, 228, 255, 1) !important; + // border-bottom: 1px solid #124C79 !important; + } + + .rows { + color: rgba(204, 228, 255, 1) !important; + + .row-item { + border-bottom: 1px solid #124c79 !important; + } + + .row-item:hover { + background: linear-gradient( + 270deg, + rgba(17, 183, 247, 0) 0%, + rgba(17, 183, 247, 0.85) 100% + ); + color: #9ac8fc; + } + } } ._sorrow { - display: inline-block; - width: 15px; - height: 15px; - background: url('/assets/images/homepage/bigscreen/sorrow.png'); - background-repeat: no-repeat; - background-size: 100% 100%; - margin-left: 13px; + display: inline-block; + width: 15px; + height: 15px; + background: url("/assets/images/homepage/bigscreen/sorrow.png"); + background-repeat: no-repeat; + background-size: 100% 100%; + margin-left: 13px; } .subtitle_ { - float: right; - margin-top: 12px; - margin-right: 20px; - width: 200px; - text-align: center; - - ._item_select { - width: 60px; - height: 20px; - display: inline-block; - font-size: 14px; - color: #24DCF7; - border: 1px solid #12B2E5; - background-color: rgba(91, 193, 255, 0.2); - margin-right: 3px; - cursor: pointer; - } - - ._item { - width: 60px; - height: 20px; - display: inline-block; - font-size: 14px; - color: #4C9FFF; - border: 1px solid #0B6AEA; - background-color: rgba(35, 108, 254, 0.3); - margin-right: 3px; - cursor: pointer; - } + float: right; + margin-top: 12px; + margin-right: 20px; + width: 200px; + text-align: center; + + ._item_select { + width: 60px; + height: 20px; + display: inline-block; + font-size: 14px; + color: #24dcf7; + border: 1px solid #12b2e5; + background-color: rgba(91, 193, 255, 0.2); + margin-right: 3px; + cursor: pointer; + } + + ._item { + width: 60px; + height: 20px; + display: inline-block; + font-size: 14px; + color: #4c9fff; + border: 1px solid #0b6aea; + background-color: rgba(35, 108, 254, 0.3); + margin-right: 3px; + cursor: pointer; + } } .children-container { - height: calc(100% - 42px); - background-image: linear-gradient(180deg, #04377ecc 1%, #001241 100%); + height: calc(100% - 42px); + // background-image: linear-gradient(180deg, #04377ecc 1%, #001241 100%); + background-image: linear-gradient(180deg, #04377ecc 1%, #001241 100%); } .box_header_bg { - background: url(/assets/images/homepage/bigscreen/headertitlebg.png) no-repeat; - background-size: 100% 100%; - height: 42px; - padding-top: 4px; - word-break: keep-all; - white-space: nowrap; - width: 100%; -} \ No newline at end of file + background: url(/assets/images/homepage/bigscreen/headertitlebg.png) no-repeat; + background-size: 100% 100%; + height: 42px; + padding-top: 4px; + word-break: keep-all; + white-space: nowrap; + width: 100%; +} diff --git a/super-screen/client/src/components/ysPlayerIframe.js b/super-screen/client/src/components/ysPlayerIframe.js new file mode 100644 index 0000000..3d708e0 --- /dev/null +++ b/super-screen/client/src/components/ysPlayerIframe.js @@ -0,0 +1,52 @@ +/** + * 萤石视频直播(基于萤石云iframe模式,使用方式简单) + * 官方参考:https://open.ys7.com/console/ezopenIframe.html + */ +'use strict'; + +import React from 'react'; +import { connect } from 'react-redux'; + +const YSIframePlayer = props => { + + const { containerId, height, width, url, autoplay, audio, videoState, ysToken } = props; + const at = ysToken + if (!url || !at) return null; + const src = `https://open.ys7.com/ezopen/h5/iframe?audio=${audio ? '1' : '0'}&url=${url}&autoplay=${autoplay || 1}&accessToken=${at}` + // const src = `https://open.ys7.com/ezopen/h5/iframe?audio=1&url=${url}&autoplay=${autoplay || 1}&accessToken=${at}` + return ( +
+ + { + videoState && videoState.status == 0 ? +
+ 设备中断,正在处理中... +
+ : '' + } +
+ ) +} + +function mapStateToProps (state) { + const { auth, } = state; + return { + user: auth.user, + }; +} + +export default connect(mapStateToProps)(YSIframePlayer); \ No newline at end of file diff --git a/super-screen/client/src/sections/community-safty/components/infrastructure.js b/super-screen/client/src/sections/community-safty/components/infrastructure.js index 366e469..0d4626f 100644 --- a/super-screen/client/src/sections/community-safty/components/infrastructure.js +++ b/super-screen/client/src/sections/community-safty/components/infrastructure.js @@ -8,7 +8,7 @@ function Infrastructure(props) { method: 'mockGet', }); const datas = devices?.map(s => { - s.data = JSON.parse(s.data) + if (typeof (s.data) == 'string') s.data = JSON.parse(s.data) return s; }) diff --git a/super-screen/client/src/sections/community-safty/containers/gis.js b/super-screen/client/src/sections/community-safty/containers/gis.js index fff92a0..a8e9c7d 100644 --- a/super-screen/client/src/sections/community-safty/containers/gis.js +++ b/super-screen/client/src/sections/community-safty/containers/gis.js @@ -99,55 +99,22 @@ function Map(props) { map.setRotation(1.7000) - //初始层级 zoom14以下显示聚合点 const data = [ - { lng: 116.117906, lat: 28.678096, type: 'home', name: '廉租房1', kind: 'markergreen' }, - { lng: 116.195238, lat: 28.842114, type: 'home', name: '廉租房2', kind: 'markerblue' }, - { lng: 116.037227, lat: 28.558811, type: 'home', name: '廉租房3', kind: 'markeryellow' }, - { lng: 115.925856, lat: 28.558811, type: 'home', name: '廉租房4', kind: 'markergreen' }, - { lng: 115.989847, lat: 28.484411, type: 'home', name: '廉租房5', kind: 'markergreen' }, - - { lng: 116.054664, lat: 28.538966, type: 'device', name: '廉租房1', kind: 'markergreen' }, - { lng: 116.074711, lat: 28.746745, type: 'device', name: '廉租房2', kind: 'markerblue' }, - { lng: 116.111632, lat: 28.56532, type: 'device', name: '廉租房3', kind: 'markeryellow' }, - { lng: 115.978519, lat: 28.56532, type: 'device', name: '廉租房4', kind: 'markergreen' }, - { lng: 115.95792, lat: 28.417395, type: 'device', name: '廉租房5', kind: 'markergreen' }, + { lng: 115.886724, lat: 28.534257, type: 'home', name: '城西幸福庄园', kind: 'markergreen' }, + { lng: 115.956004, lat: 28.541413, type: 'home', name: '城东幸福庄园', kind: 'markerblue' }, + { lng: 115.9335, lat: 28.541146, type: 'home', name: '城南幸福庄园', kind: 'markeryellow' }, + { lng: 115.91131, lat: 28.525062, type: 'home', name: '小蓝经投公租房', kind: 'markergreen' }, ] - //zoom14以上显示详情 - const databig = [ - { lng: 115.924246, lat: 28.554835, type: 'device', name: '廉租房1', kind: 'markergreenbig' }, - { lng: 115.921495, lat: 28.553053, type: 'device', name: '廉租房2', kind: 'markerbluebig' }, - { lng: 115.919115, lat: 28.557256, type: 'device', name: '廉租房3', kind: 'markeryellowbig' }, - ] - //初始点位显示 - data.filter(s => s.type == tab).map((x, index) => { - var marker = new AMap.Marker({ - position: new AMap.LngLat(x.lng, x.lat), - // 将一张图片的地址设置为 icon - icon: '/assets/images/homepage/communtity/markerblue.png', - // 设置了 icon 以后,设置 icon 的偏移量,以 icon 的 [center bottom] 为原点 - offset: new AMap.Pixel(-13, -30), - zooms: [3, 14], - }); - marker.setTitle(x.name); - map.add(marker); - marker.on('click', () => { - map.setZoom(17.4) - map.setCenter([115.922069, 28.554867]) - map.setPitch(47.30) - map.setRotation(1.7000) - }) - }) //下钻点位显示 - databig.map((x, index) => { + data.map((x, index) => { var marker = new AMap.Marker({ position: new AMap.LngLat(x.lng, x.lat), // 将一张图片的地址设置为 icon - icon: '/assets/images/homepage/communtity/' + x.kind + '.png', + icon: '/assets/images/homepage/communtity/markergreen.png', // 设置了 icon 以后,设置 icon 的偏移量,以 icon 的 [center bottom] 为原点 offset: new AMap.Pixel(-13, -30), - zooms: [15, 19], + zooms: [3, 19], }); marker.setTitle(x.name); map.add(marker); diff --git a/super-screen/client/src/sections/community-safty/containers/homePage.js b/super-screen/client/src/sections/community-safty/containers/homePage.js index 4142f6a..51cfb70 100644 --- a/super-screen/client/src/sections/community-safty/containers/homePage.js +++ b/super-screen/client/src/sections/community-safty/containers/homePage.js @@ -60,9 +60,7 @@ function homePage(props) {
- 社区安全 -
- 流动人口 + 房屋租赁安全
{ dispatch(push('/homepage')) }} className='_exit' >返回平台
diff --git a/super-screen/client/src/sections/fire-control/actions/fire.js b/super-screen/client/src/sections/fire-control/actions/fire.js index 4a823a0..e651ca6 100644 --- a/super-screen/client/src/sections/fire-control/actions/fire.js +++ b/super-screen/client/src/sections/fire-control/actions/fire.js @@ -3,60 +3,97 @@ import { basicAction } from '@peace/utils' import { ApiTable } from '$utils' -export function getFireAlarmList(query) { - return dispatch => basicAction({ - type: 'get', - dispatch: dispatch, - query: query || {}, - actionType: 'GET_FIRE_ALARM', - url: `${ApiTable.getFireAlarmList}`, - msg: { error: '获取消防告警列表失败' }, - reducer: { name: 'alarms' } - }); -} - -export function addFireAlarm(params) { - return (dispatch) => basicAction({ - type: 'post', - data: params, - dispatch, - actionType: 'ADD_RIST_REPORT', - url: ApiTable.getFireAlarmList, - msg: { - option: '新增消防告警', - }, - }); -} - -export function modifyFireAlarm(id, params) { - return (dispatch) => basicAction({ - type: 'put', - data: params, - dispatch, - actionType: 'MODIFY_FIRE_ALARM', - url: ApiTable.modifyFireAlarm.replace('{id}', id), - msg: { - option: '', - }, - }); -} - -export function getFireDevice() { - return dispatch => basicAction({ - type: 'get', - dispatch: dispatch, - actionType: 'GET_FIRE_DEVICE', - url: `${ApiTable.getFireDevice}`, - msg: { error: '获取消防设备失败' }, - }); -} - -export function getFireTrend() { - return dispatch => basicAction({ - type: 'get', - dispatch: dispatch, - actionType: 'GET_FIRE_TREND', - url: `${ApiTable.getFireTrend}`, - msg: { error: '获取火情趋势失败' }, - }); +export function getFireAlarmList (query) { + return dispatch => basicAction({ + type: 'get', + dispatch: dispatch, + query: query || {}, + actionType: 'GET_FIRE_ALARM', + url: `${ApiTable.getFireAlarmList}`, + msg: { error: '获取消防告警列表失败' }, + reducer: { name: 'alarms' } + }); } + +export function addFireAlarm (params) { + return (dispatch) => basicAction({ + type: 'post', + data: params, + dispatch, + actionType: 'ADD_RIST_REPORT', + url: ApiTable.getFireAlarmList, + msg: { + option: '新增消防告警', + }, + }); +} + +export function modifyFireAlarm (id, params) { + return (dispatch) => basicAction({ + type: 'put', + data: params, + dispatch, + actionType: 'MODIFY_FIRE_ALARM', + url: ApiTable.modifyFireAlarm.replace('{id}', id), + msg: { + option: '', + }, + }); +} + + +export function getVideoCenterList () { + return dispatch => basicAction({ + type: 'get', + dispatch: dispatch, + actionType: 'GET_VIDEO_CENTER_LIST', + url: ApiTable.videoCenterList, + msg: { error: '获取视频中心列表失败' }, + reducer: { name: 'videoCenterList' } + }); +} + +export function getDetails () { + return dispatch => basicAction({ + type: 'get', + dispatch: dispatch, + actionType: 'GET_DETAILS', + url: ApiTable.details, + msg: { error: '获取南昌市道路数据失败' }, + // reducer: { name: 'videoCenterList' } + }); +} + +export function getSurroundingConditions (query = {}) { + return dispatch => basicAction({ + type: 'get', + dispatch: dispatch, + query: query, + actionType: 'GET_SURROUNDING_CONDITION', + url: ApiTable.surroundingConditions, + msg: { error: '获取周边路况数据失败' }, + // reducer: { name: 'videoCenterList' } + }); +} + + +export function getFireDevice () { + return dispatch => basicAction({ + type: 'get', + dispatch: dispatch, + actionType: 'GET_FIRE_DEVICE', + url: `${ApiTable.getFireDevice}`, + msg: { error: '获取消防设备失败' }, + }); +} + +export function getFireTrend () { + return dispatch => basicAction({ + type: 'get', + dispatch: dispatch, + actionType: 'GET_FIRE_TREND', + url: `${ApiTable.getFireTrend}`, + msg: { error: '获取火情趋势失败' }, + }); +} + diff --git a/super-screen/client/src/sections/fire-control/components/Right-top2.js b/super-screen/client/src/sections/fire-control/components/Right-top2.js new file mode 100644 index 0000000..e4d0d89 --- /dev/null +++ b/super-screen/client/src/sections/fire-control/components/Right-top2.js @@ -0,0 +1,209 @@ +import React, { useEffect, useState } from 'react' +import { connect } from 'react-redux'; +import { Box, YSIframePlayer } from '$components'; +import { Select } from 'antd'; +import { ArrowDownOutlined, ArrowUpOutlined } from '@ant-design/icons'; +import './style.less'; + + +const DataTop5 = ({ dispatch, actions, longitudeLatitude }) => { + const [videoList, setVideoList] = useState([]) + const [options, setOptions] = useState([]) + const [traffic, setTraffic] = useState({}) + let weeks = { 1: '周一', 2: '周二', 3: '周三', 4: '周四', 5: '周五', 6: '周六', 7: '周日' } + + useEffect(() => { + dispatch(actions.firecontrol.getDetails()).then(res => { + if (res.success) { + setTraffic(res.payload.data?.data?.detail || {}); + } + }) + }, []) + + useEffect(() => { + dispatch(actions.firecontrol.getSurroundingConditions({ center: `${longitudeLatitude?.longitude},${longitudeLatitude?.latitude}` })).then(res => { + if (res.success) { + // setTraffic(res.payload.data?.data?.detail || {}); + } + }) + }, [longitudeLatitude]) + + console.log(longitudeLatitude); + + return
+
+
+ 周边路况实时数据 +
+
+ {longitudeLatitude?.longitude ? + <> + {/*
+
+
= 1 && traffic?.index < 1.5) ? + "#00FF87" : (traffic?.index >= 1.5 && traffic?.index < 1.8) ? + "#FFCC00;" : (traffic?.index >= 1.8 && traffic?.index < 2) ? + "#DE0102;" : (traffic?.index >= 2) ? "#8E0E0B;" : "" + }}>畅通
+
路况整体评价
+
+
+
+
平均通行速度
+
{traffic?.road_network_speed || '--'}
km/h
+
+
+
拥堵距离
+
{traffic?.yongdu_length_4 || '--'}
km
+
+
+
+
+
较10分钟前拥堵趋势:
+
+
+
+ 持平 +
+ +
+
与1设法厕任务v
+ +
+
+
+
路况描述:
+
dewbfdhuihseacf dsjhcf ewdcjaiopsdc op sadc jwe dcfp weopdcf ujew fdc
+ +
*/} + + + + : <> +
+
+ 南昌市
+
NANCHANG CITY
+
+
+
+
+
= 1 && traffic?.index < 1.5) ? + "#00FF87" : (traffic?.index >= 1.5 && traffic?.index < 1.8) ? + "#FFCC00;" : (traffic?.index >= 1.8 && traffic?.index < 2) ? + "#DE0102;" : (traffic?.index >= 2) ? "#8E0E0B;" : "" + }}>{ + (traffic?.index >= 1 && traffic?.index < 1.5) ? + "畅通" : (traffic?.index >= 1.5 && traffic?.index < 1.8) ? + "缓行" : (traffic?.index >= 1.8 && traffic?.index < 2) ? + "拥堵" : (traffic?.index >= 2) ? "严重拥堵" : "" + }
+
路况整体评价
+
+
+
实时拥堵指数
+
+
{traffic?.index || '--'}
+
+ 较上周同期{traffic?.last_index > traffic?.index ? "下降" : '上升'} + {((traffic?.last_index > traffic?.index ? (traffic?.last_index - traffic?.index) / traffic?.last_index : (traffic?.index - traffic?.last_index) / traffic?.last_index) * 100).toFixed(2)}% +
+ {traffic?.last_index > traffic?.index ? + + : } +
+
+
+
+
+ +
+
+
实时拥堵排行
+
+
{traffic?.rank || '--'}
+
/{traffic?.count || '--'}
+
全国重点城市拥堵排行
+ +
+
+
+
+
+
实时平均速度
+
{traffic?.road_network_speed || '--'}
km/h
+
+
+
实时严重拥堵里程
+
{traffic?.yongdu_length_4 || '--'}
km
+
+
+ +
+
+ +
+
+
近30日最高拥堵指数
+
+
{traffic?.month_max_yongdu_index || '--'}
+
{traffic?.month_max_congest_time} {weeks[traffic?.month_max_week_day]}
+
+
+
+
+ + } + +
+ +
+
+} +function mapStateToProps (state) { + const { auth, global } = state + return { + user: auth.user, + actions: global.actions, + } +} +export default connect(mapStateToProps)(DataTop5); + + diff --git a/super-screen/client/src/sections/fire-control/components/alarm-add.js b/super-screen/client/src/sections/fire-control/components/alarm-add.js index b2bf6dd..18d6225 100644 --- a/super-screen/client/src/sections/fire-control/components/alarm-add.js +++ b/super-screen/client/src/sections/fire-control/components/alarm-add.js @@ -57,7 +57,12 @@ function FireAddForm(props) { : '请选择事件地点'}
- { + form.setFieldValue('typeParam', null) + form.setFieldValue('scene', null) + }} + placeholder="请选择警情类型"> {eventType_Data.map(s => )} diff --git a/super-screen/client/src/sections/fire-control/components/item-left.js b/super-screen/client/src/sections/fire-control/components/item-left.js index 01d7d1d..f709d40 100644 --- a/super-screen/client/src/sections/fire-control/components/item-left.js +++ b/super-screen/client/src/sections/fire-control/components/item-left.js @@ -2,7 +2,7 @@ import React from 'react' import { Box, AutoRollComponent } from '$components'; import moment from 'moment' import { getName, getPhone } from '$utils'; -import TimeComponent from './time'; +import TimeComponent, { formatSeconds } from './time'; import { typeParam_data } from '../constants/index' import './style.less' function BasicInfo(props) { @@ -75,7 +75,7 @@ function BasicInfo(props) {
-
路线规划
+
路线规划 {alarmInfo?.routes?.time && `(${formatSeconds(alarmInfo?.routes?.time, true)})`}
3} diff --git a/super-screen/client/src/sections/fire-control/components/right-bottom.js b/super-screen/client/src/sections/fire-control/components/right-bottom.js index e63c64b..bac90fa 100644 --- a/super-screen/client/src/sections/fire-control/components/right-bottom.js +++ b/super-screen/client/src/sections/fire-control/components/right-bottom.js @@ -1,29 +1,72 @@ import React, { useEffect, useState } from 'react' -import { Box } from '$components'; +import { connect } from 'react-redux'; +import { Box, YSIframePlayer } from '$components'; +import { Select } from 'antd'; import './style.less'; -function DataTop5(props) { - - - return -
-
-
南昌大道14:12:32
-
-
-
南昌大道11:34:12
-
-
-
南昌大道08:34:12
-
-
-
南昌大道09:12:34
-
-
-
-} +const DataTop5 = ({ dispatch, actions }) => { + const [videoList, setVideoList] = useState([]) + const [options, setOptions] = useState([]) + const [videoData, setVideoData] = useState({}) + + + useEffect(() => { + dispatch(actions.firecontrol.getVideoCenterList()).then(res => { + if (res.success) { + setVideoList(res.payload.data || []) + setOptions(res.payload.data?.map(v => ({ value: v.deviceSerial, label: v.deviceName })) || []) + setVideoData(res.payload.data[0] || {}) + } + }) + }, []) + -export default DataTop5; + return
+
+
+ 视频监控 +