-
BINsrc/assets/images/equip/home/kx.png
-
BINsrc/assets/images/equip/home/mark_green.png
-
BINsrc/assets/images/equip/home/mark_red.png
-
BINsrc/assets/images/equip/home/mark_yellow.png
-
BINsrc/assets/images/equip/home/poto.png
-
BINsrc/assets/images/equip/home/rerm.png
-
BINsrc/assets/images/equip/home/yc.png
-
215src/components/MapComponets/BaseMap/index.jsx
-
47src/components/MapComponets/MarkCenter/index.jsx
-
189src/components/MapComponets/ParkingViewMarkers/index.jsx
-
71src/components/MapComponets/ParkingViewMarkers/index.scss
-
16src/components/MapComponets/index.jsx
-
7src/pages/DataAnalysisPrediction/MemberStat/ParkingAly/index.scss
-
157src/pages/DataAnalysisPrediction/MemberStat/ParkingAly/loadable.jsx
-
7src/pages/DataAnalysisPrediction/MemberStat/PayAly/index.scss
-
405src/pages/DataAnalysisPrediction/MemberStat/PayAly/loadable.jsx
-
302src/pages/DataAnalysisPrediction/MemberStat/RegisterAly/loadable.jsx
-
466src/pages/DataAnalysisPrediction/ParkingOverview/index.scss
-
1553src/pages/DataAnalysisPrediction/ParkingOverview/loadable.jsx
-
35src/services/ElectInvoice/index.js
-
100src/services/ParkingOverview/index.js
-
2src/services/index.js
After Width: 194 | Height: 122 | Size: 5.4 KiB |
After Width: 29 | Height: 35 | Size: 1.7 KiB |
After Width: 29 | Height: 35 | Size: 1.7 KiB |
After Width: 29 | Height: 35 | Size: 1.7 KiB |
After Width: 18 | Height: 16 | Size: 1.2 KiB |
After Width: 11 | Height: 14 | Size: 1.1 KiB |
After Width: 194 | Height: 122 | Size: 16 KiB |
@ -0,0 +1,47 @@ |
|||||
|
import React, { useState, useEffect, useRef } from "react"; |
||||
|
import L from "leaflet"; |
||||
|
import "leaflet/dist/leaflet.css"; |
||||
|
// import "leaflet-canvas-marker" |
||||
|
import "../js/leaflet.canvas-markers"; |
||||
|
// import "./index.scss"; |
||||
|
import Rerm from "../Marker/default-marker2.png"; |
||||
|
|
||||
|
function Markers(props) { |
||||
|
const map = props.__map__; |
||||
|
const { |
||||
|
data = {}, |
||||
|
iconSize = [30, 40], // 点位图片大小 |
||||
|
iconAnchor = [11, 11], // 图片偏移量 |
||||
|
} = props; |
||||
|
const [Marker, setMarker] = useState(null); |
||||
|
useEffect(() => { |
||||
|
if (data.lng) { |
||||
|
addMarker(data); |
||||
|
} |
||||
|
}, [data]); |
||||
|
const addMarker = (data) => { |
||||
|
if (Marker) { |
||||
|
map.removeLayer(Marker); |
||||
|
} |
||||
|
let marker = L.marker([data.lat, data.lng], { |
||||
|
icon: L.icon({ |
||||
|
iconUrl: Rerm, |
||||
|
iconSize, |
||||
|
iconAnchor, |
||||
|
}), |
||||
|
}) |
||||
|
.addTo(map) |
||||
|
.bindTooltip(`<span>${data.name}</span>`, { |
||||
|
offset: [20, -5], |
||||
|
direction: "right", |
||||
|
}); |
||||
|
setMarker(marker); |
||||
|
setTimeout(() => { |
||||
|
map.setView([data.lat, data.lng]); |
||||
|
}, 800); |
||||
|
}; |
||||
|
|
||||
|
return null; |
||||
|
} |
||||
|
|
||||
|
export default Markers; |
@ -0,0 +1,189 @@ |
|||||
|
import React, { useState, useEffect, useRef } from "react"; |
||||
|
import L from "leaflet"; |
||||
|
import "leaflet/dist/leaflet.css"; |
||||
|
// import "leaflet-canvas-marker" |
||||
|
import "../js/leaflet.canvas-markers"; |
||||
|
import "./index.scss"; |
||||
|
import mgreen from "@/assets/images/equip/home/mark_green.png"; |
||||
|
import mgred from "@/assets/images/equip/home/mark_red.png"; |
||||
|
import mgyellow from "@/assets/images/equip/home/mark_yellow.png"; |
||||
|
|
||||
|
function Markers(props) { |
||||
|
const map = props.__map__; |
||||
|
const { |
||||
|
data = [], |
||||
|
iconSize = [30, 40], // 点位图片大小 |
||||
|
iconAnchor = [15, 20], // 图片偏移量 |
||||
|
tooltipKey = "name", // 提示信息的key |
||||
|
// contentCb, // 生成弹窗显示内容方法事件 |
||||
|
clickCb, // 点击事件 |
||||
|
} = props; |
||||
|
const [massLayer, setMassLayer] = useState(null); // 海量点图层 |
||||
|
const massLayerRef = useRef(massLayer); |
||||
|
massLayerRef.current = massLayer; |
||||
|
const [massObj, setMassObj] = useState({}); // 海量点对象 |
||||
|
const massObjRef = useRef(); |
||||
|
massObjRef.current = massObj; |
||||
|
// const imgurls = (val) => { |
||||
|
|
||||
|
// } |
||||
|
useEffect(() => { |
||||
|
return () => { |
||||
|
if (map && massLayerRef.current) { |
||||
|
if (massLayerRef.current._latlngMarkers) { |
||||
|
// 判断是否有点位存在 |
||||
|
massLayerRef.current.clearLayers(); // 清除点位图层 |
||||
|
} |
||||
|
} |
||||
|
}; |
||||
|
}, []); |
||||
|
|
||||
|
useEffect(() => { |
||||
|
if (map && !massLayer) { |
||||
|
let _massLayer = L.canvasIconLayer({}); // 创建海量点图层 |
||||
|
setMassLayer(_massLayer); |
||||
|
_massLayer.addTo(map); |
||||
|
if (data.length) { |
||||
|
let _mass = handleLocation(data); // 处理点位数据 |
||||
|
addMarker(_mass, _massLayer); // 添加点位 |
||||
|
} |
||||
|
} |
||||
|
}, [map]); |
||||
|
|
||||
|
useEffect(() => { |
||||
|
if (massLayerRef.current) { |
||||
|
if (massLayerRef.current._latlngMarkers) { |
||||
|
// 判断是否有点位存在 |
||||
|
massLayerRef.current.clearLayers(); // 清除点位图层 |
||||
|
massLayerRef.current._onClickListeners = []; // 清除监听事件 |
||||
|
} |
||||
|
if (data.length) { |
||||
|
let _mass = handleLocation(data); // 处理点位数据 |
||||
|
addMarker(_mass, massLayerRef.current); // 添加点位 |
||||
|
} |
||||
|
} |
||||
|
}, [data]); |
||||
|
|
||||
|
const handleLocation = (arr = []) => { |
||||
|
if (!Array.isArray(arr)) { |
||||
|
console.log("传值必须为数组"); |
||||
|
return false; |
||||
|
} |
||||
|
let object = {}; |
||||
|
for (let i = 0; i < arr.length; i++) { |
||||
|
let elem = arr[i]; |
||||
|
if (!parseFloat(elem.latitude) || !parseFloat(elem.longitude)) { |
||||
|
// 经纬度必须有 |
||||
|
continue; |
||||
|
} |
||||
|
let typeKey = "type_" + elem.type; |
||||
|
if (object.hasOwnProperty(typeKey)) { |
||||
|
object[typeKey].nodes.push({ |
||||
|
lnglat: [parseFloat(elem.lat), parseFloat(elem.lng)], |
||||
|
name: elem.text, |
||||
|
style: 0, |
||||
|
locationId: elem.id, |
||||
|
type: elem.type, |
||||
|
action: elem.action, |
||||
|
data: elem, |
||||
|
}); |
||||
|
} else { |
||||
|
object[typeKey] = { |
||||
|
type: elem.type, |
||||
|
iconStyle: [ |
||||
|
L.icon({ |
||||
|
iconUrl: |
||||
|
elem.type == 1 ? mgred : elem.type == 3 ? mgreen : mgyellow, |
||||
|
iconSize: iconSize, |
||||
|
iconAnchor: iconAnchor, |
||||
|
}), |
||||
|
], |
||||
|
nodes: [ |
||||
|
{ |
||||
|
lnglat: [parseFloat(elem.lat), parseFloat(elem.lng)], |
||||
|
name: elem.text, |
||||
|
style: 0, |
||||
|
locationId: elem.id, |
||||
|
type: elem.type, |
||||
|
action: elem.action, |
||||
|
data: elem, |
||||
|
}, |
||||
|
], |
||||
|
}; |
||||
|
} |
||||
|
} |
||||
|
setMassObj(object); |
||||
|
return object; |
||||
|
}; |
||||
|
|
||||
|
const addMarker = (markerArr, _massLayer) => { |
||||
|
for (let [key, value] of Object.entries(markerArr)) { |
||||
|
if (!value.hasOwnProperty("massMarkers")) { |
||||
|
value.massMarkers = []; |
||||
|
value.nodes.forEach((elem) => { |
||||
|
let marker = L.marker([elem.lnglat[0], elem.lnglat[1]], { |
||||
|
icon: value.iconStyle[0], |
||||
|
}); |
||||
|
marker.data = elem; |
||||
|
value.massMarkers.push(marker); |
||||
|
marker.bindTooltip(`<span>${elem[tooltipKey]}</span>`, { |
||||
|
offset: [20, -5], |
||||
|
direction: "right", |
||||
|
}); |
||||
|
}); |
||||
|
_massLayer.addLayers(value.massMarkers); |
||||
|
} else { |
||||
|
_massLayer.addLayers(value.massMarkers); |
||||
|
} |
||||
|
} |
||||
|
_massLayer._onClickListeners = []; |
||||
|
if (clickCb) { |
||||
|
_massLayer.addOnClickListener(function (e, data) { |
||||
|
if (data.length == "1") { |
||||
|
let elem = data[0].data.data.data; |
||||
|
clickCb(elem); |
||||
|
} else { |
||||
|
map.openPopup(renderMarkerList(data), e.latlng, { |
||||
|
className: "markers-list-box", |
||||
|
}); |
||||
|
let dom = document.querySelectorAll(".marker-list-item"); |
||||
|
dom.forEach((elem) => { |
||||
|
elem.addEventListener("click", function (e) { |
||||
|
map.closePopup(); |
||||
|
let type = e.target.dataset.type, |
||||
|
id = e.target.dataset.id; |
||||
|
let marker = massObjRef.current["type_" + type].nodes.filter( |
||||
|
(i) => i.locationId == id |
||||
|
)[0]; |
||||
|
let elem = marker.data; |
||||
|
clickCb(elem); |
||||
|
}); |
||||
|
}); |
||||
|
} |
||||
|
}); |
||||
|
} |
||||
|
let markers = []; |
||||
|
for (let [key, value] of Object.entries(markerArr)) { |
||||
|
markers = [...markers, ...value.massMarkers]; |
||||
|
} |
||||
|
}; |
||||
|
|
||||
|
const renderMarkerList = (data) => { |
||||
|
let template = `<div class="marker-list-content"> |
||||
|
<div class="marker-list-header">请选择点位</div> |
||||
|
<div class="marker-list"> |
||||
|
`; |
||||
|
data.forEach((elem) => { |
||||
|
let _data = elem.data.data; |
||||
|
if (_data.name && _data.locationId) { |
||||
|
template += `<div class="marker-list-item" data-type="${_data.type}" data-id="${_data.locationId}" title="${_data.name}">${_data.name}</div>`; |
||||
|
} |
||||
|
}); |
||||
|
template += `</div></div>`; |
||||
|
return template; |
||||
|
}; |
||||
|
|
||||
|
return null; |
||||
|
} |
||||
|
|
||||
|
export default Markers; |
@ -0,0 +1,71 @@ |
|||||
|
.markers-list-box { |
||||
|
width: 300px !important; |
||||
|
.leaflet-popup-content-wrapper { |
||||
|
padding: 0; |
||||
|
border-radius: 0; |
||||
|
color: #ccddff; |
||||
|
background: #172c4d !important; |
||||
|
} |
||||
|
.leaflet-popup-content { |
||||
|
margin: 0; |
||||
|
width: 100% !important; |
||||
|
} |
||||
|
.leaflet-popup-tip-container { |
||||
|
.leaflet-popup-tip { |
||||
|
background: #172c4d; |
||||
|
} |
||||
|
} |
||||
|
.leaflet-popup-close-button { |
||||
|
display: none; |
||||
|
} |
||||
|
.marker-list-content { |
||||
|
.marker-list-header { |
||||
|
height: 32px; |
||||
|
line-height: 32px; |
||||
|
vertical-align: middle; |
||||
|
padding: 0 10px; |
||||
|
font-size: 14px; |
||||
|
font-weight: bold; |
||||
|
letter-spacing: 1px; |
||||
|
width: 100%; |
||||
|
overflow: hidden; |
||||
|
white-space: nowrap; |
||||
|
text-overflow: ellipsis; |
||||
|
} |
||||
|
.marker-list { |
||||
|
padding: 10px; |
||||
|
color: var(--color-text); |
||||
|
max-height: 200px; |
||||
|
overflow-y: auto; |
||||
|
overflow-x: hidden; |
||||
|
&::-webkit-scrollbar-track-piece { |
||||
|
background-color: transparent; |
||||
|
border-radius: 8px; |
||||
|
} |
||||
|
&::-webkit-scrollbar { |
||||
|
width: 8px; |
||||
|
height: 8px; |
||||
|
} |
||||
|
&::-webkit-scrollbar-thumb { |
||||
|
background-clip: padding-box; |
||||
|
border-radius: 8px; |
||||
|
min-height: 28px; |
||||
|
} |
||||
|
.marker-list-item { |
||||
|
width: 100%; |
||||
|
height: 24px; |
||||
|
line-height: 24px; |
||||
|
white-space: nowrap; |
||||
|
overflow: hidden; |
||||
|
text-overflow: ellipsis; |
||||
|
cursor: pointer; |
||||
|
&:hover { |
||||
|
text-decoration: underline; |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
.construction-polygon { |
||||
|
font-size: 14px; |
||||
|
} |
@ -1,11 +1,15 @@ |
|||||
import BaseMap from "./BaseMap" |
|
||||
import BaseGaodeMap from "./BaseGaodeMap" |
|
||||
import Markers from "./Markers" |
|
||||
import Marker from "./Marker" |
|
||||
|
import BaseMap from "./BaseMap"; |
||||
|
import BaseGaodeMap from "./BaseGaodeMap"; |
||||
|
import Markers from "./Markers"; |
||||
|
import Marker from "./Marker"; |
||||
|
import ParkingViewMarkers from "./ParkingViewMarkers"; |
||||
|
import MarkCenter from "./MarkCenter"; |
||||
|
|
||||
export { |
export { |
||||
BaseMap, |
BaseMap, |
||||
BaseGaodeMap, |
BaseGaodeMap, |
||||
Markers, |
Markers, |
||||
Marker |
|
||||
} |
|
||||
|
Marker, |
||||
|
MarkCenter, |
||||
|
ParkingViewMarkers, |
||||
|
}; |
1553
src/pages/DataAnalysisPrediction/ParkingOverview/loadable.jsx
File diff suppressed because it is too large
View File
@ -0,0 +1,100 @@ |
|||||
|
import ajax from "../../config/ajax"; |
||||
|
//-----------------------------停车业务概括数据----------------------------------
|
||||
|
export default { |
||||
|
//获取泊位总数弹框数据列表
|
||||
|
getParkingBoW: (params) => { |
||||
|
return ajax({ |
||||
|
url: "/api/ana/overview/berthList", |
||||
|
type: "post", |
||||
|
data: params, |
||||
|
}); |
||||
|
}, |
||||
|
//获取实时泊位显示数据
|
||||
|
getSituationData: (params) => { |
||||
|
return ajax({ |
||||
|
url: "/api/ana/overview/berthSituation", |
||||
|
type: "get", |
||||
|
data: params, |
||||
|
}); |
||||
|
}, |
||||
|
//获取实时泊位显示数据详情
|
||||
|
getSituationDetailData: (params) => { |
||||
|
return ajax({ |
||||
|
url: "/api/ana/overview/getBerthDetail", |
||||
|
type: "get", |
||||
|
data: params, |
||||
|
}); |
||||
|
}, |
||||
|
//获取地图车场数据
|
||||
|
getMapData: (params) => { |
||||
|
return ajax({ |
||||
|
url: "/api/ana/overview/getParks", |
||||
|
type: "get", |
||||
|
data: params, |
||||
|
}); |
||||
|
}, |
||||
|
//获取停车场模糊检索
|
||||
|
searchPark: (params) => { |
||||
|
return ajax({ |
||||
|
url: "/api/ana/overview/searchPaking", |
||||
|
type: "get", |
||||
|
data: params, |
||||
|
}); |
||||
|
}, |
||||
|
//获取位置模糊检索
|
||||
|
searchGeocode: (params) => { |
||||
|
return ajax({ |
||||
|
url: "/api/ana/overview/geocode", |
||||
|
type: "get", |
||||
|
data: params, |
||||
|
}); |
||||
|
}, |
||||
|
//获取今日收入和服务车辆
|
||||
|
GetDataStatic: (params) => { |
||||
|
return ajax({ |
||||
|
url: "/api/ana/overview/dataStatic", |
||||
|
type: "get", |
||||
|
data: params, |
||||
|
}); |
||||
|
}, |
||||
|
//获取收入分析
|
||||
|
GetRevenueAnalysis: (params) => { |
||||
|
return ajax({ |
||||
|
url: "/api/ana/overview/revenueAnalysis", |
||||
|
type: "get", |
||||
|
data: params, |
||||
|
}); |
||||
|
}, |
||||
|
//获取车场评价
|
||||
|
GetParkingEvaluate: (params) => { |
||||
|
return ajax({ |
||||
|
url: "/api/ana/overview/parkingEvaluate", |
||||
|
type: "get", |
||||
|
data: params, |
||||
|
}); |
||||
|
}, |
||||
|
//获取客诉类型分析
|
||||
|
GetComplaintType: (params) => { |
||||
|
return ajax({ |
||||
|
url: "/api/ana/overview/complaintType", |
||||
|
type: "get", |
||||
|
data: params, |
||||
|
}); |
||||
|
}, |
||||
|
//获取左边数据(不包括7日利用率和周转)
|
||||
|
GetOverviewData: (params) => { |
||||
|
return ajax({ |
||||
|
url: "/api/ana/overview/overviewData", |
||||
|
type: "get", |
||||
|
data: params, |
||||
|
}); |
||||
|
}, |
||||
|
//获取左边数据(7日利用率和周转)
|
||||
|
GetUseInfo: (params) => { |
||||
|
return ajax({ |
||||
|
url: "/api/ana/overview/berthUseInfo", |
||||
|
type: "get", |
||||
|
data: params, |
||||
|
}); |
||||
|
}, |
||||
|
}; |