liujiangyong 2 years ago
parent
commit
76dfda7f38
  1. 2
      api/.vscode/launch.json
  2. 156
      api/app/lib/controllers/superScreen/fire.js
  3. 3
      api/app/lib/middlewares/authenticator.js
  4. 10
      api/app/lib/routes/superScreen/fire.js
  5. 30
      api/config.js
  6. BIN
      super-screen/client/assets/images/homepage/bigscreen/background_n.png
  7. BIN
      super-screen/client/assets/images/homepage/bigscreen/blue.png
  8. BIN
      super-screen/client/assets/images/homepage/bigscreen/dateDook.png
  9. BIN
      super-screen/client/assets/images/homepage/bigscreen/green.png
  10. BIN
      super-screen/client/assets/images/homepage/bigscreen/red.png
  11. BIN
      super-screen/client/assets/images/homepage/bigscreen/seniority.png
  12. 2
      super-screen/client/src/components/index.js
  13. 27
      super-screen/client/src/components/public/index.less
  14. 52
      super-screen/client/src/components/ysPlayerIframe.js
  15. 2
      super-screen/client/src/sections/community-safty/components/infrastructure.js
  16. 47
      super-screen/client/src/sections/community-safty/containers/gis.js
  17. 4
      super-screen/client/src/sections/community-safty/containers/homePage.js
  18. 37
      super-screen/client/src/sections/fire-control/actions/fire.js
  19. 209
      super-screen/client/src/sections/fire-control/components/Right-top2.js
  20. 7
      super-screen/client/src/sections/fire-control/components/alarm-add.js
  21. 4
      super-screen/client/src/sections/fire-control/components/item-left.js
  22. 75
      super-screen/client/src/sections/fire-control/components/right-bottom.js
  23. 3
      super-screen/client/src/sections/fire-control/components/style.less
  24. 9
      super-screen/client/src/sections/fire-control/components/time.js
  25. 4
      super-screen/client/src/sections/fire-control/constants/index.js
  26. 25
      super-screen/client/src/sections/fire-control/containers/gis.js
  27. 13
      super-screen/client/src/sections/fire-control/containers/homePage.js
  28. 2
      super-screen/client/src/sections/water-prevention/containers/homePage.js
  29. 8
      super-screen/client/src/utils/webapi.js
  30. 2
      super-screen/config.js
  31. 1
      super-screen/routes/attachment/index.js

2
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", //

156
api/app/lib/controllers/superScreen/fire.js

@ -1,7 +1,10 @@
'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;
@ -58,6 +61,130 @@ function updateAlarm(opts) {
}
}
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) {
@ -101,10 +228,35 @@ function getFireTrend(opts) {
}
}
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
getFireTrend,
videoList,
getDetails,
getSurroundingConditions
}

3
api/app/lib/middlewares/authenticator.js

@ -61,6 +61,9 @@ let isPathExcluded = function (opts, path, method) {
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' });

10
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));
};

30
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,13 +35,20 @@ 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();
@ -64,10 +74,12 @@ const product = {
entry: require('./app').entry,
opts: {
dev,
yingshiKey: YINGSHI_KEY,
yingshiSecret: YINGSHI_SECRET,
baiduAK: BAIDU_AK,
exclude: [
// "*"
], // 不做认证的路由,也可以使用 exclude: ["*"] 跳过所有路由
sms: {
///阿里云-安心云
accessKey: 'LTAI5tAFdjz7j38aNF2C9Qe8',
@ -83,7 +95,6 @@ const product = {
password: 'Fs2689'
}
},
pssaRequest: [],
backupsUrl: BACKUPS_URL,
k8s: KUBESPHERE_URL,
dbConfig: DATABASE_CONFIG,
@ -92,7 +103,16 @@ const product = {
pssaRequest: [{// name 会作为一个 request 出现在 ctx.app.fs
name: 'anxinyun',
root: AXY_API_URL
}],
}, {
name: 'yingshiRequest',
root: YINGSHI_URL,
params: {}
},
{
name: 'baiDu',
root: BAIDU_API,
params: {}
},],
}
}, {
entry: require('./app/lib/middlewares/proxy').entry,

BIN
super-screen/client/assets/images/homepage/bigscreen/background_n.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 17 KiB

BIN
super-screen/client/assets/images/homepage/bigscreen/blue.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.1 KiB

BIN
super-screen/client/assets/images/homepage/bigscreen/dateDook.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 39 KiB

BIN
super-screen/client/assets/images/homepage/bigscreen/green.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.1 KiB

BIN
super-screen/client/assets/images/homepage/bigscreen/red.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.7 KiB

BIN
super-screen/client/assets/images/homepage/bigscreen/seniority.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 38 KiB

2
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,

27
super-screen/client/src/components/public/index.less

@ -6,7 +6,7 @@
height: 31px;
font-family: YouSheBiaoTiHei;
font-size: 24px;
color: #FFFFFF;
color: #ffffff;
letter-spacing: 2px;
padding-left: 15px;
}
@ -35,7 +35,11 @@
}
.row-item:hover {
background: linear-gradient(270deg, rgba(17, 183, 247, 0) 0%, rgba(17, 183, 247, 0.85) 100%);
background: linear-gradient(
270deg,
rgba(17, 183, 247, 0) 0%,
rgba(17, 183, 247, 0.85) 100%
);
color: #9ac8fc;
}
}
@ -57,11 +61,15 @@
color: rgba(204, 228, 255, 1) !important;
.row-item {
border-bottom: 1px solid #124C79 !important;
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%);
background: linear-gradient(
270deg,
rgba(17, 183, 247, 0) 0%,
rgba(17, 183, 247, 0.85) 100%
);
color: #9ac8fc;
}
}
@ -71,7 +79,7 @@
display: inline-block;
width: 15px;
height: 15px;
background: url('/assets/images/homepage/bigscreen/sorrow.png');
background: url("/assets/images/homepage/bigscreen/sorrow.png");
background-repeat: no-repeat;
background-size: 100% 100%;
margin-left: 13px;
@ -89,8 +97,8 @@
height: 20px;
display: inline-block;
font-size: 14px;
color: #24DCF7;
border: 1px solid #12B2E5;
color: #24dcf7;
border: 1px solid #12b2e5;
background-color: rgba(91, 193, 255, 0.2);
margin-right: 3px;
cursor: pointer;
@ -101,8 +109,8 @@
height: 20px;
display: inline-block;
font-size: 14px;
color: #4C9FFF;
border: 1px solid #0B6AEA;
color: #4c9fff;
border: 1px solid #0b6aea;
background-color: rgba(35, 108, 254, 0.3);
margin-right: 3px;
cursor: pointer;
@ -111,6 +119,7 @@
.children-container {
height: calc(100% - 42px);
// background-image: linear-gradient(180deg, #04377ecc 1%, #001241 100%);
background-image: linear-gradient(180deg, #04377ecc 1%, #001241 100%);
}

52
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 (
<div
style={{ position: 'relative', height: '100%', width: '100%' }}>
<iframe
frameBorder="0"
id={containerId || 'myPlayer'}
src={src}
// https://open.ys7.com/doc/zh/book/index/live_proto.html 单个播放器的长宽比例限制最小为{width: 400px;height: 300px;}
width={width || 400}
height={height || 300}
allowFullScreen
wmode="transparent"
>
</iframe>
{
videoState && videoState.status == 0 ?
<div style={{
height: width || 300, width: width || 400, position: 'absolute', top: 0, background: '#000',
display: 'flex', justifyContent: 'center', alignItems: 'center', color: '#fff'
}}>
设备中断正在处理中...
</div>
: ''
}
</div>
)
}
function mapStateToProps (state) {
const { auth, } = state;
return {
user: auth.user,
};
}
export default connect(mapStateToProps)(YSIframePlayer);

2
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;
})

47
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);

4
super-screen/client/src/sections/community-safty/containers/homePage.js

@ -60,9 +60,7 @@ function homePage(props) {
<div className='homepage'>
<div className='_title'>
<div className='_title_text'>
<span>社区安全</span>
<div className='_title_dot'></div>
<span>流动人口</span>
<span>房屋租赁安全</span>
</div>
<Weather />
<div onClick={() => { dispatch(push('/homepage')) }} className='_exit' >返回平台</div>

37
super-screen/client/src/sections/fire-control/actions/fire.js

@ -41,6 +41,42 @@ export function modifyFireAlarm(id, params) {
});
}
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',
@ -60,3 +96,4 @@ export function getFireTrend() {
msg: { error: '获取火情趋势失败' },
});
}

209
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 <div style={{ height: '100%', width: '100%', margin: "0px 0px 28px" }}>
<div style={{
height: "100%", listStyle: 'none',
}}>
<div className='box_header_bg' >
<span className='card-title'>周边路况实时数据</span>
</div>
<div className='children-container' style={{ padding: '20px' }}>
{longitudeLatitude?.longitude ?
<>
{/* <div style={{
height: "23%", display: "flex",
background: 'linear-gradient(180deg, #04377ecc 1%, #001241 100%)'
}}>
<div style={{ width: "34%", display: 'flex', flexDirection: "column", justifyContent: "center", alignItems: "center" }}>
<div style={{
fontFamily: "YouSheBiaoTiHei", fontSize: 28, letterSpacing: 2,
color: (traffic?.index >= 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;" : ""
}}>畅通</div>
<div style={{ fontSize: 14, color: "#C0E2FF;" }}>路况整体评价</div>
</div>
<div style={{ width: "62%", display: 'flex', }}>
<div style={{ width: "50%", display: 'flex', flexDirection: "column", justifyContent: "space-evenly", alignItems: "center" }}>
<div style={{ height: 22, background: "rgb(0 88 204 / 50%)", width: '90%', textAlign: 'center' }}>平均通行速度</div>
<div ><div style={{ display: 'inline-block', transform: 'skewX(-8deg)', fontSize: 20, fontFamily: "D-DINExp-Italic", }}>{traffic?.road_network_speed || '--'}</div> <span style={{ color: '#00FF87', marginLeft: 6 }}>km/h</span></div>
</div>
<div style={{ width: "50%", display: 'flex', flexDirection: "column", justifyContent: "space-evenly", alignItems: "center" }}>
<div style={{ height: 22, background: "rgb(0 88 204 / 50%)", width: '90%', textAlign: 'center' }}>拥堵距离</div>
<div ><div style={{ display: 'inline-block', transform: 'skewX(-8deg)', fontSize: 20, fontFamily: "D-DINExp-Italic", }}>{traffic?.yongdu_length_4 || '--'}</div><span style={{ color: '#00FF87', marginLeft: 6 }}>km</span> </div>
</div>
</div>
</div>
<div style={{ display: 'flex' }}>
<div style={{ fontFamily: 'SourceHanSansCN-Bold', fontWeight: 700, fontSize: 18, width: 190 }}>较10分钟前拥堵趋势</div>
<div style={{ display: 'flex', flexDirection: 'column', alignItems: 'flex-start', width: "calc(100% - 200px)" }}>
<div style={{
display: 'flex', alignItems: 'center', justifyContent: 'space-around'
}}>
<div style={{ fontSize: 28, transform: 'skewX(-8deg)', color: '#00FF87', fontFamily: "YouSheBiaoTiHei", }}>
持平
</div>
<img src="/assets/images/homepage/bigscreen/red.png" style={{ width: 30, height: 30 }} />
</div>
<div>与1设法厕任务v</div>
</div>
</div>
<div style={{}}>
<div style={{ fontFamily: 'SourceHanSansCN-Bold', fontWeight: 700, fontSize: 18, }}>路况描述</div>
<div>dewbfdhuihseacf dsjhcf ewdcjaiopsdc op sadc jwe dcfp weopdcf ujew fdc </div>
</div> */}
</>
: <>
<div style={{
background: 'url(/assets/images/homepage/bigscreen/background_n.png)',
backgroundSize: '100% 20px', backgroundPosition: '0 14px', backgroundRepeat: 'no-repeat',
display: 'flex', alignItems: 'center', justifyContent: "space-between", padding: '0 6px',
}}>
<div style={{
fontFamily: 'YouSheBiaoTiHei', fontSize: 20
}}
>
南昌市</div>
<div style={{
fontFamily: 'YouSheBiaoTiHei', fontSize: 14
}}
>NANCHANG CITY</div>
</div>
<div style={{
height: "calc(100% - 38px)", marginTop: 20, display: 'flex', flexDirection: 'column', justifyContent: 'space-around',
}}>
<div style={{
height: "23%", display: "flex",
background: 'linear-gradient(180deg, #04377ecc 1%, #001241 100%)'
}}>
<div style={{ width: "34%", display: 'flex', flexDirection: "column", justifyContent: "center", alignItems: "center" }}>
<div style={{
fontFamily: "YouSheBiaoTiHei", fontSize: 28, letterSpacing: 2,
color: (traffic?.index >= 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) ? "严重拥堵" : ""
}</div>
<div style={{ fontSize: 14, color: "#C0E2FF;" }}>路况整体评价</div>
</div>
<div style={{ width: "62%", display: 'flex', flexDirection: "column", justifyContent: "space-evenly", }}>
<div style={{ height: 22, background: "rgb(0 88 204 / 50%)", textIndent: 20 }}>实时拥堵指数</div>
<div style={{ display: "flex", alignItems: 'center' }}>
<div style={{ fontSize: 28, transform: 'skewX(-8deg)', fontFamily: "D-DINExp-Italic", fontWeight: 'Italic', color: '#ECF7FF', marginRight: 4 }}>{traffic?.index || '--'}</div>
<div style={{ color: '#C3E6FF' }}>
较上周同期{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)}%
</div>
{traffic?.last_index > traffic?.index ?
<ArrowDownOutlined style={{ color: '#06FF07', fontSize: 18 }} />
: <ArrowUpOutlined style={{ color: '#06FF07', fontSize: 18 }} />}
</div>
</div>
</div>
<div style={{
height: "23%", display: "flex",
background: 'linear-gradient(180deg, #04377ecc 1%, #001241 100%)'
}}>
<div style={{ width: "34%", display: 'flex', flexDirection: "column", justifyContent: "center", alignItems: "center" }}>
<img src='/assets/images/homepage/bigscreen/seniority.png' style={{ width: "80%" }} />
</div>
<div style={{ width: "62%", display: 'flex', flexDirection: "column", justifyContent: "space-evenly", }}>
<div style={{ height: 22, background: "rgb(0 88 204 / 50%)", textIndent: 20 }}>实时拥堵排行</div>
<div style={{ display: "flex", alignItems: 'center' }}>
<div style={{ fontSize: 28, fontFamily: "D-DINExp-Italic", transform: 'skewX(-8deg)', fontWeight: 'Italic', color: '#ECF7FF', marginRight: 4 }}>{traffic?.rank || '--'}</div>
<div style={{ marginRight: 16, fontSize: 20, transform: 'skewX(-8deg)' }}>/{traffic?.count || '--'}</div>
<div style={{ color: '#C3E6FF' }}>全国重点城市拥堵排行</div>
</div>
</div>
</div>
<div style={{
height: "23%", display: "flex",
background: 'linear-gradient(180deg, #04377ecc 1%, #001241 100%)'
}}>
<div style={{ width: "50%", display: 'flex', flexDirection: "column", justifyContent: "space-evenly", alignItems: "center" }}>
<div style={{ height: 22, background: "rgb(0 88 204 / 50%)", width: '90%', textAlign: 'center' }}>实时平均速度</div>
<div ><div style={{ display: 'inline-block', transform: 'skewX(-8deg)', fontSize: 28, fontFamily: "D-DINExp-Italic", }}>{traffic?.road_network_speed || '--'}</div> <span style={{ color: '#00FF87', marginLeft: 20 }}>km/h</span></div>
</div>
<div style={{ width: "50%", display: 'flex', flexDirection: "column", justifyContent: "space-evenly", alignItems: "center" }}>
<div style={{ height: 22, background: "rgb(0 88 204 / 50%)", width: '90%', textAlign: 'center' }}>实时严重拥堵里程</div>
<div ><div style={{ display: 'inline-block', transform: 'skewX(-8deg)', fontSize: 28, fontFamily: "D-DINExp-Italic", }}>{traffic?.yongdu_length_4 || '--'}</div><span style={{ color: '#00FF87', marginLeft: 20 }}>km</span> </div>
</div>
</div>
<div style={{
height: "23%", display: "flex",
background: 'linear-gradient(180deg, #04377ecc 1%, #001241 100%)'
}}>
<div style={{ width: "34%", display: 'flex', flexDirection: "column", justifyContent: "center", alignItems: "center" }}>
<img src='/assets/images/homepage/bigscreen/dateDook.png' style={{ width: "80%" }} />
</div>
<div style={{ width: "62%", display: 'flex', flexDirection: "column", justifyContent: "space-evenly", }}>
<div style={{ height: 22, background: "rgb(0 88 204 / 50%)", textIndent: 20 }}>近30日最高拥堵指数</div>
<div style={{ display: "flex", alignItems: 'center' }}>
<div style={{ fontSize: 28, fontFamily: "D-DINExp-Italic", fontWeight: 'Italic', color: '#ECF7FF', marginRight: 38 }}>{traffic?.month_max_yongdu_index || '--'}</div>
<div style={{ color: '#C3E6FF' }}>{traffic?.month_max_congest_time} {weeks[traffic?.month_max_week_day]}</div>
</div>
</div>
</div>
</div></>
}
</div>
</div>
</div >
}
function mapStateToProps (state) {
const { auth, global } = state
return {
user: auth.user,
actions: global.actions,
}
}
export default connect(mapStateToProps)(DataTop5);

7
super-screen/client/src/sections/fire-control/components/alarm-add.js

@ -57,7 +57,12 @@ function FireAddForm(props) {
: '请选择事件地点'}</div>
</Form.Item>
<Form.Item name="type" label="警情类型" rules={[{ required: true, message: '请选择警情类型!' }]}>
<Select placeholder="请选择警情类型">
<Select
onChange={(s) => {
form.setFieldValue('typeParam', null)
form.setFieldValue('scene', null)
}}
placeholder="请选择警情类型">
{eventType_Data.map(s => <Option value={s}>{s}</Option>)}
</Select>
</Form.Item>

4
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) {
<div className='left_third_bg' style={{ height: 160, paddingTop: 20 }}>
<div className='left_item_left3' />
<div className='left_item_right1' style={{ textAlign: 'left' }}>
<div><span style={{ marginRight: 30, marginBottom: 15 }}>路线规划</span></div>
<div><span style={{ marginRight: 30, marginBottom: 15 }}>路线规划 {alarmInfo?.routes?.time && `(${formatSeconds(alarmInfo?.routes?.time, true)})`}</span></div>
<AutoRollComponent
key={alarmInfo?.id}
canScroll={alarmInfo?.routes?.steps?.length > 3}

75
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) {
const DataTop5 = ({ dispatch, actions }) => {
const [videoList, setVideoList] = useState([])
const [options, setOptions] = useState([])
const [videoData, setVideoData] = useState({})
return <Box title={"视频监控"} bodyPaddingTop={1} >
<div className='video_container'>
<div className='_item'>
<div className='video_bottom'><span>南昌大道</span><span>14:12:32</span></div>
</div>
<div className='_item'>
<div className='video_bottom'><span>南昌大道</span><span>11:34:12</span></div>
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] || {})
}
})
}, [])
return <div style={{ height: '100%', width: '100%', margin: "0px 0px 28px" }}>
<div style={{
height: "100%", listStyle: 'none',
}}>
<div className='box_header_bg' >
<span className='card-title'>视频监控</span>
<Select
className="gis-search-select"
popupClassName="super-dropdownClassName"
style={{
width: 100,
float: 'right',
margin: '18px 20px 0 0 '
}}
value={videoData?.deviceSerial}
onChange={v => {
setVideoData(videoList?.find(s => s.deviceSerial == v) ||{})
}}
options={options}
/>
</div>
<div className='_item'>
<div className='video_bottom'><span>南昌大道</span><span>08:34:12</span></div>
<div className='children-container'>
<YSIframePlayer
containerId={`yingshiPlay_lu_${videoData?.deviceSerial}`}
height='100%'
width="100%"
url={`ezopen://open.ys7.com/${videoData?.deviceSerial}/${'1'}.hd.live`}
audio="0"
ysToken={videoData?.token}
videoState={{
status: videoData?.status
}}
/>
</div>
<div className='_item'>
<div className='video_bottom'><span>南昌大道</span><span>09:12:34</span></div>
</div>
</div>
</Box>
}
export default DataTop5;
function mapStateToProps (state) {
const { auth, global } = state
return {
user: auth.user,
actions: global.actions,
}
}
export default connect(mapStateToProps)(DataTop5);

3
super-screen/client/src/sections/fire-control/components/style.less

@ -502,3 +502,6 @@
}
}
}

9
super-screen/client/src/sections/fire-control/components/time.js

@ -22,7 +22,7 @@ export default TimeComponent;
//秒数转化为天时分秒
export const formatSeconds = (value) => {
export const formatSeconds = (value, symbol) => {
var secondTime = parseInt(value);// 秒
var minuteTime = 0;// 分
var hourTime = 0;// 小时
@ -46,12 +46,13 @@ export const formatSeconds = (value) => {
}
}
}
var result = "" + (parseInt(secondTime) < 10 ? '0' + parseInt(secondTime) : parseInt(secondTime));
result = "" + (parseInt(minuteTime) < 10 ? '0' + parseInt(minuteTime) : parseInt(minuteTime)) + ":" + result;
result = "" + (parseInt(hourTime) < 10 ? '0' + parseInt(hourTime) : parseInt(hourTime)) + ":" + result;
var result = symbol ? '' : "" + (parseInt(secondTime) < 10 ? '0' + parseInt(secondTime) : parseInt(secondTime));
result = "" + ((!symbol && parseInt(minuteTime) < 10) ? '0' + parseInt(minuteTime) : parseInt(minuteTime)) + (symbol ? '分钟' : ":") + result;
result = (symbol && parseInt(hourTime) == 0) ? result : "" + (!symbol && parseInt(hourTime) < 10 ? '0' + parseInt(hourTime) : parseInt(hourTime)) + (symbol ? '小时' : ":") + result;
if (dayTime > 0) {
result = "" + parseInt(dayTime) + "天 " + result;
}
// console.log('result', result);
return result;
}

4
super-screen/client/src/sections/fire-control/constants/index.js

@ -1,7 +1,7 @@
const typeParam_data = {
'火灾扑救': {
name: '着火物质',
options: ['固体物质', '液体或可熔物质', '气体', '带电物体和精密仪器等物质', '烹饪器具内的烹饪物',]
options: ['固体物质', '液体或可熔物质', '金属', '气体', '带电物体和精密仪器等物质', '烹饪器具内的烹饪物',]
},
'救援抢险': {
name: '事件类型',
@ -10,7 +10,7 @@ const typeParam_data = {
},
'自然灾害': {
name: '灾害类型',
options: ['水旱', '气象', '地质灾害', '等自然灾害', '森林、草原火灾']
options: ['水旱', '气象', '地质灾害', '森林、草原火灾']
},
'灾难事故': {
name: '事故类型',

25
super-screen/client/src/sections/fire-control/containers/gis.js

@ -18,7 +18,7 @@ const tabs = [
]
function Map(props) {
const { dispatch, actions, emergencyList, propTab } = props;
const { dispatch, actions, emergencyList, propTab, setLongitudeLatitude } = props;
const [delay, setDelay] = useState(true)
const [tab, setTab] = useState('xfyjwz')
const [visible, setVisible] = useState(false)
@ -60,13 +60,13 @@ function Map(props) {
}
useEffect(() => {
if (!delay && alarmList?.length > 0 && emergencyList['xfjy']) {
if (!delay && (alarmList?.length > 0 || emergencyList['xfjy'])) {
map.clearMap()
map && renderMarkers()
map && renderAlarms()
setMapInitFit()
}
}, [delay, alarmList, emergencyList])
}, [delay, alarmList, emergencyList, propTab])
const renderMarkers = () => {
const data = emergencyList['xfjy']
@ -204,6 +204,7 @@ function Map(props) {
renderAlarmInfowindow(x)
}
}, 50)
setLongitudeLatitude({ longitude: x.longitude, latitude: x.latitude })
})
})
}
@ -218,11 +219,8 @@ function Map(props) {
if (result.routes && result.routes.length) {
// 绘制第一条路线,也可以按需求绘制其它几条路线
drawRoute(result.routes[0])
props.routeCallback({ routes: result.routes[0] })
props.alarmOk({
alarmInfo: { ...alarmInfo, routes: result.routes[0] },
rescueInfo: rescueInfo
})
}
} else {
}
@ -299,7 +297,8 @@ function Map(props) {
</div>
</div>
<div className='alarm_confirm'>
{
propTab == 'overview' && <div className='alarm_confirm'>
<div className='hande_button'
onClick={() => {
map.clearInfoWindow();
@ -313,10 +312,18 @@ function Map(props) {
))
const location = list[0]?.location
drawDrivings([x.longitude, x.latitude], location.split(','), x, list[0])
props.alarmOk({
alarmInfo: { ...x },
rescueInfo: list[0]
})
setTimeout(() => {
drawDrivings([x.longitude, x.latitude], location.split(','), x, list[0])
}, 200);
}
}}
>一键护航</div>
</div>
</div>}
</div>,
document.getElementById(`alarmcontentid${x.location}`));
}

13
super-screen/client/src/sections/fire-control/containers/homePage.js

@ -8,6 +8,7 @@ import LeftMiddle from '../components/left-middle'
import LeftBottom from '../components/left-bottom'
import RightTop from '../components/right-top'
import RightMiddle from '../components/right-middle'
import RightTop2 from '../components/Right-top2'
import RightBottom from '../components/right-bottom'
import Gis from './gis';
import './style.less'
@ -23,6 +24,8 @@ function homePage(props) {
const [tab, setTab] = useState('overview')
const [emengencyTab, setEmengencyTab] = useState('xfyjwz');
const [alarmInfo, setAlarmInfo] = useState({})
const [longitudeLatitude, setLongitudeLatitude] = useState({})
const [fireDevice, setFireDevice] = useState([])
const [fireTrend, setFireTrend] = useState([])
@ -58,9 +61,7 @@ function homePage(props) {
<div className='homepage'>
<div className='_title'>
<div className='_title_text'>
<span>智慧消防</span>
<div className='_title_dot'></div>
<span>一键护航</span>
<span>消防一键护航</span>
</div>
<Weather />
<div onClick={() => { dispatch(push('/homepage')) }} className='_exit' >返回平台</div>
@ -92,6 +93,7 @@ function homePage(props) {
<div className='homepage-center'>
<Gis
emergencyList={emergencyList}
setLongitudeLatitude={setLongitudeLatitude}
dispatch={dispatch}
actions={actions}
propTab={tab}
@ -106,11 +108,14 @@ function homePage(props) {
</div>
<div className='homepage-left homepage-left-right'>
{tab == 'overview' ? <div className="list">
<div className='child-right' style={childStyle}>
{/* <div className='child-right' style={childStyle}>
<RightTop />
</div>
<div className='child-right' style={childStyle}>
<RightMiddle cardContentHeight={cardContentHeight} />
</div> */}
<div className='child-right' style={{ height: 'calc(64% + 17px)', color: '#fff', marginBottom: 17 }}>
<RightTop2 longitudeLatitude={longitudeLatitude} />
</div>
<div className='child-right' style={childStyle}>
<RightBottom />

2
super-screen/client/src/sections/water-prevention/containers/homePage.js

@ -176,7 +176,7 @@ function homePage(props) {
<div className='homepage'>
<div className='_title'>
<div className='water_title_text'>
水务防汛实时监测预警系统
防汛提前知
</div>
<Weather />
<div onClick={() => { dispatch(push('/homepage')) }} className='_exit' >返回平台</div>

8
super-screen/client/src/utils/webapi.js

@ -136,8 +136,16 @@ export const ApiTable = {
//消防
getFireAlarmList: 'fire/alarm',
modifyFireAlarm: 'fire/alarm/{id}',
//获取摄像头数据
videoCenterList: 'videoCenter/list',
details: '/trafficindex/city/details',
surroundingConditions: 'traffic/v1/around',
getFireDevice: 'fire/device',
getFireTrend: 'fire/trend',
};
export const RouteTable = {

2
super-screen/config.js

@ -27,6 +27,7 @@ const ANXINCLOUD_QINIU_SECRETKEY = process.env.ANXINCLOUD_QINIU_SECRETKEY || fla
const ANXINCLOUD_QINIU_BUCKET_RESOURCE = process.env.ANXINCLOUD_QINIU_BUCKET_RESOURCE || flags.qnbkt;
const ANXINCLOUD_QINIU_DOMAIN_QNDMN_RESOURCE = process.env.ANXINCLOUD_QINIU_DOMAIN_QNDMN_RESOURCE || flags.qndmn;
const weatherUrl = process.env.ANXINCLOUD_WEATHERAPP_API || "https://weatherssj.anxinyun.cn/weatherApp/weather/getImmeData"
const BAIDU_API = process.env.BAIDU_API || "https://jiaotong.baidu.com"
//阿里OSS
const ALI_OSS_ACCESSKEY = process.env.ALI_OSS_ACCESSKEY || flags.aliOssAccessKey;
@ -87,6 +88,7 @@ const product = {
region: ALI_OSS_REGION
},
weatherUrl,
baiDuAPi: BAIDU_API
}
},
{

1
super-screen/routes/attachment/index.js

@ -229,7 +229,6 @@ module.exports = {
}
}
router.use(download_);
router.post('/_upload/new', upload);
router.delete('/_upload/cleanup', remove);

Loading…
Cancel
Save