月球大数据地理空间分析展示平台-【前端】-月球2期前端
Surpriseplus
2023-08-22 e2c94dcb58b199eb57c164a67f1b038d401063d7
图层管理属性查询;空间查询下载借款给调试,分屏对比功能修改;
已添加3个文件
已修改12个文件
1693 ■■■■ 文件已修改
public/CIMSDK/Assets/Images/color.png 补丁 | 查看 | 原始文档 | blame | 历史
public/CIMSDK/Workers/image/location.png 补丁 | 查看 | 原始文档 | blame | 历史
public/config/config.js 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/api/api.js 9 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/assets/js/Map/config.js 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/assets/js/Map/index.js 25 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/assets/js/Map/menuTool.js 155 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/assets/js/Map/rightServer.js 328 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/store/index.ts 3 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/Index.vue 4 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/layer/attributeList.vue 210 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/layer/doubleLayer.vue 473 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/layer/layerManage.vue 4 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/menus.vue 71 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/query/SpatialQuery.vue 408 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
public/CIMSDK/Assets/Images/color.png
public/CIMSDK/Workers/image/location.png
public/config/config.js
@@ -1 +1,2 @@
const BASE_URL = "http://192.168.20.83:8088/MoonServer/"; //后端接口地址
// const BASE_URL = "http://192.168.20.106:9000/MoonServer/"; //后端接口地址
src/api/api.js
@@ -17,9 +17,16 @@
export function dataQuery_selectFields(params) {
  //请求地址
  return request.get("/dataQuery/selectFields", { params: params });
  return request.get("/dataQuery/selectTabFields", { params: params });
}
//数据查询=>下载DB数据
export function dataQuery_downloadDbData(params) {
  //请求地址
  return request.post("/dataQuery/downloadDbData", params);
}
//获取RSA加密公钥
export function sign_getPublicKey(params) {
  //请求地址
src/assets/js/Map/config.js
@@ -1,5 +1,5 @@
//是否为生产环境
const isWeb = true;
const isWeb = false;
//是否为生产环境
const webUrl = isWeb ? "/web" : "";
//配置文件地址
src/assets/js/Map/index.js
@@ -38,37 +38,14 @@
    sgworld.Creator.SimpleGraphic.edit(true, { editProp: true });
    //=======================
    window.Viewer.imageryLayers.removeAll();
    Viewer.animation.container.style.visibility = "hidden";
    Viewer.timeline.container.style.visibility = "hidden";
    //=======================
    //大气层
    Viewer.scene.globe.showGroundAtmosphere = false;
    // server.AddDemLayer("", 12316);
    // server.AddTmsLayer(
    //   "http://172.16.2.10:50001/sj_raster/v6/service/10003901/1"
    // );
    // var param = {
    //     name: labelName,
    //     id: earthCtrl.factory.createUUID(),
    //     text: "文字工具",
    //     font: '50pt monospace',
    //     outlineWidth: 2,
    //     fillColor: SmartEarth.Cesium.Color.RED,
    //     lon: 47.5087,
    //     lat: 23.6963,
    //     alt: 10
    // };
    // labelEntity = earthCtrl.factory.createLabel(param);
    // server.AddTmsLayer('http://localhost:8080/abc');
    // earthCtrl.camera.flyTo(47.5087, 23.6963, 300, 9.5, -45, 0.0, 5);
    // //添加鼠标左击事件
    // this.addMouseLeftClickEvents();
    // this.addMouseMouseMoveEvents();
  },
  //鼠标左键点击事件添加
  addMouseLeftClickEvents() {
src/assets/js/Map/menuTool.js
@@ -3,7 +3,8 @@
import rightServer from "./rightServer";
import config from "./config";
import CryptoJS from "crypto-js";
// import { Store } from "vuex";
import store from "@/store";
const menuTool = {
  toolMenu: null,
  toolFlag: null,
@@ -355,34 +356,7 @@
      destination: Cesium.Rectangle.fromDegrees(west, south, east, north),
    });
    // var e = Viewer.entities.add({
    //   name: "正方",
    //   polygon: {
    //     hierarchy: geometry1,
    //     //height : 100000,
    //     material: Cesium.Color.RED,
    //     outline: true,
    //     outlineColor: Cesium.Color.RED,
    //   },
    // });
    // const stripeMaterial = new Cesium.StripeMaterialProperty({
    //   evenColor: Cesium.Color.WHITE.withAlpha(0.5),
    //   oddColor: Cesium.Color.BLUE.withAlpha(0.5),
    //   repeat: 5.0,
    // });
    // var e = Viewer.entities.add({
    //   rectangle: {
    //     coordinates: geometry,
    //     outline: true,
    //     outlineColor: Cesium.Color.WHITE,
    //     outlineWidth: 4,
    //     stRotation: Cesium.Math.toRadians(45),
    //     material: stripeMaterial,
    //   },
    // });
    // this.squareOjb.push(e);
    // // earthCtrl.Creator.SimpleGraphic.clear();
    // Viewer.entities.remove(entity);
    setTimeout(() => {
      window.functionForJs({
@@ -421,6 +395,8 @@
      window.DoubleScreen = null;
      const compass = document.getElementsByClassName("bottom_btn")[0];
      compass.style.right = "70px";
      store.state.doubleMap = false;
      store.state.doubleMenu = false;
      return;
    }
    window.DoubleScreen = new SmartEarth.DoubleScreen(
@@ -428,18 +404,23 @@
      {},
      SmartEarth
    );
    DoubleScreen.right._Viewer.imageryLayers.removeAll();
    var terrain = new Cesium.CesiumTerrainProvider({
      url: config.moonTerrain,
      tilingScheme: new Cesium.GeographicTilingScheme({
        ellipsoid: Cesium.Ellipsoid.MOON,
      }),
    });
    DoubleScreen.right._Viewer.terrainProvider = terrain;
    rightServer.AddWmtesLayer(config.moonWmts);
    window.rightViewer = DoubleScreen.right._Viewer;
    window.rightViewer.imageryLayers.removeAll();
    window.rightViewer = DoubleScreen.right._Viewer;
    window.rightViewer.animation.container.style.visibility = "hidden";
    // window.rightViewer.timeline.container.style.visibility = "hidden";
    //大气层
    window.rightViewer.scene.globe.showGroundAtmosphere = false;
    window.rightViewer.scene.skyAtmosphere.show = false;
    const compass = document.getElementsByClassName("bottom_btn")[0];
    compass.style.right = "calc(50% + 70px)";
    store.state.doubleMap = true;
    setTimeout(() => {
      window.functionGetLayer({
        type: "getlayer",
        value: true,
      });
    }, 100);
  },
  //土方量计算
  Volumetric() {
@@ -551,5 +532,101 @@
    earthCtrl.analysis.deleteObject();
  },
  clearLeftTools(res) { },
  //空间查询属性定位
  spaceLocation(res) {
    var name = '空间查询';
    debugger
    this.setClearLocation(name);
    switch (res.type) {
      case 'MultiPolygon':
        for (var i in res.coordinates) {
          this.setLocationPolygon(res.coordinates[i], name)
        }
        break;
      case 'MultiLineString':
        for (var i in res.coordinates) {
          this.setLocationLine(res.coordinates[i], name)
        }
        break;
      case 'Point':
        this.setLocationPoint(res.coordinates, name)
        break;
    }
  },
  //清空之前绘制图形
  setClearLocation(res) {
    for (var i = 0; i < window.Viewer.entities._entities._array.length; i++) {
      if (window.Viewer.entities._entities._array[i].name == res) {
        window.Viewer.entities.remove(window.Viewer.entities._entities._array[i])
        i = i - 1;
      }
    }
  },
  setLocationPolygon(res, name) {
    var position = [];
    var geom = res[0]
    for (var i in geom) {
      position.push(geom[i][0], geom[i][1])
    }
    var locationPolygonEntity = window.Viewer.entities.add({
      name: name,
      polygon: {
        hierarchy: { positions: Cesium.Cartesian3.fromDegreesArray(position) },
        outline: true,
        outlineWidth: 100,
        arcType: Cesium.ArcType.RHUMB,
        material: Cesium.Color.CORNFLOWERBLUE.withAlpha(0.4),
        outline: true, // height is required for outline to display
        outlineColor: Cesium.Color.DODGERBLUE,
      }
    });
    window.Viewer.flyTo(locationPolygonEntity, {
      duration: 5,
      offset: new SmartEarth.Cesium.HeadingPitchRange(0.0, SmartEarth.Cesium.Math.toRadians(-20.0))
    });
  },
  setLocationPoint(res, name) {
    const position = window.Viewer.entities.add({
      name: name,
      position: Cesium.Cartesian3.fromDegrees(res[0], res[1]),
      billboard: {
        image: config.StaticFileBaseUrl + '/Workers/image/location.png',
        // è®¾ç½®è´´åœ°
        heightReference: Cesium.Color.CORNFLOWERBLUE.withAlpha(0.4),
        verticalOrigin: Cesium.VerticalOrigin.BOTTOM,
        scale: 5.0,
      },
    });
    window.Viewer.flyTo(position, {
      duration: 5,
      offset: new SmartEarth.Cesium.HeadingPitchRange(0.0, SmartEarth.Cesium.Math.toRadians(-20.0))
    });
  },
  setLocationLine(res, name) {
    var position = [];
    for (var i in res) {
      position.push(res[i][0], res[i][1])
    }
    var polyline = window.Viewer.entities.add({
      name: name,
      polyline: {
        positions: Cesium.Cartesian3.fromDegreesArray(position),
        width: 10.0,
        material: new Cesium.PolylineOutlineMaterialProperty({
          color: Cesium.Color.CORNFLOWERBLUE.withAlpha(0.4),
          outlineWidth: 1,
          outlineColor: Cesium.Color.CORNFLOWERBLUE,
        }),
        clampToGround: true,
      },
    })
    window.Viewer.flyTo(polyline, {
      duration: 5,
      offset: new SmartEarth.Cesium.HeadingPitchRange(0.0, SmartEarth.Cesium.Math.toRadians(-20.0))
    });
  }
};
export default menuTool;
src/assets/js/Map/rightServer.js
@@ -1,7 +1,196 @@
const rightServer = {
import { getToken } from "@/utils/auth";
//配置文件地址
import config from "./config";
    AddWmtesLayer(url) {
        var urlTemplateImageryProvider = DoubleScreen.right.factory.createImageryLayer({
const rightServer = {
    layerList: [],
    addTreeData(treeNode) {
        if (!treeNode.checked) {
            this.delLayer(treeNode.id);
            return;
        }
        //判断是否为代理
        if (treeNode.proxy) {
            this.addProxyAddress(treeNode); //有代理
        } else {
            this.addUrlAddress(treeNode); //无代理
        }
    },
    //代理地址
    addProxyAddress(res) {
        //判断数据类型
        switch (res.data) {
            case 1: //数字正射影像图
                this.setDataType(res);
                break;
            case 2: //场景地形数据
                this.setTerrainData(res);
                break;
            case 3: //数字高程模型(晕渲图)
                this.setDataType(res);
                break;
            case 4: //单波段栅格数据
                this.setDataType(res);
                break;
            case 5: //多光谱栅格数据
                this.setDataType(res);
                break;
            case 6: //高光谱栅格数据
                this.setDataType(res);
                break;
            case 7: //矢量图层
                this.setVectorData(res);
                break;
            case 8: //三维模型
                this.setModelData(res);
                break;
        }
    },
    //普通地址
    addUrlAddress(res) {
        switch (res.category) {
            case 0: //其他
                break;
            case 1: //GisServer
                this.addProxyAddress(res);
                break;
            case 2: //GeoServer
                this.addGeoServerAddress(res);
                break;
            case 3: //数简
                this.addProxyAddress(res);
                break;
        }
    },
    //Geoserver服务
    addGeoServerAddress(res) {
        //判断数据类型
        switch (res.data) {
            case 1: //数字正射影像图
                this.setGeoDataType(res);
                break;
            case 2: //场景地形数据
                this.setTerrainData(res);
                break;
            case 3: //数字高程模型(晕渲图)
                this.setGeoDataType(res);
                break;
            case 4: //单波段栅格数据
                this.setGeoDataType(res);
                break;
            case 5: //多光谱栅格数据
                this.setGeoDataType(res);
                break;
            case 6: //高光谱栅格数据
                this.setGeoDataType(res);
                break;
            case 7: //矢量图层
                this.setGeoVectorData(res);
                break;
            case 8: //三维模型
                this.setModelData(res);
                break;
        }
    },
    setGeoDataType(res) {
        switch (res.type) {
            case 0: //URL
                break;
            case 1: //TMS
                this.setAddTmsLayer(res);
                break;
            case 2: //WMTS
                this.setAddWmtsLayer(res);
                break;
            case 3: //WMS
                this.setAddGeoWmsLayer(res);
                break;
        }
    },
    setGeoVectorData(res) {
        switch (res.type) {
            case 0: //URL
                break;
            case 3: //WMS
                this.setAddGeoWmsLayer(res);
                break;
            case 4: //WFS
                break;
        }
    },
    setDataType(res) {
        switch (res.type) {
            case 0: //URL
                break;
            case 1: //TMS
                this.setAddTmsLayer(res);
                break;
            case 2: //WMTS
                this.setAddWmtsLayer(res);
                break;
            case 3: //WMS
                this.setAddWmsLayer(res);
                break;
        }
    },
    setTerrainData(res) {
        switch (res.type) {
            case 0: //URL
                this.setAddTearrinLayer(res);
                break;
            case 1: //TMS
                this.setAddTearrinLayer(res);
                break;
        }
    },
    setVectorData(res) {
        switch (res.type) {
            case 0: //URL
                break;
            case 3: //WMS
                this.setAddWmsLayer(res);
                break;
            case 4: //WFS
                break;
        }
    },
    setModelData(res) {
        switch (res.type) {
            case 0: //Tileset
                this.setAddModelLayer(res);
                break;
            case 3: //WMS
                this.setAddModelLayer(res);
                break;
            case 5: //WFS
                break;
        }
    },
    //获取服务地址
    getLayrUrl(res) {
        var url;
        if (res.proxy) {
            const token = getToken();
            url = config.proxy + res.proxy.replaceAll("{token}", token);
        } else {
            url = res.url;
        }
        return url;
    },
    //加载TMS服务
    setAddTmsLayer(res) {
        var url = this.getLayrUrl(res);
        var urlTemplateImageryProvider = new Cesium.UrlTemplateImageryProvider({
            url: url + '/{z}/{x}/{reverseY}.png',
        });
        let img_layer = window.rightViewer.imageryLayers.addImageryProvider(urlTemplateImageryProvider);
        this.layerList.push({ id: res.id, layerData: img_layer, type: "tms" });
    },
    //加载WMTS服务
    setAddWmtsLayer(res) {
        var url = this.getLayrUrl(res);
        var urlTemplateImageryProvider = new Cesium.WebMapTileServiceImageryProvider({
            sourceType: "wmts",
            url: url,
            layer: "",
@@ -33,9 +222,136 @@
                ellipsoid: Cesium.Ellipsoid.MOON,
            }),
        });
        let img_layer = window.rightViewer.imageryLayers.addImageryProvider(urlTemplateImageryProvider);
        this.layerList.push({
            id: res.id,
            layerData: img_layer,
            type: "wmts",
        });
    },
    //加载地形服务
    setAddTearrinLayer(res) {
        this.setChangeTearrinLayer();
        var url = this.getLayrUrl(res);
        window.terrainLayer = new Cesium.CesiumTerrainProvider({
            url: url,
        });
        window.rightViewer.terrainProvider = window.terrainLayer;
        this.layerList.push({ id: res.id, type: "dem" });
    },
    //加载WMS服务
    setAddWmsLayer(res) {
        var url = this.getLayrUrl(res);
        var img_layer = window.rightViewer.createImageryProvider(
            "giserver",
            "wms",
            {
                url: url,
                layers: "",
                parameters: {
                    format: "image/png",
                    transparent: true,
                },
            },
            "0",
            undefined,
            true,
            ""
        );
        this.layerList.push({
            id: res.id,
            layerData: img_layer,
            type: "wmts",
        });
    },
    //加载模型服务
    setAddModelLayer(res) {
        var url = this.getLayrUrl(res);
        let tileset = window.rightViewer.scene.primitives.add(
            new Cesium.Cesium3DTileset({
                name: res.cnName,
                url: url,
                skipLevelOfDetail: true, // åœ¨éåŽ†æ—¶å€™è·³è¿‡è¯¦æƒ…ï¼šfalse
                baseScreenSpaceError: 1024,
                maximumScreenSpaceError: 64, // æœ€å¤§å±å¹•空间错误:16,数值加大能让最终成像变模糊
                skipScreenSpaceErrorFactor: 16,
                skipLevels: 1,
                immediatelyLoadDesiredLevelOfDetail: false,
                loadSiblings: true, // è‡ªåŠ¨ä»Žä¸­å¿ƒå¼€å§‹è¶…æ¸…åŒ–æ¨¡åž‹ï¼šfalse
                cullWithChildrenBounds: true, // ä½¿ç”¨å­é¡¹è¾¹ç•Œä½“积的并集来剔除图块:true
                cullRequestsWhileMoving: true,
                cullRequestsWhileMovingMultiplier: 10, // å€¼è¶Šå°èƒ½å¤Ÿæ›´å¿«çš„剔除:60
                preloadWhenHidden: true,
                preferLeaves: true, // é¢„装子节点:false
                maximumMemoryUsage: 768, // å†…存分配变小有利于内存回收,提升性能体验
                progressiveResolutionHeightFraction: 0.5, // æ•°å€¼åäºŽ0能够让初始加载变得模糊
                dynamicScreenSpaceErrorDensity: 0.5, // æ•°å€¼åŠ å¤§ï¼Œèƒ½è®©å‘¨è¾¹åŠ è½½å˜å¿«
                dynamicScreenSpaceErrorFactor: 2, // åŠ¨æ€å±å¹•ç©ºé—´è¯¯å·®çš„ç³»æ•°
                dynamicScreenSpaceError: true, // å‡å°‘离相机较远的屏幕空间错误:false,全屏加载完之后才清晰化房屋
            })
        );
        tileset.readyPromise.then((tileset) => {
            tileset.id = res.id;
        });
        this.layerList.push({ id: res.id, layerData: tileset, type: "tileset" });
    },
    //地形移除事件
    setChangeTearrinLayer() {
        this.layerList.forEach((e, i) => {
            switch (e.type) {
                case "dem":
                    window.rightViewer.terrainProvider = new Cesium.EllipsoidTerrainProvider(
                        {}
                    );
                    this.layerList.splice(i, 1);
                    break;
            }
        });
    },
    //清除图层
    delLayer(code) {
        this.layerList.forEach((e, i) => {
            if (e.id === code) {
                switch (e.type) {
                    case "wmts":
                        window.rightViewer.imageryLayers.remove(e.layerData);
                        break;
                    case "tms":
                        window.rightViewer.imageryLayers.remove(e.layerData);
                        break;
                    case "dem":
                        window.rightViewer.terrainProvider = new Cesium.EllipsoidTerrainProvider(
                            {}
                        );
                        break;
                    case "tileset":
                        window.rightViewer.scene.primitives.remove(e.layerData)
                        break;
                }
                this.layerList.splice(i, 1);
            }
        });
    },
    //加载GeoServer-WMS服务
    setAddGeoWmsLayer(res) {
        var url = this.getLayrUrl(res);
        let layer = new SmartEarth.Cesium.WebMapServiceImageryProvider({
            url: url,
            layers: res.tab,
            parameters: {
                transparent: true,
                format: "image/png",
                srs: "EPSG:104903",
                styles: "",
            },
            tileWidth: 512,
            tileHeight: 512,
        });
        layer.name = `Wms_Layer${res.id}`;
}
export default rightServer;
        let img_layer = window.rightViewer.imageryLayers.addImageryProvider(layer);
        this.layerList.push({ id: res.id, layerData: img_layer, type: "wmts" });
    },
};
export default rightServer;
src/store/index.ts
@@ -18,6 +18,9 @@
    },
    chekNowLayers: [],
    exportImgUrl: "",
    tab: null,
    doubleMap: false,
    doubleMenu: false,
  },
  mutations: {
    //获取登录Code
src/views/Index.vue
@@ -1,6 +1,8 @@
<template>
  <div class="body_box">
    <div id="cesiumContainer"></div>
    <div id="cesiumContainer">
    </div>
    <export-map
      v-if="layerExportshow"
      @SETexportMap="SETexportMap"
src/views/layer/attributeList.vue
@@ -1,15 +1,69 @@
<template>
  <div v-drag="true" class="spatialBox">
  <div
    v-drag="true"
    class="spatialBox"
  >
    <!--     v-resizable="'right, bottom'" -->
    <div class="spatialTitle">
      <label>属性</label>
      <el-icon @click="setSpatialClose" :size="20" style="cursor: pointer">
      <el-icon
        @click="setSpatialClose"
        :size="20"
        style="cursor: pointer"
      >
        <Close />
      </el-icon>
    </div>
    <div class="spatialContent">
      <div>
        <el-row :gutter="20">
          <el-col :span="16">
            <el-input
              v-model="listData.filter"
              type="text"
              placeholder="请选择..."
              disabled
            />
          </el-col>
          <el-col :span="8">
            <el-button
              :icon="Plus"
              type="success"
              @click="dialogVisible = true"
            >高级查询</el-button>
            <el-button
              :icon="Refresh"
              type="info"
              @click="setdialogRefresh"
            >重置</el-button>
          </el-col>
        </el-row>
      </div>
      <div class="spatialTable">
        <el-table :data="tableData" style="width: 100%; height: 82%">
        <el-table
          :data="tableData"
          style="width: 100%; height: 75%"
        >
          <el-table-column
            align="center"
            type="index"
            label="序号"
            width="70"
          />
          <el-table-column
            label="定位"
            width="100"
            align="center"
          >
            <template #default="scope">
              <el-button
                :icon="Location"
                size="small"
                @click.prevent="spaceLocation(scope.$index, scope.row)"
              >
              </el-button>
            </template>
          </el-table-column>
          <el-table-column
            v-for="(item, index) in attributeData"
            :key="index"
@@ -18,7 +72,7 @@
            show-overflow-tooltip
            align="center"
            :fit="true"
            width="120"
            min-width="120"
          ></el-table-column>
        </el-table>
        <div class="spatialBottom">
@@ -36,6 +90,63 @@
        </div>
      </div>
    </div>
    <!-- é«˜çº§æŸ¥è¯¢ -->
    <el-dialog
      v-model="dialogVisible"
      title="高级查询"
      width="30%"
      :show-close="false"
      :close-on-click-modal="false"
      :close-on-press-escape="false"
    >
      <div>
        <el-row :gutter="20">
          <el-col :span="8">
            <el-select
              v-model="formSql.field"
              class="m-2"
              placeholder="Select"
              @change="setFieldChange($event)"
            >
              <el-option
                v-for="item in fieldOption"
                :key="item.field"
                :label="item.alias"
                :value="item.field"
              />
            </el-select>
          </el-col>
          <el-col :span="8">
            <el-select
              v-model="formSql.type"
              class="m-2"
              placeholder="Select"
            >
              <el-option
                v-for="item in condOption"
                :key="item.value"
                :label="item.label"
                :value="item.value"
              />
            </el-select>
          </el-col>
          <el-col :span="8">
            <el-input v-model="formSql.value"></el-input>
          </el-col>
        </el-row>
      </div>
      <template #footer>
        <span class="dialog-footer">
          <el-button @click="dialogVisible = false">取消</el-button>
          <el-button
            type="primary"
            @click="setInsertDialog"
          > æ·»åŠ  </el-button>
        </span>
      </template>
    </el-dialog>
  </div>
</template>
@@ -51,13 +162,15 @@
  watch,
} from "vue";
import config from "@/assets/js/Map/config";
import { User, Lock, Plus } from "@element-plus/icons-vue";
import { User, Lock, Plus, Location } from "@element-plus/icons-vue";
import { dataQuery_selectByPage, dataQuery_selectFields } from "@/api/api";
import { ElMessage } from "element-plus";
import store from "@/store";
import menuTool from "@/assets/js/Map/menuTool";
import WKT from "terraformer-wkt-parser";
const emits = defineEmits(["spatialClose"]);
const setSpatialClose = () => {
  menuTool.setClearLocation("空间查询");
  emits("spatialClose", false);
};
const dialogVisible = ref(false);
@@ -67,7 +180,7 @@
  count: 0,
  wkt: null,
  hasGeom: 1,
  filter: "",
  name: "",
});
const condOption = ref([]);
@@ -80,12 +193,26 @@
  value: "",
  cut: "",
});
//定位显示
const spaceLocation = (index, row) => {
  var geom = menuTool.decr(row.geom);
  var wkt = WKT.parse(geom);
  menuTool.spaceLocation(wkt);
};
//defineProps æ¥æŽ¥æ”¶ç»„件的传值
const props = defineProps({
  layerData: Object,
});
const setdialogRefresh = () => {
  listData.value.filter = "";
  listData.value.pageIndex = 1;
  listData.value.pageSize = 10;
  var res = attributeData.value[0];
  conditionChange(res);
  setQueySpatialData();
};
const handleSizeChange = (res) => {
  listData.value.pageSize = res;
  setQueySpatialData();
@@ -97,6 +224,7 @@
//查询列表数据
const setQueySpatialData = async () => {
  listData.value.name = listData.value.name.replaceAll("_", "");
  const data = await dataQuery_selectByPage(listData.value);
  if (data.code != 200) {
    return ElMessage.error("空间查询失败");
@@ -106,22 +234,61 @@
};
const setQueySpatialFields = async () => {
  const data = await dataQuery_selectFields({ name: listData.value.name });
  const data = await dataQuery_selectFields({
    ns: "mn",
    tab: listData.value.name,
  });
  if (data.code != 200) {
    return ElMessage.error("字段查询失败");
  }
  attributeData.value = data.result;
  var std = data.result.filter((res) => {
    if (res.showtype > 0) {
      return res;
    }
  });
  attributeData.value = std;
  fieldOption.value = std;
  conditionChange(data.result[0]);
  setQueySpatialData();
};
const setInsertDialog = () => {
  if (!formSql.value.value) {
    return ElMessage.error("请输入要查询的参数");
  }
  dialogVisible.value = false;
  if (listData.value.filter != "") {
    listData.value.filter += " and ";
  }
  const val = null;
  if (formSql.value.cut === "long" || formSql.value.cut === "integer") {
    val = parseInt(formSql.value.value);
  } else if (formSql.value.cut === "double") {
    if (formSql.value.value.indexOf(".") != -1) {
      val = parseInt(formSql.value.value);
    } else {
      val = parseFloat(formSql.value.value).toFixed(1);
    }
  } else if (formSql.value.cut == "date" || formSql.value.cut == "datetime") {
    var time = new Date(formSql.value.value);
    var m = time.getMonth() + 1;
    var d = time.getDate();
    var y = time.getFullYear();
    val = "'" + y + "-" + add0(m) + "-" + add0(d) + "'";
  } else {
    val = "'" + formSql.value.value + "'";
  }
  listData.value.filter +=
    formSql.value.field + " " + formSql.value.type + " " + val;
  var res = attributeData.value[0];
  conditionChange(res);
  setQueySpatialData();
};
const conditionChange = (res) => {
  formSql.value.value = "";
  formSql.value.field = res.field;
  formSql.value.cut = res.type;
  const type = res.type;
  var type = res.type;
  var std = [];
  if (type == "text" || type == "blob") {
    std = config.conditions[0];
@@ -137,17 +304,20 @@
      value: std[i],
    });
  }
  debugger;
  condOption.value = str;
  formSql.value.type = std[0];
};
//页面初始化
const startQueryData = () => {
  listData.value.wkt = store.state.spatialQueryData.wkt;
  listData.value.name = "lunarplacenane";
  listData.value.hasGeom = 1;
  //
  setQueySpatialFields();
  if (store.state.tab) {
    listData.value.wkt = "";
    listData.value.name = store.state.tab.tab.replaceAll("moon:", "");
    listData.value.hasGeom = 1;
    setQueySpatialFields();
  }
};
watch(
@@ -158,7 +328,9 @@
  },
  { deep: true }
);
onMounted(() => {});
onMounted(() => {
  startQueryData();
});
</script>
<style lang="less" scoped>
src/views/layer/doubleLayer.vue
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,473 @@
<template>
  <div
    v-drag
    class="layerBox"
  >
    <div class="layerTitle">
      <div class="tileLeft">
        <div
          @click="setCloseLayer"
          class="titleImg"
        >
          <ArrowLeft />
        </div>
        <div class="titleLable">图层管理</div>
      </div>
      <!-- <div
        class="titleImg set"
        @click="layerSetBox"
      >
        <Setting />
      </div> -->
    </div>
    <div class="layerContent">
      <el-tree
        node-key="id"
        :props="props"
        :highlight-current="false"
        :current-node-key="selectedNodeId"
        :data="treeData"
        :expand-on-click-node="false"
        show-checkbox
        @check="handleCheckChange"
        ref="estreeRef"
        v-if="treeData.length"
        :default-checked-keys="DefaultId"
      >
        <template #default="{ node, data }">
          <span class="custom-tree-node">
            <span class="label">{{ node.label }}</span>
            <!-- <span>
              <a @click="append(data)"> Append </a>
              <a style="margin-left: 8px" @click="remove(node, data)">
                Delete
              </a>
            </span> -->
            <span
              class="button"
              v-if="data.isLayer == 1"
            >
              <el-dropdown trigger="click">
                <span class="el-dropdown-link">
                  <el-icon class="el-icon--right">
                    <MoreFilled />
                  </el-icon>
                </span>
                <template #dropdown>
                  <el-dropdown-menu>
                    <el-dropdown-item @click.native="clickdropdown(1, data)">详细</el-dropdown-item>
                    <el-dropdown-item
                      v-if="data.type == 3"
                      @click.native="clickdropdown(2, data)"
                    >属性</el-dropdown-item>
                  </el-dropdown-menu>
                </template>
              </el-dropdown>
            </span>
          </span>
        </template>
      </el-tree>
    </div>
  </div>
  <layer-set
    v-if="layerSetIsshow"
    @SETstate="SETstate"
    :layerTree="treeData"
    @addlayer="addlayer"
    @delLayer="delLayer"
  ></layer-set>
  <attribute-list
    v-if="layerAttributeIsshow"
    :layerData="layerObjData"
    @spatialClose="setSpatialClose"
  ></attribute-list>
  <layer-detail
    :layerData="layerObjData"
    v-if="layerDetailIsshow"
    @detailClose="detailClose"
  ></layer-detail>
</template>
<script lang="ts" setup>
import {
  ref,
  onMounted,
  onBeforeUnmount,
  reactive,
  defineProps,
  defineEmits,
  nextTick,
} from "vue";
import layerSet from "./layerSet";
import attributeList from "./attributeList";
import layerDetail from "./layerDetail";
import { useStore } from "vuex"; // å¼•å…¥useStore æ–¹æ³•
import { perms_selectLayers } from "@/api/api";
import rightServer from "@/assets/js/Map/rightServer";
import { ElMessage } from "element-plus";
const store = useStore(); // è¯¥æ–¹æ³•用于返回store å®žä¾‹
const stretchValue = ref("");
let estreeRef = ref();
const transparence = ref(0);
var treeData = ref([]);
var layerListData = ref([]);
let menuOption = reactive([]);
const layerSetIsshow = ref(false);
const layerAttributeIsshow = ref(false);
const layerDetailIsshow = ref(false);
const props = {
  label: "cnName",
  children: "children",
};
const layerObjData = ref(null);
// å½“前选中的节点 id
const selectedNodeId = ref(null as any); //做类型断言处理
const emits = defineEmits(["setDobuleCloseLayer"]);
//默认选中id
const DefaultId = ref([]);
//图层设置弹框
const layerSetBox = () => {
  layerSetIsshow.value = !layerSetIsshow.value;
};
//关闭状态
const SETstate = (res) => {
  layerSetIsshow.value = res;
};
const setCloseLayer = () => {
  store.state.doubleMenu = true;
  store.state.doubleMap = false;
};
//选择图层
const handleCheckChange = (data, checked) => {
  layerAttributeIsshow.value = false;
  layerDetailIsshow.value = false;
  let isCheck = checked.checkedKeys.indexOf(data.id) > -1;
  // this.setVisiable(data, isCheck);
  let son = estreeRef.value.getCheckedNodes();
  store.commit("SET_CHECKLAYER", son);
  setVisiable(data, isCheck);
  // server.addLayer(layerArr, isCheck);
};
const setVisiable = (treeNode, checked) => {
  if (checked !== undefined) {
    treeNode.checked = checked;
  } else {
    treeNode.checked = !treeNode.checked;
  }
  if (treeNode.children) {
    treeNode.children.forEach((item) => {
      setVisiable(item, treeNode.checked);
    });
    return;
  }
  if (!treeNode.isAdd) {
    rightServer.addTreeData(treeNode);
    return;
  }
};
const defaultLayer = (val) => {
  val.forEach((e) => {
    DefaultId.value.forEach((v) => {
      if (e.id == v) {
        setVisiable(e, true);
        // return;
      }
    });
  });
};
const clickdropdown = (res, e) => {
  layerAttributeIsshow.value = false;
  layerDetailIsshow.value = false;
  layerObjData.value = e;
  if (res == 2) {
    layerAttributeIsshow.value = true;
    store.state.tab = e;
  } else {
    if (!e.checked) {
      return ElMessage.error("请先勾选图层");
    }
    layerDetailIsshow.value = true;
  }
};
const setSpatialClose = (res) => {
  layerAttributeIsshow.value = res;
};
const detailClose = (res) => {
  layerDetailIsshow.value = res;
};
//编辑图层树
const addlayer = (res) => {
  let node;
  layerListData.value.forEach((e) => {
    if (e.id == res.id) {
      node = estreeRef.value.getNode(e);
    }
  });
  // å°†å˜åŠ¨ä¹‹å‰çš„node备份
  let copyNode = { ...node };
  copyNode.previousSibling = { ...node.previousSibling };
  copyNode.nextSibling = { ...node.nextSibling };
  if (res.type === 1) {
    // ä¸Šç§»
    if (node.previousSibling) {
      // åˆ é™¤åŽŸå…ˆçš„node
      estreeRef.value.remove(node.data);
      // æ‹¿åˆ°copy的node
      // nodeData = CircularJSON.parse(window.sessionStorage.getItem("menuNode"));
      // å¤åˆ¶è¯¥node到指定位置(参数:1. è¦å¢žåŠ çš„èŠ‚ç‚¹çš„ data 2. è¦å¢žåŠ çš„èŠ‚ç‚¹çš„åŽä¸€ä¸ªèŠ‚ç‚¹çš„ data、key æˆ–者 node)
      estreeRef.value.insertBefore(
        copyNode.data,
        copyNode.previousSibling.data
      );
      // window.sessionStorage.removeItem("menuNode");
    }
  } else {
    // ä¸‹ç§»
    if (node.nextSibling) {
      estreeRef.value.remove(node.data);
      estreeRef.value.insertAfter(copyNode.data, copyNode.nextSibling.data);
    }
  }
};
//删除图层树
const delLayer = (res) => {
  // menuOption = menuOption.filter((item) => {
  //   return item.id != res;
  // });
  // treeData = handleTree(menuOption, "id", "pid", "children");
};
const getLayer = async () => {
  const dt = await perms_selectLayers();
  if (dt.code == 200) {
    treeData.value = setTreeData(dt.result).sort(function (a, b) {
      return a.sort - b.sort;
    });
    var std = [];
    var terrainId = null;
    dt.result.filter((res) => {
      if (res.isLayer == 1 && res.status == 1) {
        if (res.type == 1 && res.data == 2) {
          if (!terrainId) {
            terrainId = res.id;
            std.push(res.id);
          }
        } else {
          std.push(res.id);
        }
      }
    });
    DefaultId.value = std;
    //添加默认选中图层
    layerListData.value = dt.result;
    defaultLayer(dt.result);
    nextTick(() => {
      let son = estreeRef.value.getCheckedNodes();
      store.commit("SET_CHECKLAYER", son);
    });
  }
};
//构造树
function setTreeData(source) {
  let cloneData = JSON.parse(JSON.stringify(source)); // å¯¹æºæ•°æ®æ·±åº¦å…‹éš†
  return cloneData.filter((father) => {
    // å¾ªçŽ¯æ‰€æœ‰é¡¹
    let branchArr = cloneData.filter((child) => father.id == child.pid);
    if (branchArr.length > 0) {
      branchArr.sort(function (a, b) {
        return a.sort - b.sort;
      });
    }
    branchArr.length > 0 ? (father.children = branchArr) : ""; // ç»™çˆ¶çº§æ·»åŠ ä¸€ä¸ªchildren属性,并赋值
    // å±žäºŽåŒä¸€å¯¹è±¡é—®é¢˜ï¼Œä¾‹å¦‚:令 a=b、c=1 ï¼Œç„¶åŽå†ä»¤ b.c=c ï¼Œ é‚£ä¹ˆ a.c=b.c=c=1 ï¼›åŒç†ï¼ŒåŽç»­ä»¤ c.d=2 ,那么 a.c.d ä¹Ÿæ˜¯=2;
    // ç”±æ­¤å¾ªçŽ¯å¤šæ¬¡åŽï¼Œå°±èƒ½å½¢æˆç›¸åº”çš„æ ‘å½¢æ•°æ®ç»“æž„
    return father.pid == 0; // è¿”回一级菜单
  });
}
const functionGetLayer = (res) => {
  getLayer();
};
onMounted(() => {
  window.functionGetLayer = functionGetLayer;
});
</script>
<style lang="less" scoped>
.layerBox {
  width: 359px;
  height: 680px;
  right: calc(50% - 370px);
  top: 105px;
  position: absolute;
  z-index: 30;
  background: rgba(7, 8, 14, 0.8);
  box-shadow: inset 0px 10px 40px 10px rgba(38, 47, 71, 1);
  .layerTitle {
    width: calc(100% - 27px);
    height: 42px;
    background: #0e151f;
    box-shadow: 0px 0px 6px 0px #080c13,
      0px 14px 16px 0px rgba(38, 47, 71, 0.68);
    display: flex;
    justify-content: space-between;
    padding-left: 7px;
    padding-right: 20px;
    color: white;
    .tileLeft {
      height: 100%;
      display: flex;
      align-items: center;
      .titleLable {
        font-size: 18px;
        font-family: Source Han Sans CN;
        font-weight: 400;
        color: #ffffff;
      }
    }
    .titleImg {
      width: 20px;
      height: 100%;
      display: flex;
      align-items: center;
      color: rgba(104, 156, 255, 1);
    }
    .set {
      cursor: pointer;
    }
  }
  .layerContent {
    height: 625px;
    padding: 0 8px;
    overflow: auto;
    overflow-y: auto;
  }
  .layerContent::-webkit-scrollbar {
    width: 8px;
  }
  .layerContent::-webkit-scrollbar-thumb {
    border-radius: 10px;
    background: rgba(0, 0, 0, 0.2);
  }
  .layerContent::-webkit-scrollbar-track {
    border-radius: 0;
    background: rgba(0, 0, 0, 0);
  }
  .el-tree {
    width: 100%;
    overflow-y: auto;
  }
  .layerContent .el-tree-node__content {
    overflow: hidden;
  }
  .layerContent .custom-tree-node {
    overflow: hidden;
    flex-shrink: 1;
    flex-grow: 1;
    display: flex;
    align-items: center;
    justify-content: space-between;
    font-size: 16px;
    padding-right: 8px;
  }
  .layerContent .custom-tree-node .label {
    flex-shrink: 1;
    overflow: hidden;
    text-overflow: ellipsis;
  }
  .layerContent .custom-tree-node .button {
    flex-grow: 0;
    flex-shrink: 0;
  }
}
.dropdown_box {
  position: relative;
}
/deep/.el-select-dropdown__item {
  font-size: 12px !important;
}
.el-tree {
  background: transparent;
}
/deep/ .el-tree-node {
  background: #0d131d;
  color: #ffffff;
  font-size: 20px;
  font-weight: 300;
  margin-top: 3px;
  padding: 8px;
}
/deep/ .el-tree-node:focus > .el-tree-node__content {
  background: transparent;
}
/deep/ .el-tree-node__content:hover {
  background: #0d131d;
}
/deep/ .el-tree-node__children {
  background: #1e2a3d;
  .el-tree-node {
    background: #1e2a3d;
    margin-top: 0;
    padding: 4px;
  }
}
/deep/
  .el-tree--highlight-current
  .el-tree-node.is-current
  > .el-tree-node__content {
  background: rgba(104, 156, 255, 0.5) !important;
}
.highlight {
  background: rgba(104, 156, 255, 0.5) !important;
}
// .custom-tree-node {
//   flex: 1;
//   display: flex;
//   align-items: center;
//   justify-content: space-between;
//   font-size: 16px;
//   padding-right: 8px;
// }
.el-dropdown-menu {
  background: rgba(7, 8, 14, 0.8);
  box-shadow: inset 0px 10px 40px 10px rgba(38, 47, 71, 1);
  color: #fff;
  border: 0;
  /deep/ .el-dropdown-menu__item {
    color: #fff;
  }
}
/deep/ .el-dropdown-menu__item:not(.is-disabled):focus {
  background-color: rgba(104, 156, 255, 0.5);
  color: #fff;
}
</style>
<style>
.el-popper.is-light {
  border: 1px solid rgba(7, 8, 14, 0.8) !important;
}
.el-scrollbar {
  border: 0 !important;
}
</style>
src/views/layer/layerManage.vue
@@ -77,7 +77,7 @@
    @delLayer="delLayer"
  ></layer-set>
  <attribute-list
    v-show="layerAttributeIsshow"
    v-if="layerAttributeIsshow"
    :layerData="layerObjData"
    @spatialClose="setSpatialClose"
  ></attribute-list>
@@ -187,8 +187,10 @@
  layerAttributeIsshow.value = false;
  layerDetailIsshow.value = false;
  layerObjData.value = e;
  if (res == 2) {
    layerAttributeIsshow.value = true;
    store.state.tab = e;
  } else {
    if (!e.checked) {
      return ElMessage.error("请先勾选图层");
src/views/menus.vue
@@ -1,10 +1,21 @@
<template>
  <div class="menus" v-show="fullScreen">
  <div
    class="menus"
    v-show="fullScreen"
  >
    <div class="logo_box">
      <img src="../assets/img/logo.png" alt="" class="logo" />
      <img
        src="../assets/img/logo.png"
        alt=""
        class="logo"
      />
      <div class="logo_name">
        <h3>月球大数据地理空间分析展示平台</h3>
        <img src="../assets/img/logob.png" alt="" class="logo_name_b" />
        <img
          src="../assets/img/logob.png"
          alt=""
          class="logo_name_b"
        />
      </div>
    </div>
    <div class="menus_box">
@@ -29,7 +40,10 @@
      </div>
    </div>
  </div>
  <div class="content_box" v-show="fullScreen">
  <div
    class="content_box"
    v-show="fullScreen"
  >
    <div
      v-show="checkMenuFlag == 'l1'"
      style="position: relative; display: flex"
@@ -46,10 +60,31 @@
    <search v-if="thematicMapBtnState"> </search>
  </div>
  <top-btn v-show="fullScreen" v-if="thematicMapBtnState"></top-btn>
  <top-btn
    v-show="fullScreen"
    v-if="thematicMapBtnState"
  ></top-btn>
  <thematic-map v-show="!thematicMapBtnState"></thematic-map>
  <div class="fullScreen_btn" v-show="!fullScreen" @click="screen"></div>
  <div
    class="fullScreen_btn"
    v-show="!fullScreen"
    @click="screen"
  ></div>
  <div
    v-show="store.state.doubleMenu"
    class="setDobuleMap"
    @click="setDoubleScreenMap"
  >
    <Operation />
  </div>
  <div
    @setDobuleCloseLayer="setDobuleCloseLayer"
    v-show="store.state.doubleMap"
  >
    <double-layer></double-layer>
  </div>
</template>
<script lang="ts" setup>
@@ -61,6 +96,7 @@
  defineProps,
  defineEmits,
} from "vue";
import { Operation } from "@element-plus/icons-vue";
import menuData from "@/assets/js/Map/menuData";
import menuTool from "@/assets/js/Map/menuTool";
//顶部菜单
@@ -75,11 +111,22 @@
import plotting from "@/views/plotting/plotting.vue";
//底图切换
import baseMapSwitching from "@/views/baseMapSwitching/baseMapSwitching.vue";
//分屏菜单
import doubleLayer from "@/views/layer/doubleLayer.vue";
import store from "@/store";
const menuOptions = ref([]);
const checkMenuFlag = ref("");
let fullScreen = ref(true);
let thematicMapState = ref(true);
let thematicMapBtnState = ref(true);
const setDoubleScreenMap = () => {
  store.state.doubleMenu = false;
  store.state.doubleMap = true;
};
const setDobuleCloseLayer = () => {
  store.state.doubleMenu = true;
  store.state.doubleMap = false;
};
const setMenuClick = (res) => {
  if (res.id == "l6") {
    // fullScreen.value = !fullScreen.value;
@@ -199,6 +246,18 @@
    }
  }
}
.setDobuleMap {
  position: absolute;
  top: 105px;
  right: calc(50% - 50px);
  z-index: 30;
  width: 20px;
  height: 20px;
  color: #d6e4ff;
  background: rgba(7, 8, 14, 0.8);
  box-shadow: inset 0px 10px 40px 10px rgba(38, 47, 71, 1);
  padding: 10px;
}
.menu_Image_box {
  height: 778px;
  width: 100%;
src/views/query/SpatialQuery.vue
@@ -6,12 +6,22 @@
    <!--     v-resizable="'right, bottom'" -->
    <div class="spatialTitle">
      <label>空间查询</label>
      <el-icon
        @click="setSpatialClose"
        :size="20"
      >
        <Close />
      </el-icon>
      <div>
        <el-icon
          @click="setSpatialDownload"
          :size="20"
          style="margin-right: 20px;"
        >
          <Download />
        </el-icon>
        <el-icon
          @click="setSpatialClose"
          :size="20"
        >
          <Close />
        </el-icon>
      </div>
    </div>
    <div class="spatialContentBox">
      <div class="spatialMenu">
@@ -54,6 +64,26 @@
            :data="tableData"
            style="width: 100%; height: 73%;"
          >
            <el-table-column
              align="center"
              type="index"
              label="序号"
              width="70"
            />
            <el-table-column
              label="定位"
              width="100"
              align="center"
            >
              <template #default="scope">
                <el-button
                  :icon="Location"
                  size="small"
                  @click.prevent="spaceLocation(scope.$index, scope.row)"
                >
                </el-button>
              </template>
            </el-table-column>
            <el-table-column
              v-for="(item, index) in attributeData"
              :key="index"
@@ -104,9 +134,9 @@
            >
              <el-option
                v-for="item in fieldOption"
                :key="item.id"
                :key="item.field"
                :label="item.alias"
                :value="item.id"
                :value="item.field"
              />
            </el-select>
          </el-col>
@@ -141,11 +171,89 @@
        </span>
      </template>
    </el-dialog>
    <!-- ä¸‹è½½ä¿¡æ¯ -->
    <el-dialog
      v-model="downloaVisible"
      title="下载"
      width="30%"
    >
      <div
        class="spatialTable"
        style="max-height: 40vh;"
      >
        <el-table
          :data="downTable"
          @selection-change="handleSelectionChange"
          style="width: 100%; height: 73%;"
        >
          <el-table-column
            type="selection"
            width="55"
          />
          <el-table-column
            align="center"
            type="index"
            label="序号"
            width="70"
          />
          <el-table-column
            align="center"
            label="表名"
            prop="cnName"
          />
        </el-table>
        <el-form
          ref="downFormRef"
          class="setdownFrom"
          :model="downFrom"
          :rules="rules"
          label-width="180px"
        >
          <el-form-item
            label="请输入密码:"
            prop="pass"
          >
            <el-input
              type="password"
              v-model="downFrom.pass"
              autocomplete="off"
              show-password
              placeholder="请输入密码"
            ></el-input>
          </el-form-item>
          <el-form-item
            label="请再次输入密码:"
            prop="repass"
          >
            <el-input
              type="password"
              show-password
              v-model="downFrom.repass"
              autocomplete="off"
              placeholder="请再次输入密码"
            ></el-input>
          </el-form-item>
          <el-form-item>
            <el-button
              type="primary"
              size="small"
              @click="submitForm(downFormRef)"
            >提交</el-button>
            <el-button size="small">取消</el-button>
          </el-form-item>
        </el-form>
      </div>
    </el-dialog>
    <iframe
      id="Iframe1"
      src=""
      style="display: none; border: 0; padding: 0; height: 0; width: 0"
    ></iframe>
  </div>
</template>
<script lang="ts" setup>
window.encrypt = null;
import {
  ref,
  onMounted,
@@ -155,16 +263,27 @@
  defineEmits,
  nextTick,
} from "vue";
import menuTool from "@/assets/js/Map/menuTool";
import config from "@/assets/js/Map/config";
import { User, Lock, Plus, Refresh } from "@element-plus/icons-vue";
import { dataQuery_selectByPage, dataQuery_selectFields } from "@/api/api";
import { User, Lock, Plus, Refresh, Location } from "@element-plus/icons-vue";
import {
  dataQuery_selectByPage,
  dataQuery_selectFields,
  dataQuery_downloadDbData,
  sign_getPublicKey,
} from "@/api/api";
import { ElMessage } from "element-plus";
import store from "@/store";
import WKT from "terraformer-wkt-parser";
import type { FormInstance, FormRules } from "element-plus";
import { removeToken, getToken } from "@/utils/auth";
import JSEncrypt from "jsencrypt";
const emits = defineEmits(["SETspatialClose"]);
const setSpatialClose = () => {
  menuTool.setClearLocation("空间查询");
  emits("SETspatialClose", false);
};
var encrypt = new JSEncrypt();
const dialogVisible = ref(false);
const listData = ref({
  pageIndex: 1,
@@ -175,18 +294,142 @@
  filter: "",
  name: "",
});
const condOption = ref([]);
const fieldOption = ref([]);
const attributeData = ref([]);
const tableData = ref([]);
const menuList = ref([]);
const downTable = ref([]);
const formSql = ref({
  field: "",
  type: "",
  value: "",
  cut: "",
});
const downloaVisible = ref(false);
const isActive = ref(null);
const multipleSelection = ref([]);
const downFormRef = ref<FormInstance>();
const downFrom = ref({
  pass: "",
  repass: "",
});
const validatepass = (rule: any, value: any, callback: any) => {
  var passwordreg =
    /^(?![a-zA-Z]+$)(?![A-Z0-9]+$)(?![A-Z\W!@#$%^&*`~()\\-_+=,.?;<>]+$)(?![a-z0-9]+$)(?![a-z\W!@#$%^&*`~()\\-_+=,.?;<>]+$)(?![0-9\W!@#$%^&*`~()\\-_+=,.?;<>]+$)[a-zA-Z0-9\W!@#$%^&*`~()\\-_+=,.?;<>]{12,20}$/;
  if (!passwordreg.test(value)) {
    callback(new Error("密码必须由数字、字母、特殊字符组合,请输入13-20位"));
  } else {
    callback();
  }
};
const validaterepass = (rule: any, value: any, callback: any) => {
  var passwordreg =
    /^(?![a-zA-Z]+$)(?![A-Z0-9]+$)(?![A-Z\W!@#$%^&*`~()\\-_+=,.?;<>]+$)(?![a-z0-9]+$)(?![a-z\W!@#$%^&*`~()\\-_+=,.?;<>]+$)(?![0-9\W!@#$%^&*`~()\\-_+=,.?;<>]+$)[a-zA-Z0-9\W!@#$%^&*`~()\\-_+=,.?;<>]{12,20}$/;
  if (!passwordreg.test(value)) {
    callback(new Error("密码必须由数字、字母、特殊字符组合,请输入13-20位"));
  } else if (value != downFrom.value.pass) {
    callback(new Error("两次输入密码不一致,请重新输入"));
  } else {
    callback();
  }
};
const rules = reactive<FormRules<typeof downFrom>>({
  pass: [{ validator: validatepass, trigger: "blur" }],
  repass: [{ validator: validaterepass, trigger: "blur" }],
});
const submitForm = (formEl: FormInstance | undefined) => {
  if (!formEl) return;
  formEl.validate((valid) => {
    if (valid) {
      console.log("submit!");
      if (multipleSelection.value.length <= 0) {
        ElMessage.error("请选择要下载的表");
      } else {
        setDownLoadFrom();
      }
    } else {
      console.log("erro submit!");
      return false;
    }
  });
};
const getpublickey = async () => {
  const res = await sign_getPublicKey();
  if (res && res.code == 200) {
    encrypt.setPublicKey(res.result);
  }
};
const setDownLoadFrom = async () => {
  downloaVisible.value = false;
  var entities = [];
  var tabs = [];
  for (var i in multipleSelection.value) {
    var tab = multipleSelection.value[i].tab;
    if (tab.indexOf("moon:") > -1) {
      tab = tab.replaceAll("moon:", "");
    }
    tabs.push(tab);
    var entity = tab;
    if (entity.indexOf("_") > -1) {
      entity = entity.replaceAll("_", "");
    }
    entities.push(entity);
  }
  var obj = {
    pwd: encrypt.encrypt(downFrom.value.pass),
    filter: listData.value.filter,
    tabs: tabs,
    entities: entities,
    wkt: listData.value.wkt,
  };
  const data = await dataQuery_downloadDbData(obj);
  if (data.code != 200 && !data.result) {
    setClearDownload();
    return ElMessage.error("数据下载失败");
  }
  var token = getToken();
  var url =
    config.proxy +
    "/dataLib/downloadFile?token=" +
    token +
    "&guid=" +
    data.result +
    "&pwd=" +
    encodeURIComponent(downFrom.value.pass);
  $("#Iframe1").attr("src", url).click();
  setClearDownload();
};
const setClearDownload = () => {
  downFrom.value = {
    pass: "",
    repass: "",
  };
  multipleSelection.value = [];
  downTable.value = [];
};
const handleSelectionChange = (res) => {
  multipleSelection.value = res;
};
//下载
const setSpatialDownload = () => {
  downTable.value = menuList.value;
  downloaVisible.value = true;
};
//定位显示
const spaceLocation = (index, row) => {
  var geom = menuTool.decr(row.geom);
  var wkt = WKT.parse(geom);
  menuTool.spaceLocation(wkt);
};
const handleSizeChange = (res) => {
  listData.value.pageSize = res;
  setQueySpatialData();
@@ -196,7 +439,12 @@
  setQueySpatialData();
};
const setMenuListClick = (res) => {
  listData.value.name = res.name;
  if (res.tab && res.tab.indexOf("moon:") > -1) {
    listData.value.name = res.tab.replaceAll("moon:", "");
  } else {
    listData.value.name = res.tab;
  }
  isActive.value = res.id;
  listData.value.filter = "";
  listData.value.pageIndex = 1;
@@ -253,6 +501,7 @@
};
//查询列表数据
const setQueySpatialData = async () => {
  listData.value.name = listData.value.name.replaceAll("_", "");
  const data = await dataQuery_selectByPage(listData.value);
  if (data.code != 200) {
    return ElMessage.error("空间查询失败");
@@ -262,12 +511,22 @@
};
const setQueySpatialFields = async () => {
  const data = await dataQuery_selectFields({ name: listData.value.name });
  const data = await dataQuery_selectFields({
    ns: "mn",
    tab: listData.value.name,
  });
  if (data.code != 200) {
    return ElMessage.error("字段查询失败");
  }
  attributeData.value = data.result;
  fieldOption.value = data.result;
  var std = data.result.filter((res) => {
    if (res.showtype > 0) {
      return res;
    }
  });
  attributeData.value = std;
  fieldOption.value = std;
  conditionChange(data.result[0]);
  setQueySpatialData();
};
@@ -287,8 +546,7 @@
  formSql.value.value = "";
  formSql.value.field = res.field;
  formSql.value.cut = res.type;
  const type = res.type;
  var type = res.type;
  var std = [];
  if (type == "text" || type == "blob") {
    std = config.conditions[0];
@@ -324,17 +582,16 @@
  menuList.value = str;
  listData.value.wkt = store.state.spatialQueryData.wkt;
  var val_name = menuList.value[0].tab.replaceAll("moon:", "");
  val_name = val_name.replaceAll("_", "");
  listData.value.name = val_name;
  listData.value.name = menuList.value[0].tab.replaceAll("moon:", "");
  isActive.value = menuList.value[0].id;
  listData.value.hasGeom = 1;
  //
  setQueySpatialFields();
};
onMounted(() => {
  startQueryData();
  getpublickey();
});
</script>
@@ -400,57 +657,6 @@
    height: calc(100% - 10px);
    width: calc(80% - 20px);
    padding: 10px;
    .spatialTable {
      margin-top: 10px;
      width: 100%;
      height: 100%;
      position: relative;
      .el-table /deep/ .el-table__header-wrapper tr th {
        background-color: rgba(38, 47, 71, 1) !important;
        color: #d6e4ff;
      }
      // ä¿®æ”¹æ¯è¡Œæ ·å¼ï¼š
      .el-table /deep/ .el-table__row {
        background-color: rgba(38, 47, 71, 1) !important;
        color: #d6e4ff;
      }
      .el-table /deep/ .el-table__body tr.current-row > td {
        background-color: rgba(38, 47, 71, 1) !important;
      }
      .el-table /deep/ .el-table__body tr:hover > td {
        background-color: rgba(38, 47, 71, 1) !important;
      }
      // ä¿®æ”¹è¡¨æ ¼æ¯è¡Œè¾¹æ¡†çš„æ ·å¼ï¼š
      .el-table /deep/ td,
      .el-table /deep/ th.is-leaf {
        // border-bottom: 1px solid #409eff;
        // border-right: 1px solid #409eff;
      }
      .el-table /deep/ .el-table__cell {
        padding: 8px 0;
      }
      // è®¾ç½®è¡¨æ ¼æ¯è¡Œçš„高度:
      .el-table /deep/ .el-table__header tr,
      .el-table /deep/ .el-table__header th {
        height: 50px;
      }
      .el-table__body tr,
      .el-table__body td {
        height: 50px;
        padding: 0;
      }
      // è®¾ç½®è¡¨æ ¼è¾¹æ¡†é¢œè‰²ï¼š
      .el-table--border::after,
      .el-table--group::after {
        width: 0;
      }
      .el-table::before {
        height: 0;
      }
    }
  }
  .spatialBottom {
    padding: 10px;
@@ -518,6 +724,62 @@
  ::-webkit-scrollbar-track:hover {
    background: rgba(38, 47, 71, 0);
  }
  .spatialTable {
    margin-top: 10px;
    width: 100%;
    height: 100%;
    position: relative;
    .el-table /deep/ .el-table__header-wrapper tr th {
      background-color: rgba(38, 47, 71, 1) !important;
      color: #d6e4ff;
    }
    // ä¿®æ”¹æ¯è¡Œæ ·å¼ï¼š
    .el-table /deep/ .el-table__row {
      background-color: rgba(38, 47, 71, 1) !important;
      color: #d6e4ff;
    }
    .el-table /deep/ .el-table__body tr.current-row > td {
      background-color: rgba(38, 47, 71, 1) !important;
    }
    .el-table /deep/ .el-table__body tr:hover > td {
      background-color: rgba(38, 47, 71, 1) !important;
    }
    // ä¿®æ”¹è¡¨æ ¼æ¯è¡Œè¾¹æ¡†çš„æ ·å¼ï¼š
    .el-table /deep/ td,
    .el-table /deep/ th.is-leaf {
      // border-bottom: 1px solid #409eff;
      // border-right: 1px solid #409eff;
    }
    .el-table /deep/ .el-table__cell {
      padding: 8px 0;
    }
    // è®¾ç½®è¡¨æ ¼æ¯è¡Œçš„高度:
    .el-table /deep/ .el-table__header tr,
    .el-table /deep/ .el-table__header th {
      height: 50px;
    }
    .el-table__body tr,
    .el-table__body td {
      height: 50px;
      padding: 0;
    }
    // è®¾ç½®è¡¨æ ¼è¾¹æ¡†é¢œè‰²ï¼š
    .el-table--border::after,
    .el-table--group::after {
      width: 0;
    }
    .el-table::before {
      height: 0;
    }
  }
  .setdownFrom {
    margin-top: 10px;
    /deep/.el-form-item__label {
      color: #d6e4ff !important;
    }
  }
}
</style> 
<style lang="less"  >