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

4 months ago
<template>
3 months ago
<div class="container">
2 months ago
<div class="containertwo">
2 months ago
<!-- 地图区域 -->
2 months ago
<div class="mapareaone">
2 months ago
<!-- 展开/隐藏控制按钮放在盒子右侧外部 -->
<div class="collapse-control" @click="toggleCollapse">
2 months ago
<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">
2 months ago
</div>
2 months ago
2 months ago
<!-- 左侧项目列表区域 -->
<div class="leftdiv" v-show="!isCollapsed">
<!-- 项目列表内容 -->
<div class="mainarea" style="background-color: #FFFFFF;">
2 months ago
<ProjectList />
</div>
</div>
2 months ago
<!-- 右侧搜索 -->
2 months ago
<div class="rightdiv">
<el-input v-model="searchBox" placeholder="请输入项目名称" class="search-input" @input="handleSearchInput"
@clear="handleClear" clearable>
2 months ago
<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>
2 months ago
2 months ago
<!-- 右侧地图区域 -->
2 months ago
<div class="map-container">
<div id="mars2dContainerSSS" class="mars2d-container"></div>
2 months ago
2 months ago
</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>
2 months ago
</div>
3 months ago
</div>
</div>
4 months ago
</template>
<script>
2 months ago
import 'mars2d/mars2d.css';
import * as mars2d from 'mars2d';
2 months ago
import ProjectList from '@/views/components/analysis/projectList.vue'
2 months ago
import { getBasicInformationPage } from "@/api/ManageApi/index";
import { debounce } from 'lodash';
2 months ago
import suzhouData from '@/assets/json/suzhou.json'
// 自定义指令
// 点击外部关闭弹窗
2 months ago
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);
}
};
2 months ago
3 months ago
export default {
2 months ago
components: {
ProjectList,
3 months ago
},
2 months ago
directives: {
'click-outside': clickOutside
},
2 months ago
data() {
2 months ago
const basePathUrl = window.basePathUrl || "";
2 months ago
return {
2 months ago
markerIcon: require('@/assets/images/detailsicon/icon-定位@2x.png'),
projectMarker: null,
2 months ago
isCollapsed: false,
searchBox: '',
searchList: [],
dialogVisible: false,
selectedProject: {
name: '',
xzfl: '',
projectLeader: '',
phone: '',
ztze: '',
xmfrdwxz: ''
2 months ago
},
showLocationIcon: false,
iconPosition: {
position: 'absolute',
top: '0px',
left: '0px'
},
hasSearched: false,
// 状态颜色映射
xzflColors: {
'在建': '#6EDABE',
'拟建': '#FFBF6B',
'已建': '#2B62F1'
},
xzflMap: {
1: '已建',
2: '在建',
3: '拟建'
},
2 months ago
// 地图相关配置
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
}
],
2 months ago
center: { lat: 31.3356, lng: 120.7157 },
2 months ago
zoom: 11,
minZoom: 10,
maxZoom: 20,
2 months ago
// zoomControl: true,
2 months ago
chinaCRS: 'GCJ02'
},
map: null
2 months ago
};
},
created() {
this.debouncedSearch = debounce(this.toSearch, 300);
2 months ago
},
2 months ago
mounted() {
this.initMap();
},
beforeDestroy() {
if (this.map) {
this.map.destroy();
}
},
2 months ago
methods: {
2 months ago
// 初始化地图
initMap() {
this.map = new mars2d.Map('mars2dContainerSSS', this.mapOptions);
this.map.on('load', this.onMapLoad);
},
onMapLoad() {
this.addSuzhouIndustrialParkLayer();
},
2 months ago
// 园区
2 months ago
async addSuzhouIndustrialParkLayer() {
try {
2 months ago
const geoJsonData = suzhouData; // 直接使用导入的数据
2 months ago
const graphicLayer = new mars2d.layer.GraphicLayer({
name: "苏州园区高亮区域",
zIndex: 10
});
this.map.addLayer(graphicLayer);
const polygon = mars2d.Util.geoJsonToGraphics(geoJsonData, {
style: {
fill: true,
fillColor: "#2B62F1",
2 months ago
fillOpacity: 0.3,
2 months ago
stroke: true,
color: "#2B62F1",
opacity: 0.8,
weight: 3
},
tooltip: "苏州工业园区"
});
graphicLayer.addGraphic(polygon);
2 months ago
} catch (error) {
console.error('加载苏州园区数据失败:', error);
}
},
2 months ago
toggleCollapse() {
this.isCollapsed = !this.isCollapsed;
2 months ago
},
handleSearchInput() {
if (this.searchBox.trim() === '') {
this.searchList = [];
this.hasSearched = false;
2 months ago
this.showLocationIcon = false;
2 months ago
this.showLocationIcon = false;
2 months ago
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;
2 months ago
if (this.searchList.length === 0) {
this.$message.warning('查无此项目');
}
2 months ago
} else {
this.searchList = [];
2 months ago
this.$message.warning('查无此项目');
2 months ago
}
})
.catch(error => {
console.error('搜索失败:', error);
this.hasSearched = true;
this.searchList = [];
2 months ago
this.$message.error('搜索失败,请重试');
2 months ago
});
},
centerMap(item) {
2 months ago
if (!item.longitude || !item.latitude) {
this.$message.warning('该项目未落图!');
return;
}
2 months ago
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 || '暂无'
};
2 months ago
// 解析坐标并定位
if (item.jsdd && item.jsdd.includes(',')) {
const [lng, lat] = item.jsdd.split(',').map(Number);
this.map.flyTo([lat, lng], 17);
}
2 months ago
// 坐标定位
this.map.flyTo([item.latitude, item.longitude], 17);
// 标记
this.addProjectMarker(item);
},
2 months ago
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);
2 months ago
}
2 months ago
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;
2 months ago
},
closeDialog() {
this.dialogVisible = false;
},
2 months ago
}
2 months ago
}
3 months ago
</script>
4 months ago
<style scoped>
2 months ago
.collapse-control {
position: absolute;
2 months ago
left: -1.5rem;
2 months ago
top: 12.5rem;
width: auto;
height: 2rem;
border-radius: 0 4px 4px 0;
cursor: pointer;
display: flex;
align-items: center;
justify-content: center;
2 months ago
z-index: 1001;
2 months ago
transition: all 0.3s ease;
}
.control-icon {
width: 3.5rem;
height: 3.5rem;
}
.leftdiv {
2 months ago
width: 38%;
2 months ago
height: 100%;
2 months ago
position: absolute;
left: 0rem;
top: 0rem;
background: #FFFFFF;
border-radius: 0.5rem;
transition: all 0.3s ease;
2 months ago
z-index: 1000;
overflow: hidden;
overflow-y: auto;
2 months ago
}
.mainarea {
height: 100%;
overflow: auto;
}
2 months ago
.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;
2 months ago
z-index: 900;
2 months ago
}
.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);
2 months ago
z-index: 900;
2 months ago
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;
}
2 months ago
/* 悬浮div */
2 months ago
.app-container {
position: absolute;
2 months ago
top: 20%;
left: 53%;
height: 15rem;
2 months ago
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 {
2 months ago
color: #3D424C;
font-family: aliregular;
4 months ago
}
2 months ago
2 months ago
/* 所有容器 */
.container {
position: relative;
height: 100%;
}
.mapareaone {
height: 100%;
grid-column: span 2;
width: 100%;
position: relative;
}
.containertwo {
height: 100%;
position: relative;
}
2 months ago
.map-container {
width: 100%;
height: 25rem;
2 months ago
position: relative;
}
.mars2d-container {
width: 100%;
height: 100%;
border-radius: 0.5rem;
}
4 months ago
</style>