mapEcharts文件import React, { memo } from "react";import GisMap from "./gisMap/gisMap";import ActivitiesList from "./activitiesList/activitiesList";import AreaListInfomation from "./areaListInfomation/areaListInfomation";import SourcesStatistics from "./sourcesStatistics/sourcesStatistics";import TopListInfomation from "./topListInfomation/topListInfomation";import mStyle from "./mapEcharts.module.less";interface Iprops { params: any; showDetail: (pointData: any) => void}const MapEcharts: React.FC= ({ params, showDetail }) => { const onShowDetail = (pointData: any) => { showDetail(pointData); }; return (
);};export default memo(MapEcharts);gismap.tsx文件import React, { memo } from "react";import gStyle from "./gisMap.module.less";import MapLand from "../mapLand/mapLand";interface IProps { params: any; showDetail: (pointData: any) => void;}const GisMap: React.FC= ({ params, showDetail }) => { const onShowDetail = (pointData: any) => { showDetail(pointData); }; return (
);};export default memo(GisMap);activitiesList.tsx文件// 请求的结果{code: 200, msg: "成功",…}code: 200data: {soilPollutionStatus: 10, removeSurveyList: 1052, inTheRiskAssessmentDirectory: 3,…}inTheRiskAssessmentDirectory: 3inTheRiskManagementAndRepairDirectory: 9removeSurveyList: 1052removedFromTheListOfRiskManagementAndRestoration: 0removedFromtheRiskAssessmentList: 2soilPollutionStatus: 10msg: "成功"import React, { memo, useEffect, useState } from "react";import Title from "components/BaseTitle/baseTitle";import aStyle from "./activitiesList.module.less";import ApiFetch from "utils/apiFetch";import { contaminatedLandManage } from "utils/apiGroup";import Nodata from "components/Nodata/Nodata";interface Iprops { params: any}interface IList { name: string, key: string, code: number}const ARR_LIST: IList[] = [ { name: "土壤污染状况调查名录", key: "soilPollutionStatus", code: 0 }, { name: "移出调查名录", key: "removeSurveyList", code: 1 }, { name: "在风险评估名录", key: "inTheRiskAssessmentDirectory", code: 2 }, { name: "移出风险评估名录", key: "removedFromtheRiskAssessmentList", code: 3 }, { name: "在风险管控与修复名录", key: "inTheRiskManagementAndRepairDirectory", code: 4 }, { name: "移出风险管控与修复名录", key: "removedFromTheListOfRiskManagementAndRestoration", code: 5 },];const ActivitiesList: React.FC= ({ params }) => { const [list, setList] = useState([]); useEffect (() => { BlockList(); }, [JSON.stringify(params)]); const BlockList = async () => { const par = { // endTime: params.endTime, // startTime: params.startTime, regionCodes: params.regionCodes }; const res: any = await ApiFetch.post(contaminatedLandManage.riskManageMentList, par); if (res._success) { if (res.data) { const tempList = ARR_LIST.map((item: IList) => { return { name: item.name, value: res.data[item.key] }; }); setList(tempList); } else { setList([]); } } else { setList([]); } }; return (
<div className={aStyle.moreBox}> { list.length ? (list || []).map((item: {code: number, name: string, value: number}) => { return <div key={item.name} className={aStyle.oneBox}> <div>{item.name}</div> <div className={aStyle.font}>{item.value}</div> </div>; }) : <Nodata /> } </div> </div> ); }; export default memo(ActivitiesList); activitiesList.module.less文件 .wrapper { background: #fff; box-shadow: 0.02rem 0.02rem 0.1rem 0 rgba(0, 0, 0, 0.1); flex: 1 1; min-height: 0; overflow: hidden; margin-bottom: 0.1rem; padding-top: 0.15rem; .moreBox { width: 100%; display: flex; flex-flow: row wrap; padding-left: 0.2rem; height: calc(100% - 0.2rem); padding-top: 0.1rem; border-radius: 0.01rem; .oneBox { margin: 0rem 0.1rem 0.1rem 0rem; background: #F5F6FA; display: flex; width: calc((100% - 0.4rem) /3); flex-flow: column nowrap; align-items: center; justify-content: center; &:hover { background-color: #427aff; color: #fff; cursor: pointer; >div:last-child { color: #fff; } } >div { display: flex; align-items: center; padding: 0 0.1rem; text-align: center; &:first-child { width: 1.4rem; text-align: center; } &:last-child { color: #427aff; } } } } } sourcesStatistics.tsx //调接口后的数据 [{…}, {…}, {…}, {…}, {…}, {…}] 0: {name: "土地整备项目", amount: 5, percent: 0.4167} 1: {name: "城市更新或土地用途变更项目", amount: 1, percent: 0.0833} 2: {name: "国有用地出让项目", amount: 0, percent: 0} 3: {name: "生态环境主管部门责令开展调查项目", amount: 0, percent: 0} 4: {name: "其他(企业自行申请的项目)", amount: 0, percent: 0} 5: {name: "合计", amount: 6, percent: 0.5} length: 6 __proto__: Array(0) import React, { memo, useEffect } from "react"; import sStyle from "./sourcesStatistics.module.less"; import Title from "components/BaseTitle/baseTitle"; import { useStore } from "store/appStore"; import echarts from "echarts/lib/echarts"; import { useState } from "utils/declare"; import { contaminatedLandManage } from "utils/apiGroup"; import ApiFetch from "utils/apiFetch"; interface IProps { params: any; } const SourcesStatistics: React.FC<IProps> = ({ params }) => { const store = useStore(); const size = store.rootFontSize; const [list, setList] = useState([]); const [totalNumber, setTotalNumber] = useState(0); useEffect (() => { landInfo(); }, [JSON.stringify(params)]); useEffect(() => { if (list.length) { drawChart(list.slice(0, -1).map((item: any) => item.amount)); const total = list.slice(0, list.length - 1).reduce((currentItem: any, nextCurrentItem: any) => { return currentItem + nextCurrentItem.amount; }, 0); setTotalNumber(total); } }, [JSON.stringify(list)]); const landInfo = async () => { const par = { endTime: params.endTime, startTime: params.startTime, regionCodes: params.regionCodes, selects: params.selects, }; const res: any = await ApiFetch.post(contaminatedLandManage.LandSourceStatistics, par); if (res._success) { if (res.data) { setList(res.data); } else { setList([]); } } else { setList([]); } }; // const manyColors = ["#11D5F8", "#749DFD", "#5342FF", "#5342FF", "#5342FF"]; // const arrs = [ // { code: 1, name: "城市更新或土地用途变更项目", value: 100 }, // { code: 2, name: "土地正备项目", value: 100 }, // { code: 3, name: "国有用地出让项目", value: 80 }, // { code: 4, name: "国有用地出让项目", value: 80 }, // { code: 5, name: "其他(企业自行申请的项目)", value: 80 } // ]; const drawChart = (arrs: any) => { const domId = document.getElementById("lang_bg_area_analysisSourcesone") as HTMLCanvasElement; if (!domId) return; const myChart = echarts.init(domId); myChart.clear(); const option: any = { tooltip: { show: true, formatter: (item: any) => { return `<div class="tool-Tips"> <div>${item.name}</div> <div>地块数: ${item.value}</div> </div>`; }, backgroundColor: "transparent", borderColor: "transparent", padding: [0, 0, 15, 0], textStyle: { fontSize: 0.16 * size, color: "#333" }, confine: true, }, grid: [{ // top: 0.2 * size, right: 0.1 * size, bottom: 0, left: 0.3 * size, containLabel: true }], series: [ { name: "qq", type: "pie", radius: ["62%", "88%"], center: ["50%", "50%"], hoverAnimation: true, hoverOffset: 6, data: arrs, labelLine: { show: false, }, label: { show: false, }, }, ], color: ["#9999FF", "#00CCFF", "#5342FF", "#6BA4FF", "#AF68FF"], }; myChart.setOption(option); // 鼠标移除后事件 myChart.on("mouseout", function (params: any) { // setHoverActive(3); }); }; return ( <div className={sStyle.wrapper}> <Title title="深圳市地块来源统计" /> <div className={sStyle.echartsCon}> { <> <div className={sStyle.itemContent}> <div className={sStyle.echarts} id="lang_bg_area_analysisSourcesone"></div> <div className={sStyle.total}> <div>{totalNumber}</div> </div> </div> <div className={sStyle.lengendWrapper}> <div className={sStyle.lengendCon}> { (list || []).slice(0, -1).map((item: any, index: number) => { return <div className={`${sStyle.item} ${sStyle.active}`} key={index} > <div style={{ marginTop: "0.07rem" }}>{item && item.name}</div> <div style={{ marginTop: "0.07rem" }}>{item || item.amount === 0 ? `${item.amount}` : "--"}</div> </div>; }) } </div> </div> </> } </div> </div> ); }; export default memo(SourcesStatistics); sourcesStatistics.module.less文件 .wrapper { background: #fff; box-shadow: 0.02rem 0.02rem 0.1rem 0 rgba(0, 0, 0, 0.1); flex: 0 0 2.25rem; overflow: hidden; // margin-bottom: 0.1rem; padding-top: 0.15rem; display: flex; flex-direction: column; .echartsCon { display: flex; flex-direction: row; margin: 0rem 0.2rem 0; height: 100%; width: calc(100% - 0.4rem); .echarts { height: 100%; width: 1.4rem; } .itemContent { width: 1.4rem; height: 100%; position: relative; .total { color: #333; position: absolute; top: 50%; transform: translateY(-50%); width: 100%; text-align: center; > div { &:first-child { font-size: 0.2rem; } &:last-child { font-size: 0.36rem; } } } } .lengendWrapper { display: flex; flex-direction: column; justify-content: center; flex: 1 1; min-width: 0; .title { margin-left: 0.2rem; color: #333; line-height: 1; margin-bottom: 0.1rem; } .lengendCon { // flex: 1 1 0; min-width: 0; // height: 100%; display: flex; flex-direction: column; // justify-content: center; .item { position: relative; display: flex; width: calc(100% - 0.2rem); margin-left: 0.2rem; padding-left: 0.3rem; line-height: 1; > div { font-size: 0.14rem; color: #666; margin-bottom: 0.1rem; &:first-child { // width: 0.56rem; // margin-right: 0.2rem; } &:nth-child(2) { flex: 1 1; min-width: 0; text-align: right; } &:last-child { width: 0.6rem; margin-left: 0.2rem; text-align: right; } } &:first-child { // margin-bottom: 0.1rem; &::before { content: ""; left: 0; top: 50%; transform: translateY(-50%); position: absolute; height: 0.1rem; width: 0.1rem; background: #11D5F8; } } &:nth-child(2) { // margin-bottom: 0.1rem; &::before { content: ""; left: 0; top: 50%; transform: translateY(-50%); position: absolute; height: 0.1rem; width: 0.1rem; background: #749DFD; } } &:nth-child(3) { &::before { content: ""; left: 0; top: 50%; transform: translateY(-50%); position: absolute; height: 0.1rem; width: 0.1rem; background: #5342FF; } } &:nth-child(4) { &::before { content: ""; left: 0; top: 50%; transform: translateY(-50%); position: absolute; height: 0.1rem; width: 0.1rem; background: #5342FF; } } &:last-child { // margin-bottom: 0.1rem; &::before { content: ""; left: 0; top: 50%; transform: translateY(-50%); position: absolute; height: 0.1rem; width: 0.1rem; background: #5342FF; } } } .active { > div { color: #333; } } } } :global(.tool-Tips) { background: #fff; box-shadow: 0 0 0.05rem 0 rgba(0, 0, 0, 0.25); border-radius: 0.01rem; padding: 0.1rem 0.2rem; > div { color: #333; font-size: 0.16rem; &:not(:first-child) { font-size: 0.14rem; > span { font-size: 0.14rem; color: #427aff; } } } } } } topListInfomation.tsx文件 // 调接口后的数据 {code: 200, msg: "成功",…} code: 200 data: [{name: "有色金属压延加工", amount: 12, percent: 0.2143}, {name: "国际组织", amount: 12, percent: 0.2143},…] 0: {name: "有色金属压延加工", amount: 12, percent: 0.2143} amount: 12 name: "有色金属压延加工" percent: 0.2143 1: {name: "国际组织", amount: 12, percent: 0.2143} 2: {name: "通用仪器仪表制造", amount: 11, percent: 0.1964} 3: {name: "非木竹材林产品采集", amount: 7, percent: 0.125} 4: {name: "海洋石油开采", amount: 2, percent: 0.0357} 5: {name: "其他体育组织", amount: 2, percent: 0.0357} 6: {name: "木材和竹材采运", amount: 2, percent: 0.0357} 7: {name: "电力供应", amount: 1, percent: 0.0179} 8: {name: "食品、饮料及烟草制品批发", amount: 1, percent: 0.0179} 9: {name: "陆地石油开采", amount: 1, percent: 0.0179} 10: {name: "其他", amount: 5, percent: 0.0892} msg: "成功" import React, { memo, useEffect, useState } from "react"; import tStyle from "./topListInfomation.module.less"; import Title from "components/BaseTitle/baseTitle"; import { useStore } from "store/appStore"; import echarts from "echarts/lib/echarts"; import { contaminatedLandManage } from "utils/apiGroup"; import ApiFetch from "utils/apiFetch"; import Nodata from "components/Nodata/Nodata"; interface IProps { params: any, } const TopListInfomation: React.FC<IProps> = ({ params }) => { const store = useStore(); const size = store.rootFontSize; const [list, setList] = useState([]); useEffect(() => { drawEcharts(); }, [list]); useEffect(() => { landInfoTopTen(); }, [JSON.stringify(params)]); const landInfoTopTen = async () => { const par = { endTime: params.endTime, startTime: params.startTime, plotSourceTypes: params.plotSourceTypes, }; const res: any = await ApiFetch.post(contaminatedLandManage.TopTenSiteDirectOryInfo, par); if (res._success && res.status) { setList(res.data); } else { setList([]); } }; const drawEcharts = () => { const el = document.getElementById("land_category_analysisTest") as HTMLCanvasElement; if (!el) return; const myChart = echarts.init(el); const opt: any = { tooltip: { trigger: "axis", show: true, axisPointer: { type: "none", }, confine: true, position: "top", padding: [0, 0, 0.2 * size, 0], hideDelay: 200, backgroundColor: "transparent", formatter: (item: any) => { return renderTipsView(item); } }, grid: [{ top: 0.1 * size, right: 0.3 * size, bottom: 0 * size, left: 0, containLabel: true }], xAxis: { type: "category", offset: 0, boundaryGap: true, axisTick: { show: false, interval: 0 }, interval: 0, axisLine: { lineStyle: { color: "#ccc", width: 0.01 * size, } }, splitLine: { show: false }, nameTextStyle: { padding: [0, 0, 0, 0.3 * size] }, axisLabel: { fontSize: 0.14 * size, color: "#666", align: "center", fontWeight: "300", interval: 0, rotate: -30, margin: 25, formatter: function(value: any) { return `{style|${value.length > 4 ? (value.slice(0, 4) + "...") : value}}`; }, rich: { style: { color: "#666", fontSize: 0.14 * size, padding: [0, 0, 0, 0.2 * size] } } }, data: list.map((item: any) => item.name), // data: getAxisValue() // data: ["化学原材料物品", "金属制品等材料", "金属制品等材料", "金属制品等材料", "金属制品等材料", "金属制品等材料", "金属制品等材料", "金属制品等材料", "金属制品等材料", "金属制品等材料", "金属制品等材料"] }, yAxis: { type: "value", nameLocation: "end", // name: "单位(km²)", axisLine: { show: false }, splitLine: { show: true, lineStyle: { color: "rgba(0,0,0,0.09)", width: 0.01 * size, type: "dashed" } }, axisLabel: { fontSize: size * 0.14, color: "#999" }, nameTextStyle: { fontSize: size * 0.14, color: "#999", padding: [0, 0, 0, 0.1 * size] }, axisTick: { show: false }, }, series: [ { type: "bar", label: { show: false, position: "top", color: "#333", distance: 0.05 * size, fontSize: 0.14 * size }, itemStyle: { color: { type: "linear", x: 0, y: 0, x2: 0, y2: 1, colorStops: [{ offset: 0, color: "#427AFF" // 0% 处的颜色 }], global: false // 缺省为 false } }, emphasis: { itemStyle: { color: { type: "linear", x: 0, y: 0, x2: 0, y2: 1, colorStops: [{ offset: 0, color: "#427AFF" // 0% 处的颜色 }], global: false // 缺省为 false }, shadowColor: "rgba(0,0,0,0.35)", shadowOffsetX: 0, shadowOffsetY: 0.02 * size, shadowBlur: 0.04 * size } }, barWidth: 0.15 * size, data: list.map((item: any) => item.amount) } ], }; myChart.setOption(opt); }; const renderTipsView = (name: any) => { return `<div class="land-category-tips"> <div>${name[0].axisValue}</div> <div class="times"><span>地块数</span>: <span>${name[0].value}</span></div> </div> `; }; return ( <div className={tStyle.wrapper}> <Title title="TOP10行业地块名录信息" /> <div className={tStyle.echartsCon}> { list.length ? <div className={tStyle.echarts} id="land_category_analysisTest"></div> : <Nodata /> } </div> </div> ); }; export default memo(TopListInfomation); topListInfomation.module.less文件 .wrapper { background: #fff; box-shadow: 0.02rem 0.02rem 0.1rem 0 rgba(0, 0, 0, 0.1); width: calc(50% - 0.1rem); margin-right: 0.2rem; flex-shrink: 0; flex-grow: 0; overflow: hidden; padding-top: 0.15rem; flex-direction: column; .echartsCon { flex: 1 1; margin: 0.2rem 0.2rem 0; height: 100%; width: calc(100% - 0.4rem); // overflow: hidden; display: flex; flex-wrap: wrap; .echarts { height: 1.69rem; width: 8.20rem; :global(.land-category-tips) { background: #fff; box-shadow: 0 0 0.05rem 0 rgba(0, 0, 0, 0.25); border-radius: 0.01rem; padding: 0.1rem 0.2rem; > div { color: #333; font-size: 0.16rem; .times { color: #427AFF; } > span:nth-child(1) { font-size: 0.14rem; } > span:nth-child(2) { color: #427aff; font-size: 0.14rem; } } } } } } {code: 200, msg: "成功", data: [{regionCode: "440304000000", regionName: "福田区", value: "54"},…]} code: 200 data: [{regionCode: "440304000000", regionName: "福田区", value: "54"},…] 0: {regionCode: "440304000000", regionName: "福田区", value: "54"} 1: {regionCode: "440303000000", regionName: "罗湖区", value: "43"} 2: {regionCode: "440308000000", regionName: "盐田区", value: "21"} 3: {regionCode: "440305000000", regionName: "南山区", value: "72"} 4: {regionCode: "440306000000", regionName: "宝安区", value: "344"} 5: {regionCode: "440307000000", regionName: "龙岗区", value: "239"} 6: {regionCode: "440309000000", regionName: "龙华区", value: "150"} 7: {regionCode: "440310000000", regionName: "坪山区", value: "67"} 8: {regionCode: "440311000000", regionName: "光明区", value: "125"} 9: {regionCode: "440312000000", regionName: "大鹏新区", value: "33"} 10: {regionCode: "440313000000", regionName: "深汕合作区", value: "0"} msg: "成功" areaListInfomation.tsx import React, { memo, useEffect, useState } from "react"; import aStyle from "./areaListInfomation.module.less"; import Title from "components/BaseTitle/baseTitle"; import { useStore } from "store/appStore"; import echarts from "echarts/lib/echarts"; import { contaminatedLandManage } from "utils/apiGroup"; import ApiFetch from "utils/apiFetch"; import Nodata from "components/Nodata/Nodata"; interface IProps { params: any, } const AreaListInfomation: React.FC<IProps> = ({ params }) => { const store = useStore(); const size = store.rootFontSize; const [list, setList] = useState([]); useEffect(() => { drawEcharts(); }, [list]); useEffect (() => { landInfo(); }, [JSON.stringify(params)]); const landInfo = async () => { const par = { endTime: params.endTime, startTime: params.startTime, // keyword: params.keyword, // plotSourceTypes: params.plotSourceTypes, // policyCode: params.policyCode, // polluteLevels: params.polluteLevels, // regionCodes: params.regionCodes, selects: params.selects, // surveyTypes: params.surveyTypes, // syncProvince: params.syncProvince, // trades: params.trades, // waterDrinks: params.waterDrinks, // waterPollutes: params.waterPollutes }; const res: any = await ApiFetch.post(contaminatedLandManage.directoryLandInfo, par); if (res._success && res.status) { setList(res.data); } else { setList([]); } }; const drawEcharts = () => { console.log(params, "paramsareaList"); const el = document.getElementById("land_category_analysis") as HTMLCanvasElement; if (!el) return; const myChart = echarts.init(el); const opt: any = { tooltip: { trigger: "axis", show: true, axisPointer: { type: "none", }, confine: true, position: "top", padding: [0, 0, 0.2 * size, 0], hideDelay: 200, backgroundColor: "transparent", formatter: (item: any) => { return renderTipsView(item); } }, grid: [{ top: 0.2 * size, right: 0.3 * size, bottom: 0 * size, left: 0, containLabel: true }], xAxis: { type: "category", axisTick: { show: false, interval: 0 }, interval: 0, axisLine: { lineStyle: { color: "#ccc", width: 0.01 * size, } }, splitLine: { show: false }, axisLabel: { fontSize: 0.14 * size, color: "#666666", align: "center", fontWeight: "300", interval: 0, rotate: -30, margin: 25, }, data: list.map((item: any) => item.regionName), // data: ["罗湖区", "福田区", "南山区", "宝安区", "光明区", "平山区", "龙华区", "龙岗区", "大鹏新区", "盐田区", "深汕合作区"] }, yAxis: { type: "value", nameLocation: "end", axisLine: { show: false }, splitLine: { show: true, lineStyle: { color: "rgba(0,0,0,0.09)", width: 0.01 * size, type: "dashed" } }, axisLabel: { fontSize: size * 0.14, color: "#999" }, nameTextStyle: { fontSize: size * 0.14, color: "#999", padding: [0, 0, 0, 0.1 * size] }, axisTick: { show: false }, }, series: [ { type: "bar", label: { show: false, position: "top", color: "#333", distance: 0.05 * size, fontSize: 0.14 * size }, itemStyle: { color: { type: "linear", x: 0, y: 0, x2: 0, y2: 1, colorStops: [{ offset: 0, color: "#60D522" // 0% 处的颜色 }], global: false // 缺省为 false } }, emphasis: { itemStyle: { color: { type: "linear", x: 0, y: 0, x2: 0, y2: 1, colorStops: [{ offset: 0, color: "#60D522" // 0% 处的颜色 }], global: false // 缺省为 false }, shadowColor: "rgba(0,0,0,0.35)", shadowOffsetX: 0, shadowOffsetY: 0.02 * size, shadowBlur: 0.04 * size } }, barWidth: 0.15 * size, data: list // data: [13, 10, 15, 6, 12, 8, 3, 18, 7, 7, 20], } ], }; myChart.setOption(opt); }; const renderTipsView = (name: any) => { return `<div class="land-category-tips"> <div>${name[0].axisValue}</div> <div class="times"><span>地块数</span>: <span>${name[0].value}</span></div> </div> `; }; return ( <div className={aStyle.wrapper}> <Title title="各区地块名录信息" /> <div className={aStyle.echartsCon}> { list.length ? <div className={aStyle.echarts} id="land_category_analysis"></div> : <Nodata /> } </div> </div> ); }; export default memo(AreaListInfomation); areaListInfomation.module.less .wrapper { background: #fff; box-shadow: 0.02rem 0.02rem 0.1rem 0 rgba(0, 0, 0, 0.1); width: calc(50% - 0.1rem); margin-right: 0.2rem; flex-shrink: 0; flex-grow: 0; overflow: hidden; padding-top: 0.15rem; flex-direction: column; .echartsCon { flex: 1 1; margin: 0.2rem 0.2rem 0; height: 100%; width: calc(100% - 0.4rem); // overflow: hidden; display: flex; flex-wrap: wrap; .echarts { height: 1.69rem; width: 8.20rem; :global(.land-category-tips) { background: #fff; box-shadow: 0 0 0.05rem 0 rgba(0, 0, 0, 0.25); border-radius: 0.01rem; padding: 0.1rem 0.2rem; > div { color: #333; font-size: 0.16rem; > span:nth-child(1) { font-size: 0.14rem; } > span:nth-child(2) { color: #427aff; font-size: 0.14rem; } } } } } } mapLand.tsx import React, { memo, useState, useEffect } from "react"; import MapTool from "components/MapTools/Maptool"; import PointDetail from "./pointDetail"; import { InitGisApi, IGisApi, /* renderArea */ } from "utils/esri-api"; import { DISTRICT_CENTER, // DefaultLandCenter, landDefaultZoom, // SSCenter, MAP_URL, IMG_URL, extent, RELIEF_URL, DefaultCenter, DefaultZoom } from "utils/commonConsts"; import ApiFetch from "utils/apiFetch"; import { pollutePlotMenuList, contaminatedLandManage } from "utils/apiGroup"; import noInvestigationImg from "assets/image/overviewMap/noInvestigation.png"; import { useStore } from "store/appStore"; import { IDefaultParam } from "../../headFilter/headFilter"; import lStyle from "./mapLand.module.less"; interface IProps { param: IDefaultParam; showDetail: (pointData: any) => void; } const mapTypes = [ { code: 0, name: "矢量图" }, { code: 1, name: "影像图" }, { code: 2, name: "地形图" } ]; let timer: any; let DEFAULT_ZOOM = landDefaultZoom; const MapLand: React.FC<IProps> = ({ param, showDetail }) => { const store = useStore(); const size = store.rootFontSize; const [mapId] = useState(`${new Date().getTime()}_land_mapContainer`); const [isFull, setIsFull] = useState(false); const mapInfos = ["baseMapLayer", "imgMapLayer", "releafMapLayer"]; const [map, setMap] = useState<any>(); const [baseMapInfos, setBaseMapInfos] = useState<any>(); const [gisApi, setGisApi] = useState<IGisApi>(); const [cooperZoneVisible, setCooperZoneVisible] = useState(true); const [pieceMap, setPieceMap] = useState(0); const [showResetBtn, setShowResetBtn] = useState(false); const [pointStyle, setPointStyle] = useState<any>(); const [showPoint, setShowPoint] = useState(false); const [restMapTool, setRestMapTool] = useState(false); const [pointData, setPointData] = useState<any[]>(); const [mapData, setMapData] = useState(); const [rgcenter, setRgCenter] = useState<number[]>(DefaultCenter); useEffect(() => { (async () => { setGisApi(await InitGisApi()); })(); document.addEventListener( "click", (e: any) => { if (e.target.nodeName.toLowerCase() === "image" || (e.target.nodeName.toLowerCase() === "path")) return; setShowPoint(false); }, false ); return () => { map && map.destroy(); clearTimeout(timer); document.addEventListener( "click", (e: any) => { if (e.target.nodeName.toLowerCase() === "image" || (e.target.nodeName.toLowerCase() === "path")) return; }, false ); }; }, []); const getDetailData = async (plotCode: string) => { const res: any = await ApiFetch.post(contaminatedLandManage.popupInfo, { param: plotCode }); if (res._success && res.data) { setPointData({ ...res.data[0], plotCode }); } }; useEffect(() => { if (!map) return; mapToFulled && mapToFulled(isFull); clearTimeout(timer); timer = setTimeout(() => { map.resize(true); map.reposition(); }, 0); }, [isFull]); useEffect(() => { if (param.searchValue === "") mapBack(); }, [param && param.searchValue]); useEffect(() => { if (param.regionCode === "440300000000") { map && (map.getZoom() === DefaultZoom ? map.centerAt(DefaultCenter) : map.centerAndZoom(DefaultCenter, DefaultZoom)); setRgCenter(DefaultCenter); } else { const fd = DISTRICT_CENTER.find((item: any) => String(item.regionCode).slice(0, 6) === String(param.regionCode).slice(0, 6)); fd && setRgCenter(fd.center); if (!fd || !map) return; map.getZoom() === 14 ? map.centerAt(fd.center) : map.centerAndZoom(fd.center, 14); } }, [param && param.regionCode]); useEffect(() => { if (!gisApi) return; gisApi.parser.parse(); const i = new gisApi.ArcGISTiledMapServiceLayer(IMG_URL, { id: "imgMapLayer", visible: false }); const b = new gisApi.ArcGISTiledMapServiceLayer(MAP_URL, { id: "baseMapLayer", visible: true }); const r = new gisApi.ArcGISTiledMapServiceLayer(RELIEF_URL, { id: "releafMapLayer", visible: false }); setBaseMapInfos({ baseMapLayer: b, imgMapLayer: i, releafMapLayer: r, }); const ext = new gisApi.Extent(extent); const m = new gisApi.Map(mapId, { extent: ext, fitExtent: true, slider: false, logo: false, nav: false, center: rgcenter || DefaultCenter, zoom: landDefaultZoom, minZoom: landDefaultZoom, maxZoom: 17 }); m.addLayers([i, b, r]); m.on("load", () => { setMap(m); }); m.on("zoom-start", (e: any) => { }); m.on("zoom-end", (e: any) => { setShowResetBtn(true); }); m.on("pan-start", () => { }); m.on("pan-end", (e: any) => { setShowResetBtn(true); }); }, [gisApi]); useEffect(() => { drawLayer(mapData || []); }, [JSON.stringify(mapData), map]); useEffect(() => { getMapData(); }, [JSON.stringify(param)]); const mapToFulled = (full: boolean) => { setIsFull(full); }; const getMapData = async () => { const res = await ApiFetch.post(pollutePlotMenuList.mapDataApi, param); drawLayer(res.data); setMapData(res.data); }; const drawLayer = (data?: any[]) => { if (!map || !gisApi) return; clearLayers(); const layer = new gisApi.GraphicsLayer({ id: "pointLayer" }); layer.on("click", (e: any) => { const data: any = e.graphic._dataAttrs; setShowPoint(true); getDetailData(data.plotCode); const pos = setPosition(Number(data.longitude), Number(data.latitude)); setPointStyle({ left: (pos || {}).x || 0, top: (pos || {}).y || 0 }); }); layer.on("mouse-over", (e: any) => { const data: any = e.graphic; const icon = noInvestigationImg; const markerSymbol = new gisApi.PictureMarkerSymbol( icon, 0.25 * size, 0.25 * size ); data.setSymbol(markerSymbol); }); layer.on("mouse-out", (e: any) => { const data: any = e.graphic; const icon = noInvestigationImg; const markerSymbol = new gisApi.PictureMarkerSymbol( icon, 0.2 * size, 0.2 * size ); data.setSymbol(markerSymbol); }); map.addLayer(layer, 100); (data || []).forEach((item: any) => { if (item.longitude && item.latitude) { const markerPosition = new gisApi.Point( Number(item.longitude), Number(item.latitude) ); const icon = noInvestigationImg; const markerSymbol = new gisApi.PictureMarkerSymbol( icon, 0.2 * size, 0.2 * size ); const markerImage = new gisApi.Graphic(markerPosition, markerSymbol); Object.keys(item).forEach(k => { markerImage.attr(k, item[k]); }); layer.add(markerImage); } }); }; const setPosition = (longitude: number, latitude: number) => { if (!map || !gisApi) return null; const point = new gisApi.Point(Number(longitude), Number(latitude)); const pos = map ? map.toScreen(point) : null; return pos; }; const showCooperZone = (): any => { setCooperZoneVisible(!cooperZoneVisible); setPieceMap(Number(!pieceMap)); setShowResetBtn(!pieceMap); }; const changeImgMap = (i: number) => { if (!map) return; const type = mapInfos[i]; mapInfos.forEach((item: string) => { if (type === item) { !map.getLayer(item) && map.addLayer(baseMapInfos[item]); baseMapInfos[item].setVisibility(true); } else { baseMapInfos[item].setVisibility(false); } }); }; const mapToFull = () => { setCooperZoneVisible(true); setIsFull(!isFull); }; const mapBack = () => { if (!map) return; if (map.getZoom() === DEFAULT_ZOOM) { map.centerAt(DefaultCenter).then(() => { setCooperZoneVisible(true); setRestMapTool(!restMapTool); setPieceMap(0); setShowResetBtn(false); }); } else { map.centerAndZoom(DefaultCenter).then(() => { setCooperZoneVisible(true); setRestMapTool(!restMapTool); setPieceMap(0); setShowResetBtn(false); }); } }; const clearLayers = () => { if (!map) return; try { const layerArr = map.getLayersVisibleAtScale(); layerArr.forEach((item: any) => { if (item && !item.url && item.id !== "highlight" && item.id !== "RegionLayers") { map.removeLayer(item); } }); } catch (e) { console.error(e); } }; const onClickedDetail = () => { showDetail(pointData); }; return ( <div className={`${lStyle.mapWrapper} ${isFull ? lStyle.fullWrapper : ""}`}> <div className={lStyle.mapContainer} id={mapId}> <MapTool mapTypeLists={mapTypes} changeCenter={showCooperZone} changeBasemapType={changeImgMap} restMapTool={restMapTool} /> <PointDetail onClose={() => setShowPoint(false)} userClassName={lStyle.pointDetail} showDetail={onClickedDetail} show={showPoint} data={pointData} style={pointStyle} /> <div className={lStyle.mapBtns}> <div className={lStyle.backbtn} onClick={mapBack} style={{ display: !showResetBtn ? "none" : "block" }} > <i className="iconfont paicon-mapback" style={{ fontSize: "0.4rem" }} /> </div> <div className={lStyle.fullBtn} onClick={mapToFull}> <i className={`iconfont ${ isFull ? "paicon-narrow" : "paicon-amplification" }`} /> </div> </div> </div> </div> ); }; const areEqual = (props: IProps, nextProps: IProps) => JSON.stringify(props.param) === JSON.stringify(nextProps.param); export default memo(MapLand, areEqual);