bugfix
This commit is contained in:
11
index.html
11
index.html
@ -9,13 +9,14 @@
|
||||
<link href="/favicon.ico" rel="icon">
|
||||
<script type="text/javascript">
|
||||
window._AMapSecurityConfig = {
|
||||
securityJsCode: '7d1b758db4876389af608259c4c99832',
|
||||
securityJsCode: '2b65e7751cb17e4605f4c4cdccf885f6',
|
||||
// securityJsCode: '7d1b758db4876389af608259c4c99832',
|
||||
}
|
||||
</script>
|
||||
<script src='//webapi.amap.com/maps?v=1.4.15&key=bfc7224388e835679ffe74cfbd28c8d6' type="text/javascript"></script>
|
||||
<script src="https://webapi.amap.com/maps?v=1.4.11&key=bfc7224388e835679ffe74cfbd28c8d6&plugin=AMap.DistrictSearch"
|
||||
type="text/javascript"></script>
|
||||
<script src="//webapi.amap.com/ui/1.0/main.js?v=1.0.11"></script>
|
||||
<!-- <script src='//webapi.amap.com/maps?v=1.4.15&key=bfc7224388e835679ffe74cfbd28c8d6' type="text/javascript"></script>-->
|
||||
<!-- <script src="https://webapi.amap.com/maps?v=1.4.11&key=bfc7224388e835679ffe74cfbd28c8d6&plugin=AMap.DistrictSearch"-->
|
||||
<!-- type="text/javascript"></script>-->
|
||||
<!-- <script src="//webapi.amap.com/ui/1.0/main.js?v=1.0.11"></script>-->
|
||||
<title>中科云</title>
|
||||
<!--[if lt IE 11]>
|
||||
<script>window.location.href = '/html/ie.html';</script><![endif]-->
|
||||
|
@ -16,16 +16,19 @@
|
||||
"url": "https://gitee.com/y_project/RuoYi-Vue.git"
|
||||
},
|
||||
"dependencies": {
|
||||
"@amap/amap-jsapi-loader": "^1.0.1",
|
||||
"@element-plus/icons-vue": "1.1.4",
|
||||
"@vueuse/core": "8.5.0",
|
||||
"@wangeditor/editor": "^5.1.23",
|
||||
"@wangeditor/editor-for-vue": "^5.1.12",
|
||||
"animejs": "^3.2.1",
|
||||
"axios": "0.26.1",
|
||||
"echarts": "^5.4.0",
|
||||
"echarts-extension-amap": "^1.10.1",
|
||||
"element-plus": "2.1.8",
|
||||
"file-saver": "2.0.5",
|
||||
"fuse.js": "6.5.3",
|
||||
"html2canvas": "^1.4.1",
|
||||
"js-cookie": "3.0.1",
|
||||
"js-md5": "^0.7.3",
|
||||
"jsencrypt": "3.2.1",
|
||||
|
BIN
src/assets/images/map_back.png
Normal file
BIN
src/assets/images/map_back.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 508 B |
11
src/views/website/home/comp/MapFullpage.vue
Normal file
11
src/views/website/home/comp/MapFullpage.vue
Normal file
@ -0,0 +1,11 @@
|
||||
<script setup>
|
||||
|
||||
</script>
|
||||
|
||||
<template>
|
||||
|
||||
</template>
|
||||
|
||||
<style scoped lang="scss">
|
||||
|
||||
</style>
|
@ -1,22 +1,22 @@
|
||||
<template>
|
||||
<div class="paging">
|
||||
<el-icon
|
||||
class="prev"
|
||||
:style="{
|
||||
cursor: page === 1 ? 'not-allowed' : 'pointer',
|
||||
color: page === 1 ? '#999' : '#4f93ed',
|
||||
}"
|
||||
class="prev"
|
||||
@click="prev"
|
||||
>
|
||||
<ArrowLeftBold/>
|
||||
</el-icon>
|
||||
<div class="page-num">{{ page }}</div>
|
||||
<el-icon
|
||||
class="next"
|
||||
:style="{
|
||||
cursor: Math.ceil(total / 5) <= page ? 'not-allowed' : 'pointer',
|
||||
color: Math.ceil(total / 5) <= page ? '#999' : '#4f93ed',
|
||||
}"
|
||||
class="next"
|
||||
@click="next"
|
||||
>
|
||||
<ArrowRightBold/>
|
||||
@ -26,6 +26,8 @@
|
||||
|
||||
<script setup>
|
||||
import {toRefs} from "vue";
|
||||
import {ArrowLeftBold, ArrowRightBold} from "@element-plus/icons-vue";
|
||||
|
||||
const emit = defineEmits(["update:page"]);
|
||||
const props = defineProps({
|
||||
total: {
|
||||
@ -40,7 +42,7 @@ const props = defineProps({
|
||||
const {total, page} = toRefs(props);
|
||||
|
||||
const prev = () => {
|
||||
if (page.value == 1) return;
|
||||
if (page.value === 1) return;
|
||||
emit("update:page", page.value - 1);
|
||||
};
|
||||
const next = () => {
|
||||
@ -50,6 +52,7 @@ const next = () => {
|
||||
</script>
|
||||
<style lang="scss" scoped>
|
||||
.paging {
|
||||
display: flex;
|
||||
width: 100px;
|
||||
z-index: 9999;
|
||||
position: absolute;
|
||||
@ -58,6 +61,7 @@ const next = () => {
|
||||
transform: translateX(-50%);
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
|
||||
.prev,
|
||||
.next {
|
||||
user-select: none;
|
||||
@ -66,5 +70,9 @@ const next = () => {
|
||||
width: 30px;
|
||||
height: 30px;
|
||||
}
|
||||
|
||||
.page-num {
|
||||
color: white;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
413
src/views/website/home/comp/index0.vue
Normal file
413
src/views/website/home/comp/index0.vue
Normal file
@ -0,0 +1,413 @@
|
||||
<script setup>
|
||||
import AMapLoader from '@amap/amap-jsapi-loader';
|
||||
import {computed, onMounted, ref, shallowRef} from "vue";
|
||||
import {init, registerMap} from "echarts";
|
||||
import {
|
||||
countAchievementByArea,
|
||||
countAchievementByCity,
|
||||
countAchievementByProvince,
|
||||
countDemandByProvince,
|
||||
countEnterpriseByArea,
|
||||
countEnterpriseByCity,
|
||||
countEnterpriseByProvince,
|
||||
countExpertByArea,
|
||||
countExpertByCity,
|
||||
countExpertByProvince
|
||||
} from "@/api/website/home";
|
||||
import backBtnPng from '@/assets/images/map_back.png'
|
||||
import RegionPagine from "@/views/website/home/comp/RegionPagine.vue";
|
||||
import html2canvas from "html2canvas";
|
||||
import anime from "animejs";
|
||||
|
||||
const leftBoxPageNum = ref(1)
|
||||
const mapRef = ref(null);
|
||||
const districtSearch = shallowRef(null)
|
||||
const myEcharts = shallowRef(null)
|
||||
const map = shallowRef(null)
|
||||
const mapData = ref([])
|
||||
|
||||
const methods = [
|
||||
{
|
||||
name: "expert",
|
||||
title: "专家分布地图",
|
||||
byProvince: countExpertByProvince,
|
||||
byCity: countExpertByCity,
|
||||
byArea: countExpertByArea
|
||||
},
|
||||
{
|
||||
name: "technology",
|
||||
title: "技术分布地图",
|
||||
byProvince: countAchievementByProvince,
|
||||
byCity: countAchievementByCity,
|
||||
byArea: countAchievementByArea
|
||||
},
|
||||
{
|
||||
name: "demand",
|
||||
title: "需求分布地图",
|
||||
byProvince: countDemandByProvince,
|
||||
byCity: countDemandByProvince,
|
||||
byArea: countDemandByProvince
|
||||
},
|
||||
{
|
||||
name: "enterprise",
|
||||
title: "企业分布地图",
|
||||
byProvince: countEnterpriseByProvince,
|
||||
byCity: countEnterpriseByCity,
|
||||
byArea: countEnterpriseByArea
|
||||
},
|
||||
]
|
||||
|
||||
const methodIndex = ref(0)
|
||||
|
||||
const areaCount = ref([]) // 按行政区划统计
|
||||
const industryCount = ref([]) // 按领域统计
|
||||
const areaCountPaged = computed(() => areaCount.value.slice((leftBoxPageNum.value - 1) * 5, leftBoxPageNum.value * 5))
|
||||
const options = {
|
||||
// nameProperty: 'adcode',
|
||||
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"},
|
||||
],
|
||||
textStyle: {
|
||||
color: "#fff",
|
||||
},
|
||||
visibility: "off",
|
||||
},
|
||||
tooltip: {
|
||||
//提示框信息
|
||||
trigger: "item",
|
||||
formatter: "{b}\n{c}人",
|
||||
},
|
||||
series: [
|
||||
{
|
||||
type: "map",
|
||||
name: "中国",
|
||||
map: "map",
|
||||
data: []
|
||||
},
|
||||
],
|
||||
}
|
||||
const loadAMap = async () => {
|
||||
const AMap = await AMapLoader.load({
|
||||
"key": "377d7c36dd385e2a722f29d4c6e1ffbf", // 申请好的Web端开发者Key,首次调用 load 时必填
|
||||
"version": "2.0", // 指定要加载的 JS API 的版本,缺省时默认为 1.4.15
|
||||
"plugins": ["AMap.DistrictSearch", "AMap.DistrictExplorer"], // 需要使用的的插件列表,如比例尺'AMap.Scale'等
|
||||
"AMapUI": {
|
||||
// 是否加载 AMapUI,缺省不加载
|
||||
version: '1.1', // AMapUI 缺省 1.1
|
||||
plugins: [], // 需要加载的 AMapUI ui插件
|
||||
},
|
||||
})
|
||||
map.value = new AMap.Map("container", {
|
||||
zoom: 4, //级别
|
||||
center: [108.946609, 34.262324], //中心点坐标
|
||||
// viewMode: '3D' //使用3D视图
|
||||
});
|
||||
map.value.on("click", mapClick)
|
||||
districtSearch.value = new AMap.DistrictSearch({
|
||||
level: 'province',
|
||||
extensions: 'all',
|
||||
subdistrict: 1,
|
||||
showbiz: false,
|
||||
})
|
||||
}
|
||||
const loading = ref(false)
|
||||
const loadDistrict = (adcode) => {
|
||||
loading.value = true
|
||||
AMapUI.loadUI(["geo/DistrictExplorer"], (DistrictExplorer) => {
|
||||
const districtExplorer = new DistrictExplorer({
|
||||
map: map //关联的地图实例
|
||||
});
|
||||
|
||||
districtExplorer.loadAreaNode(adcode, async (error, areaNode) => {
|
||||
if (error) {
|
||||
console.error(error);
|
||||
loading.value = false
|
||||
return;
|
||||
}
|
||||
const parentAdcode = areaNode.getAdcode()
|
||||
// 绘制载入的区划节点
|
||||
const geoJSON = {
|
||||
type: 'FeatureCollection',
|
||||
features: areaNode.getSubFeatures(),
|
||||
}
|
||||
const level = getLevel(adcode)
|
||||
let result
|
||||
try {
|
||||
if (level === 0) {
|
||||
result = await methods[methodIndex.value]['byProvince']()
|
||||
} else if (level === 1) {
|
||||
result = await methods[methodIndex.value]['byCity'](adcode)
|
||||
} else if (level === 2) {
|
||||
result = await methods[methodIndex.value]['byArea'](adcode)
|
||||
}
|
||||
} catch (e) {
|
||||
loading.value = false
|
||||
return
|
||||
}
|
||||
industryCount.value = result.industry
|
||||
areaCount.value = result.count
|
||||
mapData.value = geoJSON.features.map(el => {
|
||||
const areaProp = el.properties
|
||||
return {
|
||||
adcode: areaProp.adcode,
|
||||
name: areaProp.name,
|
||||
value: result.count.find(el => el.code == areaProp.adcode)?.count ?? 0
|
||||
}
|
||||
})
|
||||
|
||||
registerMap("map", {geoJSON, specialAreas: {}})
|
||||
options.series[0].data = mapData.value
|
||||
myEcharts.value.setOption(
|
||||
options
|
||||
)
|
||||
loading.value = false
|
||||
});
|
||||
})
|
||||
}
|
||||
|
||||
// 返回地图上一级
|
||||
const backMap = () => {
|
||||
// loadDistrict(parentAdcode)
|
||||
loadDistrict("100000")
|
||||
}
|
||||
|
||||
|
||||
onMounted(async () => {
|
||||
await loadAMap()
|
||||
myEcharts.value = init(mapRef.value)
|
||||
myEcharts.value.on('click', mapClick)
|
||||
loadDistrict("100000")
|
||||
})
|
||||
|
||||
/**
|
||||
* 根据adcode判断省市区级别
|
||||
* @param adcode
|
||||
* @return {number} 国家: 0 省: 1 市: 2 区: 3
|
||||
*/
|
||||
const getLevel = (adcode) => {
|
||||
adcode = adcode.toString()
|
||||
if (adcode === '100000') {
|
||||
return 0
|
||||
}
|
||||
const splitPattern = /(\d{2})(\d{2})(\d{2})/;
|
||||
const resultArray = adcode.match(splitPattern).slice(1);
|
||||
// 国家: 0 省: 1 市: 2 区: 3
|
||||
let result = resultArray.indexOf("00")
|
||||
if (result === -1) {
|
||||
result = 3
|
||||
}
|
||||
return result
|
||||
}
|
||||
const mapClick = (ev) => {
|
||||
const level = getLevel(ev.data.adcode)
|
||||
if (level === 3) {
|
||||
return
|
||||
}
|
||||
loadDistrict(ev.data.adcode)
|
||||
}
|
||||
|
||||
const handleScroll = (ev) => {
|
||||
let direction = ev.deltaY > 0 ? 'down' : 'up'
|
||||
// 判断滚轮滚动方向
|
||||
if (direction === 'down' && methodIndex.value < methods.length - 1) {
|
||||
methodIndex.value++
|
||||
} else if (direction === 'up' && methodIndex.value > 0) {
|
||||
methodIndex.value--
|
||||
} else {
|
||||
return
|
||||
}
|
||||
ev.preventDefault()
|
||||
ev.stopPropagation()
|
||||
const pageWrap = document.querySelector('.page-wrap')
|
||||
const rootWrap = document.querySelector('.root-container')
|
||||
html2canvas(pageWrap).then(canvas => {
|
||||
if (direction === 'down') {
|
||||
rootWrap.insertBefore(canvas, pageWrap)
|
||||
} else if (direction === 'up') {
|
||||
rootWrap.appendChild(canvas)
|
||||
rootWrap.style.transform = 'translateY(-100%)'
|
||||
}
|
||||
anime({
|
||||
targets: rootWrap,
|
||||
translateY: direction === 'down' ? "-100%" : "0",
|
||||
duration: 300,
|
||||
easing: 'linear',
|
||||
complete: () => {
|
||||
rootWrap.removeChild(canvas)
|
||||
rootWrap.style.transform = 'translateY(0%)'
|
||||
}
|
||||
})
|
||||
})
|
||||
loadDistrict("100000")
|
||||
}
|
||||
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="root-wrap">
|
||||
<div class="root-container">
|
||||
<div class="page-wrap" @wheel="handleScroll">
|
||||
<div class="title">{{
|
||||
methods[methodIndex].title
|
||||
}}
|
||||
</div>
|
||||
<div v-if="loading" class="loading-modal">
|
||||
</div>
|
||||
<!-- 返回上一级按钮 -->
|
||||
<div class="back-btn" @click="backMap">
|
||||
<img :src="backBtnPng" alt="back"/>
|
||||
</div>
|
||||
<!-- 人数表格 -->
|
||||
<div class="people-count">
|
||||
<div class="table">
|
||||
<div class="head">
|
||||
<div class="th">
|
||||
<div class="title">地区</div>
|
||||
<div class="count">人数</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="body">
|
||||
<div v-for="item in areaCountPaged"
|
||||
:key="item.adcode" class="tr">
|
||||
<div class="title">{{ item.name }}</div>
|
||||
<div class="count">{{ item.count }}</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<RegionPagine v-model:page="leftBoxPageNum" :total="areaCount.length"/>
|
||||
</div>
|
||||
<div id="map-container" ref="mapRef"></div>
|
||||
<div
|
||||
id="container"
|
||||
style="width: 100%; height: 100%; background-color: rgb(0, 0, 0); display: none"
|
||||
>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
</template>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.scroll-to-top {
|
||||
animation: 1s linear infinite page-scroll;
|
||||
}
|
||||
|
||||
.root-wrap {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
overflow: hidden;
|
||||
|
||||
.root-container {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
|
||||
> canvas {
|
||||
transition: all 0.3s linear;
|
||||
}
|
||||
|
||||
.page-wrap {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
//top: 0;
|
||||
//left: 0;
|
||||
position: relative;
|
||||
//transition: all 0.3s linear;
|
||||
//animation: 1s linear forwards page-scroll;
|
||||
.loading-modal {
|
||||
position: absolute;
|
||||
left: 0;
|
||||
top: 0;
|
||||
background: #f0f2f5;
|
||||
}
|
||||
|
||||
#map-container {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
background: linear-gradient(0deg, #010101, #041744);
|
||||
}
|
||||
|
||||
> .title {
|
||||
position: absolute;
|
||||
top: 75px;
|
||||
width: 100%;
|
||||
text-align: center;
|
||||
font-size: 36px;
|
||||
font-family: Source Han Sans CN, sans-serif;
|
||||
font-weight: 300;
|
||||
color: #ffffff;
|
||||
z-index: 101;
|
||||
}
|
||||
|
||||
.back-btn {
|
||||
position: absolute;
|
||||
left: 120px;
|
||||
top: 120px;
|
||||
z-index: 99;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.people-count {
|
||||
position: absolute;
|
||||
top: 300px;
|
||||
left: 120px;
|
||||
z-index: 101;
|
||||
|
||||
.table {
|
||||
border: 1px solid #0054ff;
|
||||
|
||||
.head, .body {
|
||||
.tr, .th {
|
||||
display: flex;
|
||||
color: white;
|
||||
|
||||
.title, .count {
|
||||
width: 100px;
|
||||
padding: 8px 12px;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.title {
|
||||
border-right: 1px solid #0054ff;
|
||||
}
|
||||
}
|
||||
|
||||
.th {
|
||||
border-bottom: 1px solid #0054ff;
|
||||
}
|
||||
|
||||
.tr {
|
||||
color: rgb(161, 192, 255);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
.pagination {
|
||||
display: flex;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//@keyframes page-scroll {
|
||||
// 0% {
|
||||
// transform: translateY(0);
|
||||
// }
|
||||
// 100% {
|
||||
// transform: translateY(-100%);
|
||||
// }
|
||||
//}
|
||||
</style>
|
@ -146,7 +146,7 @@ const testEnter = (ev) => {
|
||||
console.log("rere");
|
||||
};
|
||||
const queryParams = reactive({
|
||||
queryType: undefined,
|
||||
// queryType: undefined,
|
||||
keyword: "",
|
||||
queryType: "2",
|
||||
});
|
||||
|
@ -469,7 +469,7 @@ function loadMap(mapName, data) {
|
||||
width: 100%;
|
||||
text-align: center;
|
||||
font-size: 36px;
|
||||
font-family: Source Han Sans CN;
|
||||
font-family: Source Han Sans CN,sans-serif;
|
||||
font-weight: 300;
|
||||
color: #ffffff;
|
||||
}
|
||||
|
@ -58,6 +58,7 @@ import {
|
||||
onUnmounted,
|
||||
computed,
|
||||
} from "vue";
|
||||
import index0 from "./comp/index0.vue"
|
||||
import index1 from "./comp/index1.vue";
|
||||
import index2 from "./comp/index2.vue";
|
||||
import index3 from "./comp/index3.vue";
|
||||
@ -152,41 +153,47 @@ let state = reactive({
|
||||
},
|
||||
showBox: 0,
|
||||
boxList: [
|
||||
|
||||
{
|
||||
comp: shallowRef(index1),
|
||||
zIndex: 1,
|
||||
title: "index1",
|
||||
},
|
||||
{
|
||||
comp: shallowRef(index0),
|
||||
zIndex: 1,
|
||||
title: "index1",
|
||||
},
|
||||
// {
|
||||
// comp: shallowRef(index2),
|
||||
// zIndex: 1,
|
||||
// title: "index2",
|
||||
// },
|
||||
{
|
||||
comp: shallowRef(index3),
|
||||
zIndex: 1,
|
||||
title: "index3",
|
||||
},
|
||||
// {
|
||||
// comp: shallowRef(index3),
|
||||
// zIndex: 1,
|
||||
// title: "index3",
|
||||
// },
|
||||
// {
|
||||
// comp: shallowRef(index4),
|
||||
// zIndex: 1,
|
||||
// title: "index4",
|
||||
// },
|
||||
{
|
||||
comp: shallowRef(index5),
|
||||
zIndex: 1,
|
||||
title: "index5",
|
||||
},
|
||||
{
|
||||
comp: shallowRef(index6),
|
||||
zIndex: 1,
|
||||
title: "index6",
|
||||
},
|
||||
{
|
||||
comp: shallowRef(index7),
|
||||
zIndex: 1,
|
||||
title: "index7",
|
||||
},
|
||||
// {
|
||||
// comp: shallowRef(index5),
|
||||
// zIndex: 1,
|
||||
// title: "index5",
|
||||
// },
|
||||
// {
|
||||
// comp: shallowRef(index6),
|
||||
// zIndex: 1,
|
||||
// title: "index6",
|
||||
// },
|
||||
// {
|
||||
// comp: shallowRef(index7),
|
||||
// zIndex: 1,
|
||||
// title: "index7",
|
||||
// },
|
||||
{
|
||||
comp: shallowRef(index8),
|
||||
zIndex: 1,
|
||||
|
@ -32,8 +32,8 @@ export default defineConfig(({ mode, command }) => {
|
||||
// https://cn.vitejs.dev/config/#server-proxy
|
||||
"/dev-api": {
|
||||
// target: "http://101.34.131.16:1618",
|
||||
// target: "http://101.34.131.16:1618",
|
||||
target: "http://192.168.0.201:1618",
|
||||
target: "http://101.34.131.16:1618",
|
||||
// target: "http://192.168.0.201:1618",
|
||||
// target: 'http://172.18.3.127:1618',
|
||||
changeOrigin: true,
|
||||
rewrite: (p) => p.replace(/^\/dev-api/, ""),
|
||||
|
Reference in New Issue
Block a user