Merge pull request '添加地图相关组件' (#1) from main_hzz into main

Reviewed-on: #1
This commit is contained in:
huzhaozeng 2026-03-31 14:18:34 +08:00
commit 2baa272f9d
15 changed files with 442 additions and 16 deletions

View File

@ -19,6 +19,7 @@
"ant-design-vue": "^4.2.6", "ant-design-vue": "^4.2.6",
"axios": "^1.2.0", "axios": "^1.2.0",
"better-scroll": "^2.4.2", "better-scroll": "^2.4.2",
"dayjs": "^1.11.20",
"default-passive-events": "^2.0.0", "default-passive-events": "^2.0.0",
"echarts": "^5.2.2", "echarts": "^5.2.2",
"element-plus": "^2.2.27", "element-plus": "^2.2.27",

Binary file not shown.

After

Width:  |  Height:  |  Size: 42 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 19 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 39 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 89 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 23 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 89 KiB

View File

@ -0,0 +1,107 @@
<template>
<div class="baselayer-switcher">
<div
class="switcher-item"
v-for="item in data"
:key="item.name"
:class="{ active: item.name === activeLayer }"
@click="activeLayer = item.name"
>
<img :src="item.img" alt="" />
<div class="label">{{ item.name }}</div>
</div>
<div class="nineSectionsImg">
<img :src="nineSectionsImg" alt="" />
</div>
</div>
</template>
<script setup lang="ts">
import { ref, watch, onMounted } from "vue";
import mapShiliangtu from "@/assets/images/map-shiliangtu.png";
import mapDixingtu from "@/assets/images/map-dixingtu.png";
import mapYingxiangtu from "@/assets/images/map-yingxiangtu.png";
import nineSectionsShiliang from "@/assets/images/nineSections-shiliang.png";
import nineSectionsDixing from "@/assets/images/nineSections-dixing.png";
import nineSectionsYingxiang from "@/assets/images/nineSections-yingxiang.png";
const data = ref([
{ name: "矢量", img: mapShiliangtu },
{ name: "地形", img: mapDixingtu },
{ name: "影像", img: mapYingxiangtu },
]);
const nineSectionsImg = ref(nineSectionsShiliang);
const nineSectionsData = ref([
{ name: "矢量", img: nineSectionsShiliang },
{ name: "地形", img: nineSectionsDixing },
{ name: "影像", img: nineSectionsYingxiang },
]);
const activeLayer = ref("矢量");
watch(activeLayer, (val) => {
nineSectionsImg.value =
nineSectionsData.value.find((item) => item.name === val)?.img || "";
});
</script>
<style lang="scss" scoped>
.baselayer-switcher {
display: flex;
position: absolute;
bottom: 20px;
right: 480px;
z-index: 200;
.switcher-item {
background: #d8d8d8;
border-radius: 2px;
width: 85px;
height: 60px;
display: none;
position: relative;
cursor: pointer;
img {
height: 100%;
width: 100%;
}
.label {
position: absolute;
bottom: 0;
right: 0;
padding: 2px 3px;
background-color: #00000059;
color: #fff;
border-radius: 2px 0 0 2px / 2px 0px 0px 2px;
}
&:hover {
border: 1px solid #3a7098;
.label {
background-color: #005293;
}
}
}
.switcher-item:not(:first-child) {
margin-left: 4px;
}
.active {
display: block;
border: 1px solid #3a7098;
.label {
background-color: #005293;
}
}
&:hover {
.switcher-item {
display: block;
}
}
.nineSectionsImg {
position: absolute;
right: 56px;
bottom: 92px;
border: 1px solid grey;
pointer-events: none;
img {
max-width: 100px;
width: 100px !important;
}
}
}
</style>

View File

@ -1,11 +1,34 @@
<script setup lang="ts">
</script>
<template> <template>
<div class="gis-view"> <div class="gis-view">
<div id="mapContainer" /> <div id="mapContainer" />
<!-- 地图图例 -->
<!-- tabType="{baseType[0]?.tagType}"
legendData="{legendData}"
legendDataMap="{legendDataMap}"
setLegendDataMap="{updateLegendDataMap}"
dvtpType="{dvtpType}"
mapList="{mapList}"
loading="{loading}"
pointData="{pointData}" -->
<MapLegend />
<!-- 地图筛选器 -->
<MapFilter />
<!-- 地图控制器 -->
<MapController />
<!-- 基础图层切换器 -->
<BaseLayerSwitcher />
<!-- <MapFilter inverse={true} searchList={mapSearchList} pointData={pointData} fish={fish}
wqElementsList={wqElementsList} className={'map-filter'} initialValues={{ timeRange: searchTimeRange, dvtp: dvtpType, year: yearTime }}
getFormRef={(ref: any) => (mapFilterFormRef.current = ref)}
fetchPointData={fetchPointData} /> -->
</div> </div>
</template> </template>
<script setup lang="ts">
import MapLegend from "@/components/mapLegend/index.vue";
import MapFilter from "@/components/mapFilter/index.vue";
import MapController from "@/components/mapController/index.vue";
import BaseLayerSwitcher from "@/components/baseLayerSwitcher/index.vue";
</script>
<style lang="scss" scoped> <style lang="scss" scoped>
.gis-view { .gis-view {

View File

@ -0,0 +1,103 @@
<template>
<div class="map-controller">
<div class="map-controller-group">
<div class="map-controller-item" v-for="item in controllers" :key="item.key">
<a-tooltip :title="item.name" placement="left">
<i class="icon iconfont" :class="'icon-' + item.icon"></i>
</a-tooltip>
</div>
</div>
</div>
</template>
<script setup lang="ts">
import { ref } from "vue";
const isFullScreen = ref(false);
const mapType = ref("2D");
const controllers = ref([
{
name: "全屏",
key: "fullScreen",
icon: isFullScreen.value ? "exitFullScreen" : "fullScreen",
},
{
name: "定位",
key: "positioning",
icon: "iconGlobal",
},
{
name: "放大",
key: "zoomIn",
icon: "zoomIn",
},
{
name: "缩小",
key: "zoomOut",
icon: "zoomOut",
},
{
name: "3D",
key: "dim",
icon: mapType.value === "2D" ? "a-3D" : "a-2D",
},
{
name: "图层",
//
key: "layerController",
icon: "layer"
},
{
name: "下载",
key: "screenShot",
icon: "downLoad",
},
{
name: "梯级",
key: "TJ",
icon: "tiji",
},
{
name: "倾斜摄影",
key: "OSBGController",
icon: "obliquePhotography",
},
{
name: "三维漫游",
key: "threedRoam",
icon: "roaming",
},
]);
</script>
<style lang="scss" scoped>
.map-controller {
position: absolute;
right: 480px;
bottom: 114px;
z-index: 10;
.map-controller-group {
box-shadow: 0 1px 2px #00000026;
background-color: #fff;
border: none;
.map-controller-item {
height: 40px;
width: 40px;
color: #000;
line-height: 40px;
text-align: center;
position: relative;
cursor: pointer;
.iconfont {
font-size: 20px;
}
&:hover {
background-color: #005292;
color: #ffffff;
}
}
.map-controller-group:not(:first-child) {
margin-top: 10px;
}
}
}
</style>

View File

@ -0,0 +1,75 @@
<template>
<div class="map-filter-container">
<div class="toolbar">
<a-form :model="formModel" :rules="rules" ref="formRef">
<a-row :gutter="10">
<a-col>
<a-form-item label="" name="siteRangePicker">
<a-select
v-model:value="formModel.siteRangePicker"
placeholder="装机容量"
style="width: 120px"
>
<a-select-option v-for="item in siteRangePicker" :key="item.value">{{
item.label
}}</a-select-option>
</a-select>
</a-form-item>
</a-col>
<a-col>
<a-form-item label="" name="siteRangePicker">
<a-select
v-model:value="formModel.siteRangePicker"
placeholder="请输入关键字检索"
style="width: 200px"
/>
</a-form-item>
</a-col>
</a-row>
</a-form>
</div>
</div>
</template>
<script setup lang="ts">
import { onMounted, ref } from "vue";
const siteRangePicker = [
{ label: "0-10", value: "0-10" },
{ label: "10-20", value: "10-20" },
{ label: "20-30", value: "20-30" },
{ label: "30-40", value: "30-40" },
{ label: "40-50", value: "40-50" },
{ label: "50-60", value: "50-60" },
];
const formModel = ref({
siteRangePicker: [],
});
const rules = ref({
siteRangePicker: [{ required: true, message: "请选择装机容量" }],
});
const formRef = ref<any>(null);
</script>
<style lang="scss" scoped>
.map-filter-container {
position: absolute;
left: 220px;
top: 15px;
z-index: 99;
padding: 6px 0px;
background: #e5edf3;
border: none;
:deep(.ant-form-item) {
margin-bottom: 0;
}
:deep(.ant-row) {
margin: 0 !important;
}
.toolbar {
width: 100%;
display: flex;
flex-flow: row;
overflow: visible;
}
}
</style>

View File

@ -0,0 +1,114 @@
<template>
<div class="mapLegendView">
<div class="legendTitle">
图例
<span class="legendBtn" @click="isOpen = !isOpen">
<i class="icon iconfont" :class="isOpen ? 'icon-fold' : 'icon-unFold'"></i>
</span>
</div>
<div class="legendContent" v-show="isOpen">
<a-spin :spinning="data === 0">
<div class="legendGroup" v-for="i in data">
<div class="groupTitle">工程</div>
<div class="groupContent">
<div class="legendItem" v-for="j in 10" :key="j">
<div class="legendIcon smallIcon"></div>
<div class="legendIconTitle">
大型水电站-已建
<!-- <span
><br />
2.装机容量(万kW)
</span> -->
</div>
</div>
</div>
</div>
</a-spin>
</div>
</div>
</template>
<script setup lang="ts">
import { onMounted, ref } from "vue";
const data = ref(0);
onMounted(() => {
setTimeout(() => {
data.value = 10;
}, 1000);
console.log(data.value);
});
const isOpen = ref(true);
</script>
<style lang="scss" scoped>
.mapLegendView {
position: absolute;
left: 0;
bottom: 0;
min-width: 72px;
margin: 24px 0 16px 16px;
border: 1px solid #ccdae7;
padding: 6px;
z-index: 9;
background-color: #ffffff;
}
.legendTitle {
font-size: 16px;
font-weight: 700;
display: flex;
justify-content: space-between;
cursor: pointer;
.legendBtn {
cursor: pointer;
}
}
.legendContent {
white-space: nowrap;
max-width: 450px;
max-height: 392px;
overflow-x: scroll;
overflow-y: scroll;
border-top: 1px solid #eeeeee;
overflow-y: hidden;
// &::-webkit-scrollbar {
// width: 0;
// }
.legendGroup {
display: inline-block;
vertical-align: top;
padding: 0 4px;
.groupTitle {
text-align: left;
font-weight: 700;
font-size: 14px;
cursor: pointer;
}
.groupContent {
font-size: 14px;
padding: 10px 0;
margin-bottom: 0;
.gray {
filter: grayscale(100%);
color: #00000073;
}
.legendItem {
cursor: pointer;
margin-right: 10px;
padding: 4px 0;
min-height: 30px;
display: flex;
flex-direction: row;
.legendIcon {
width: 22px !important;
height: 22px !important;
background-color: red;
}
.legendIconTitle {
cursor: pointer;
flex: 1 1;
}
}
}
}
}
</style>

View File

@ -81,7 +81,7 @@ const selectedItem: any = ref(1);
</div> </div>
</template> </template>
<style scoped lang="scss"> <style scoped lang="scss">
@import "@/styles/variables.module.scss"; @use "@/styles/variables.module.scss" as *;
.jidiSelectorMod { .jidiSelectorMod {
width: 175px; width: 175px;
max-height: 941px; max-height: 941px;

View File

@ -63,6 +63,9 @@ svg {
height: 100%; height: 100%;
background-color: #ffffff; background-color: #ffffff;
} }
.leftContent {
width: 188px;
}
.rightContent { .rightContent {
height: 98%; height: 98%;
position: relative; position: relative;

View File

@ -27,7 +27,7 @@ export default ({ mode }: ConfigEnv): UserConfig => {
// 线上API地址 // 线上API地址
//target: 'http://192.168.1.20:8090/', //target: 'http://192.168.1.20:8090/',
// 本地API地址 // 本地API地址
target: 'http://10.84.1.66:8093', target: 'http://localhost:8093',
changeOrigin: true, changeOrigin: true,
rewrite: path => rewrite: path =>
path.replace(new RegExp('^' + env.VITE_APP_BASE_API), '') path.replace(new RegExp('^' + env.VITE_APP_BASE_API), '')