|
|
@ -1,15 +1,12 @@ |
|
|
|
import React, { useEffect, useState } from 'react'; |
|
|
|
import { connect } from 'react-redux'; |
|
|
|
import { render } from 'react-dom'; |
|
|
|
import { Row, Col, Modal, Form, Input, Select, Button } from 'antd'; |
|
|
|
import { Row, Col, message } from 'antd'; |
|
|
|
import FireAddForm from '../components/alarm-add' |
|
|
|
import LoacationSelect from '../components/location-select'; |
|
|
|
import './gis.less' |
|
|
|
const MAPDOMID = 'fs-amap-container-fire'; |
|
|
|
const LOCATION_MAP_ID = 'location_map_id'; |
|
|
|
let map = null; |
|
|
|
let heatmap = null; |
|
|
|
let loca = null; |
|
|
|
let interval = null; |
|
|
|
|
|
|
|
const tabs = [ |
|
|
|
{ name: '应急机构', tab: 'yjjg', className: 'emergency_button' }, |
|
|
@ -18,17 +15,32 @@ const tabs = [ |
|
|
|
{ name: '医疗机构', tab: 'yljg', className: 'emergency_button' }, |
|
|
|
{ name: '避难场所', tab: 'bncs', className: 'emergency_button' }, |
|
|
|
] |
|
|
|
|
|
|
|
const { Option } = Select; |
|
|
|
|
|
|
|
function Map(props) { |
|
|
|
const { dispatch, actions } = props; |
|
|
|
const [delay, setDelay] = useState(true) |
|
|
|
const [tab, setTab] = useState('yjjg') |
|
|
|
const [visible, setVisible] = useState(false) |
|
|
|
const [level, setLevel] = useState('I') |
|
|
|
const [alarmData, setAlarmData] = useState() |
|
|
|
const [locationVisible, setLocationVisible] = useState(false) |
|
|
|
const [lnglat, setLnglat] = useState() |
|
|
|
const [location, setLocation] = useState({}) |
|
|
|
const [alarmList, setAlarmList] = useState() |
|
|
|
//查询告警列表数据
|
|
|
|
const getData = () => { |
|
|
|
dispatch(actions?.firecontrol?.getFireAlarmList()).then(res => { |
|
|
|
if (res?.payload?.data) { |
|
|
|
setAlarmList(res?.payload?.data) |
|
|
|
} |
|
|
|
}) |
|
|
|
} |
|
|
|
useEffect(() => { |
|
|
|
if (!delay && alarmList?.length > 0) { |
|
|
|
setTimeout(() => { |
|
|
|
map && renderAlarms() |
|
|
|
}, 1000); |
|
|
|
} |
|
|
|
}, [delay, alarmList]) |
|
|
|
|
|
|
|
// 地图初始化
|
|
|
|
const loadMap = () => { |
|
|
|
// 图片图层 实现瓦片地图中国地图样式 bounds 第一个点为左下角 第二个点为右上角
|
|
|
@ -59,14 +71,14 @@ function Map(props) { |
|
|
|
|
|
|
|
|
|
|
|
map.on('complete', () => { |
|
|
|
map.setZoom(17.4) |
|
|
|
map.setCenter([115.922069, 28.554867]) |
|
|
|
map.setPitch(47.30) |
|
|
|
map.setRotation(1.7000) |
|
|
|
// map.setZoom(17.4)
|
|
|
|
// map.setCenter([115.922069, 28.554867])
|
|
|
|
// map.setPitch(47.30)
|
|
|
|
// map.setRotation(1.7000)
|
|
|
|
setTimeout(() => { |
|
|
|
setDelay(false) |
|
|
|
}, 1000); |
|
|
|
map && renderAlarms() |
|
|
|
|
|
|
|
}); |
|
|
|
|
|
|
|
map.on('click', (e) => { |
|
|
@ -84,16 +96,12 @@ function Map(props) { |
|
|
|
console.log('Rotation' + Rotation) |
|
|
|
console.log('e.lnglat' + e.lnglat) |
|
|
|
}) |
|
|
|
|
|
|
|
loca = new Loca.Container({ map: map }) |
|
|
|
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
// 初始化GIS 组件销毁清空定时器
|
|
|
|
useEffect(() => { |
|
|
|
loadMap(); |
|
|
|
|
|
|
|
getData() |
|
|
|
}, []); |
|
|
|
|
|
|
|
useEffect(() => { |
|
|
@ -101,54 +109,23 @@ function Map(props) { |
|
|
|
}, [level]) |
|
|
|
|
|
|
|
|
|
|
|
useEffect(() => { |
|
|
|
|
|
|
|
setTimeout(() => { |
|
|
|
if (locationVisible && document.getElementById(LOCATION_MAP_ID)) { |
|
|
|
const locationMap = new AMap.Map(LOCATION_MAP_ID, { |
|
|
|
// center: [116.054664, 28.538966],
|
|
|
|
zoomEnable: true, |
|
|
|
dragEnable: true, |
|
|
|
cursor: 'pointer', |
|
|
|
}); |
|
|
|
|
|
|
|
locationMap.on('click', (e) => { |
|
|
|
locationMap.clearMap(); |
|
|
|
const marker = new AMap.Marker({ |
|
|
|
icon: '/assets/images/homepage/fire/position.png', |
|
|
|
position: e.lnglat, |
|
|
|
offset: new AMap.Pixel(-5, -15) |
|
|
|
}); |
|
|
|
marker.setMap(locationMap); |
|
|
|
setLnglat(e.lnglat.lng + ',' + e.lnglat.lat) |
|
|
|
}) |
|
|
|
} |
|
|
|
}, 200); |
|
|
|
|
|
|
|
|
|
|
|
}, [locationVisible]) |
|
|
|
|
|
|
|
const renderAlarms = () => { |
|
|
|
// map.clearMap();
|
|
|
|
const alarms = [ |
|
|
|
{ lng: 115.92365, lat: 28.557404, type: 'device', name: '廉租房1', kind: 'markeralarm' }, |
|
|
|
] |
|
|
|
|
|
|
|
alarms.map((x, index) => { |
|
|
|
alarmList?.map((x, index) => { |
|
|
|
var marker = new AMap.Marker({ |
|
|
|
position: new AMap.LngLat(x.lng, x.lat), |
|
|
|
position: new AMap.LngLat(x.longitude, x.latitude), |
|
|
|
// 将一张图片的地址设置为 icon
|
|
|
|
icon: '/assets/images/homepage/communtity/' + x.kind + '.png', |
|
|
|
icon: '/assets/images/homepage/communtity/markeralarm.png', |
|
|
|
// 设置了 icon 以后,设置 icon 的偏移量,以 icon 的 [center bottom] 为原点
|
|
|
|
offset: new AMap.Pixel(-13, -30), |
|
|
|
zooms: [15, 19], |
|
|
|
zooms: [3, 19], |
|
|
|
}); |
|
|
|
marker.setTitle(x.name); |
|
|
|
marker.setTitle(x.location); |
|
|
|
map.add(marker); |
|
|
|
|
|
|
|
var circle = new AMap.Circle({ |
|
|
|
center: [x.lng, x.lat], |
|
|
|
radius: 300, //半径
|
|
|
|
center: [x.longitude, x.latitude], |
|
|
|
radius: 5000, //半径
|
|
|
|
borderWeight: 3, |
|
|
|
strokeColor: "#AE0000", |
|
|
|
strokeOpacity: 1, |
|
|
@ -167,24 +144,20 @@ function Map(props) { |
|
|
|
let infowindow = new AMap.InfoWindow({ |
|
|
|
isCustom: true, //使用自定义窗体
|
|
|
|
content: `<div id="map-content" class="fire-gis-infowindow fire-gis-infowindow-alarm">
|
|
|
|
<div style="height:${360}px;" id="alarmcontentid${x.name}"></div></div>`, |
|
|
|
<div style="height:${360}px;" id="alarmcontentid${x.location}"></div></div>`, |
|
|
|
offset: new AMap.Pixel(233, 260) |
|
|
|
}); |
|
|
|
|
|
|
|
let alarmOk = new AMap.InfoWindow({ |
|
|
|
isCustom: true, //使用自定义窗体
|
|
|
|
// content: `<div id="map-content" class="gis-infowindow gis-infowindow-alarm">
|
|
|
|
// <div style="height:${360}px;" id="contentid${x.name}"></div></div>`,
|
|
|
|
offset: new AMap.Pixel(233, 440) |
|
|
|
}); |
|
|
|
|
|
|
|
marker.on('click', () => { |
|
|
|
let position = marker.getPosition ? marker.getPosition() : marker.getCenter(); |
|
|
|
infowindow.open(map, position); |
|
|
|
map.setCenter(position) |
|
|
|
map.setZoom(17.4) |
|
|
|
map.setPitch(47.30) |
|
|
|
map.setRotation(1.7000) |
|
|
|
setAlarmData(x) |
|
|
|
setTimeout(() => { |
|
|
|
if (document.getElementById(`alarmcontentid${x.name}`)) { |
|
|
|
if (document.getElementById(`alarmcontentid${x.location}`)) { |
|
|
|
renderAlarmInfowindow(x) |
|
|
|
} |
|
|
|
}, 50) |
|
|
@ -192,15 +165,84 @@ function Map(props) { |
|
|
|
}) |
|
|
|
} |
|
|
|
|
|
|
|
//驾车路线规划
|
|
|
|
const drawDrivings = (location1, location2) => { |
|
|
|
var driving = new AMap.Driving({ |
|
|
|
map: map, |
|
|
|
}); |
|
|
|
// 根据起终点经纬度规划驾车导航路线
|
|
|
|
driving.search(new AMap.LngLat(location1[0], location1[1]), new AMap.LngLat(location2[0], location2[1]), function (status, result) { |
|
|
|
// result 即是对应的驾车导航信息,相关数据结构文档请参考 https://lbs.amap.com/api/javascript-api/reference/route-search#m_DrivingResult
|
|
|
|
if (status === 'complete') { |
|
|
|
if (result.routes && result.routes.length) { |
|
|
|
// 绘制第一条路线,也可以按需求绘制其它几条路线
|
|
|
|
drawRoute(result.routes[0]) |
|
|
|
} |
|
|
|
} else { |
|
|
|
} |
|
|
|
}); |
|
|
|
// driving.clear() //清除路线
|
|
|
|
} |
|
|
|
|
|
|
|
function drawRoute(route) { |
|
|
|
var path = parseRouteToPath(route) |
|
|
|
|
|
|
|
// var startMarker = new AMap.Marker({
|
|
|
|
// position: path[0],
|
|
|
|
// icon: 'https://webapi.amap.com/theme/v1.3/markers/n/start.png',
|
|
|
|
// map: map
|
|
|
|
// })
|
|
|
|
|
|
|
|
// var endMarker = new AMap.Marker({
|
|
|
|
// position: path[path.length - 1],
|
|
|
|
// icon: 'https://webapi.amap.com/theme/v1.3/markers/n/end.png',
|
|
|
|
// map: map
|
|
|
|
// })
|
|
|
|
|
|
|
|
var routeLine = new AMap.Polyline({ |
|
|
|
path: path, |
|
|
|
isOutline: true, |
|
|
|
outlineColor: '#ffeeee', |
|
|
|
borderWeight: 2, |
|
|
|
strokeWeight: 5, |
|
|
|
strokeOpacity: 0.9, |
|
|
|
strokeColor: '#0091ff', |
|
|
|
lineJoin: 'round' |
|
|
|
}) |
|
|
|
|
|
|
|
map.add(routeLine); |
|
|
|
|
|
|
|
// 调整视野达到最佳显示区域
|
|
|
|
map.setFitView([startMarker, endMarker, routeLine]) |
|
|
|
} |
|
|
|
|
|
|
|
// 解析DrivingRoute对象,构造成AMap.Polyline的path参数需要的格式
|
|
|
|
// DrivingResult对象结构参考文档 https://lbs.amap.com/api/javascript-api/reference/route-search#m_DriveRoute
|
|
|
|
function parseRouteToPath(route) { |
|
|
|
var path = [] |
|
|
|
|
|
|
|
for (var i = 0, l = route.steps.length; i < l; i++) { |
|
|
|
var step = route.steps[i] |
|
|
|
|
|
|
|
for (var j = 0, n = step.path.length; j < n; j++) { |
|
|
|
path.push(step.path[j]) |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
return path |
|
|
|
} |
|
|
|
|
|
|
|
const renderAlarmInfowindow = (x) => { |
|
|
|
return x && render(<div> |
|
|
|
<div className='gis_exit' onClick={() => { |
|
|
|
map.setCenter([115.922069, 28.554867]) |
|
|
|
map.setCenter([116.054664, 28.538966]) |
|
|
|
map.setZoom(10.3) |
|
|
|
map.setPitch(22.9) |
|
|
|
map.setRotation(0) |
|
|
|
map.clearInfoWindow(); |
|
|
|
}} /> |
|
|
|
|
|
|
|
<div className='gis_item'> |
|
|
|
{/* <div className='gis_item'> |
|
|
|
<span className='gis_title'>地址信息:</span> |
|
|
|
<span className='gis_text'>南湖大道</span> |
|
|
|
</div> |
|
|
@ -211,12 +253,12 @@ function Map(props) { |
|
|
|
<div className='gis_item'> |
|
|
|
<span className='gis_title'>告警内容</span> |
|
|
|
<span className='gis_text'>火情</span> |
|
|
|
</div> |
|
|
|
</div> */} |
|
|
|
|
|
|
|
<div className='clear_alarm'>消除警情</div> |
|
|
|
{/* <div className='clear_alarm'>消除警情</div> */} |
|
|
|
|
|
|
|
<div><span className='confirm_text'>请根据火灾态势,选择应急预案等级</span></div> |
|
|
|
<Row style={{ paddingLeft: 16, paddingRight: 16, marginTop: 12 }}> |
|
|
|
<div style={{ marginTop: 50 }}><span className='confirm_text' >请根据火灾态势,选择应急预案等级</span></div> |
|
|
|
<Row style={{ paddingLeft: 16, paddingRight: 16, marginTop: 12, marginTop: 20 }}> |
|
|
|
{['I', 'II', 'III', 'IV'].map(s => { |
|
|
|
return <Col |
|
|
|
onClick={() => { setLevel(s) }} |
|
|
@ -229,86 +271,35 @@ function Map(props) { |
|
|
|
</Row> |
|
|
|
<div className='alarm_confirm'> |
|
|
|
<div className='alarm_cancel'>否</div> |
|
|
|
<div className='alarm_ok' onClick={() => { props.alarmOk() }}>是</div> |
|
|
|
<div className='alarm_ok' onClick={() => { |
|
|
|
map.clearInfoWindow(); |
|
|
|
drawDrivings([x.longitude, x.latitude], [115.895753, 28.553354]) |
|
|
|
props.alarmOk() |
|
|
|
}}>是</div> |
|
|
|
</div> |
|
|
|
</div>, |
|
|
|
document.getElementById(`alarmcontentid${x.name}`)); |
|
|
|
document.getElementById(`alarmcontentid${x.location}`)); |
|
|
|
} |
|
|
|
|
|
|
|
const renderLeftTop = () => { |
|
|
|
return <div className='home_left_add' onClick={() => { setVisible(true) }} /> |
|
|
|
} |
|
|
|
|
|
|
|
const layout = { |
|
|
|
labelCol: { span: 8 }, |
|
|
|
wrapperCol: { span: 12 }, |
|
|
|
}; |
|
|
|
|
|
|
|
const [form] = Form.useForm(); |
|
|
|
const renderInfowindow = () => { |
|
|
|
return <div className='report_container'> |
|
|
|
<div className='gis_exit' onClick={() => { setVisible(false) }} /> |
|
|
|
<Form |
|
|
|
form={form} |
|
|
|
{...layout} |
|
|
|
name="control-hooks" |
|
|
|
style={{ maxWidth: 600 }} |
|
|
|
> |
|
|
|
<Form.Item name="createTime" label="时间" rules={[{ required: true, message: '请选择时间!' }]} > |
|
|
|
<Select placeholder="请选择事件时间" > </Select> |
|
|
|
</Form.Item> |
|
|
|
<Form.Item onFocus={() => { |
|
|
|
setLocationVisible(true) |
|
|
|
}} |
|
|
|
name="地点" label="地点" > |
|
|
|
{/* <Select placeholder="请选择事件地点" > </Select> */} |
|
|
|
<div |
|
|
|
onClick={() => { setLocationVisible(true) }} |
|
|
|
style={{ color: 'rgba(89, 153, 200, 1)', paddingLeft: 12 }}>请选择事件地点</div> |
|
|
|
</Form.Item> |
|
|
|
<Form.Item name="场所" label="场所" rules={[{ required: true, message: '请选择场所!' }]}> |
|
|
|
<Select placeholder="请选择事件场所" > </Select> |
|
|
|
</Form.Item> |
|
|
|
<Form.Item name="燃烧物质" label="燃烧物质" rules={[{ required: true, message: '请选择燃烧物质!' }]}> |
|
|
|
<Select placeholder="请选择事件燃烧物质" > </Select> |
|
|
|
</Form.Item> |
|
|
|
<Form.Item name="危险等级" label="危险等级" rules={[{ required: true, message: '请选择危险等级!' }]} > |
|
|
|
<Select placeholder="请选择事件危险等级" > </Select> |
|
|
|
</Form.Item> |
|
|
|
|
|
|
|
<div className='flex-row flex-content-around'> |
|
|
|
<div className='cancel_button' onClick={() => { setVisible(false) }}>取消</div> |
|
|
|
<div onClick={() => { form?.submit() }} className='report_button'>上报</div> |
|
|
|
</div> |
|
|
|
|
|
|
|
</Form> |
|
|
|
|
|
|
|
|
|
|
|
</div > |
|
|
|
} |
|
|
|
|
|
|
|
const renderLocationInfowindow = () => { |
|
|
|
return <div className='location_infowindow'> |
|
|
|
<div className='gis_exit' onClick={() => { setLocationVisible(false) }} /> |
|
|
|
|
|
|
|
<div className='info_div'> |
|
|
|
<span className='location_title'>经纬度:</span> |
|
|
|
<span>{lnglat}</span> |
|
|
|
</div> |
|
|
|
<div className='info_div'> |
|
|
|
<span className='location_title'>坐标点位置:</span> |
|
|
|
<Input style={{ width: '70%' }} /> |
|
|
|
</div> |
|
|
|
<div id={LOCATION_MAP_ID} className='location_map'></div> |
|
|
|
const onFinish = (values) => { |
|
|
|
|
|
|
|
<div className='location_btn_container'> |
|
|
|
<div className='reset_btn'> |
|
|
|
重置点位 |
|
|
|
</div> |
|
|
|
<div className='ok_btn'> |
|
|
|
确认选择 |
|
|
|
</div> |
|
|
|
</div> |
|
|
|
</div> |
|
|
|
dispatch(actions.firecontrol.addFireAlarm( |
|
|
|
{ |
|
|
|
...values, |
|
|
|
state: 1, |
|
|
|
location: location?.location, |
|
|
|
longitude: location?.lnglat?.split(',')[0], |
|
|
|
latitude: location?.lnglat?.split(',')[1], |
|
|
|
} |
|
|
|
)).then(res => { |
|
|
|
//getData()
|
|
|
|
message.success('新增上报信息成功') |
|
|
|
setVisible(false) |
|
|
|
}) |
|
|
|
} |
|
|
|
|
|
|
|
return ( |
|
|
@ -354,22 +345,20 @@ function Map(props) { |
|
|
|
<FireAddForm |
|
|
|
visible={visible} |
|
|
|
onCancel={() => setVisible(false)} |
|
|
|
locationClick={() => setLocationVisible(true)} |
|
|
|
location={location} |
|
|
|
onFinish={onFinish} |
|
|
|
/> |
|
|
|
|
|
|
|
{/* 位置选点 */} |
|
|
|
<Modal |
|
|
|
maskClosable={false} |
|
|
|
wrapClassName="custom-modal" |
|
|
|
visible={locationVisible} |
|
|
|
closable={false} |
|
|
|
width="569px" |
|
|
|
centered |
|
|
|
footer={null} |
|
|
|
bodyStyle={{}} |
|
|
|
destroyOnClose |
|
|
|
> |
|
|
|
{renderLocationInfowindow()} |
|
|
|
</Modal> |
|
|
|
<LoacationSelect |
|
|
|
locationVisible={locationVisible} |
|
|
|
onCancel={() => setLocationVisible(false)} |
|
|
|
locationSelect={(location) => { |
|
|
|
setLocation(location) |
|
|
|
setLocationVisible(false) |
|
|
|
}} |
|
|
|
/> |
|
|
|
</> |
|
|
|
); |
|
|
|
} |
|
|
|