Files

548 lines
15 KiB
Vue
Raw Normal View History

2022-09-20 17:31:39 +08:00
<template>
<div class="box3" v-loading="loading">
<div class="tit">需求分布地图</div>
<div v-if="state.isShowGoBack" class="close-back" @click="goBack">
<img src="./img/back_button.png" />
</div>
<!-- echartsDom 兼容缩放 -->
<div ref="map" class="map echartsDom" id="map"></div>
<div class="leftBox">
<div class="head">
<div class="a">地区</div>
<div class="b">需求数量</div>
</div>
<template v-if="snapTree.length > 0">
<div
v-for="v in snapTree.slice(
(leftBoxPageNum - 1) * 5,
leftBoxPageNum * 5
)"
>
<div class="a">{{ v.name }}</div>
<div class="b">{{ v.count }}</div>
</div>
</template>
2022-09-20 17:31:39 +08:00
<div v-else>
<div class="a">暂无</div>
<div class="b">暂无</div>
</div>
<RegionPagine
v-if="snapTree.length"
v-model:page="leftBoxPageNum"
:total="snapTree.length"
></RegionPagine>
2022-09-20 17:31:39 +08:00
</div>
2022-11-25 17:30:39 +08:00
<div class="rightBox">
2022-09-20 17:31:39 +08:00
<div class="head">
<div class="a">领域</div>
<div class="b">需求数量</div>
</div>
<div
2022-11-25 17:30:39 +08:00
v-if="Object.keys(industryTree).length > 0"
v-for="(v, k) in industryTree"
2022-09-20 17:31:39 +08:00
>
<div class="a" :title="k">{{ k }}</div>
<div class="b">{{ v }}</div>
</div>
<div v-else>
<div class="a">暂无</div>
<div class="b">暂无</div>
</div>
2022-11-25 17:30:39 +08:00
</div>
2022-09-20 17:31:39 +08:00
</div>
</template>
<script setup>
import { defineComponent, getCurrentInstance, onMounted, reactive } from "vue";
2022-10-01 09:12:01 +08:00
import * as echarts from "echarts";
2022-10-19 00:22:39 +08:00
import {
countDemandByProvince,
countDemandByCity,
countDemandByArea,
} from "@/api/website/home/index";
import RegionPagine from "./RegionPagine.vue";
2022-10-01 09:12:01 +08:00
// import { demand } from "@/api/website/home/index";
2022-09-20 17:31:39 +08:00
const { proxy } = getCurrentInstance();
const loading = shallowRef(true);
2022-11-25 17:30:39 +08:00
let treeData = {};
const snapTree = shallowRef([]);
2022-11-25 17:30:39 +08:00
const industryTree = shallowRef({});
const leftBoxPageNum = ref(1);
2022-10-19 00:22:39 +08:00
const searchRegionData = async (code, level) => {
if (level == "province") {
const provcode = code.substring(0, 2) + "0000";
let data = {};
if (
snapTree.value.length &&
snapTree.value[0].code.substring(0, 2) == code.substring(0, 2) &&
snapTree.value[0].code.substring(2, 4) != code.substring(2, 4)
) {
data = snapTree.value;
} else {
const resp = await countDemandByCity(provcode);
2022-11-25 17:30:39 +08:00
snapTree.value = resp.count;
industryTree.value = resp.industry ?? {};
data = resp.count;
2022-10-19 00:22:39 +08:00
}
return data.find((item) => item.code == code) || false;
} else if (level == "city") {
const ctcode = code.substring(0, 4) + "00";
let data = {};
if (
snapTree.value.length &&
snapTree.value[0].code.substring(0, 4) == code.substring(0, 4) &&
snapTree.value[0].code.substring(4, 6) != code.substring(4, 6)
) {
data = snapTree.value;
} else {
const resp = await countDemandByArea(ctcode);
2022-11-25 17:30:39 +08:00
snapTree.value = resp.count;
industryTree.value = resp.industry ?? {};
data = resp.count;
2022-10-19 00:22:39 +08:00
}
return data.find((item) => item.code == code) || false;
} else {
2022-11-25 17:30:39 +08:00
if (Object.keys(treeData).length) {
industryTree.value = treeData.industry ?? {};
snapTree.value = treeData.count ?? [];
2022-11-25 17:30:39 +08:00
return treeData.count.find((item) => item.code == code) || false;
2022-10-19 00:22:39 +08:00
} else {
2022-11-25 17:30:39 +08:00
const { count, industry } = await countDemandByProvince();
industryTree.value = industry ?? {};
return count.find((item) => item.code == code) || false;
2022-10-19 00:22:39 +08:00
}
}
};
2022-09-20 17:31:39 +08:00
function deepFindTree(code, tree) {
let snap = false;
for (const key in tree) {
if (Object.hasOwnProperty.call(tree, key)) {
if (code == key) {
snap = tree[code];
break;
} else if (tree[key]["children"] != null) {
snap = deepFindTree(code, tree[key]["children"]);
if (snap) {
break;
}
} else {
snap = false;
}
}
}
return snap;
}
function getIndustry(object) {
let snap = {};
for (const key in object) {
if (Object.hasOwnProperty.call(object, key)) {
const element = object[key];
if (element["industry"] != null) {
for (const ek in element["industry"]) {
if (Object.hasOwnProperty.call(element["industry"], ek)) {
const ele = element["industry"][ek];
if (!Object.hasOwnProperty.call(snap, ek)) {
snap[ek] = 0;
}
snap[ek] += ele;
}
}
// for (let index = 0; index < element['industry'].length; index++) {
// const ele = element['industry'][index];
// if(Object.hasOwnProperty.call(snap, ele)) {
// }
// }
}
}
}
return snap;
}
const state = reactive({
loading: false,
isShowGoBack: false,
nameType: "",
// cityName: "中国",
cityName: "china",
areaCode: 10000,
AreaCodeStack: ["中国"],
geoJsonData: "",
echartsMap: null,
map: null,
uimap: null,
district: null,
polygons: [],
cityCode: "100000",
citySelect: null,
districtSelect: null,
opts: {},
areaData: {},
mapData: [],
zip: {}, //打包zip
codeList: [],
isCodeListLoadComplete: false, //codeList是否全部获取完毕
downloadTips: "下载geoJson数据", //下载进度提示
isShowTips: false, //是否显示下载提示
});
onMounted(() => {
// 数据接口
2022-11-25 17:30:39 +08:00
countDemandByProvince().then((resp) => {
treeData = resp;
snapTree.value = resp.count;
industryTree.value = resp.industry ?? {};
2022-10-19 00:22:39 +08:00
loading.value = false;
});
2022-09-20 17:31:39 +08:00
// let echartsDomList = document.querySelectorAll('.echartsDom');
// // 兼容echarts
// echartsDomList.forEach(element => {
// element.style.zoom = window.devicePixelRatio;
// element.style.transform = "scale(" + (1 / window.devicePixelRatio) + ")";
// element.style.transformOrigin = "0%0%";
// element.style.width = window.devicePixelRatio * 100 + '%';
// element.style.height = window.devicePixelRatio * 100 + '%';
// console.log(element.style.zoom, 'element.style.zoom')
// });
let height = document.body.clientHeight;
let width = document.body.clientWidth;
let dom = proxy.$refs["map"];
dom.style.width = width + "px";
dom.style.height = height - 80 + "px";
state.echartsMap = echarts.init(dom);
state.echartsMap.on("click", echartsMapClick);
setTimeout(() => {
state.map = new AMap.Map("container", {
resizeEnable: true,
center: [116.30946, 39.937629],
zoom: 3,
});
state.opts = {
subdistrict: 1, //返回下一级行政区
showbiz: false, //最后一级返回街道信息
};
state.district = new AMap.DistrictSearch(state.opts); //注意:需要使用插件同步下发功能才能这样直接使用
state.district.search("中国", (status, result) => {
if (status == "complete") {
getData(result.districtList[0], "", 100000);
}
});
}, 4000);
});
function goBack() {
state.isShowGoBack = false;
loading.value = true;
2022-10-19 00:22:39 +08:00
state.district.search("中国", async (status, result) => {
2022-09-20 17:31:39 +08:00
if (status == "complete") {
2022-10-19 00:22:39 +08:00
await getData(result.districtList[0], "", 100000);
2022-11-25 17:30:39 +08:00
snapTree.value = treeData.count;
2022-09-20 17:31:39 +08:00
}
});
}
2022-10-19 00:22:39 +08:00
async function echartsMapClick(params) {
2022-09-20 17:31:39 +08:00
//地图点击事件
if (params.data.cityCode == "710000") {
return;
}
if (params.data.level == "district") {
return;
}
if (params.data.level == "street") return; //此处的params.data为state.mapData里的数据
2022-10-19 00:22:39 +08:00
await searchRegionData(params.data.cityCode, params.data.level);
// snapTree.value = {};
// if (snap) {
// snapTree.value = snap["children"];
// }
2022-09-20 17:31:39 +08:00
state.cityCode = params.data.cityCode;
state.cityName = params.data.name;
state.district.setLevel(params.data.level); //行政区级别
state.district.setExtensions("all");
state.isShowGoBack = true;
loading.value = true;
//行政区查询
//按照adcode进行查询可以保证数据返回的唯一性
state.district.search(state.cityCode, (status, result) => {
if (status === "complete") {
if (params.data.level == "district") {
return;
}
state.AreaCodeStack.push(result.districtList[0].adcode);
getData(result.districtList[0], params.data.level, state.cityCode); //这个getData函数在前面已经定义过了
}
});
}
2022-10-19 00:22:39 +08:00
async function getData(data, level, adcode) {
2022-09-20 17:31:39 +08:00
//处理获取出来的边界数据
var subList = data.districtList;
if (subList) {
var curlevel = subList[0].level;
if (curlevel === "street") {
//为了配合echarts地图区县名称显示正常这边街道级别数据需要特殊处理
let mapJsonList = state.geoJsonData.features;
let mapJson = {};
for (let i in mapJsonList) {
if (mapJsonList[i].properties.name == state.cityName) {
mapJson["features"] = [].concat(mapJsonList[i]);
}
}
state.mapData = [];
2022-10-19 00:22:39 +08:00
let item = await searchRegionData(cityCode, level);
2022-09-20 17:31:39 +08:00
if (item) {
console.log("1 searchRegionData(cityCode)", item);
}
//这个mapData里包含每个区域的code、名称、对应的等级实现第三步功能时能用上
state.mapData.push({
name: state.cityName,
value: item ? item.count : 0,
level: curlevel,
});
loadMap(state.cityName, mapJson);
state.geoJsonData = mapJson;
return;
}
//街道级以上的数据处理方式
state.mapData = [];
for (var i = 0, l = subList.length; i < l; i++) {
var name = subList[i].name;
var cityCode = subList[i].adcode;
//这个mapData里包含每个区域的code、名称、对应的等级实现第三步功能时能用上
2022-10-19 00:22:39 +08:00
let item = await searchRegionData(cityCode, level);
2022-09-20 17:31:39 +08:00
if (item) {
console.log("2 searchRegionData(cityCode)", item);
}
state.mapData.push({
name: name,
value: item ? item.count : 0,
cityCode: cityCode,
level: curlevel,
});
}
loadMapData(adcode);
}
}
function loadMapData(areaCode) {
AMapUI.loadUI(["geo/DistrictExplorer"], (DistrictExplorer) => {
//创建一个实例
var districtExplorer = (window.districtExplorer = new DistrictExplorer({
eventSupport: true, //打开事件支持
map: state.map,
}));
districtExplorer.loadAreaNode(areaCode, (error, areaNode) => {
if (error) {
console.error(error);
return;
}
let mapJson = {};
//特别注意这里哦如果查看过正常的geojson文件都会发现文件都是以features 字段开头的,所以这里要记得加上
mapJson.features = areaNode.getSubFeatures();
console.log("------------------");
for (var i = 0; i < mapJson.features.length; i++) {
if (
mapJson.features[i].properties.adcode == 810000 ||
mapJson.features[i].properties.adcode == 820000
) {
mapJson.features.splice(i, 1); // 删除下标为i 的元素i开始只删除一个就它自己了
i--; // 删除一个元素后数组长度减一了
}
}
console.log("------------------");
loadMap(state.cityName, mapJson);
});
});
}
function loadMap(mapName, data) {
if (data) {
echarts.registerMap(mapName, data); //把geoJson数据注入echarts
//配置echarts的option
var option = {
visualMap: {
type: "piecewise",
left: "center", //组件离容器左侧的距离,'left', 'center', 'right','20%'
bottom: "30",
orient: "horizontal", //图例排列方向
padding: 5,
pieces: [
{ gte: 0, lte: 99, label: "99", color: "#CAE9FD" },
{ gte: 100, lte: 299, label: "100-299", color: "#7ED2F7" },
{ gte: 300, lte: 499, label: "299-499", color: "#039DDD" },
{ gte: 500, label: "500", color: "#0D4884" },
// {max: 30, label: '安全', color: '#2c9a42'},
// {min: 30, max: 60, label: '警告', color: '#d08a00'},
// {min: 60, label: '危险', color: '#c23c33'},
],
// color: '#fff',
textStyle: {
color: "#333333",
},
visibility: "off",
},
tooltip: {
//提示框信息
trigger: "item",
formatter: "{b}\n{c}个",
},
series: [
{
name: "数据名称",
type: "map",
roam: false,
top: "15%",
bottom: state.isShowGoBack ? "8%" : "-20%",
mapType: mapName,
selectedMode: "single",
showLegendSymbol: false,
visibility: "off",
backgroundColor: "transparent",
itemStyle: {
normal: {
color: "#333333",
areaColor: "#fff",
borderColor: "#666666",
borderWidth: 0.5,
label: {
show: false,
2022-09-20 17:31:39 +08:00
textStyle: {
color: "#333333",
},
},
},
emphasis: {
areaColor: "rgb(38, 219, 11)",
borderColor: "#666666",
areaStyle: {
color: "#333333",
},
label: {
show: true,
textStyle: {
color: "#333333",
},
// formatter: function (value) { //标签的格式化工具。
// return value.name + '' + value.value; // 范围标签显示内容。
// }
},
},
},
data: state.mapData, //这个data里包含每个区域的code、名称、对应的等级实现第三步功能时能用上
},
],
};
state.echartsMap.setOption(option);
loading.value = false;
}
}
</script>
<style lang="scss" scoped>
.box3 {
width: 100%;
height: 100%;
position: relative;
.tit {
position: absolute;
top: 75px;
width: 100%;
text-align: center;
font-size: 36px;
font-family: Source Han Sans CN;
font-weight: 300;
color: #333333;
}
}
.map {
width: 100%;
height: 100%;
// background-image: url(./img/lightEffect.png);
background-size: 644px 272px;
background-repeat: no-repeat;
background-position: center top;
}
.close-back {
background: url(img/close_back.png) no-repeat;
transition: all 0.5s;
height: 70px;
width: 85px;
color: #fff;
left: 65px;
position: absolute;
top: 100px;
cursor: pointer;
z-index: 1000;
&:hover {
left: 55px;
}
img {
margin: 28px auto 0;
width: 30px;
display: block;
transition: all 0.5s;
}
}
.leftBox {
left: 6%;
}
.rightBox {
right: 6%;
max-height: 465px !important;
}
.leftBox,
.rightBox {
position: absolute;
top: 25%;
max-width: 250px;
min-width: 200px;
max-height: 256px;
// overflow: hidden;
2022-09-20 17:31:39 +08:00
border: 1px solid #dcdcdc;
color: #666666;
& > div {
display: flex;
}
.head {
border-bottom: 1px solid #dcdcdc;
color: #333333;
}
.a {
flex: 1;
border-right: 1px solid #dcdcdc;
text-align: center;
line-height: 42px;
overflow: hidden;
white-space: nowrap;
text-overflow: ellipsis;
}
.b {
text-align: center;
line-height: 42px;
width: 90px;
}
}
.rightBox {
overflow: hidden;
}
2023-01-04 16:11:46 +08:00
// :deep(.pagine) {
// .prev,
// .next {
// color: #4f93ed !important;
// }
// }
2022-10-01 09:12:01 +08:00
</style>