Swanky 2 years ago
parent 120fb10d65
commit b0fb0c6512
  1. 14
      public/config/app.json
  2. 1
      public/index.html
  3. 3
      src/components/Main/Content/FilterPanel/index.js
  4. 22
      src/components/Main/Content/index.js
  5. 20
      src/components/Main/Map/ImageLayer/index.js
  6. 3
      src/components/Main/Map/MapContext.js
  7. 26
      src/components/Main/Map/ZoneLayer/index.js
  8. 93
      src/components/Main/Map/index.js
  9. 82
      src/components/Main/Map/utils/helper.js
  10. 34
      src/components/Main/components/Cdth/CdthFilter/index.js
  11. 39
      src/components/Main/components/Cdzzy/CdzzyFilter/index.js
  12. 37
      src/components/Main/components/Stxfgc/StxfgcFilter/index.js
  13. 26
      src/components/Main/components/Wlwsb/WlwsbFilter/index.js
  14. 34
      src/components/Main/components/Yhsw/YhswFilter/index.js
  15. 11
      src/components/Main/index.js
  16. 8
      src/setupProxy.js
  17. 5
      src/utils/apis/CommonApi.js

@ -1,3 +1,15 @@
{ {
siteTitle: '' siteTitle: '',
xyzImageOpts: {
maximumLevel: 21,
url: 'https://map.shuxitech.com/vt/lyrs=s&hl=zh-CN&x={x}&y={y}&z={z}', // 使 {s} subdomains
subdomains: [0, 1, 2, 3, 4, 5, 6, 7]
},
initExtent: [
101.86701132942844, 30.431779754918296, 103.7517428402498, 33.31724803784266
],
zoneLayerOpt: {
geoserverRoot: 'geoserver2',
layerName: 'ne:c_area'
}
} }

@ -14,6 +14,7 @@
manifest.json provides metadata used when your web app is installed on a manifest.json provides metadata used when your web app is installed on a
user's mobile device or desktop. See https://developers.google.com/web/fundamentals/web-app-manifest/ user's mobile device or desktop. See https://developers.google.com/web/fundamentals/web-app-manifest/
--> -->
<link rel="stylesheet" href="%PUBLIC_URL%/cdn/Cesium/Widgets/widgets.css">
<link rel="manifest" href="%PUBLIC_URL%/manifest.json" /> <link rel="manifest" href="%PUBLIC_URL%/manifest.json" />
<!-- <!--
Notice the use of %PUBLIC_URL% in the tags above. Notice the use of %PUBLIC_URL% in the tags above.

@ -11,7 +11,8 @@ export default function FilterPanel(props) {
// height: 500, // height: 500,
border: "1px solid #157DD0", border: "1px solid #157DD0",
background: "rgba(2,38,65,0.95)", background: "rgba(2,38,65,0.95)",
zIndex: 10 zIndex: 10,
pointerEvents: "auto"
}}> }}>
<div className='layout-h center' style={{ <div className='layout-h center' style={{
padding: 12, padding: 12,

@ -14,6 +14,9 @@ import WlwsbLeft from '../components/Wlwsb/WlwsbLeft';
import CdzzyLeft from '../components/Cdzzy/CdzzyLeft'; import CdzzyLeft from '../components/Cdzzy/CdzzyLeft';
import FilterPanel from './FilterPanel'; import FilterPanel from './FilterPanel';
import CdzyFilter from '../components/Cdzy/CdzyFilter'; import CdzyFilter from '../components/Cdzy/CdzyFilter';
import CdthFilter from '../components/Cdth/CdthFilter';
import StxfgcFilter from '../components/Stxfgc/StxfgcFilter';
import CdzzyFilter from '../components/Cdzzy/CdzzyFilter';
const items = [{ const items = [{
name: '草地资源', name: '草地资源',
@ -25,6 +28,7 @@ const items = [{
name: '草地退化', name: '草地退化',
key: 'cdth', key: 'cdth',
LeftPanel: CdthLeft, LeftPanel: CdthLeft,
Filter: CdthFilter
}, { }, {
name: '有害生物', name: '有害生物',
key: 'yhsw', key: 'yhsw',
@ -34,10 +38,12 @@ const items = [{
name: '生态修复工程', name: '生态修复工程',
key: 'stxfgc', key: 'stxfgc',
LeftPanel: StxfgcLeft, LeftPanel: StxfgcLeft,
Filter: StxfgcFilter
}, { }, {
name: '草地征占用', name: '草地征占用',
key: 'cdzzy', key: 'cdzzy',
LeftPanel: CdzzyLeft, LeftPanel: CdzzyLeft,
Filter: CdzzyFilter
}, { }, {
name: '物联网设备', name: '物联网设备',
key: 'wlwsb', key: 'wlwsb',
@ -54,7 +60,9 @@ export default function Content(props) {
const Filter = currentItem?.Filter; const Filter = currentItem?.Filter;
return <div className='wh100 main-content layout-h'> return <div className='wh100 main-content layout-h'>
<div className='left-panel layout-v'> <div className='left-panel layout-v' style={{
pointerEvents: "auto"
}}>
{LeftPanel ? <LeftPanel /> : <Left />} {LeftPanel ? <LeftPanel /> : <Left />}
</div> </div>
<div className='fill relative'> <div className='fill relative'>
@ -65,7 +73,8 @@ export default function Content(props) {
position: "absolute", position: "absolute",
left: 10, left: 10,
top: 10, top: 10,
cursor: "pointer" cursor: "pointer",
pointerEvents: "auto"
}} className='layout-h center'> }} className='layout-h center'>
<img alt='' src={`${toPng('图层')}`} /> <img alt='' src={`${toPng('图层')}`} />
<div className='layout-h center j-center fill' style={{ <div className='layout-h center j-center fill' style={{
@ -85,7 +94,9 @@ export default function Content(props) {
background: "rgba(2,38,65,0.85)", background: "rgba(2,38,65,0.85)",
padding: 8, padding: 8,
left: 16, left: 16,
paddingBottom: 0 paddingBottom: 0,
pointerEvents: "auto"
}}> }}>
{items.map((item, i) => { {items.map((item, i) => {
return <div className='layout-h center' key={i} style={{ return <div className='layout-h center' key={i} style={{
@ -100,6 +111,7 @@ export default function Content(props) {
} else { } else {
setCurrent(item.key); setCurrent(item.key);
} }
setFilterVisible(false)
}}> }}>
<div style={{ <div style={{
fontSize: 16, fontSize: 16,
@ -121,7 +133,9 @@ export default function Content(props) {
{Filter && <Filter />} {Filter && <Filter />}
</FilterPanel> </FilterPanel>
</div> </div>
<div className='right-panel layout-v'> <div className='right-panel layout-v' style={{
pointerEvents: "auto"
}}>
{RightPanel ? <RightPanel /> : null} {RightPanel ? <RightPanel /> : null}
</div> </div>
</div>; </div>;

@ -0,0 +1,20 @@
import { useState, useEffect, useContext } from 'react'
import GlobalContext from '../../../../utils/GlobalContext';
import { MapContext } from '../MapContext';
export default function ImageLayer(props) {
const { xyzImageOpts } = useContext(GlobalContext);
const { viewer } = useContext(MapContext);
useEffect(() => {
if (viewer) {
let l = new window.Cesium.UrlTemplateImageryProvider({
...xyzImageOpts
// maximumLevel: 18,
// url: xyzImageryUrl || 'https://server.arcgisonline.com/ArcGIS/rest/services/World_Imagery/MapServer/tile/{z}/{y}/{x}'
});
viewer.imageryLayers.addImageryProvider(l);
}
}, [viewer, xyzImageOpts])
return null;
}

@ -0,0 +1,3 @@
import React from "react";
export const MapContext = React.createContext();

@ -0,0 +1,26 @@
import { useState, useEffect, useContext } from 'react'
import CommonApi from '../../../../utils/apis/CommonApi';
import { addGeoserverLayer, addPolyline } from '../utils/helper';
import { MapContext } from '../MapContext';
import GlobalContext from '../../../../utils/GlobalContext';
export default function ZoneLayer(props) {
const { viewer } = useContext(MapContext);
const { zoneLayerOpt, initExtent } = useContext(GlobalContext);
useEffect(() => {
if (viewer) {
addGeoserverLayer({
...zoneLayerOpt,
extent: initExtent,
viewer
})
CommonApi.getSubZone().then(data => {
addPolyline({ features: data.features, viewer });
})
}
}, [viewer, zoneLayerOpt, initExtent])
return <>
</>;
}

@ -0,0 +1,93 @@
import { useState, useEffect, useContext } from 'react'
import { MapContext } from './MapContext';
import GlobalContext from '../../../utils/GlobalContext';
import ImageLayer from './ImageLayer';
import ZoneLayer from './ZoneLayer';
const Cesium = window.Cesium;
const turf = window.turf;
export default function Map(props) {
const [viewer, setViewer] = useState();
const { xyzImageOpts } = useContext(GlobalContext)
useEffect(() => {
setTimeout(() => {
Cesium.Ion.defaultAccessToken = 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJqdGkiOiJkMmZjMmYyZC1lZTkzLTQzYjctYmE2NS01NTQ0NzQyMWZhNDMiLCJpZCI6MTA2NjEsImlhdCI6MTYwNjI4NjY2MH0.PN1-x4vXpC68czogub9X0UDA3GaGE-31PZVbrRyI7CQ';
const viewer = window.vvv = new Cesium.Viewer("map", {
animation: false, //是否显示动画控件
homeButton: false, //是否显示home键
geocoder: false,// 查询
baseLayerPicker: false, //是否显示图层选择控件
timeline: false, //是否显示时间线控件
fullscreenButton: false, //是否全屏显示
scene3DOnly: true, //如果设置为true,则所有几何图形以3D模式绘制以节约GPU资源
infoBox: false, //是否显示点击要素之后显示的信息
sceneModePicker: false, //是否显示投影方式控件 三维/二维
navigationHelpButton: false, //是否显示帮助信息控件
terrainProvider: new Cesium.CesiumTerrainProvider({
url: "/terrain"
}),
skyAtmosphere: false,
contextOptions: {
webgl: {
alpha: true,
},
},
});
viewer.scene.globe.terrainExaggeration = 1.5;
viewer.imageryLayers.removeAll()
viewer.scene.skyBox.destroy();
viewer.scene.skyBox = undefined;
viewer.scene.sun.destroy();
viewer.scene.sun = undefined;
viewer.scene.moon.destroy();
viewer.scene.moon = undefined;
// viewer.scene.sun.show = false;
// viewer.scene.moon.show = false;
// viewer.scene.skyBox.show = false;
viewer.scene.undergroundMode = false;
viewer.scene.fxaa = true;
viewer.scene.postProcessStages.fxaa.enabled = true;
viewer._cesiumWidget._creditContainer.style.display = "none";
viewer.scene.globe.baseColor = Cesium.Color.fromCssColorString('#041320')// new Cesium.Color(0, 0, 0, 0);
viewer.scene.backgroundcolor = Cesium.Color.fromCssColorString('#041320');
viewer.scene.screenSpaceCameraController.enableCollisionDetection = true;
// viewer.scene.skyAtmosphere.show = false
// viewer.scene.screenSpaceCameraController.minimumZoomDistance = props.minimumZoomDistance || 1000;
viewer.scene.screenSpaceCameraController.maximumZoomDistance = 50000;
viewer.camera.setView({
// 设置相机位置
destination: {
x: -1192369.4758368244,
y: 5416503.688356532,
z: 3317519.447624021
},
orientation: {
heading: 0.06728175754222843,
pitch: -0.5237859735536086,
roll: 0.0012702968682072324
}
});
setViewer(viewer)
}, 1000);
}, [])
return <MapContext.Provider value={{
viewer
}}>
<div id="map" style={{
position: "absolute",
top: 0,
left: 0,
bottom: 0,
right: 0,
pointerEvents: "auto"
}}></div>
<ImageLayer />
<ZoneLayer />
</MapContext.Provider>;
}

@ -0,0 +1,82 @@
const Cesium = window.Cesium;
const turf = window.turf;
export const addPolyline = ({ features, viewer }) => {
if (features.length === 0) {
return;
}
const instances = features.forEach(f => {
var coordinates = f.geometry.coordinates;
var polygon = window.turf.polygon(coordinates);
var center = window.turf.centerOfMass(polygon).geometry.coordinates;
console.log(center)
var position = window.Cesium.Cartesian3.fromDegrees(center[0], center[1])
viewer.entities.add({
position: position,
heightReference: window.Cesium.HeightReference.CLAMP_TO_GROUND,
label: {
font: "normal 18px MicroSoft YaHei",
clampToGround: true,
text: f.properties.name,
fillColor: window.Cesium.Color.WHITE,
outlineColor: window.Cesium.Color.BLACK,
outlineWidth: 4,
heightReference: window.Cesium.HeightReference.CLAMP_TO_GROUND
},
});
// const polygonArr = f.geometry.coordinates.toString().split(',').filter(v => {
// return v !== '0'
// });
// const id = 'zone-' + Math.random().toString().substring(3)
// viewer.entities.add({
// id: id,
// name: '',
// polyline: {
// positions: Cesium.Cartesian3.fromDegreesArray(polygonArr),
// width: 5,
// clampToGround: true,
// // heightReference: Cesium.HeightReference.CLAMP_TO_GROUND,
// material: Cesium.Color.BLUE
// }
// })
// this.createGroundPolylineGeometryInstance(f);
})
}
export const addGeoserverLayer = ({ layerName, extent, isWms, viewer, geoserverRoot = 'geoserver' }) => {
let layer;
if (isWms) {
let imageryProvider = new Cesium.WebMapServiceImageryProvider({
url: `/${geoserverRoot}/ne/wms`,
layers: layerName,
tileWidth: 256,
tileHeight: 256,
enablePickFeatures: false,
parameters: { transparent: true, format: 'image/png' },
version: '1.1.0'
});
layer = viewer.imageryLayers.addImageryProvider(imageryProvider);
} else {
// const geoserverOptions = geoserverOptions;
let matrixIds = ['EPSG:4326:0', 'EPSG:4326:1', 'EPSG:4326:2', 'EPSG:4326:3', 'EPSG:4326:4', 'EPSG:4326:5', 'EPSG:4326:6', 'EPSG:4326:7', 'EPSG:4326:8', 'EPSG:4326:9', 'EPSG:4326:10',
'EPSG:4326:11', 'EPSG:4326:12', 'EPSG:4326:13', 'EPSG:4326:14', 'EPSG:4326:15', 'EPSG:4326:16', 'EPSG:4326:17', 'EPSG:4326:18', 'EPSG:4326:19', 'EPSG:4326:20', 'EPSG:4326:21'];
var wmtsImageryProvider = new Cesium.WebMapTileServiceImageryProvider({
url: `/${geoserverRoot}/gwc/service/wmts`,
layer: layerName,
style: '',
format: 'image/png',
tileMatrixSetID: 'EPSG:4326',
rectangle: Cesium.Rectangle.fromDegrees(...extent),
tileMatrixLabels: matrixIds,
tilingScheme: new Cesium.GeographicTilingScheme({
numberOfLevelZeroTilesX: 2,
numberOfLevelZeroTilesY: 1
}),
// subdomains: geoserverOptions?.subdomains || []
});
layer = viewer.imageryLayers.addImageryProvider(wmtsImageryProvider);
}
return layer;
}

@ -0,0 +1,34 @@
import { Col, Divider, Form, Radio, Row, Select } from 'antd';
import { useState, useEffect } from 'react'
import ZoneSelector from '../../../../common/ZoneSelector';
import CdzyApi from '../../../../../utils/apis/CdzyApi';
export default function CdthFilter(props) {
const [form] = Form.useForm();
useEffect(() => {
form.setFieldsValue({
area_code: "-1",
degradation_level: "-1"
})
}, [form])
return <Form form={form} layout={"vertical"}>
<Form.Item label="行政地域" name="area_code">
<ZoneSelector />
</Form.Item>
<Divider style={{
borderColor: "#075C88"
}} />
<Form.Item label="草地退化等级" name="degradation_level">
<Radio.Group>
<Radio value={"-1"}>全部</Radio>
<Radio value={"未退化"}>未退化</Radio>
<Radio value={"轻度退化"}>轻度退化</Radio>
<Radio value={"中度退化"}>中度退化</Radio>
<Radio value={"重度退化"}>重度退化</Radio>
</Radio.Group>
</Form.Item>
</Form>;
}

@ -0,0 +1,39 @@
import { Col, Divider, Form, Input, Radio, Row, Select, Space } from 'antd';
import { useState, useEffect } from 'react'
import ZoneSelector from '../../../../common/ZoneSelector';
import CdzyApi from '../../../../../utils/apis/CdzyApi';
export default function CdzzyFilter(props) {
const [form] = Form.useForm();
useEffect(() => {
form.setFieldsValue({
area_code: "-1"
})
}, [form])
return <Form form={form} layout={"vertical"}>
<Space size={24}>
<Form.Item label="行政地域" name="area_code">
<ZoneSelector />
</Form.Item>
<Form.Item label="年份" name="year">
<Input style={{
width: 100
}} />
</Form.Item>
</Space>
<Divider style={{
marginTop: 0,
borderColor: "#075C88"
}} />
<Form.Item label="占用类型" name="name">
<Radio.Group>
<Radio value={"-1"}>全部</Radio>
<Radio value={"临时占用"}>临时占用</Radio>
<Radio value={"永久占用"}>永久占用</Radio>
</Radio.Group>
</Form.Item>
</Form>;
}

@ -0,0 +1,37 @@
import { Col, Divider, Form, Input, Radio, Row, Select, Space } from 'antd';
import { useState, useEffect } from 'react'
import ZoneSelector from '../../../../common/ZoneSelector';
import CdzyApi from '../../../../../utils/apis/CdzyApi';
export default function StxfgcFilter(props) {
const [form] = Form.useForm();
useEffect(() => {
form.setFieldsValue({
area_code: "-1"
})
}, [form])
return <Form form={form} layout={"vertical"}>
<Space size={24}>
<Form.Item label="行政地域" name="area_code">
<ZoneSelector />
</Form.Item>
<Form.Item label="年份" name="year">
<Input style={{
width: 100
}} />
</Form.Item>
</Space>
<Divider style={{
borderColor: "#075C88",
marginTop: 0
}} />
<Form.Item label="项目名称" name="name">
<Input style={{
width: 250
}} />
</Form.Item>
</Form>;
}

@ -0,0 +1,26 @@
import { Col, Divider, Form, Input, Radio, Row, Select, Space } from 'antd';
import { useState, useEffect } from 'react'
import ZoneSelector from '../../../../common/ZoneSelector';
import CdzyApi from '../../../../../utils/apis/CdzyApi';
export default function WlwsbFilter(props) {
const [form] = Form.useForm();
useEffect(() => {
form.setFieldsValue({
area_code: "-1"
})
}, [form])
return <Form form={form} layout={"vertical"}>
<Form.Item label="设备类型" name="name">
<Radio.Group>
<Radio value={"-1"}>全部</Radio>
<Radio value={"气象站"}>气象站</Radio>
<Radio value={"摄像头"}>摄像头</Radio>
<Radio value={"虫情设备"}>虫情设备</Radio>
</Radio.Group>
</Form.Item>
</Form>;
}

@ -0,0 +1,34 @@
import { Col, Divider, Form, Radio, Row, Select } from 'antd';
import { useState, useEffect } from 'react'
import ZoneSelector from '../../../../common/ZoneSelector';
import CdzyApi from '../../../../../utils/apis/CdzyApi';
export default function YhswFilter(props) {
const [form] = Form.useForm();
useEffect(() => {
form.setFieldsValue({
area_code: "-1",
degradation_level: "-1"
})
}, [form])
return <Form form={form} layout={"vertical"}>
<Form.Item label="行政地域" name="area_code">
<ZoneSelector />
</Form.Item>
<Divider style={{
borderColor: "#075C88"
}} />
<Form.Item label="有害生物类别" name="degradation_level">
<Radio.Group>
<Radio value={"-1"}>全部</Radio>
<Radio value={"未退化"}>虫害</Radio>
<Radio value={"轻度退化"}>毒草害</Radio>
<Radio value={"中度退化"}>地面鼠</Radio>
<Radio value={"重度退化"}>地下鼠</Radio>
</Radio.Group>
</Form.Item>
</Form>;
}

@ -4,6 +4,7 @@ import './index.less';
import Header from './Header'; import Header from './Header';
import Content from './Content'; import Content from './Content';
import { useSize } from 'ahooks' import { useSize } from 'ahooks'
import Map from './Map';
export default function Main(props) { export default function Main(props) {
const { siteTitle } = useContext(GlobalContext); const { siteTitle } = useContext(GlobalContext);
// const rootRef = useRef(); // const rootRef = useRef();
@ -45,14 +46,18 @@ export default function Main(props) {
scale, scale,
width: screenSize[0], width: screenSize[0],
height: screenSize[1], height: screenSize[1],
transformOrigin: '0 0' transformOrigin: '0 0',
pointerEvents: "none"
}) })
} }
}, [size]); }, [size]);
return <div className='main' ref={rootRef}> return <div className='main relative' ref={rootRef}>
<Map />
{style && <div className='layout-v' style={style}> {style && <div className='layout-v' style={style}>
<div className='header layout-h'> <div className='header layout-h' style={{
pointerEvents: "auto"
}}>
<Header rootRef={rootRef} /> <Header rootRef={rootRef} />
</div> </div>
<div className='fill h0'> <div className='fill h0'>

@ -14,9 +14,11 @@ module.exports = function (app) {
}) })
) )
app.use( app.use(
proxy('/geoserver', { proxy('/geoserver2', {
"target": "http://geo.qklny.cn/", "target": "http://geo.qklny.cn",
changeOrigin: true changeOrigin: true,
pathRewrite: { '^/geoserver2': '/geoserver' }
}) })
) )
} }

@ -9,4 +9,9 @@ export default class CommonApi {
code code
}); });
} }
static async getSubZone() {
const resp = await FetchHelper.getJson(`/openApi/index/map/xzdy`);
const data = JSON.parse(resp.data?.[0]?.geojson);
return data;
}
} }
Loading…
Cancel
Save