540 lines
16 KiB
Vue
540 lines
16 KiB
Vue
<template>
|
||
<div ref="vChartRef" >
|
||
<div class="layer-container" @click="handlerMap"
|
||
:style="{'background-color':props.chartConfig.option.boxStyle?.backgroundColor,
|
||
'border-color':props.chartConfig.option.boxStyle?.borderColor}">
|
||
<div class="title">
|
||
{{ props.chartConfig.option.boxStyle?.title }}
|
||
</div>
|
||
<div class="layer-item-container">
|
||
<div v-for="(item,index) in handlerLayers" :key="index" style="color:#fff;">
|
||
<div class="layer-category">
|
||
<div class="arrow" @click="handnlerFoldGroupLayer(item)">
|
||
<CaretDownOutlined v-show="item.fold" />
|
||
<CaretRightOutlined v-show="!item.fold" />
|
||
</div>
|
||
<div class="layer-category-checkbox" :style="{'background':item.show ? '#00E832':'#fff'}" @click="handlerChangeAllLayer(item)">
|
||
|
||
</div>
|
||
<div class="layer-category-name">
|
||
{{ item.name }}({{item.children.length}})
|
||
</div>
|
||
</div>
|
||
<div class="layer-item" v-for="(it,idx) in item.children" :key="idx" v-show="item.fold">
|
||
<div class="layer-checkbox" :style="{'background':it.show ? '#00E832':'#fff'}" @click="handlerChangeLayer(it,item)">
|
||
<!-- <CheckOutlined v-show="it.show" /> -->
|
||
</div>
|
||
<div class="layer-name" @click="handlerChangeLayer(it,item)">
|
||
{{ it.name }}
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</template>
|
||
|
||
<script setup lang="ts">
|
||
import { ref, PropType, toRefs, watch,onMounted,nextTick } from 'vue'
|
||
import AMapLoader from '@amap/amap-jsapi-loader'
|
||
import { CreateComponentType } from '@/packages/index.d'
|
||
import { useChartDataFetch } from '@/hooks'
|
||
import { useChartEditStore } from '@/store/modules/chartEditStore/chartEditStore'
|
||
import { MarkerEnum, ThemeEnum } from './config'
|
||
import { isArray } from '@/utils';
|
||
import axios from 'axios';
|
||
import { CaretDownOutlined, StarFilled, StarTwoTone,CheckOutlined,CaretRightOutlined } from '@ant-design/icons-vue';
|
||
|
||
import * as mars3d from "mars3d";
|
||
import { option } from '@/views/chart/ContentConfigurations/components/CanvasPage/components/CreateColorRenderChart/barOptions'
|
||
|
||
import { EventBus } from '@/utils/eventBus';
|
||
|
||
let map: mars3d.Map; // 地图对象
|
||
|
||
const props = defineProps({
|
||
chartConfig: {
|
||
type: Object as PropType<CreateComponentType>,
|
||
required: true
|
||
}
|
||
})
|
||
|
||
const layers = ref(null)
|
||
|
||
const handlerLayers:any = ref([]);
|
||
|
||
const handlerGetLayerTree = ()=>{
|
||
axios.get('http://221.2.83.254:9006/applicationMars/getApplicationInfo/feixian').then((res)=>{
|
||
layers.value = res.data.data
|
||
let configLayers = [];
|
||
let GEOSERVER_BASE_API = "http://221.2.83.254:9007/";
|
||
res.data.data.forEach((item, index) => {
|
||
let group:Object;
|
||
group = {
|
||
id: parseInt(Math.random() * 10000000),
|
||
name: item.serverName,
|
||
type: "group",
|
||
fold:true,
|
||
show:false,
|
||
};
|
||
|
||
let layerGroup = group;
|
||
layerGroup.children = [];
|
||
configLayers.unshift(group);
|
||
|
||
if (item.children && item.children.length > 0) {
|
||
item.children.forEach((it, idx) => {
|
||
|
||
let attribute = JSON.parse(it.attribute);
|
||
|
||
// 处理根据字段分类渲染样式的图层
|
||
if(attribute && attribute.symbol && attribute.symbol.styleField && attribute.symbol.styleFieldOptions && Object.keys(attribute.symbol.styleFieldOptions).length>0){
|
||
// console.log(attribute.layers,attribute)
|
||
attribute.type = 'geojson';
|
||
if(attribute.layers){
|
||
attribute.url = "geoserver/ksp/ows?service=WFS&version=1.0.0&request=GetFeature&typeName="+attribute.layers+"&maxFeatures=1000000&outputFormat=application%2Fjson";
|
||
}
|
||
|
||
// delete attribute.layers;
|
||
delete attribute.parameters;
|
||
delete attribute.highlight;
|
||
console.log("图层属性信息:",attribute.url,attribute);
|
||
|
||
|
||
if(!attribute.symbol.styleOptions){
|
||
attribute.symbol.styleOptions = {
|
||
"opacity": 0.8,
|
||
"color": "",
|
||
"width": 2,
|
||
"clampToGround": true
|
||
}
|
||
}
|
||
attribute.zIndex = 10000000000;
|
||
}
|
||
|
||
// 如果是动态线类型
|
||
if(attribute.dynamic){
|
||
attribute.type = 'geojson';
|
||
if(attribute.layers){
|
||
attribute.url = "geoserver/ksp/ows?service=WFS&version=1.0.0&request=GetFeature&typeName="+attribute.layers+"&maxFeatures=1000000&outputFormat=application%2Fjson";
|
||
attribute.symbol = {
|
||
type: "polyline",
|
||
styleOptions: {
|
||
clampToGround:true,
|
||
width: 5,
|
||
materialType: mars3d.MaterialType.LineFlow,
|
||
materialOptions: {
|
||
// color: Cesium.Color.CHARTREUSE,
|
||
image: "img/textures/line-color-yellow.png",
|
||
speed: 8
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
// 设置标签文字偏移量
|
||
if(attribute.symbol && attribute.symbol.styleOptions && attribute.symbol.styleOptions.label){
|
||
attribute.symbol.styleOptions.label.pixelOffsetY = -40
|
||
let oldText = attribute.symbol.styleOptions.label.text;
|
||
attribute.symbol.styleOptions.label = {
|
||
text: oldText,
|
||
font_size: 14,
|
||
// color: Cesium.Color.AZURE,
|
||
outline: true,
|
||
// outlineColor: Cesium.Color.BLACK,
|
||
outlineWidth: 2,
|
||
// horizontalOrigin: Cesium.HorizontalOrigin.CENTER,
|
||
// verticalOrigin: Cesium.VerticalOrigin.BOTTOM,
|
||
// pixelOffset: new Cesium.Cartesian2(10, -25) // 偏移量
|
||
pixelOffsetY:-40
|
||
}
|
||
|
||
}
|
||
|
||
// 设置PID
|
||
attribute.pid = group.id;
|
||
|
||
// 去掉所有图层点击选中样式
|
||
delete attribute.highlight;
|
||
|
||
// 如果不为空
|
||
if(attribute.symbol && attribute.symbol.styleOptions && attribute.symbol.styleOptions.label && attribute.symbol.styleOptions.label.text){
|
||
/**
|
||
* 图标标题显示情况:
|
||
key:字段中文名称,value:字段英文名称
|
||
* 1. key:value
|
||
* 2. key:value@key:value
|
||
* 3. key:value@,@key:value
|
||
* 4. @value
|
||
* 5. @value1@value2
|
||
* 6. @value1@,@value2
|
||
* 7. key:value1@value2
|
||
* */
|
||
let text = "";
|
||
if(attribute.symbol.styleOptions.label.text.match("@")){
|
||
let arr = attribute.symbol.styleOptions.label.text.split("@");
|
||
if(arr.length>0){
|
||
arr.forEach((item,index)=>{
|
||
if(item.match(":")){
|
||
let garr = item.split(":")
|
||
text = text+garr[0]+":{"+garr[1]+"}"
|
||
}else if(item.length==1){
|
||
text = text+item
|
||
}else if(item.length>1){
|
||
text = text+"{"+item+"}"
|
||
}
|
||
})
|
||
}
|
||
}else if(attribute.symbol.styleOptions.label.text.length>1 && attribute.symbol.styleOptions.label.text.match(":") ){
|
||
let garr = attribute.symbol.styleOptions.label.text.split(":")
|
||
text = text+garr[0]+":{"+garr[1]+"}"
|
||
}else if(attribute.symbol.styleOptions.label.text.length>1 && !attribute.symbol.styleOptions.label.text.match(":")){
|
||
text = "{"+attribute.symbol.styleOptions.label.text+"}";
|
||
}
|
||
attribute.symbol.styleOptions.label.text = text;
|
||
}
|
||
|
||
let ipinfo = matchHttpIpPort(attribute.url);
|
||
|
||
if(ipinfo){ // 如果匹配得到则替换为配置文件中的
|
||
attribute.url = attribute.url.replace(ipinfo[0],GEOSERVER_BASE_API);
|
||
}else{ //如果没有匹配到则直接拼接
|
||
attribute.url = GEOSERVER_BASE_API+attribute.url
|
||
}
|
||
|
||
// 根据图层类型设置数据过滤条件 过滤掉被删除的数据
|
||
if(attribute.type == 'geojson'){
|
||
attribute.url = attribute.url + "&cql_filter=is_del%20=0"
|
||
}else if(attribute.type == 'wms'){
|
||
attribute.parameters.cql_filter="is_del=0"
|
||
attribute.zIndex = 1;
|
||
|
||
}
|
||
|
||
if(attribute.name == '防火驿站'){
|
||
attribute.show = true;
|
||
}
|
||
|
||
configLayers.unshift(attribute);
|
||
|
||
attribute.show = attribute.show ? true : false;
|
||
|
||
layerGroup.children.push(attribute);
|
||
});
|
||
}
|
||
|
||
handlerLayers.value.push(layerGroup);
|
||
});
|
||
|
||
console.log("configlayers",handlerLayers.value);
|
||
// window.globalMap.setLayersOptions(configLayers);
|
||
})
|
||
}
|
||
|
||
const matchHttpIpPort = (url) => { // 匹配“ http://ip:port ”
|
||
const ipRegex = /^http\:\/\/\b(?:[0-9]{1,3}\.){3}[0-9]{1,3}\b\:\b[0-9]{1,5}\//;
|
||
const match = url.match(ipRegex)
|
||
if (match) {
|
||
return match;
|
||
}
|
||
return null;
|
||
}
|
||
|
||
const handlerChangeAllLayer = (group) =>{
|
||
if(group.show == false){
|
||
group.children?.forEach((item,index)=>{
|
||
item.show = true;
|
||
|
||
})
|
||
}else{
|
||
group.children?.forEach((item,index)=>{
|
||
item.show = false;
|
||
})
|
||
}
|
||
group.show = !group.show;
|
||
}
|
||
|
||
const handlerChangeLayer = (options,group)=>{
|
||
if(options.show == true){
|
||
group.show = false;
|
||
}
|
||
options.show = !options.show;
|
||
let layer = window.globalMap.getLayerById(options.id);
|
||
|
||
if(layer){
|
||
layer.show = !layer.show
|
||
}else{
|
||
if(options.type == "geojson"){
|
||
layer = new mars3d.layer.GeoJsonLayer(options);
|
||
layer.show = true;
|
||
}else if(options.type == "wms"){
|
||
layer = new mars3d.layer.WmsLayer(options);
|
||
layer.show = true;
|
||
}
|
||
window.globalMap.addLayer(layer);
|
||
}
|
||
}
|
||
|
||
const handnlerFoldGroupLayer = (item)=>{
|
||
item.fold = !item.fold;
|
||
}
|
||
|
||
const ch = ()=>{
|
||
|
||
}
|
||
|
||
const handlerMap = ()=>{
|
||
|
||
}
|
||
let {
|
||
amapKey,
|
||
amapStyleKey,
|
||
amapLon,
|
||
amapLat,
|
||
amapZindex,
|
||
mapMarkerType,
|
||
lang,
|
||
amapStyleKeyCustom,
|
||
features,
|
||
viewMode,
|
||
showLabel,
|
||
pitch,
|
||
skyColor,
|
||
marker,
|
||
satelliteTileLayer,
|
||
roadNetTileLayer,
|
||
trafficTileLayer
|
||
} = toRefs(props.chartConfig.option.mapOptions)
|
||
|
||
let mapIns: any = null
|
||
let markers: any = []
|
||
let AMapIns: any = null
|
||
|
||
const vChartRef = ref<HTMLElement>()
|
||
|
||
onMounted(()=>{
|
||
handlerGetLayerTree();
|
||
EventBus.on(props.chartConfig.id + 'GraphicClick', (data) => {
|
||
console.log('data', data);
|
||
});
|
||
})
|
||
|
||
|
||
|
||
const isFirstLoad = ref(true);
|
||
const initMap = (newData: any) => {
|
||
// 第一次加载
|
||
if(isFirstLoad.value){
|
||
map = new mars3d.Map(vChartRef.value, newData);
|
||
}else{ // 之后更新
|
||
// map.setOptions(newData);
|
||
map.setSceneOptions(newData.scene);
|
||
}
|
||
isFirstLoad.value = false;
|
||
|
||
window.globalMap = map;
|
||
|
||
|
||
return null;
|
||
// 初始化
|
||
AMapLoader.load({
|
||
key: amapKey.value, //api服务key--另外需要在public中使用安全密钥!!!
|
||
version: '1.4.15', // 指定要加载的 JSAPI 的版本,缺省时默认为 1.4.15
|
||
plugins: ['AMap.PlaceSearch', 'AMap.AutoComplete'] // 需要使用的的插件列表
|
||
}).then(AMap => {
|
||
AMapIns = AMap
|
||
mapIns = new AMap.Map(vChartRef.value, {
|
||
resizeEnable: true,
|
||
zoom: amapZindex.value, // 地图显示的缩放级别
|
||
center: [amapLon.value, amapLat.value],
|
||
lang: lang.value,
|
||
features: features.value,
|
||
pitch: pitch.value, // 地图俯仰角度,有效范围 0 度- 83 度
|
||
skyColor: skyColor.value,
|
||
viewMode: viewMode.value, // 地图模式
|
||
showLabel: showLabel.value, // 是否显示地图文字标记
|
||
willReadFrequently: true
|
||
})
|
||
dataHandle(props.chartConfig.option.dataset)
|
||
|
||
let satelliteLayer = new AMap.TileLayer.Satellite({
|
||
zIndex: satelliteTileLayer.value.zIndex,
|
||
opacity: satelliteTileLayer.value.opacity,
|
||
zooms: satelliteTileLayer.value.zooms
|
||
})
|
||
let roadNetLayer = new AMap.TileLayer.RoadNet({
|
||
zIndex: roadNetTileLayer.value.zIndex,
|
||
opacity: roadNetTileLayer.value.opacity,
|
||
zooms: roadNetTileLayer.value.zooms
|
||
})
|
||
let trafficLayer = new AMap.TileLayer.Traffic({
|
||
zIndex: trafficTileLayer.value.zIndex,
|
||
opacity: trafficTileLayer.value.opacity,
|
||
zooms: trafficTileLayer.value.zooms
|
||
})
|
||
mapIns.remove([satelliteLayer, roadNetLayer, trafficLayer])
|
||
if (satelliteTileLayer.value.show) {
|
||
mapIns.add([satelliteLayer])
|
||
}
|
||
if (roadNetTileLayer.value.show) {
|
||
mapIns.add([roadNetLayer])
|
||
}
|
||
if (trafficTileLayer.value.show) {
|
||
mapIns.add([trafficLayer])
|
||
}
|
||
|
||
mapIns.setMapStyle(
|
||
`amap://styles/${amapStyleKeyCustom.value !== '' ? amapStyleKeyCustom.value : amapStyleKey.value}`
|
||
)
|
||
})
|
||
.catch(e => {})
|
||
}
|
||
|
||
const dataHandle = (newData: any) => {
|
||
if (!mapIns && !AMapIns) {
|
||
// initMap(props.chartConfig.option)
|
||
return
|
||
}
|
||
if (isArray(newData.markers)) {
|
||
// 先清除旧标记
|
||
mapIns.remove(markers)
|
||
markers = []
|
||
// 记录新标记
|
||
if (mapMarkerType.value === MarkerEnum.MARKER) {
|
||
newData.markers.forEach((markerItem: any) => {
|
||
const markerInstance = new AMapIns.Marker({
|
||
position: [markerItem.position[0], markerItem.position[1]],
|
||
offset: new AMapIns.Pixel(-13, -30)
|
||
})
|
||
markers.push(markerInstance)
|
||
markerInstance.setMap(mapIns)
|
||
})
|
||
} else if (mapMarkerType.value === MarkerEnum.CIRCLE_MARKER) {
|
||
newData.markers.forEach((markerItem: any) => {
|
||
const markerInstance = new AMapIns.CircleMarker({
|
||
center: [markerItem.position[0], markerItem.position[1]],
|
||
radius: markerItem.value,
|
||
...marker.value
|
||
})
|
||
markers.push(markerInstance)
|
||
markerInstance.setMap(mapIns)
|
||
})
|
||
}
|
||
}
|
||
}
|
||
|
||
const stopWatch = watch(
|
||
() => props.chartConfig.option.mapOptions,
|
||
async option => {
|
||
let options = JSON.parse(JSON.stringify(props.chartConfig.option.mapOptions))
|
||
console.log("props.chartConfig.option.mapOptions",);
|
||
await nextTick();
|
||
},
|
||
{
|
||
immediate: true,
|
||
deep: true
|
||
}
|
||
)
|
||
|
||
watch(
|
||
() => props.chartConfig.option.dataset,
|
||
newData => {
|
||
try {
|
||
dataHandle(newData)
|
||
} catch (error) {
|
||
console.log(error)
|
||
}
|
||
},
|
||
{
|
||
deep: false
|
||
}
|
||
)
|
||
|
||
// 预览
|
||
useChartDataFetch(props.chartConfig, useChartEditStore, (newData: any) => {
|
||
stopWatch()
|
||
dataHandle(newData)
|
||
})
|
||
|
||
</script>
|
||
|
||
<style scoped>
|
||
.layer-container{
|
||
width:100%;
|
||
height:100%;
|
||
padding:15px;
|
||
padding-top:0px;
|
||
padding-right:5px;
|
||
background:rgba(7,38,30,0.85);
|
||
border:1px solid #088538;
|
||
}
|
||
.layer-item-container{
|
||
width:100%;
|
||
height: calc( 100% - 50px);
|
||
overflow-y:auto;
|
||
}
|
||
|
||
.layer-container .title{
|
||
width:100%;
|
||
height:50px;
|
||
line-height:50px;
|
||
color:#CBE6CD;
|
||
font-size:16px;
|
||
}
|
||
|
||
.layer-category{
|
||
width:100%;
|
||
height:36px;
|
||
color:#CBE6CD;
|
||
font-size:16px;
|
||
line-height:36px;
|
||
display: flex;
|
||
}
|
||
|
||
.arrow{
|
||
font-size:22px;
|
||
cursor:pointer;
|
||
}
|
||
.layer-category-checkbox{
|
||
width:14px;
|
||
height:14px;
|
||
background:#fff;
|
||
margin-top:11px;
|
||
cursor:pointer;
|
||
border-radius:2px;
|
||
}
|
||
.layer-category-name{
|
||
flex:auto;
|
||
text-indent: 12px;
|
||
cursor:pointer;
|
||
}
|
||
|
||
.layer-item{
|
||
width:100%;
|
||
height:24px;
|
||
line-height:24px;
|
||
font-size:14px;
|
||
color: #CBE6CD;
|
||
display:flex;
|
||
padding-left:40px;
|
||
|
||
}
|
||
|
||
.layer-checkbox{
|
||
width:14px;
|
||
height:14px;
|
||
background:#fff;
|
||
margin-top:5px;
|
||
cursor:pointer;
|
||
border-radius:2px;
|
||
font-weight:bold;
|
||
}
|
||
|
||
.layer-name{
|
||
flex:auto;
|
||
text-indent: 12px;
|
||
cursor:pointer;
|
||
}
|
||
</style>
|