You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

517 lines
12 KiB

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

<template>
<div class="container">
<div class="containertwo">
<!-- 地图区域 -->
<div class="mapareaone">
<!-- 展开/隐藏控制按钮放在盒子右侧外部 -->
<div class="collapse-control" @click="toggleCollapse">
<img v-show="!isCollapsed" src="@/assets/images/icon-sq@2x.png" alt="隐藏" class="control-icon">
<img v-show="isCollapsed" src="@/assets/images/icon-zk@2x.png" alt="展开" class="control-icon">
</div>
<!-- 左侧项目列表区域 -->
<div class="leftdiv" v-show="!isCollapsed">
<!-- 项目列表内容 -->
<div class="mainarea" style="background-color: #FFFFFF;">
<ProjectList />
</div>
</div>
<!-- 右侧搜索 -->
<div class="rightdiv">
<el-input v-model="searchBox" placeholder="请输入项目名称" class="search-input" @input="handleSearchInput"
@clear="handleClear" clearable>
<el-button slot="append" icon="el-icon-search" @click="toSearch"></el-button>
</el-input>
</div>
<!-- 搜索结果列表 -->
<div class="search-results" v-if="searchList && searchList.length > 0">
<div class="search-item" v-for="(item, index) in searchList" :key="index" @click="centerMap(item)">
<div class="item-name">{{ item.name }}</div>
</div>
</div>
<!-- 右侧地图区域 -->
<div class="map-container">
<div id="mars2dContainerSSS" class="mars2d-container"></div>
</div>
</div>
</div>
<!-- 悬浮窗 -->
<div class="app-container" v-show="dialogVisible" v-click-outside="closeDialog">
<div class="close-btn" @click="closeDialog">
<i class="el-icon-close"></i>
</div>
<div class="dialog-content">
<div class="dialog-title">{{ selectedProject.name }}</div>
<div class="dialog-info">
<p><span class="label">状态:</span>
<span class="value" :style="{ color: xzflColors[xzflMap[selectedProject.xzfl]] }">
{{ xzflMap[selectedProject.xzfl] }}
</span>
</p>
<p><span class="label">项目单位:</span> <span class="value">{{ selectedProject.xmfrdwxz }}</span></p>
<p><span class="label">总投资额:</span> <span class="value">{{ selectedProject.ztze }}</span></p>
<p><span class="label">联系人:</span> <span class="value">{{ selectedProject.projectLeader }}</span></p>
<p><span class="label">联系电话:</span><span class="value"> {{ selectedProject.phone }}</span></p>
</div>
</div>
</div>
</div>
</template>
<script>
import 'mars2d/mars2d.css';
import * as mars2d from 'mars2d';
import ProjectList from '@/views/components/analysis/projectList.vue'
import { getBasicInformationPage } from "@/api/ManageApi/index";
import { debounce } from 'lodash';
import suzhouData from '@/assets/json/suzhou.json'
// 自定义指令
// 点击外部关闭弹窗
const clickOutside = {
bind(el, binding, vnode) {
el.clickOutsideEvent = function (event) {
if (!(el === event.target || el.contains(event.target))) {
vnode.context[binding.expression](event);
}
};
document.body.addEventListener('click', el.clickOutsideEvent);
},
unbind(el) {
document.body.removeEventListener('click', el.clickOutsideEvent);
}
};
export default {
components: {
ProjectList,
},
directives: {
'click-outside': clickOutside
},
data() {
const basePathUrl = window.basePathUrl || "";
return {
markerIcon: require('@/assets/images/detailsicon/icon-定位@2x.png'),
projectMarker: null,
isCollapsed: false,
searchBox: '',
searchList: [],
dialogVisible: false,
selectedProject: {
name: '',
xzfl: '',
projectLeader: '',
phone: '',
ztze: '',
xmfrdwxz: ''
},
showLocationIcon: false,
iconPosition: {
position: 'absolute',
top: '0px',
left: '0px'
},
hasSearched: false,
// 状态颜色映射
xzflColors: {
'在建': '#6EDABE',
'拟建': '#FFBF6B',
'已建': '#2B62F1'
},
xzflMap: {
1: '已建',
2: '在建',
3: '拟建'
},
// 地图相关配置
configUrl: basePathUrl + "config/config.json",
mapOptions: {
copyright: false,
basemaps: [
{
id: 2021,
chinaCRS: "GCJ02",
pid: 10,
name: "高德电子",
icon: "img/basemaps/gaode_vec.png",
type: "gaode",
layer: "vec",
show: true
}
],
center: { lat: 31.3356, lng: 120.7157 },
zoom: 11,
minZoom: 10,
maxZoom: 20,
// zoomControl: true,
chinaCRS: 'GCJ02'
},
map: null
};
},
created() {
this.debouncedSearch = debounce(this.toSearch, 300);
},
mounted() {
this.initMap();
},
beforeDestroy() {
if (this.map) {
this.map.destroy();
}
},
methods: {
// 初始化地图
initMap() {
this.map = new mars2d.Map('mars2dContainerSSS', this.mapOptions);
this.map.on('load', this.onMapLoad);
},
onMapLoad() {
this.addSuzhouIndustrialParkLayer();
},
// 园区
async addSuzhouIndustrialParkLayer() {
try {
const geoJsonData = suzhouData; // 直接使用导入的数据
const graphicLayer = new mars2d.layer.GraphicLayer({
name: "苏州园区高亮区域",
zIndex: 10
});
this.map.addLayer(graphicLayer);
const polygon = mars2d.Util.geoJsonToGraphics(geoJsonData, {
style: {
fill: true,
fillColor: "#2B62F1",
fillOpacity: 0.3,
stroke: true,
color: "#2B62F1",
opacity: 0.8,
weight: 3
},
tooltip: "苏州工业园区"
});
graphicLayer.addGraphic(polygon);
} catch (error) {
console.error('加载苏州园区数据失败:', error);
}
},
toggleCollapse() {
this.isCollapsed = !this.isCollapsed;
},
handleSearchInput() {
if (this.searchBox.trim() === '') {
this.searchList = [];
this.hasSearched = false;
this.showLocationIcon = false;
this.showLocationIcon = false;
return;
}
this.debouncedSearch();
},
toSearch() {
if (!this.searchBox.trim()) {
this.searchList = [];
this.hasSearched = true;
return;
}
const params = {
name: this.searchBox,
current: 1,
size: 10
};
getBasicInformationPage(params)
.then(response => {
this.hasSearched = true;
if (response && response.code === 200 && response.data) {
this.searchList = response.data.records;
if (this.searchList.length === 0) {
this.$message.warning('查无此项目');
}
} else {
this.searchList = [];
this.$message.warning('查无此项目');
}
})
.catch(error => {
console.error('搜索失败:', error);
this.hasSearched = true;
this.searchList = [];
this.$message.error('搜索失败,请重试');
});
},
centerMap(item) {
if (!item.longitude || !item.latitude) {
this.$message.warning('该项目未落图!');
return;
}
this.searchBox = item.name;
this.searchList = [];
this.selectedProject = {
name: item.name,
projectLeader: item.projectLeader || '暂无',
phone: item.phone || '暂无',
ztze: item.ztze || '暂无',
xmfrdwxz: item.xmfrdwxz || '暂无',
xzfl: item.xzfl || '暂无'
};
// 解析坐标并定位
if (item.jsdd && item.jsdd.includes(',')) {
const [lng, lat] = item.jsdd.split(',').map(Number);
this.map.flyTo([lat, lng], 17);
}
// 坐标定位
this.map.flyTo([item.latitude, item.longitude], 17);
// 标记
this.addProjectMarker(item);
},
handleClear() {
this.showLocationIcon = false;
this.searchList = [];
this.hasSearched = false;
this.searchBox = '';
this.dialogVisible = false;
// 移除标记
if (this.projectMarker) {
this.map.removeLayer(this.projectMarker);
this.projectMarker = null;
}
this.map.setView(this.mapOptions.center, this.mapOptions.zoom);
},
addProjectMarker(item) {
if (this.projectMarker) {
this.map.removeLayer(this.projectMarker);
}
this.projectMarker = new mars2d.graphic.Marker({
latlng: [item.latitude, item.longitude],
style: {
image: this.markerIcon,
width: 32,
height: 44,
anchor: [16, 44]
},
interactive: true,
cursor: 'pointer'
});
// 点击图标
this.projectMarker.on(mars2d.EventType.click, (event) => {
this.selectedProject = { ...item };
this.dialogVisible = true;
});
this.map.addLayer(this.projectMarker);
},
showDialog() {
this.dialogVisible = true;
},
closeDialog() {
this.dialogVisible = false;
},
}
}
</script>
<style scoped>
.collapse-control {
position: absolute;
left: -1.5rem;
top: 12.5rem;
width: auto;
height: 2rem;
border-radius: 0 4px 4px 0;
cursor: pointer;
display: flex;
align-items: center;
justify-content: center;
z-index: 1001;
transition: all 0.3s ease;
}
.control-icon {
width: 3.5rem;
height: 3.5rem;
}
.leftdiv {
width: 38%;
height: 100%;
position: absolute;
left: 0rem;
top: 0rem;
background: #FFFFFF;
border-radius: 0.5rem;
transition: all 0.3s ease;
z-index: 1000;
overflow: hidden;
overflow-y: auto;
}
.mainarea {
height: 100%;
overflow: auto;
}
.icondiv {
width: 8rem;
height: 8rem;
position: relative;
}
.icondiv img {
width: 1.7rem;
height: 2rem;
transition: all 0.2s ease;
}
.icondiv img:hover {
transform: scale(1.1);
}
.rightdiv {
width: 30%;
position: absolute;
right: 1rem;
top: 1rem;
z-index: 900;
}
.search-results {
position: absolute;
right: 1rem;
top: 3.5rem;
width: 30%;
background-color: #FFFFFF;
border: 1px solid #E5E5E5;
border-radius: 0.5rem;
box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.1);
z-index: 900;
max-height: 15rem;
overflow-y: auto;
}
.search-item {
padding: 0.5rem;
cursor: pointer;
transition: background-color 0.3s ease;
}
.search-item:hover {
background-color: #F2F4F7;
}
.item-name {
margin-bottom: 0.3rem;
}
.item-address {
font-size: 0.88rem;
color: #606266;
}
/* 悬浮div */
.app-container {
position: absolute;
top: 20%;
left: 53%;
height: 15rem;
width: 18rem;
background-color: #fff;
border-radius: 4px;
box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.1);
z-index: 2000;
padding: 15px;
}
.close-btn {
position: absolute;
top: 5px;
right: 5px;
cursor: pointer;
font-size: 16px;
color: #909399;
}
.close-btn:hover {
color: #409EFF;
}
.dialog-content {
height: 100%;
}
.dialog-title {
font-size: 16px;
font-family: aliregular;
margin-bottom: 15px;
padding-bottom: 10px;
border-bottom: 1px solid #EBEEF5;
color: #2B62F1;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
.dialog-info {
font-size: 14px;
color: #606266;
}
.dialog-info p {
margin-bottom: 10px;
}
.label {
color: #9E9E9E;
font-family: aliregular;
width: 3rem;
}
.value {
color: #3D424C;
font-family: aliregular;
}
/* 所有容器 */
.container {
position: relative;
height: 100%;
}
.mapareaone {
height: 100%;
grid-column: span 2;
width: 100%;
position: relative;
}
.containertwo {
height: 100%;
position: relative;
}
.map-container {
width: 100%;
height: 25rem;
position: relative;
}
.mars2d-container {
width: 100%;
height: 100%;
border-radius: 0.5rem;
}
</style>