Browse Source

公交GIS布点

dev
巴林闲侠 1 year ago
parent
commit
1237f377b9
  1. 33
      api/app/lib/controllers/overview/operation.js
  2. 3
      api/app/lib/index.js
  3. 3
      api/app/lib/routes/overview/index.js
  4. 44
      api/app/lib/schedule/zhidiao.js
  5. 1
      api/package.json
  6. BIN
      web/client/assets/images/gis/bus.png
  7. 1
      web/client/src/layout/index.js
  8. 24
      web/client/src/sections/quanju/actions/example.js
  9. 12
      web/client/src/sections/quanju/containers/footer/operation/index.js
  10. 49
      web/client/src/sections/quanju/containers/footer/operation/left.js
  11. 155
      web/client/src/sections/quanju/containers/public/olMap.js
  12. 2
      web/client/src/utils/webapi.js

33
api/app/lib/controllers/overview/operation.js

@ -144,6 +144,12 @@ async function busRunRealTime (ctx) {
}
})
app.fs.zhidiaoData ?
app.fs.zhidiaoData.busRun = busRunRes :
app.fs.zhidiaoData = {
busRun: busRunRes
}
let now = moment()
let hourBefour = now.subtract(1, 'h')
ctx.status = 200;
@ -157,8 +163,35 @@ async function busRunRealTime (ctx) {
}
}
async function busLine (ctx) {
try {
const { models } = ctx.fs.dc;
const { app } = ctx
const { busLicence } = ctx.query
const zhidiaoData = app.fs.zhidiaoData
let rslt = {}
if (zhidiaoData) {
let corBus = (zhidiaoData.busRun || []).find(b => b.busNoChar == busLicence)
if (corBus) {
rslt = (zhidiaoData.busLine || {})[corBus.lineNo] || {}
}
}
ctx.status = 200;
ctx.body = rslt
} catch (error) {
ctx.fs.logger.error(`path: ${ctx.path}, error: ${error}`);
ctx.status = 400;
ctx.body = {
message: typeof error == 'string' ? error : undefined
}
}
}
module.exports = {
busCarLevelList,
vehicleStatistic,
busRunRealTime,
busLine,
};

3
api/app/lib/index.js

@ -6,6 +6,7 @@ const path = require('path');
const authenticator = require('./middlewares/authenticator');
// const apiLog = require('./middlewares/api-log');
const paasRequest = require('./service/paasRequest');
const schedule = require('./schedule')
module.exports.entry = function (app, router, opts) {
app.fs.logger.log('info', '[FS-AUTH]', 'Inject auth and api mv into router.');
@ -18,6 +19,8 @@ module.exports.entry = function (app, router, opts) {
// router.use(apiLog(app, opts));
// 实例其他平台请求方法
paasRequest(app, opts)
// 定时任务
schedule(app, opts)
router = routes(app, router, opts);
};

3
api/app/lib/routes/overview/index.js

@ -26,4 +26,7 @@ module.exports = function (app, router, opts) {
app.fs.api.logAttr['GET/bus/run_realtime'] = { content: '获取公交实时运行信息', visible: false };
router.get('/bus/run_realtime', operation.busRunRealTime);
app.fs.api.logAttr['GET/bus/run/line'] = { content: '获取公交运行路线', visible: false };
router.get('/bus/run/line', operation.busLine);
}

44
api/app/lib/schedule/zhidiao.js

@ -0,0 +1,44 @@
const zhidiaoSystem = require('../../../utils/zhidiaoSystem.js');
const moment = require('moment')
let isDev = false
isDev = true
module.exports = function (app, opts) {
const busLines = app.fs.scheduleInit(
{
interval: '24 0 */1 * * *',
immediate: true,
proRun: false,
disabled: false
},
async () => {
try {
const { models, ORM: sequelize } = app.fs.dc
const Authorization = zhidiaoSystem.createAuthorization()
const busRunRes = await app.fs.zhidiaoRequest.get(`getBusRunList`, {
header: {
Authorization: Authorization
}
})
const busLineRes = await app.fs.zhidiaoRequest.get(`getLinePointList`, {
header: {
Authorization: Authorization
}
})
console.log(`定时获取BUS路线信息`);
app.fs.zhidiaoData = {
busLine: busLineRes,
busRun: busRunRes
}
} catch (error) {
console.error(error);
}
}
)
return {
busLines,
}
}

1
api/package.json

@ -28,6 +28,7 @@
"koa2-swagger-ui": "^5.3.0",
"md5-node": "^1.0.1",
"moment": "^2.24.0",
"node-schedule": "^2.1.1",
"path": "^0.12.7",
"path-to-regexp": "^3.0.0",
"pg": "^7.9.0",

BIN
web/client/assets/images/gis/bus.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.2 KiB

1
web/client/src/layout/index.js

@ -61,7 +61,6 @@ const Root = props => {
flat(routes);
//将路由信息全部放在session,方便后面拿了用(权限控制的时候)
//console.log('combineRoutes1', combineRoutes)
sessionStorage.setItem('allRoutes', JSON.stringify(combineRoutes));
return combineRoutes;
}

24
web/client/src/sections/quanju/actions/example.js

@ -1,6 +1,6 @@
'use strict';
import { basicAction } from '@peace/utils'
import { basicAction, clearData } from '@peace/utils'
import { ApiTable } from '$utils'
export function getMembers (orgId) {
@ -180,13 +180,25 @@ export function getVideoCenterList () {
});
}
export function getBusRuntTime () {
export function getBusRunTime () {
return dispatch => basicAction({
type: 'get',
dispatch: dispatch,
actionType: 'GET_VIDEO_CENTER_LIST',
url: ApiTable.videoCenterList,
msg: { error: '获取视频中心列表失败' },
reducer: { name: 'videoCenterList' }
actionType: 'GET_BUS_REALTIME_LIST',
url: ApiTable.busRealtimeList,
msg: { error: '获取公交实时信息失败' },
reducer: { name: 'busRunTime', params: { noClear: true } }
});
}
export const getBuslineActionType = 'GET_BUS_LINE'
export function getBusline (busLicence) {
return dispatch => basicAction({
type: 'get',
dispatch: dispatch,
actionType: getBuslineActionType,
url: ApiTable.busLine + `?busLicence=${busLicence}`,
msg: { error: '获取公交路线信息失败' },
reducer: { name: 'busLine', params: { noClear: true } }
});
}

12
web/client/src/sections/quanju/containers/footer/operation/index.js

@ -2,8 +2,9 @@ import React, { useEffect, useState } from 'react'
import Left from './left'
import Right from './right'
import { connect } from 'react-redux'
import { getBusTierList } from '../../../actions/example'
import { getBusTierList, getBusRunTime } from '../../../actions/example'
let busRealtimeInterval = null
const Operation = (props) => {
const [roadData, setRoadData] = useState()
@ -14,6 +15,13 @@ const Operation = (props) => {
setLoading(false)
setRoadData(res.payload.data || {})
})
busRealtimeInterval = setInterval(() => {
dispatch(getBusRunTime())
}, 1000 * 16)
dispatch(getBusRunTime())
return () => {
clearInterval(busRealtimeInterval)
}
}, [])
return (
@ -23,7 +31,7 @@ const Operation = (props) => {
</div>
)
}
function mapStateToProps(state) {
function mapStateToProps (state) {
return {

49
web/client/src/sections/quanju/containers/footer/operation/left.js

@ -1,11 +1,15 @@
import React, { useState, useEffect } from 'react';
import { connect } from 'react-redux';
import { Input, Tree } from 'antd'
import { Input, Tree, message } from 'antd'
import Module from '../../public/module'
import { getBusTierList } from '../../../actions/example'
import { getBusTierList, getBusline, getBuslineActionType } from '../../../actions/example'
import { basicAction, clearData } from '@peace/utils'
import './style.less'
const Left = (props) => {
const { busTier, dispatch } = props
const style = { height: "97%", marginTop: "3%" }
const [treeData, setTreeData] = useState([])
const [treeDataList, setTreeDataList] = useState([])
const [expandedKeys, setExpandedKeys] = useState([]);
@ -20,10 +24,7 @@ const Left = (props) => {
useEffect(() => {
const { dispatch } = props
dispatch(getBusTierList())
}, [])
const { busTier } = props
const style = { height: "97%", marginTop: "3%" }
const onChange = (e) => {
const { value } = e.target;
@ -38,7 +39,6 @@ const Left = (props) => {
};
const loop = (treeData) =>
treeData.map((item) => {
// console.log(item,'===> item -----');
const index = item.title != null && item.title.indexOf(searchValue);
const beforeStr = item.title != null && item.title.substr(0, index);
const afterStr = item.title != null && item.title.substr(index + searchValue.length);
@ -95,11 +95,13 @@ const Left = (props) => {
title: s.name,
children: s.child.map(i => {
return {
key: i.name == '--' || i.name == null ? Math.ceil(Math.random() * 100) : i.name,
key:
i.name == '--' || i.name == null ? Math.ceil(Math.random() * 100) : i.name,
title: i.name,
children: i.child.map(x => {
return {
key: x.name == '--' || x.name == null ? Math.ceil(Math.random() * 100) : x.name,
key: 'bus_' + x.id + '_' + x.name || '--',
// key: x.name == '--' || x.name == null ? Math.ceil(Math.random() * 100) : x.name,
title: x.name == null ? '--' : x.name,
}
})
@ -128,7 +130,7 @@ const Left = (props) => {
setTreeDataList(dataList)
}, [busTier])
return (
<div style={{ position:'absolute',left:0, width: "23%", height: "100%", marginLeft: "1%" }}>
<div style={{ position: 'absolute', left: 0, width: "23%", height: "100%", marginLeft: "1%" }}>
<Module style={style} customize={true} title={"公交车辆信息"}>
<div style={{ width: '90%', height: '96%', margin: '2% 5%', overflow: 'hidden' }}>
<div style={{ border: '1px solid rgba(10, 114, 255, 1)', backgroundColor: 'rgba(10, 114, 255, 0.1)' }}>
@ -160,6 +162,31 @@ const Left = (props) => {
expandedKeys={expandedKeys}
autoExpandParent={autoExpandParent}
treeData={loop(treeData)}
onSelect={(selectedKeys, { selected, selectedNodes, node, event }) => {
let isClear = true
if (selectedKeys.length) {
if (selected) {
let k = selectedKeys[0]
let kArr = k.split('_')
let busLicence = kArr[2]
if (busLicence && busLicence != '--') {
dispatch(getBusline(busLicence)).then(res => {
if (res.success) {
let data = res.payload.data
if (!data || !data.length) {
message.warning(`没有查询到${busLicence}的路线信息`)
}
}
})
isClear = false
}
}
}
if (isClear) {
clearData(dispatch, { actionType: getBuslineActionType })
}
}}
/> : <div style={{ width: '100%', color: '#fff', textAlign: 'center', marginTop: '90%' }}></div>
}
@ -169,8 +196,8 @@ const Left = (props) => {
</div>
);
};
function mapStateToProps(state) {
const { busTier } = state
function mapStateToProps (state) {
const { busTier, } = state
return {
busTier: busTier
}

155
web/client/src/sections/quanju/containers/public/olMap.js

@ -6,10 +6,12 @@ import moment from 'moment';
import { OlMapRequest } from '$utils'
const OlMap = (props) => {
const { dispatch, actions, user, olMapArcgisHost, olMapGeoDataHost, patrolList, roadProjectList, tab } = props
const { dispatch, actions, user, olMapArcgisHost, olMapGeoDataHost, patrolList, roadProjectList, tab, busRunTime, busLine } = props
const [olMapOpenData, setOlMapOpenData] = useState([])
const [olMap, setOlMap] = useState()
const [pointItem, setPointItem] = useState({})
//
const [busRunData, setBusRunData] = useState([])
useEffect(() => {
setOlMapOpenData([])
@ -158,9 +160,11 @@ const OlMap = (props) => {
roadProjectList.forEach((d, index) => {
olMap.removeGeometryLayer('geometry_road_' + index)
})
busRunData.forEach((d, index) => {
olMap.removeGeometryLayer('geometry_bus_' + index)
})
patrolList.forEach((d, index) => {
console.log(d, index);
olMap.addGeometryLayer({
features: [
{
@ -221,6 +225,9 @@ const OlMap = (props) => {
patrolList.forEach((d, index) => {
olMap.removeGeometryLayer('geometry_patrol_' + index)
})
busRunData.forEach((d, index) => {
olMap.removeGeometryLayer('geometry_bus_' + index)
})
roadProjectList.forEach((d, index) => {
olMap.addGeometryLayer({
@ -268,7 +275,141 @@ const OlMap = (props) => {
}
}, [roadProjectList, olMap, tab])
useEffect(() => {
if (busRunTime && busRunTime.length) {
setBusRunData(busRunTime)
}
}, [busRunTime])
const drawBusRunPoint = () => {
patrolList.forEach((d, index) => {
olMap.removeGeometryLayer('geometry_patrol_' + index)
})
roadProjectList.forEach((d, index) => {
olMap.removeGeometryLayer('geometry_road_' + index)
})
busRunData.forEach((d, index) => {
olMap.addGeometryLayer({
features: [
{
name: 'busPoint',
attributes: {
callbackParams: {
type: 'busPoint',
busNo: d.busNo,
},
callback: (p) => {
setPointItem(p)
setOlMapOpenData([{
n: '车牌号',
v: d.busNoChar
}, {
n: '司机',
v: d.employeeName
}, {
n: '工号',
v: d.opNo
}, {
n: '调度状态',
v: d.willRun,
map: [
{ text: '非运营', value: '0' },
{ text: '运营', value: '1' },
{ text: '维修', value: '2' },
{ text: '保养', value: '3' },
{ text: '专车', value: '4' },
{ text: '机动车', value: '5' },
{ text: '包车', value: '6' },
{ text: '班车', value: '7' },
{ text: '检车', value: '8' },
],
}, {
n: '实际发车时间',
v: d.lastDepTime
}, {
n: '定位时间',
v: d.siteTime
},])
olMap.addOverlay('clickOpen', {
id: 'clickOpen',
offset: [0, 4], // 偏移
position: [d.lng, d.lat], // 坐标
// position: [115.944220000000, 28.545380000000],
autoPan: true,
autoPanMargin: 100,
positioning: 'top-right'
})
}
},
geometry: [d.lng, d.lat],
// geometry: [115.944220000000, 28.545380000000],
geometryType: 'Point',
},
],
style: {
icon: {
src: '/assets/images/gis/bus.png',
scale: 0.7, // 图标引用
},
},
selectStyle: {
icon: {
src: '/assets/images/gis/bus.png',
scale: 0.8, // 图标引用
},
},
layerName: 'geometry_bus_' + index
});
});
}
useEffect(() => {
if (busRunData.length && olMap && tab == 'operation') {
if (!busLine.length) {
drawBusRunPoint()
}
}
}, [busRunData, olMap, tab])
useEffect(() => {
if (busLine && olMap && tab == 'operation') {
olMap.addGeometryLayer({
features: [
{
name: 'busLine',
attributes: {
},
geometry: busLine.map(b => {
return [b.pointLng, b.pointLat]
}),
// geometry: [115.944220000000, 28.545380000000],
geometryType: 'LineString',
style: { stroke: { width: 5, color: '#9933FF' } },
selectStyle: { stroke: { width: 8, color: '#9933FF' } },
},
],
style: { stroke: { width: 5, color: '#9933FF' } },
selectStyle: { stroke: { width: 8, color: '#9933FF' } },
layerName: 'geometry_bus_line'
});
if (busLine.length) {
olMap.setCenter([
(busLine[0].pointLng + busLine[busLine.length - 1].pointLng) / 2,
(busLine[0].pointLat + busLine[busLine.length - 1].pointLat) / 2
])
busRunData.forEach((d, index) => {
olMap.removeGeometryLayer('geometry_bus_' + index)
})
} else {
drawBusRunPoint()
}
} else if (tab != 'operation' && olMap) {
olMap.removeGeometryLayer('geometry_bus_line')
}
}, [busLine, olMap, tab])
const isRoadProject = pointItem.report_type == 'road'
// const isBusPoint = pointItem.busNoChar
return (
<div id="olMap" style={{ position: 'absolute', height: '100%', width: "100%" }}>
<div slot="overlays" style={{ display: 'none', }}>
@ -278,14 +419,15 @@ const OlMap = (props) => {
width: 340,
backgroundPosition: 'center',
backgroundSize: '100% 100%',
minHeight: 240,
minHeight: 180,
padding: '24px',
backgroundRepeat: 'no-repeat',
color: '#fff'
}}>
{
olMapOpenData.map(s => {
return <div style={{ display: 'flex' }}>
return (
<div style={{ display: 'flex' }}>
<div style={{ width: 100, textAlign: 'right' }}>{s.n} </div>
<div style={{ flex: 1 }}>
{
@ -297,6 +439,7 @@ const OlMap = (props) => {
}
</div>
</div>
)
})
}
</div>
@ -425,12 +568,14 @@ const OlMap = (props) => {
}
function mapStateToProps (state) {
const { auth, global } = state;
const { auth, global, busRunTime, busLine } = state;
return {
user: auth.user,
actions: global.actions,
olMapArcgisHost: global.olMapArcgisHost,
olMapGeoDataHost: global.olMapGeoDataHost,
busRunTime: busRunTime.data || [],
busLine: busLine.data || [],
};
}

2
web/client/src/utils/webapi.js

@ -200,6 +200,8 @@ export const ApiTable = {
//大屏运营 —— 公交车辆层级信息
getBusTier: '/operation/car_level',
busRealtimeList:'bus/run_realtime',
busLine:'bus/run/line',
//获取路政列表
getHighways: 'road_manage', putHighways: 'road_manage',

Loading…
Cancel
Save