diff --git a/package-lock.json b/package-lock.json
index 1da41e0..dd5e43c 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -30,6 +30,7 @@
"dotenv": "^10.0.0",
"dotenv-expand": "^5.1.0",
"echarts": "^5.4.3",
+ "echarts-gl": "^2.0.9",
"eslint": "^8.3.0",
"eslint-config-react-app": "^7.0.1",
"eslint-webpack-plugin": "^3.1.1",
@@ -6093,6 +6094,11 @@
"resolved": "https://registry.npmmirror.com/classnames/-/classnames-2.3.2.tgz",
"integrity": "sha512-CSbhY4cFEJRe6/GQzIk5qXZ4Jeg5pcsP7b5peFSDpffpe1cqjASH/n9UTjBwOp6XpMSTwQ8Za2K5V02ueA7Tmw=="
},
+ "node_modules/claygl": {
+ "version": "1.3.0",
+ "resolved": "https://registry.npmmirror.com/claygl/-/claygl-1.3.0.tgz",
+ "integrity": "sha512-+gGtJjT6SSHD2l2yC3MCubW/sCV40tZuSs5opdtn79vFSGUgp/lH139RNEQ6Jy078/L0aV8odCw8RSrUcMfLaQ=="
+ },
"node_modules/clean-css": {
"version": "5.3.3",
"resolved": "https://registry.npmmirror.com/clean-css/-/clean-css-5.3.3.tgz",
@@ -7128,6 +7134,18 @@
"zrender": "5.4.4"
}
},
+ "node_modules/echarts-gl": {
+ "version": "2.0.9",
+ "resolved": "https://registry.npmmirror.com/echarts-gl/-/echarts-gl-2.0.9.tgz",
+ "integrity": "sha512-oKeMdkkkpJGWOzjgZUsF41DOh6cMsyrGGXimbjK2l6Xeq/dBQu4ShG2w2Dzrs/1bD27b2pLTGSaUzouY191gzA==",
+ "dependencies": {
+ "claygl": "^1.2.1",
+ "zrender": "^5.1.1"
+ },
+ "peerDependencies": {
+ "echarts": "^5.1.2"
+ }
+ },
"node_modules/echarts/node_modules/tslib": {
"version": "2.3.0",
"resolved": "https://registry.npmmirror.com/tslib/-/tslib-2.3.0.tgz",
@@ -22695,6 +22713,11 @@
"resolved": "https://registry.npmmirror.com/classnames/-/classnames-2.3.2.tgz",
"integrity": "sha512-CSbhY4cFEJRe6/GQzIk5qXZ4Jeg5pcsP7b5peFSDpffpe1cqjASH/n9UTjBwOp6XpMSTwQ8Za2K5V02ueA7Tmw=="
},
+ "claygl": {
+ "version": "1.3.0",
+ "resolved": "https://registry.npmmirror.com/claygl/-/claygl-1.3.0.tgz",
+ "integrity": "sha512-+gGtJjT6SSHD2l2yC3MCubW/sCV40tZuSs5opdtn79vFSGUgp/lH139RNEQ6Jy078/L0aV8odCw8RSrUcMfLaQ=="
+ },
"clean-css": {
"version": "5.3.3",
"resolved": "https://registry.npmmirror.com/clean-css/-/clean-css-5.3.3.tgz",
@@ -23515,6 +23538,15 @@
}
}
},
+ "echarts-gl": {
+ "version": "2.0.9",
+ "resolved": "https://registry.npmmirror.com/echarts-gl/-/echarts-gl-2.0.9.tgz",
+ "integrity": "sha512-oKeMdkkkpJGWOzjgZUsF41DOh6cMsyrGGXimbjK2l6Xeq/dBQu4ShG2w2Dzrs/1bD27b2pLTGSaUzouY191gzA==",
+ "requires": {
+ "claygl": "^1.2.1",
+ "zrender": "^5.1.1"
+ }
+ },
"ee-first": {
"version": "1.1.1",
"resolved": "https://registry.npmmirror.com/ee-first/-/ee-first-1.1.1.tgz",
diff --git a/package.json b/package.json
index 8ee944b..b614e18 100644
--- a/package.json
+++ b/package.json
@@ -25,6 +25,7 @@
"dotenv": "^10.0.0",
"dotenv-expand": "^5.1.0",
"echarts": "^5.4.3",
+ "echarts-gl": "^2.0.9",
"eslint": "^8.3.0",
"eslint-config-react-app": "^7.0.1",
"eslint-webpack-plugin": "^3.1.1",
diff --git a/public/images/摄像头数量.png b/public/images/摄像头数量.png
new file mode 100644
index 0000000..c1d29ce
Binary files /dev/null and b/public/images/摄像头数量.png differ
diff --git a/public/images/气象站数量.png b/public/images/气象站数量.png
new file mode 100644
index 0000000..61592b1
Binary files /dev/null and b/public/images/气象站数量.png differ
diff --git a/public/images/物联网底座.png b/public/images/物联网底座.png
new file mode 100644
index 0000000..767c183
Binary files /dev/null and b/public/images/物联网底座.png differ
diff --git a/public/images/生态修复工程图标.png b/public/images/生态修复工程图标.png
new file mode 100644
index 0000000..6b917d4
Binary files /dev/null and b/public/images/生态修复工程图标.png differ
diff --git a/public/images/生态修复工程背景.png b/public/images/生态修复工程背景.png
new file mode 100644
index 0000000..6500868
Binary files /dev/null and b/public/images/生态修复工程背景.png differ
diff --git a/public/images/虫情设备数量.png b/public/images/虫情设备数量.png
new file mode 100644
index 0000000..9d71d22
Binary files /dev/null and b/public/images/虫情设备数量.png differ
diff --git a/src/components/Main/Content/index.js b/src/components/Main/Content/index.js
index c6dedbf..b2839b8 100644
--- a/src/components/Main/Content/index.js
+++ b/src/components/Main/Content/index.js
@@ -9,6 +9,9 @@ import CdzyRight from '../components/Cdzy/CdzyRight';
import CdthLeft from '../components/Cdth/CdthLeft';
import YhswLeft from '../components/Yhsw/YhswLeft';
import YhswRight from '../components/Yhsw/YhswRight';
+import StxfgcLeft from '../components/Stxfgc/StxfgcLeft';
+import WlwsbLeft from '../components/Wlwsb/WlwsbLeft';
+import CdzzyLeft from '../components/Cdzzy/CdzzyLeft';
const items = [{
name: '草地资源',
@@ -27,15 +30,15 @@ const items = [{
}, {
name: '生态修复工程',
key: 'stxfgc',
- LeftPanel: props => 4
+ LeftPanel: StxfgcLeft,
}, {
name: '草地征占用',
key: 'cdzzy',
- LeftPanel: props => 5
+ LeftPanel: CdzzyLeft,
}, {
name: '物联网设备',
key: 'wlwsb',
- LeftPanel: props => 6
+ LeftPanel: WlwsbLeft,
}]
export default function Content(props) {
diff --git a/src/components/Main/components/Cdzzy/CdzzyLeft/Zbsj/echartsOptions.js b/src/components/Main/components/Cdzzy/CdzzyLeft/Zbsj/echartsOptions.js
new file mode 100644
index 0000000..990fe0c
--- /dev/null
+++ b/src/components/Main/components/Cdzzy/CdzzyLeft/Zbsj/echartsOptions.js
@@ -0,0 +1,246 @@
+import * as echarts from 'echarts'
+import { } from 'echarts-gl'
+import _ from 'lodash';
+export const getOption = (datas) => {
+ const colors = ['#0053CF', '#F8B551']
+ let selectedIndex = '';
+ let hoveredIndex = '';
+ const sum = _.sumBy(datas, 'value');
+ let option = getPie3D(
+ datas?.map((data, i) => {
+ return {
+ name: data.name,
+ value: data.value,
+ itemStyle: {
+ color: colors[i],
+ },
+ }
+ }),
+ 0.4
+ );
+ // 生成扇形的曲面参数方程
+ function getParametricEquation(startRatio, endRatio, isSelected, isHovered, k, h) {
+ // 计算
+ const midRatio = (startRatio + endRatio) / 2;
+
+ const startRadian = startRatio * Math.PI * 2;
+ const endRadian = endRatio * Math.PI * 2;
+ const midRadian = midRatio * Math.PI * 2;
+
+ // 如果只有一个扇形,则不实现选中效果。
+ if (startRatio === 0 && endRatio === 1) {
+ // eslint-disable-next-line no-param-reassign
+ isSelected = false;
+ }
+
+ // 通过扇形内径/外径的值,换算出辅助参数 k(默认值 1/3)
+ // eslint-disable-next-line no-param-reassign
+ k = typeof k !== 'undefined' ? k : 1 / 3;
+
+ // 计算选中效果分别在 x 轴、y 轴方向上的位移(未选中,则位移均为 0)
+ const offsetX = isSelected ? Math.cos(midRadian) * 0.1 : 0;
+ const offsetY = isSelected ? Math.sin(midRadian) * 0.1 : 0;
+
+ // 计算高亮效果的放大比例(未高亮,则比例为 1)
+ const hoverRate = isHovered ? 1.05 : 1;
+
+ // 返回曲面参数方程
+ return {
+ u: {
+ min: -Math.PI,
+ max: Math.PI * 3,
+ step: Math.PI / 32,
+ },
+
+ v: {
+ min: 0,
+ max: Math.PI * 2,
+ step: Math.PI / 20,
+ },
+
+ x(u, v) {
+ if (u < startRadian) {
+ return offsetX + Math.cos(startRadian) * (1 + Math.cos(v) * k) * hoverRate;
+ }
+ if (u > endRadian) {
+ return offsetX + Math.cos(endRadian) * (1 + Math.cos(v) * k) * hoverRate;
+ }
+ return offsetX + Math.cos(u) * (1 + Math.cos(v) * k) * hoverRate;
+ },
+
+ y(u, v) {
+ if (u < startRadian) {
+ return offsetY + Math.sin(startRadian) * (1 + Math.cos(v) * k) * hoverRate;
+ }
+ if (u > endRadian) {
+ return offsetY + Math.sin(endRadian) * (1 + Math.cos(v) * k) * hoverRate;
+ }
+ return offsetY + Math.sin(u) * (1 + Math.cos(v) * k) * hoverRate;
+ },
+
+ z(u, v) {
+ if (u < -Math.PI * 0.5) {
+ return Math.sin(u);
+ }
+ if (u > Math.PI * 2.5) {
+ return Math.sin(u) * h * 0.1;
+ }
+ // 当前图形的高度是Z根据h(每个value的值决定的)
+ return Math.sin(v) > 0 ? 1 * h * 0.1 : -1;
+ },
+ };
+ }
+ // 生成模拟 3D 饼图的配置项
+ function getPie3D(pieData, internalDiameterRatio) {
+ const series = [];
+ // 总和
+ let sumValue = 0;
+ let startValue = 0;
+ let endValue = 0;
+ const legendData = [];
+ const k =
+ typeof internalDiameterRatio !== 'undefined'
+ ? (1 - internalDiameterRatio) / (1 + internalDiameterRatio)
+ : 1 / 3;
+
+ // 为每一个饼图数据,生成一个 series-surface 配置
+ for (let i = 0; i < pieData.length; i += 1) {
+ sumValue += pieData[i].value;
+
+ const seriesItem = {
+ name: typeof pieData[i].name === 'undefined' ? `series${i}` : pieData[i].name,
+ type: 'surface',
+ parametric: true,
+ wireframe: {
+ show: false,
+ },
+ pieData: pieData[i],
+ pieStatus: {
+ selected: false,
+ hovered: false,
+ k,
+ },
+ };
+
+ if (typeof pieData[i].itemStyle !== 'undefined') {
+ const { itemStyle } = pieData[i];
+
+ // eslint-disable-next-line no-unused-expressions
+ typeof pieData[i].itemStyle.color !== 'undefined' ? (itemStyle.color = pieData[i].itemStyle.color) : null;
+ // eslint-disable-next-line no-unused-expressions
+ typeof pieData[i].itemStyle.opacity !== 'undefined'
+ ? (itemStyle.opacity = pieData[i].itemStyle.opacity)
+ : null;
+
+ seriesItem.itemStyle = itemStyle;
+ }
+ series.push(seriesItem);
+ }
+ // 使用上一次遍历时,计算出的数据和 sumValue,调用 getParametricEquation 函数,
+ // 向每个 series-surface 传入不同的参数方程 series-surface.parametricEquation,也就是实现每一个扇形。
+ console.log(series);
+ for (let i = 0; i < series.length; i += 1) {
+ endValue = startValue + series[i].pieData.value;
+
+ series[i].pieData.startRatio = startValue / sumValue;
+ series[i].pieData.endRatio = endValue / sumValue;
+ series[i].parametricEquation = getParametricEquation(
+ series[i].pieData.startRatio,
+ series[i].pieData.endRatio,
+ false,
+ false,
+ k,
+ // 我这里做了一个处理,使除了第一个之外的值都是10
+ series[i].pieData.value === series[0].pieData.value ? 35 : 10
+ );
+
+ startValue = endValue;
+
+ legendData.push(series[i].name);
+ }
+
+ // 准备待返回的配置项,把准备好的 legendData、series 传入。
+ return {
+ // animation: false,
+ tooltip: {
+ formatter: (params) => {
+ if (params.seriesName !== 'mouseoutSeries') {
+ return `${params.seriesName
+ }
${option.series[params.seriesIndex].pieData.value}`;
+ }
+ return '';
+ },
+ },
+ xAxis3D: {
+ min: -1.0,
+ max: 1.0,
+ },
+ yAxis3D: {
+ min: -1.0,
+ max: 1.0,
+ },
+ zAxis3D: {
+ min: -0.5,
+ max: 0.01,
+ },
+ legend: {
+ orient: 'vertical',
+ data: datas?.map(data => data.name),
+ textStyle: {
+ color: '#fff',
+ fontSize: 15,
+ lineHeight: 20
+ // rich: richObj
+ },
+ itemWidth: 10,
+ itemHeight: 10,
+ itemGap: 20,
+ icon: 'circle',
+ formatter: function (name) {
+
+ let index = datas.findIndex((item) => item.name === name);
+ const item = datas[index];
+ const p = Math.round(item.value / sum * 10000) / 100
+ return `${item.name}: ${p}% \r\n${item.value} ${item.unit}`;
+ },
+ right: '50',
+ top: '80', //居右显示
+ },
+ grid3D: {
+ show: false,
+ boxHeight: 5,
+ top: -40,
+ left: -120,
+ viewControl: {
+ // 3d效果可以放大、旋转等,请自己去查看官方配置
+ alpha: 25,
+ beta: 0,
+ rotateSensitivity: 1,
+ zoomSensitivity: 0,
+ panSensitivity: 0,
+ distance: 300,
+ },
+ // 后处理特效可以为画面添加高光、景深、环境光遮蔽(SSAO)、调色等效果。可以让整个画面更富有质感。
+ postEffect: {
+ // 配置这项会出现锯齿,请自己去查看官方配置有办法解决
+ enable: false,
+ bloom: {
+ enable: true,
+ bloomIntensity: 0.1,
+ },
+ SSAO: {
+ enable: true,
+ quality: 'medium',
+ radius: 2,
+ },
+ // temporalSuperSampling: {
+ // enable: true,
+ // },
+ },
+ },
+ series,
+ };
+ }
+ return option;
+}
\ No newline at end of file
diff --git a/src/components/Main/components/Cdzzy/CdzzyLeft/Zbsj/index.js b/src/components/Main/components/Cdzzy/CdzzyLeft/Zbsj/index.js
new file mode 100644
index 0000000..37fccc5
--- /dev/null
+++ b/src/components/Main/components/Cdzzy/CdzzyLeft/Zbsj/index.js
@@ -0,0 +1,30 @@
+import { useState, useEffect, useRef } from 'react'
+import useEcharts from '../../../../../hooks/useEcharts';
+import CdzyApi from '../../../../../../utils/apis/CdzyApi';
+import { getOption } from './echartsOptions';
+import LittleTitle from '../../../../../common/LittleTitle';
+import HomeApi from '../../../../../../utils/apis/HomeApi';
+
+export default function Zbsj(props) {
+ const [data, setData] = useState();
+ const ref = useRef();
+ const chart = useEcharts(ref.current);
+ useEffect(() => {
+
+ HomeApi.item('cdzhy').then(resp => {
+ setData(resp.data);
+ })
+ }, []);
+ useEffect(() => {
+ if (chart && data) {
+ const options = getOption(data);
+ chart.setOption(options);
+ }
+ }, [chart, data]);
+ return <>
+