DESKTOP-6LTVLN7\Liumouren 1 ماه پیش
والد
کامیت
99ae50c628
7فایلهای تغییر یافته به همراه286 افزوده شده و 77 حذف شده
  1. 36 2
      package-lock.json
  2. 1 0
      package.json
  3. 238 69
      src/components/wgn/controlPanel.vue
  4. 2 0
      src/main.js
  5. 3 0
      src/views/Wgn.vue
  6. 3 3
      src/views/Yxgl.vue
  7. 3 3
      src/views/yxgl/StatisticalAnalysis.vue

+ 36 - 2
package-lock.json

@@ -13,6 +13,7 @@
         "echarts": "^5.6.0",
         "element-plus": "^2.2.15",
         "vue": "^3.2.13",
+        "vue-json-editor": "^1.4.3",
         "vue-json-viewer": "^3.0.4",
         "vue-router": "^4.0.3",
         "vue3-lottie": "^3.3.1",
@@ -5667,7 +5668,6 @@
     },
     "node_modules/prettier": {
       "version": "2.8.8",
-      "dev": true,
       "license": "MIT",
       "optional": true,
       "bin": {
@@ -6450,7 +6450,6 @@
     },
     "node_modules/source-map": {
       "version": "0.6.1",
-      "dev": true,
       "license": "BSD-3-Clause",
       "engines": {
         "node": ">=0.10.0"
@@ -7039,6 +7038,41 @@
       "dev": true,
       "license": "MIT"
     },
+    "node_modules/vue-json-editor": {
+      "version": "1.4.3",
+      "resolved": "https://registry.npmmirror.com/vue-json-editor/-/vue-json-editor-1.4.3.tgz",
+      "integrity": "sha512-st9HdXBgCnyEmmfWrZQiKzp4KuYXzmYVUNDn5h6Fa18MrrGS1amnyUFyv7hQFsNBDW27B7BKkdGOqszYT1srAg==",
+      "dependencies": {
+        "vue": "^2.2.6"
+      },
+      "engines": {
+        "node": ">= 4.0.0",
+        "npm": ">= 3.0.0"
+      }
+    },
+    "node_modules/vue-json-editor/node_modules/@vue/compiler-sfc": {
+      "version": "2.7.16",
+      "resolved": "https://registry.npmmirror.com/@vue/compiler-sfc/-/compiler-sfc-2.7.16.tgz",
+      "integrity": "sha512-KWhJ9k5nXuNtygPU7+t1rX6baZeqOYLEforUPjgNDBnLicfHCoi48H87Q8XyLZOrNNsmhuwKqtpDQWjEFe6Ekg==",
+      "dependencies": {
+        "@babel/parser": "^7.23.5",
+        "postcss": "^8.4.14",
+        "source-map": "^0.6.1"
+      },
+      "optionalDependencies": {
+        "prettier": "^1.18.2 || ^2.0.0"
+      }
+    },
+    "node_modules/vue-json-editor/node_modules/vue": {
+      "version": "2.7.16",
+      "resolved": "https://registry.npmmirror.com/vue/-/vue-2.7.16.tgz",
+      "integrity": "sha512-4gCtFXaAA3zYZdTp5s4Hl2sozuySsgz4jy1EnpBHNfpMa9dK1ZCG7viqBPCwXtmgc8nHqUsAu3G4gtmXkkY3Sw==",
+      "deprecated": "Vue 2 has reached EOL and is no longer actively maintained. See https://v2.vuejs.org/eol/ for more details.",
+      "dependencies": {
+        "@vue/compiler-sfc": "2.7.16",
+        "csstype": "^3.1.0"
+      }
+    },
     "node_modules/vue-json-viewer": {
       "version": "3.0.4",
       "resolved": "https://mirrors.huaweicloud.com/repository/npm/vue-json-viewer/-/vue-json-viewer-3.0.4.tgz",

+ 1 - 0
package.json

@@ -12,6 +12,7 @@
     "echarts": "^5.6.0",
     "element-plus": "^2.2.15",
     "vue": "^3.2.13",
+    "vue-json-editor": "^1.4.3",
     "vue-json-viewer": "^3.0.4",
     "vue-router": "^4.0.3",
     "vue3-lottie": "^3.3.1",

+ 238 - 69
src/components/wgn/controlPanel.vue

@@ -33,34 +33,26 @@
         </div>
       </div>
       <el-divider></el-divider>
-      <div
-        v-if="
-          SceneValue &&
-          SceneRule[SceneValue] &&
-          (SceneRule[SceneValue].elementTypes.includes('point') ||
-            SceneRule[SceneValue].elementTypes.includes('polyline') ||
-            SceneRule[SceneValue].elementTypes.includes('polygon'))
-        "
-      >
+      <div>
         元素个数:{{
-          SceneValue && SceneRule[SceneValue] ? SceneRule[SceneValue].numberOf : ""
+          SceneValue && SceneRule[SceneValue] ? SceneRule[SceneValue].numberOf : "0"
         }}
       </div>
       <div>
         参数类型:{{
-          SceneValue && SceneRule[SceneValue] ? SceneRule[SceneValue].elementTypes : ""
+          SceneValue && SceneRule[SceneValue] ? SceneRule[SceneValue].elementTypes : "[]"
         }}
       </div>
       <div>
         接口地址:{{
-          SceneValue && SceneRule[SceneValue] ? SceneRule[SceneValue].apiUrl : ""
+          SceneValue && SceneRule[SceneValue] ? SceneRule[SceneValue].apiUrl : "/"
         }}
       </div>
     </div>
     <el-divider></el-divider>
     <div>
       <!-- 元素文本渲染和操作区域 -->
-      <el-tabs tab-position="left" style="height: calc(100vh - 370px)" class="demo-tabs">
+      <el-tabs tab-position="left" style="height: calc(100vh - 250px)" class="demo-tabs">
         <el-tab-pane label="入参">
           <div
             v-if="
@@ -83,15 +75,13 @@
             </el-upload>
           </div>
           <div v-if="SceneValue && SceneRule[SceneValue]">
-            <div
-              v-for="item in SceneRule[SceneValue].elementTypes"
-              :key="item"
-              style="margin-top: 0.5rem"
-            >
+            <div v-for="item in SceneRule[SceneValue].elementTypes" :key="item">
               <div
                 v-if="SceneValue && SceneRule[SceneValue] && SceneRule[SceneValue][item]"
+                style="margin: 0.5rem 0"
               >
                 {{ item }}:<el-select
+                  @change="handleSelectChange(item, $event)"
                   v-if="SceneRule[SceneValue][item]"
                   v-model="params[item]"
                   :placeholder="'请选择' + item"
@@ -115,25 +105,29 @@
               </div>
             </div>
           </div>
-          <json-viewer
-            v-if="
+          <div
+            class="vueJsonEditor_box"
+            v-show="
               SceneValue &&
               SceneRule[SceneValue] &&
               (SceneRule[SceneValue].elementTypes.includes('point') ||
                 SceneRule[SceneValue].elementTypes.includes('polyline') ||
                 SceneRule[SceneValue].elementTypes.includes('polygon'))
             "
-            :value="jsonData"
-            :editable="true"
-            :preview-mode="false"
-            style="
-              pointer-events: auto;
-              max-height: calc(100vh - 370px) !important;
-              overflow-y: scroll !important;
-            "
-            copyable
-            @input="handleJsonInput"
-          />
+          >
+            <div class="vueJsonEditor_tools">
+              <!-- <span @click="showToMap(jsonData)">渲染到地图中</span> -->
+              <span @click="copyJsonData(jsonData)">copy</span>
+            </div>
+            <vue-json-editor
+              v-model="jsonData"
+              :value="jsonData"
+              :show-btns="false"
+              :mode="'code'"
+              :lang="'zh'"
+            >
+            </vue-json-editor>
+          </div>
         </el-tab-pane>
         <el-tab-pane label="返回">
           <div
@@ -147,17 +141,30 @@
           >
             {{ backData.message || backData.error }}
           </div>
-          <json-viewer
-            :value="backData.content"
-            :editable="true"
-            :preview-mode="false"
-            style="
-              pointer-events: auto;
-              max-height: calc(100vh - 370px) !important;
-              overflow-y: scroll !important;
+
+          <div
+            class="vueJsonEditor_box"
+            v-show="
+              SceneValue &&
+              SceneRule[SceneValue] &&
+              (SceneRule[SceneValue].elementTypes.includes('point') ||
+                SceneRule[SceneValue].elementTypes.includes('polyline') ||
+                SceneRule[SceneValue].elementTypes.includes('polygon'))
             "
-            copyable
-        /></el-tab-pane>
+          >
+            <div class="vueJsonEditor_tools">
+              <!-- <span @click="showToMap(backData.content)">渲染到地图中</span> -->
+              <span @click="copyJsonData(backData.content)">copy</span>
+            </div>
+            <vue-json-editor
+              v-model="backData.content"
+              :value="backData.content"
+              :show-btns="false"
+              :mode="'code'"
+              :lang="'zh'"
+            >
+            </vue-json-editor></div
+        ></el-tab-pane>
       </el-tabs>
     </div>
     <!-- 绘制工具栏 -->
@@ -635,7 +642,7 @@ export default {
           // 元素类型
           elementTypes: ["polygon"],
           // 元素个数
-          minNumberOf: 2,
+          numberOf: 2,
           // 后台接口路径
           apiUrl: "/geometry/union",
         },
@@ -646,7 +653,7 @@ export default {
           // 元素类型
           elementTypes: ["polygon"],
           // 元素个数
-          minNumberOf: 2,
+          numberOf: 2,
           // 后台接口路径
           apiUrl: "/geometry/intersection",
         },
@@ -657,7 +664,7 @@ export default {
           // 元素类型
           elementTypes: ["polygon"],
           // 元素个数
-          minNumberOf: 2,
+          numberOf: 2,
           // 后台接口路径
           apiUrl: "/geometry/difference",
         },
@@ -972,6 +979,143 @@ export default {
     }
   },
   methods: {
+    // 将用户输入或后台返回的geojson渲染到地图中
+    showToMap(geojson) {
+      // 1. 清除所有地图中的元素
+      this.clearAllMap();
+      // 2. 将geojson添加到地图中
+      this.addToMap(geojson);
+    },
+    // 将geojson添加到地图中
+    addToMap(geojson) {
+      if (!geojson.features && geojson.geometry) {
+        const { type, coordinates } = geojson.geometry;
+        switch (type) {
+          case "Point":
+            // 点
+            this.addPoint(coordinates);
+            break;
+          case "LineString":
+            // 线
+            this.addLine(coordinates);
+            break;
+          case "Polygon":
+            // 面
+            this.addPolygon(coordinates);
+            break;
+          default:
+            break;
+        }
+      } else if (geojson.features) {
+        const features = geojson.features;
+        // 2. 遍历features,根据type添加到地图中
+        console.log("features", features);
+        features.forEach((feature) => {
+          const { type, coordinates } = feature.geometry;
+          switch (type) {
+            case "Point":
+              // 点
+              this.addPoint(coordinates);
+              break;
+            case "LineString":
+              // 线
+              this.addLine(coordinates);
+              break;
+            case "Polygon":
+              // 面
+              this.addPolygon(coordinates);
+              break;
+            default:
+              break;
+          }
+        });
+      }
+      setTimeout(() => {
+        viewer.scene.requestRender();
+      });
+    },
+    // 添加点到地图中
+    addPoint(coordinates) {
+      // 1. 解析点的坐标
+      console.log("addPoint coordinates", coordinates);
+      // 2. 创建点实体
+      const pointEntity = viewer.entities.add(
+        new SkyScenery.Entity({
+          name: "point",
+          position: SkyScenery.Cartesian3.fromDegrees(coordinates[0], coordinates[1]),
+          type: "point",
+        })
+      );
+      // 3. 将点实体添加到drawnEntities中
+      this.drawnEntities.push(pointEntity);
+    },
+    // 添加线到地图中
+    addLine(coordinates) {
+      // 1. 解析线的坐标
+      console.log("addLine coordinates", [...coordinates]);
+      // 2. 创建线实体
+      const lineEntity = viewer.entities.add({
+        polyline: {
+          show: true,
+          positions: SkyScenery.Cartesian3.fromDegreesArray([...coordinates[0]]),
+          material: SkyScenery.Color.WHITE.withAlpha(0.5),
+          width: 3,
+        },
+      });
+      // 3. 将线实体添加到drawnEntities中
+      this.drawnEntities.push(lineEntity);
+    },
+    // 添加面到地图中
+    addPolygon(coordinates) {
+      // 1. 解析面的坐标
+      console.log("addPolygon coordinates", [...coordinates[0]]);
+      // 创建当前实体(实时渲染)
+      const polygonEntity = viewer.entities.add(
+        new SkyScenery.Entity({
+          name: " polygon",
+          polygon: {
+            hierarchy: {
+              positions: SkyScenery.Cartesian3.fromDegreesArray([...coordinates[0]]),
+            },
+            heightReference: SkyScenery.HeightReference.CLAMP_TO_GROUND,
+            material: SkyScenery.Color.CYAN.withAlpha(0.5),
+          },
+        })
+      );
+      // 3. 将面实体添加到drawnEntities中
+      this.drawnEntities.push(polygonEntity);
+      viewer.scene.requestRender();
+    },
+    handleSelectChange(item, value) {
+      this.jsonData[item] = value;
+    },
+    // 复制json数据
+    copyJsonData(data) {
+      let textarea = document.createElement("textarea");
+      try {
+        textarea.value = JSON.stringify(data, null, 2);
+        document.body.appendChild(textarea);
+        // 3. 选中文本(兼容移动端)
+        textarea.select();
+        // 兼容移动端:设置选择范围覆盖全部文本
+        textarea.setSelectionRange(0, textarea.value.length);
+        // 4. 执行复制命令
+        const isSuccess = document.execCommand("copy");
+        if (isSuccess) {
+          this.$message({
+            message: "复制成功",
+            type: "success",
+          });
+        }
+      } catch (err) {
+        this.$message({
+          message: err,
+          type: "error",
+        });
+      } finally {
+        document.body.removeChild(textarea);
+      }
+    },
     handleExceed(file) {
       this.$message({
         message: "最多只能上传一个文件",
@@ -984,9 +1128,6 @@ export default {
     uploadRemove() {
       this.currentFile = null;
     },
-    handleJsonInput(value) {
-      this.jsonData = JSON.parse(value);
-    },
     handleChange(emit) {
       this.params.unit = "";
       this.currentFile = null;
@@ -1111,7 +1252,7 @@ export default {
                 polyline: {
                   show: true,
                   positions: tempPositions,
-                  material: SkyScenery.Color.BLUE.withAlpha(0.5),
+                  material: SkyScenery.Color.WHITE.withAlpha(0.5),
                   width: 3,
                 },
               });
@@ -1143,7 +1284,7 @@ export default {
               polyline: {
                 show: true,
                 positions: [...that.currentPositions],
-                material: SkyScenery.Color.BLUE,
+                material: SkyScenery.Color.RED,
                 width: 3,
               },
             });
@@ -1168,7 +1309,7 @@ export default {
               polyline: {
                 show: true,
                 positions: [...that.currentPositions],
-                material: SkyScenery.Color.BLUE,
+                material: SkyScenery.Color.RED,
                 width: 3,
               },
             });
@@ -1217,18 +1358,15 @@ export default {
               endPosition,
               that.currentPositions[0],
             ];
-
             // 更新临时预览实体
             if (!that.tempEntity) {
               that.tempEntity = viewer.entities.add({
                 polygon: {
                   show: true,
                   hierarchy: new SkyScenery.PolygonHierarchy(tempPositions),
-                  material: new SkyScenery.ColorMaterialProperty(
-                    new SkyScenery.Color(0, 0, 1, 0.2)
-                  ),
+                  material: SkyScenery.Color.RED.withAlpha(0.3),
                   outline: true,
-                  outlineColor: SkyScenery.Color.BLUE.withAlpha(0.5),
+                  outlineColor: SkyScenery.Color.RED.withAlpha(0.8),
                   outlineWidth: 2,
                 },
               });
@@ -1275,9 +1413,7 @@ export default {
               polygon: {
                 show: true,
                 hierarchy: new SkyScenery.PolygonHierarchy(closedPositions),
-                material: new SkyScenery.ColorMaterialProperty(
-                  new SkyScenery.Color(0, 0, 1, 0.3)
-                ),
+                material: SkyScenery.Color.RED.withAlpha(0.5),
                 outline: true,
                 outlineColor: SkyScenery.Color.BLUE,
                 outlineWidth: 2,
@@ -1317,9 +1453,7 @@ export default {
         polygon: {
           show: true,
           hierarchy: new SkyScenery.PolygonHierarchy(closedPositions),
-          material: new SkyScenery.ColorMaterialProperty(
-            new SkyScenery.Color(0, 0, 1, 0.3)
-          ),
+          material: SkyScenery.Color.RED.withAlpha(0.5),
           outline: true,
           outlineColor: SkyScenery.Color.BLUE,
           outlineWidth: 2,
@@ -1624,7 +1758,6 @@ export default {
         requestData.outPrj = this.params.outPrj;
       }
       this.jsonData = requestData;
-      return requestData;
     },
     // 发送几何数据到后台接口
     sendGeometriesToBackend() {
@@ -1636,7 +1769,7 @@ export default {
         this.SceneRule[this.SceneValue].elementTypes.includes("polyline") ||
         this.SceneRule[this.SceneValue].elementTypes.includes("polygon")
       ) {
-        requestData = this.changeGeometries();
+        requestData = this.jsonData;
       } else {
         requestData = new FormData();
         this.SceneRule[this.SceneValue].elementTypes.forEach((key) => {
@@ -1707,8 +1840,13 @@ export default {
         });
     },
 
-    // 清除所有绘制的元素
+    // 清除所有绘制的元素,并更新geometries
     clearAll() {
+      this.clearAllMap();
+      this.changeGeometries();
+    },
+    // 清除所有绘制的元素
+    clearAllMap() {
       // 移除所有实体
       this.drawnEntities.forEach((entity) => {
         viewer.entities.remove(entity);
@@ -1717,10 +1855,8 @@ export default {
       // 清空数组
       this.drawnEntities = [];
       this.geometries = [];
-      this.changeGeometries();
       // 取消当前绘制模式
       this.deactivateDraw();
-
       console.log("已清除所有绘制的元素");
     },
   },
@@ -1739,7 +1875,7 @@ export default {
   position: fixed;
   top: 0px;
   right: 0;
-  background: #fff;
+  background: #08224a;
 }
 
 // 绘制按钮区域
@@ -1748,7 +1884,7 @@ export default {
   top: 10px;
   left: -120px;
   z-index: 1000;
-  background: rgba(255, 255, 255, 0.9);
+  background: #08224a;
   border-radius: 8px;
   padding: 3px 5px;
   box-shadow: 0 2px 10px rgba(0, 0, 0, 0.2);
@@ -1767,7 +1903,7 @@ export default {
 }
 
 .tool-item:hover {
-  background: #f0f0f0;
+  background: #ffffff32;
 }
 
 .tool-item.active {
@@ -1779,4 +1915,37 @@ export default {
   align-items: center;
   justify-content: space-between;
 }
+.vueJsonEditor_box {
+  width: 100%;
+  height: 100%;
+  position: relative;
+}
+.vueJsonEditor_tools {
+  position: absolute;
+  top: 8px;
+  right: 10px;
+  font-size: 14px;
+  z-index: 1;
+  color: #fff;
+}
+.vueJsonEditor_tools span {
+  padding: 2px 5px;
+  opacity: 0.8;
+  cursor: pointer;
+  border: 1px solid #ffffff00;
+  border-radius: 2px;
+  margin-right: 5px;
+  &:hover {
+    background-color: rgba(255, 255, 255, 0.2);
+    border-color: rgba(255, 255, 255, 0.4);
+  }
+}
+:deep(.ace_editor) {
+  height: 600px !important;
+  max-height: calc(100vh - 300px) !important;
+}
+:deep(.jsoneditor-modes),
+:deep(.jsoneditor-poweredBy) {
+  display: none;
+}
 </style>

+ 2 - 0
src/main.js

@@ -17,6 +17,8 @@ initApp.use(ElementPlus, {
 import * as ElementPlusIconsVue from '@element-plus/icons-vue'
 import JsonViewer from 'vue-json-viewer'
 initApp.component('JsonViewer', JsonViewer)
+import VueJsonEditor from 'vue-json-editor'
+initApp.component('VueJsonEditor', VueJsonEditor)
 
 for (const [key, component] of Object.entries(ElementPlusIconsVue)) {
     initApp.component(key, component)

+ 3 - 0
src/views/Wgn.vue

@@ -239,6 +239,9 @@ export default {
     align-items: center;
     width: -webkit-fill-available;
     justify-content: center;
+    .input-with-select {
+      background: #08224a;
+    }
   }
   &_table {
     margin-top: 50px;

+ 3 - 3
src/views/Yxgl.vue

@@ -37,7 +37,7 @@
       class="viewBox"
       :style="{
         width: isCollapse ? 'calc(100vw - 60px)' : 'calc(100% - 200px)',
-        background: menuActive == 'StatisticalAnalysis' ? '#FFF' : '#FFF',
+        background: menuActive == 'StatisticalAnalysis' ? '#08224a' : '#08224a',
         overflowY: menuActive == 'StatisticalAnalysis' ? 'auto' : 'hidden',
       }"
     >
@@ -112,7 +112,7 @@ export default {
   width: 200px;
   height: calc(100vh - 120px);
   margin: 0;
-  //   background: #08224a;
+  background: #08224a;
 }
 .viewBox {
   width: calc(100vw - 200px);
@@ -125,6 +125,6 @@ export default {
 iframe {
   width: 100%;
   height: calc(100% - 10px);
-  background: #fff;
+  background: #08224a;
 }
 </style>

+ 3 - 3
src/views/yxgl/StatisticalAnalysis.vue

@@ -595,7 +595,7 @@ export default {
     width: calc(25% - 56px);
     border-radius: 5px;
     padding: 20px 18px;
-    background: #ffffff;
+    background: #00000032;
     box-shadow: 0 0 15px 1px rgba(0, 0, 0, 0.15);
   }
 
@@ -603,7 +603,7 @@ export default {
     width: 100%;
     border-radius: 5px;
     padding: 20px 18px;
-    background: #ffffff;
+    background: #00000032;
     box-shadow: 0 0 15px 1px rgba(0, 0, 0, 0.15);
   }
 
@@ -611,7 +611,7 @@ export default {
     width: calc(100% - 36px);
     border-radius: 5px;
     padding: 20px 18px;
-    background: #ffffff;
+    background: #00000032;
     position: relative;
     flex-direction: column;
     box-shadow: 0 0 15px 1px rgba(0, 0, 0, 0.15);