ソースを参照

地图服务发布,增加数据下载

wandequan 2 年 前
コミット
608a943a9a

+ 51 - 0
package copy.json

@@ -0,0 +1,51 @@
+{
+  "name": "digital-twin-base-ui",
+  "version": "0.1.0",
+  "private": true,
+  "scripts": {
+    "serve": "vue-cli-service serve --mode dev",
+    "serve:prod": "vue-cli-service serve --mode prod",
+    "build": "vue-cli-service build --mode dev",
+    "build:prod": "vue-cli-service build --mode prod",
+    "lint": "vue-cli-service lint"
+  },
+  "dependencies": {
+    "@icon-park/vue-next": "^1.4.2",
+    "@kangc/v-md-editor": "^2.3.15",
+    "axios": "^1.1.3",
+    "copy-webpack-plugin": "^11.0.0",
+    "core-js": "^3.8.3",
+    "dayjs": "^1.11.5",
+    "echarts": "^5.4.0",
+    "element-plus": "^2.2.18",
+    "element-resize-detector": "^1.2.4",
+    "highlight": "^0.2.4",
+    "js-file-download": "^0.4.12",
+    "node-polyfill-webpack-plugin": "^2.0.1",
+    "node-sass": "^7.0.3",
+    "ol": "^7.1.0",
+    "path": "^0.12.7",
+    "qs": "^6.11.0",
+    "vue": "^3.2.13",
+    "vue-clipboard3": "^2.0.0",
+    "vue-json-viewer": "^3.0.4",
+    "vue-resource": "^1.5.3",
+    "vue-router": "^4.0.3",
+    "vuex": "^4.0.0",
+    "vuex-persistedstate": "^4.1.0",
+    "webpack": "^5.74.0"
+  },
+  "devDependencies": {
+    "@babel/core": "^7.12.16",
+    "@babel/eslint-parser": "^7.12.16",
+    "@vue/cli-plugin-babel": "~5.0.0",
+    "@vue/cli-plugin-eslint": "~5.0.0",
+    "@vue/cli-plugin-router": "~5.0.0",
+    "@vue/cli-plugin-vuex": "~5.0.0",
+    "@vue/cli-service": "~5.0.0",
+    "eslint": "^7.32.0",
+    "eslint-plugin-vue": "^8.0.3",
+    "sass": "^1.32.7",
+    "sass-loader": "^12.6.0"
+  }
+}

ファイルの差分が大きいため隠しています
+ 216 - 220
package-lock.json


+ 3 - 4
package.json

@@ -21,8 +21,7 @@
     "element-resize-detector": "^1.2.4",
     "highlight": "^0.2.4",
     "js-file-download": "^0.4.12",
-    "node-polyfill-webpack-plugin": "^2.0.1",
-    "node-sass": "^7.0.3",
+    "node-polyfill-webpack-plugin": "^2.0.1", 
     "ol": "^7.1.0",
     "path": "^0.12.7",
     "qs": "^6.11.0",
@@ -45,7 +44,7 @@
     "@vue/cli-service": "~5.0.0",
     "eslint": "^7.32.0",
     "eslint-plugin-vue": "^8.0.3",
-    "sass": "^1.32.7",
-    "sass-loader": "^12.6.0"
+    "less": "^4.0.0",
+    "less-loader": "^8.0.0"
   }
 }

+ 9 - 0
public/config.js

@@ -10,8 +10,17 @@ var systemConfig = {
         'meta': '5', //元数据菜单ID
         'iot': '6', //物联感知数据菜单ID
     },
+
+
+    mapCenter: {
+        lon: 112.52475547556074,
+        lat: 37.86090299387082
+    },
+    proxyUrl: 'http://121.43.55.7:10011/proxy?servertype={PROXYURL}&token='
 }
 
+var proxyService = "http://121.43.55.7:10011/proxy";
+
 // SkyScenery插件配置
 var SkySceneryConfig = {
     userName: "user001",

+ 2 - 1
src/App.vue

@@ -15,7 +15,7 @@ export default {
 }
 </script>
 
-<style lang="scss">
+<style lang="less">
 * {
   margin: 0;
   padding: 0;
@@ -34,3 +34,4 @@ html,body {
 }
 
 </style>
+2

+ 25 - 0
src/api/data/publish.js

@@ -0,0 +1,25 @@
+import request from "@/utils/request";
+
+// 增加数据
+const addItem = (params) => {
+    return request.postForm(proxyService + '/proxy_api/config/add', params)
+}
+// 删除数据
+const delItem = (params) => {
+    return request.deleteForm(proxyService + '/proxy_api/config/delete', params)
+}
+// 修改数据
+const updateItem = (params) => {
+    return request.postForm(proxyService + '/proxy_api/config/update', params)
+}
+// 获取列表数据
+const getList = (params) => {
+    return request.postForm(proxyService + '/proxy_api/config/getByType', params)
+}
+
+export default {
+    addItem,
+    delItem,
+    updateItem,
+    getList
+}

+ 116 - 0
src/components/dataManage/dataDetail/BusinessDownload.vue

@@ -0,0 +1,116 @@
+<template>
+  <el-dialog
+    v-if="isShow"
+    :model-value="isShow"
+    :title="dialogTitle"
+    :width="500"
+    :close-on-click-modal="false"
+    :before-close="handleClose"
+  >
+    <div class="download">
+      <el-form
+        ref="form"
+        :model="formData"
+        :rules="formDataRules"
+        style="margin: 0 15px"
+        :label-width="110"
+      >
+        <el-form-item label="下载范围:">
+          <el-radio-group v-model="formData.radio">
+            <el-radio :label="1">全部</el-radio>
+            <el-radio :label="2">当前已选中的数据</el-radio>
+          </el-radio-group>
+        </el-form-item>
+        <el-form-item
+          label="下载类型:"
+          prop="downloadType"
+        >
+          <el-select
+            v-model="formData.downloadType"
+            class="m-2"
+            placeholder="请选择下载类型"
+            size="large"
+          >
+            <el-option
+              v-for="item in downloadTypeOptions"
+              :key="item.value"
+              :label="item.label"
+              :value="item.value"
+            />
+          </el-select>
+        </el-form-item>
+      </el-form>
+    </div>
+    <template #footer>
+      <el-button
+        type="primary"
+        @click="download"
+      >下载</el-button>
+    </template>
+  </el-dialog>
+</template>
+
+<script>
+export default {
+  data() {
+    return {
+      downloadTypeOptions: [
+        {
+          value: "1",
+          label: "Excel",
+        },
+        {
+          value: "2",
+          label: "Shpfile",
+        },
+        {
+          value: "3",
+          label: "GeoJSON",
+        },
+      ],
+
+      formData: {
+        radio: 1,
+        downloadType: "",
+      },
+      formDataRules: {
+        downloadType: [
+          { required: true, message: "请选择下载类型", trigger: "change" },
+        ],
+      },
+    };
+  },
+  props: {
+    dialogTitle: String,
+    isShow: Boolean,
+    currCategory: Object,
+    close: Function,
+  },
+  watch: {},
+  mounted() {
+    console.log(this.currCategory);
+  },
+
+  methods: {
+    handleClose() {
+      this.close();
+    },
+    download() {
+      let app = this;
+      app.$refs.form.validate((valid) => {
+        if (valid) {
+        } else {
+          app.$message({ message: "请完善数据", type: "warning" });
+        }
+      });
+    },
+  },
+};
+</script>
+
+<style scope>
+.download {
+  width: 100%;
+  height: 100%;
+}
+</style>

+ 116 - 0
src/components/dataManage/dataDetail/IotDataDownload.vue

@@ -0,0 +1,116 @@
+<template>
+  <el-dialog
+    v-if="isShow"
+    :model-value="isShow"
+    :title="dialogTitle"
+    :width="500"
+    :close-on-click-modal="false"
+    :before-close="handleClose"
+  >
+    <div class="download">
+      <el-form
+        ref="form"
+        :model="formData"
+        :rules="formDataRules"
+        style="margin: 0 15px"
+        :label-width="110"
+      >
+        <el-form-item label="下载范围:">
+          <el-radio-group v-model="formData.radio">
+            <el-radio :label="1">全部</el-radio>
+            <el-radio :label="2">当前已选中的数据</el-radio>
+          </el-radio-group>
+        </el-form-item>
+        <el-form-item
+          label="下载类型:"
+          prop="downloadType"
+        >
+          <el-select
+            v-model="formData.downloadType"
+            class="m-2"
+            placeholder="请选择下载类型"
+            size="large"
+          >
+            <el-option
+              v-for="item in downloadTypeOptions"
+              :key="item.value"
+              :label="item.label"
+              :value="item.value"
+            />
+          </el-select>
+        </el-form-item>
+      </el-form>
+    </div>
+    <template #footer>
+      <el-button
+        type="primary"
+        @click="download"
+      >下载</el-button>
+    </template>
+  </el-dialog>
+</template>
+
+<script>
+export default {
+  data() {
+    return {
+      downloadTypeOptions: [
+        {
+          value: "1",
+          label: "Excel",
+        },
+        {
+          value: "2",
+          label: "Shpfile",
+        },
+        {
+          value: "3",
+          label: "GeoJSON",
+        },
+      ],
+
+      formData: {
+        radio: 1,
+        downloadType: "",
+      },
+      formDataRules: {
+        downloadType: [
+          { required: true, message: "请选择下载类型", trigger: "change" },
+        ],
+      },
+    };
+  },
+  props: {
+    dialogTitle: String,
+    isShow: Boolean,
+    currCategory: Object,
+    close: Function,
+  },
+  watch: {},
+  mounted() {
+    console.log(this.currCategory);
+  },
+
+  methods: {
+    handleClose() {
+      this.close();
+    },
+    download() {
+      let app = this;
+      app.$refs.form.validate((valid) => {
+        if (valid) {
+        } else {
+          app.$message({ message: "请完善数据", type: "warning" });
+        }
+      });
+    },
+  },
+};
+</script>
+
+<style scope>
+.download {
+  width: 100%;
+  height: 100%;
+}
+</style>

+ 116 - 0
src/components/dataManage/dataDetail/MetaDataDownload.vue

@@ -0,0 +1,116 @@
+<template>
+  <el-dialog
+    v-if="isShow"
+    :model-value="isShow"
+    :title="dialogTitle"
+    :width="500"
+    :close-on-click-modal="false"
+    :before-close="handleClose"
+  >
+    <div class="download">
+      <el-form
+        ref="form"
+        :model="formData"
+        :rules="formDataRules"
+        style="margin: 0 15px"
+        :label-width="110"
+      >
+        <el-form-item label="下载范围:">
+          <el-radio-group v-model="formData.radio">
+            <el-radio :label="1">全部</el-radio>
+            <el-radio :label="2">当前已选中的数据</el-radio>
+          </el-radio-group>
+        </el-form-item>
+        <el-form-item
+          label="下载类型:"
+          prop="downloadType"
+        >
+          <el-select
+            v-model="formData.downloadType"
+            class="m-2"
+            placeholder="请选择下载类型"
+            size="large"
+          >
+            <el-option
+              v-for="item in downloadTypeOptions"
+              :key="item.value"
+              :label="item.label"
+              :value="item.value"
+            />
+          </el-select>
+        </el-form-item>
+      </el-form>
+    </div>
+    <template #footer>
+      <el-button
+        type="primary"
+        @click="download"
+      >下载</el-button>
+    </template>
+  </el-dialog>
+</template>
+
+<script>
+export default {
+  data() {
+    return {
+      downloadTypeOptions: [
+        {
+          value: "1",
+          label: "Excel",
+        },
+        {
+          value: "2",
+          label: "Shpfile",
+        },
+        {
+          value: "3",
+          label: "GeoJSON",
+        },
+      ],
+
+      formData: {
+        radio: 1,
+        downloadType: "",
+      },
+      formDataRules: {
+        downloadType: [
+          { required: true, message: "请选择下载类型", trigger: "change" },
+        ],
+      },
+    };
+  },
+  props: {
+    dialogTitle: String,
+    isShow: Boolean,
+    currCategory: Object,
+    close: Function,
+  },
+  watch: {},
+  mounted() {
+    console.log(this.currCategory);
+  },
+
+  methods: {
+    handleClose() {
+      this.close();
+    },
+    download() {
+      let app = this;
+      app.$refs.form.validate((valid) => {
+        if (valid) {
+        } else {
+          app.$message({ message: "请完善数据", type: "warning" });
+        }
+      });
+    },
+  },
+};
+</script>
+
+<style scope>
+.download {
+  width: 100%;
+  height: 100%;
+}
+</style>

+ 115 - 0
src/components/dataManage/dataDetail/TwoDimensionalDownload.vue

@@ -0,0 +1,115 @@
+<template>
+  <el-dialog
+    v-if="isShow"
+    :model-value="isShow"
+    :title="dialogTitle"
+    :width="500"
+    :close-on-click-modal="false"
+    :before-close="handleClose"
+  >
+    <div class="download">
+      <el-form
+        ref="form"
+        :model="formData"
+        :rules="formDataRules"
+        style="margin: 0 15px"
+        :label-width="110"
+      >
+        <el-form-item label="下载范围:">
+          <el-radio-group v-model="formData.radio">
+            <el-radio :label="1">全部</el-radio>
+            <el-radio :label="2">当前已选中的数据</el-radio>
+          </el-radio-group>
+        </el-form-item>
+        <el-form-item
+          label="下载类型:"
+          prop="downloadType"
+        >
+          <el-select
+            v-model="formData.downloadType"
+            class="m-2"
+            placeholder="请选择下载类型"
+            size="large"
+          >
+            <el-option
+              v-for="item in downloadTypeOptions"
+              :key="item.value"
+              :label="item.label"
+              :value="item.value"
+            />
+          </el-select>
+        </el-form-item>
+      </el-form>
+    </div>
+    <template #footer>
+      <el-button
+        type="primary"
+        @click="download"
+      >下载</el-button>
+    </template>
+  </el-dialog>
+</template>
+
+<script>
+export default {
+  data() {
+    return {
+      downloadTypeOptions: [
+        {
+          value: "1",
+          label: "Excel",
+        },
+        {
+          value: "2",
+          label: "Shpfile",
+        },
+        {
+          value: "3",
+          label: "GeoJSON",
+        },
+      ],
+
+      formData: {
+        radio: 1,
+        downloadType: "",
+      },
+
+      formDataRules: {
+        downloadType: [
+          { required: true, message: "请选择下载类型", trigger: "change" },
+        ],
+      },
+    };
+  },
+  props: {
+    dialogTitle: String,
+    isShow: Boolean,
+    currCategory: Object,
+    close: Function,
+  },
+  watch: {},
+  mounted() {},
+
+  methods: {
+    handleClose() {
+      this.close();
+    },
+    download() {
+      let app = this;
+      app.$refs.form.validate((valid) => {
+        if (valid) {
+        } else {
+          app.$message({ message: "请完善数据", type: "warning" });
+        }
+      });
+    },
+  },
+};
+</script>
+
+<style scope>
+.download {
+  width: 100%;
+  height: 100%;
+}
+</style>

+ 12 - 0
src/components/dataManage/dataShow/BusinessData.vue

@@ -4,6 +4,7 @@
   <div v-if="currCategory.id && currCategory.id !== ''" class="data">
     <el-button v-if="auth" type="primary" @click="addDataClick">录入业务数据</el-button>
     <el-button v-if="auth" type="warning" @click="batchDelete">批量删除</el-button>
+    <el-button v-if="auth" type="primary" @click="openDownload">数据下载</el-button><br>
     <div class="operation">
       <el-form :model="filterForm" :inline="true">
         <el-form-item label="标题:" style="width: 22%">
@@ -90,11 +91,13 @@
   </div>
 
   <BusinessDataDetail v-if="isDetailShow" :is-show="isDetailShow" :dialog-title="dialogTitle" :item="currRow" :curr-category="currCategory" :close="handleDetailShow"></BusinessDataDetail>
+  <BusinessDownload v-if="isDownloadShow" :is-show="isDownloadShow" :dialog-title="'数据下载'" :item="currRow" :curr-category="currCategory" :close="handleDownloadShow"></BusinessDownload>
 </template>
 
 <script>
 import api from '@/api/data/BusinessData'
 import BusinessDataDetail from "@/components/dataManage/dataDetail/BusinessDataDetail";
+import BusinessDownload from "@/components/dataManage/dataDetail/BusinessDownload";
 import CategoryMenu from "@/components/dataManage/CategoryMenu";
 
 export default {
@@ -118,10 +121,12 @@ export default {
       },
 
       isDetailShow: false,
+      isDownloadShow:false,
     }
   },
   components: {
     BusinessDataDetail,
+    BusinessDownload,
     CategoryMenu,
   },
   created() {
@@ -290,6 +295,13 @@ export default {
         })
       })
     },
+    // 开启业务下载面板
+    openDownload(){
+      this.isDownloadShow = true
+    },
+    handleDownloadShow(){
+      this.isDownloadShow = false
+    }
   }
 }
 </script>

+ 15 - 1
src/components/dataManage/dataShow/IotData.vue

@@ -5,6 +5,7 @@
     <el-button v-if="auth" type="primary" @click="addDataClick">录入物联感知数据</el-button>
     <el-button v-if="auth" type="warning" @click="batchDelete">批量删除</el-button>
     <el-button v-if="auth && isAllView" type="info" @click="handleAllGltfView">全部预览</el-button>
+    <el-button v-if="auth" type="primary" @click="openDownload">数据下载</el-button><br>
     <div class="operation">
       <el-form :model="filterForm" :inline="true">
         <el-form-item label="标题:" style="width: 22%">
@@ -122,11 +123,13 @@
              :type="21"
              :close="()=>{this.isMapShow=false}">
   </CesiumMap>
+  <IotDataDownload v-if="isDownloadShow" :is-show="isDownloadShow" :dialog-title="'数据下载'" :item="currRow" :curr-category="currCategory" :close="handleDownloadShow"></IotDataDownload>
 </template>
 
 <script>
 import api from '@/api/data/IotData'
 import IotDataDetail from "@/components/dataManage/dataDetail/IotDataDetail";
+import IotDataDownload from "@/components/dataManage/dataDetail/IotDataDownload";
 import CategoryMenu from "@/components/dataManage/CategoryMenu";
 import CesiumMap from "@/components/map/CesiumMap.vue";
 import ModelType from "@/static/datas/ModelType.json";
@@ -157,11 +160,14 @@ export default {
       isAllView: false,
       isMapShow: false,
       mapUrl: '',
-      extraParams: {}
+      extraParams: {},
+
+      isDownloadShow:false,
     }
   },
   components: {
     IotDataDetail,
+    IotDataDownload,
     CategoryMenu,
     CesiumMap,
   },
@@ -338,6 +344,14 @@ export default {
       this.extraParams.lon = this.tableData[0].lon
       this.extraParams.lat = this.tableData[0].lat
       this.isMapShow = true;
+    },
+
+    // 开启业务下载面板
+    openDownload(){
+      this.isDownloadShow = true
+    },
+    handleDownloadShow(){
+      this.isDownloadShow = false
     }
   }
 }

+ 12 - 0
src/components/dataManage/dataShow/MetaData.vue

@@ -4,6 +4,7 @@
   <div class="data" v-if="currCategory.id && currCategory.id!==''">
     <el-button v-if="auth"  type="primary" @click="addDataClick">录入元数据</el-button>
     <el-button v-if="auth"  type="warning" @click="batchDelete">批量删除</el-button>
+    <el-button v-if="auth" type="primary" @click="openDownload">数据下载</el-button><br>
     <div class="operation">
       <el-form :model="filterForm" :inline="true">
         <el-form-item label="标题:" style="width: 22%">
@@ -89,11 +90,13 @@
   </div>
 
   <MetaDataDetail v-if="isDetailShow" :is-show="isDetailShow" :dialog-title="dialogTitle" :item="currRow" :curr-category="currCategory" :close="handleDetailShow"></MetaDataDetail>
+  <MetaDataDownload v-if="isDownloadShow" :is-show="isDownloadShow" :dialog-title="'数据下载'" :item="currRow" :curr-category="currCategory" :close="handleDownloadShow"></MetaDataDownload>
 </template>
 
 <script>
 import api from '@/api/data/MetaData'
 import MetaDataDetail from "@/components/dataManage/dataDetail/MetaDataDetail";
+import MetaDataDownload from "@/components/dataManage/dataDetail/MetaDataDownload";
 import menuApi from "@/api/data/MenuData";
 import CategoryMenu from "@/components/dataManage/CategoryMenu";
 
@@ -117,10 +120,12 @@ export default {
       },
 
       isDetailShow: false,
+      isDownloadShow:false,
     }
   },
   components: {
     MetaDataDetail,
+    MetaDataDownload,
     CategoryMenu,
   },
   created() {
@@ -265,6 +270,13 @@ export default {
         })
       })
     },
+    // 开启业务下载面板
+    openDownload(){
+      this.isDownloadShow = true
+    },
+    handleDownloadShow(){
+      this.isDownloadShow = false
+    }
   }
 }
 </script>

+ 13 - 1
src/components/dataManage/dataShow/TwoDimensionalData.vue

@@ -4,7 +4,8 @@
 
   <div v-if="currCategory.id && currCategory.id!==''" class="data">
     <el-button v-if="auth" type="primary" @click="addDataClick">录入二维数据</el-button>
-    <el-button v-if="auth" type="warning" @click="batchDelete">批量删除</el-button><br>
+    <el-button v-if="auth" type="warning" @click="batchDelete">批量删除</el-button>
+    <el-button v-if="auth" type="primary" @click="openDownload">数据下载</el-button><br>
     <div class="operation">
       <el-form :model="filterForm" :inline="true">
         <el-form-item label="标题:" style="width: 22%">
@@ -91,12 +92,14 @@
   </div>
 
   <TwoDimensionalDataDetail v-if="isDetailShow" :is-show="isDetailShow" :dialog-title="dialogTitle" :item="currRow" :curr-category="currCategory" :close="handleDetailShow"></TwoDimensionalDataDetail>
+  <TwoDimensionalDownload v-if="isDownloadShow" :is-show="isDownloadShow" :dialog-title="'数据下载'" :item="currRow" :curr-category="currCategory" :close="handleDownloadShow"></TwoDimensionalDownload>
 </template>
 
 <script>
 import api from '@/api/data/TwoDimensionalData'
 import mockData from '@/static/files/mockData'
 import TwoDimensionalDataDetail from "@/components/dataManage/dataDetail/TwoDimensionalDataDetail";
+import TwoDimensionalDownload from "@/components/dataManage/dataDetail/TwoDimensionalDownload";
 import CategoryMenu from "@/components/dataManage/CategoryMenu";
 
 export default {
@@ -120,10 +123,12 @@ export default {
       },
 
       isDetailShow: false,
+      isDownloadShow: false,
     }
   },
   components: {
     TwoDimensionalDataDetail,
+    TwoDimensionalDownload,
     CategoryMenu,
   },
   created() {
@@ -292,6 +297,13 @@ export default {
         })
       })
     },
+    // 开启数据下载面板
+    openDownload(){
+      this.isDownloadShow = true
+    },
+    handleDownloadShow(){
+      this.isDownloadShow = false
+    }
   }
 }
 </script>

+ 408 - 0
src/components/dataPublish/Publish.vue

@@ -0,0 +1,408 @@
+<template>
+  <div id="configManage">
+    <div class="functionBtn">
+      <el-select
+        v-show="proxyType!='INTEGRATION'"
+        v-model="dataType"
+        placeholder="请选择类型"
+        style="margin-right: 12px"
+        default-first-option
+      >
+        <el-option
+          v-for="(item, index) in selectOptions"
+          :key="index"
+          :label="item.label"
+          :value="item.value"
+        ></el-option>
+      </el-select>
+      <el-button
+        type="primary"
+        round
+        @click="handleDetailVisible('Add')"
+      >新增配置</el-button>
+      <el-button
+        v-show="proxyType!='INTEGRATION'"
+        round
+        @click="viewAllModel"
+      >全部预览</el-button>
+      <el-tooltip
+        content="刷新"
+        placement="right"
+      >
+        <el-button
+          circle
+          @click="refresh"
+        ><el-icon><IconPark-refresh /></el-icon></el-button>
+      </el-tooltip>
+    </div>
+    <div class="tableContent">
+      <el-table
+        ref="table"
+        :data="tableData"
+        :max-height="maxHeight"
+        v-loading="loading"
+        @current-change="(row)=>{this.currRow=row}"
+        border
+        stripe
+      >
+        <el-table-column
+          prop="id"
+          label="ID"
+          width="60"
+          align="center"
+        />
+        <el-table-column
+          prop="key"
+          label="标题"
+          min-width="100"
+        >
+          <template #default="scope">
+            <span style="font-weight: bold;font-family: JetBrainsMono-Regular,serif">{{scope.row.key}}</span>
+          </template>
+        </el-table-column>
+        <el-table-column
+          prop="content"
+          label="描述"
+          min-width="120"
+        />
+        <el-table-column
+          prop="proxyUrl"
+          label="链接"
+          min-width="180"
+        >
+          <template #default="scope">
+            <span style="font-family: JetBrainsMono-Regular,serif">{{ scope.row.proxyUrl}}</span>
+          </template>
+        </el-table-column>
+        <el-table-column
+          prop="operation"
+          label="操作"
+          min-width="120"
+        >
+          <template #default="scope">
+            <el-button
+              type="primary"
+              size="small"
+              @click="handleDetailVisible('Edit', scope.row)"
+            >
+              <el-icon><IconPark-edit /></el-icon>
+              修改
+            </el-button>
+            <el-button
+              size="small"
+              @click="deleteConfig(scope.row)"
+            >
+              <el-icon><IconPark-delete /></el-icon>
+              删除
+            </el-button>
+            <el-button
+              v-show="proxyType!='INTEGRATION'"
+              size="small"
+              @click="view(scope.row)"
+            >
+              <el-icon><IconPark-preview-open /></el-icon>
+              预览
+            </el-button>
+          </template>
+        </el-table-column>
+      </el-table>
+      <div class="pagination">
+        <el-pagination
+          background
+          layout="sizes, prev, pager, next, jumper, ->, total"
+          v-model:current-page="pageInfo.page"
+          v-model:page-size="pageInfo.pageSize"
+          :total="pageInfo.total"
+        />
+      </div>
+    </div>
+  </div>
+
+  <ConfigDetail
+    v-model:show="detailVisible"
+    :operation="detailOperation"
+    :item="currRow"
+    :is-edit="detailIsEdit"
+    :select-options="selectOptions"
+    :proxy-type="proxyType"
+    :data-type="dataType"
+    :refresh="getData"
+  >
+  </ConfigDetail>
+
+  <CesiumMap
+    v-if="isMapShow"
+    :is-show="isMapShow"
+    :type="mapType"
+    :close="closeMap"
+    :item="mapItem"
+  >
+  </CesiumMap>
+
+  <AllCesiumMap
+    v-if="isAllMapShow"
+    :is-show="isAllMapShow"
+    :type="allMapType"
+    :close="closeMap"
+    :item="tableData"
+  >
+  </AllCesiumMap>
+</template>
+
+<script>
+import ConfigDetail from "./dialog/ConfigDetail.vue";
+import CesiumMap from "./dialog/CesiumMap.vue";
+import AllCesiumMap from "./dialog/AllCesiumMap.vue";
+
+import api from "@/api/data/publish"
+
+export default {
+  data() {
+    return {
+      maxHeight: 450,
+      loading: false,
+      configData: [],
+      tableData: [],
+      currRow: {},
+      pageInfo: {
+        page: 1,
+        pageSize: 10,
+        total: 0,
+      },
+      proxyType: "",
+      dataType: "",
+      selectOptions: [],
+      dataTypes: {
+        99: {
+          label: "数据",
+          value: "UNKNOWN",
+        },
+        0: {
+          label: "全部",
+          value: "ALL",
+        },
+        1: {
+          label: "地图",
+          value: "MAP",
+        },
+        2: {
+          label: "三维模型",
+          value: "MODEL",
+        },
+        3: {
+          label: "GLTF模型",
+          value: "GLTF",
+        },
+      },
+
+      routerParam: {
+        publish_twoD: {
+          proxyType: "PUBLISH",
+          dataTypes: [1],
+        },
+        publish_threeD: {
+          proxyType: "PUBLISH",
+          dataTypes: [2, 3],
+        },
+        integration_data: {
+          proxyType: "INTEGRATION",
+          dataTypes: [99],
+        },
+      },
+
+      mapTypes: {
+        MODEL: 1,
+        GLTF: 2,
+        MAP: 4,
+      },
+
+      detailVisible: false,
+      detailOperation: "",
+      detailIsEdit: false,
+
+      isMapShow: false,
+      mapType: 0,
+      mapItem: {},
+
+      allMapType: -1,
+      isAllMapShow: false,
+    };
+  },
+  watch: {
+    "pageInfo.page": function () {
+      this.renderTable();
+    },
+    "pageInfo.pageSize": function () {
+      this.renderTable();
+    },
+    dataType: function () {
+      this.refresh();
+    },
+    "$route.name": function (val) {
+      if (val) {
+        this.initType();
+        this.refresh();
+      }
+    },
+  },
+  components: {
+    ConfigDetail,
+    CesiumMap,
+    AllCesiumMap,
+  },
+  created() {
+    this.initType();
+  },
+  mounted() {
+    let container = document.getElementById("configManage");
+    this.maxHeight = container.clientHeight * 0.85;
+    this.getData();
+  },
+  methods: {
+    initType() {
+      // let obj = this.routerParam[this.$route.name];
+      let obj = this.routerParam["publish_twoD"];
+      if (!obj) {
+        return;
+      }
+      this.proxyType = obj.proxyType;
+      this.dataType = "";
+      this.selectOptions = [];
+      //this.selectOptions.push(this.dataTypes[0])
+      for (let index of obj.dataTypes) {
+        this.selectOptions.push(this.dataTypes[index]);
+      }
+      if (this.selectOptions.length > 0) {
+        this.dataType = this.selectOptions[0].value;
+      }
+    },
+    refresh() {
+      this.pageInfo.page = 1;
+      this.pageInfo.pageSize = 10;
+      this.pageInfo.total = 0;
+      this.getData();
+    },
+    getData() {
+      if (!this.dataType || this.dataType == "") {
+        this.configData = [];
+        this.tableData = [];
+        this.pageInfo.total = 0;
+        return;
+      }
+      let that = this;
+      that.loading = true;
+
+      let params = {
+        proxyType: this.proxyType,
+        dataType: this.dataType,
+      };
+      api.getList(params)
+        .then((res) => {
+          that.configData = [];
+          if (res.code === 200) {
+            let num = 0;
+            that.configData = [];
+            that.pageInfo.total = 0;
+            if (res.content) {
+              that.configData = JSON.parse(JSON.stringify(res.content));
+              that.configData.forEach((i) => {
+                i.id = num++;
+                i.proxyUrl = systemConfig.proxyUrl.replace("{PROXYURL}", i.key);
+              });
+              that.pageInfo.total = that.configData.length;
+            }
+            this.renderTable();
+          }
+          that.loading = false;
+        })
+        .catch((err) => {
+          that.loading = false;
+          that.$message({ message: err.message, type: "error" });
+        });
+    },
+    renderTable() {
+      let start = (this.pageInfo.page - 1) * this.pageInfo.pageSize;
+      let end = this.pageInfo.page * this.pageInfo.pageSize;
+      this.tableData = this.configData.slice(start, end);
+    },
+    handleDetailVisible(operation, item) {
+      this.detailOperation = operation;
+      this.detailVisible = true;
+      this.detailIsEdit = true;
+      if (operation === "Add") {
+        this.currRow = { title: "", url: "" };
+        this.detailIsEdit = false;
+      } else {
+        this.currRow = JSON.parse(JSON.stringify(item));
+      }
+    },
+    viewAllModel() {
+      let type = this.mapTypes[this.dataType];
+      if (type) {
+        this.allMapType = type;
+        this.isAllMapShow = true;
+      } else {
+        this.$message.error("该类型暂不支持预览");
+        return;
+      }
+    },
+    view(item) {
+      // 0-GeoJson、1-3DTiles、2-gltf/glb、3-水面、4-地图
+      this.mapItem = JSON.parse(JSON.stringify(item));
+      let type = this.mapTypes[this.dataType];
+      if (type) {
+        this.mapType = type;
+        this.isMapShow = true;
+      } else {
+        this.$message.error("该类型暂不支持预览");
+        return;
+      }
+    },
+    closeMap() {
+      this.isMapShow = false;
+      this.isAllMapShow = false;
+    },
+    deleteConfig(item) {
+      let that = this;
+      this.$msgbox.confirm("确定要删除:" + item.key + "吗?").then(() => {
+        let params = {
+          proxyType: this.proxyType,
+          dataType: this.dataType,
+          index: item.id,
+        };
+        api
+          .delItem(params)
+          .then((res) => {
+            if (res.code === 200) {
+              that.$message({ message: "删除成功", type: "success" });
+              that.getData();
+            } else {
+              that.$message({ message: res.content, type: "error" });
+            }
+          })
+          .catch((err) => {
+            that.$message({ message: err.message, type: "error" });
+          });
+      });
+    },
+  },
+};
+</script>
+
+<style lang="less" scoped>
+#configManage {
+  width: 98%;
+  height: 100%;
+  margin-left: 20px;
+
+  .tableContent {
+    margin-top: 1%;
+    .pagination {
+      margin-top: 1%;
+      position: relative;
+      float: right;
+      padding-bottom: 5%;
+    }
+  }
+}
+</style>

+ 275 - 0
src/components/dataPublish/dialog/AllCesiumMap.vue

@@ -0,0 +1,275 @@
+<template>
+  <el-dialog v-if="isShow"
+             :model-value="isShow"
+             title="全部预览"
+             :width="1200"
+             :close-on-click-modal="false"
+             :before-close="handleClose"
+  >
+    <div id="AmapBox">
+      <div id="AmapContainer"></div>
+      <div id="AnavItem" >
+        <el-table :show-header="false"
+                  :cell-style="{'background-color': '#393939','color': 'whitesmoke'}"
+                  :data="data"
+                  style="width: 100%;background-color: #393939;margin-top: 10px;max-height: 100%">
+          <el-table-column prop="key" label="名称">
+            <template #default="scope">
+              <span :title="scope.row.content">{{ scope.row.key }}</span>
+            </template>
+          </el-table-column>
+          <el-table-column prop="id" label="显示" width="70" >
+            <template #default="scope">
+              <el-switch
+                  v-model="scope.row.show"
+                  @change="handleTileVisible(scope.row)"
+                  active-color="#13ce66">
+              </el-switch>
+            </template>
+          </el-table-column>
+
+        </el-table>
+
+      </div>
+    </div>
+
+  </el-dialog>
+</template>
+
+<script>
+
+let viewer = null;
+export default {
+  data() {
+    return {
+      viewer: '',
+      data: [],
+      currItem: {},
+      history: new Map(),
+      cesiumConfig: {
+        animation: false, //动画控制不显示
+        timeline: false, //时间线不显示
+        fullscreenButton: false, //全屏按钮不显示
+        imageryProvider: new SkyScenery.SingleTileImageryProvider({
+          url: (function createColorCanvas(color) {
+            let width = 1,
+                height = 1;
+            let canvas = document.createElement("canvas");
+            canvas.width = width;
+            canvas.height = height;
+            let ctx = canvas.getContext("2d");
+            ctx.fillStyle = color;
+            ctx.fillRect(0, 0, width, height);
+            return canvas.toDataURL();
+          })("#ffffff00"),
+          rectangle: SkyScenery.Rectangle.fromDegrees(-180.0, -90.0, 180.0, 90.0),
+        }),
+        infoBox: false,
+        baseLayerPicker: false, //地图切换不显示
+        geocoder: false,
+        homeButton: false,
+        selectionIndicator: false, // 去除绿色选择框
+        sceneModePicker: false,
+        navigationHelpButton: false,
+        navigationInstructionsInitiallyVisible: false,
+        scene3DOnly: true, // 仅以3D渲染以节省GPU内存
+        useBrowserRecommendedResolution: true, // 以浏览器建议的分辨率渲染
+      },
+    }
+  },
+  props: {
+    isShow: Boolean,
+    type: Number, // 0-GeoJson、1-3DTiles、2-gltf/glb、3-水面、4-地图
+    item: Object,
+    close: Function
+  },
+  watch: {
+    "isShow": function (val) {
+      this.initMap();
+    }
+  },
+  mounted() {
+    let app = this;
+    this.data = JSON.parse(JSON.stringify(this.item))
+    this.$nextTick(() => {
+      app.initMap();
+    })
+  },
+  methods: {
+    initMap() {
+      let app = this;
+      viewer = new SkyScenery.Viewer('AmapContainer', app.cesiumConfig);
+      // 加载底图
+      viewer.imageryLayers.addImageryProvider(
+          new SkyScenery.ArcGisMapServerImageryProvider({
+            url: 'https://server.arcgisonline.com/arcgis/rest/services/World_Imagery/MapServer',
+          })
+      )
+      window.viewer = viewer
+    },
+    loadingEntities(type) {
+      let app = this;
+      let tile = undefined;
+      if (!type || type === '') {
+        return;
+      }
+      // 加载3DTiles
+      else if (type === 1) {
+        let url = app.currItem.url + '/tileset.json'
+        tile = app.add3DTiles(url)
+      }
+      // 加载gltf/glb
+      else if (type === 2) {
+        tile = app.addGltf(app.currItem.url)
+      }
+      // 加载底图
+      else if (type === 4) {
+        this.addMap(app.currItem.url)
+      }
+      if (tile) {
+        this.history.set(app.currItem.url, tile)
+      }
+    },
+    handleTileVisible(row) {
+      let flag = row.show;
+      let keys = this.history.keys();
+      if (this.type != 1) {
+        for (let i = 0; i < this.data.length; i++) {
+          this.data[i]['show'] = false;
+        }
+        for (let i = 0; i < keys.length; i++) {
+          this.history.get(keys[i]).show = false;
+        }
+      }
+      row.show = flag;
+      this.currItem = row;
+      if (this.history.has(row.url)) {
+        this.history.get(row.url).show = flag;
+      } else if (flag) {
+        this.loadingEntities(this.type)
+      }
+    },
+    addMap(url) {
+      viewer.imageryLayers.removeAll(true);
+      viewer.imageryLayers.addImageryProvider(
+          new SkyScenery.ArcGisMapServerImageryProvider({
+            url: url,
+          })
+      )},
+    // 添加模型
+    add3DTiles(url) {
+      let app = this;
+      let tile = undefined;
+      if (!url || url=='') {
+        app.$message.warning('请检查模型地址');
+        //app.handleClose()
+        return;
+      }
+      tile = SkyScenery.add3DTilesData(url, viewer);
+      tile.tileFailed.addEventListener(function (err) {
+        app.$message({message: '模型加载失败', type: 'error'});
+        //app.handleClose()
+      })
+      tile.readyPromise.then(function () {
+        viewer.zoomTo(tile, {
+          heading: 2.718565,
+          pitch: -0.415366,
+          roll: 0.0,
+        });
+      }).catch(err => {
+        app.$message({
+          dangerouslyUseHTMLString: true,
+          message: '模型加载失败,' + err.statusCode + ':' + err.response,
+          type: 'error'
+        });
+        //app.handleClose()
+      });
+      return tile;
+    },
+    // 添加gltf
+    addGltf(url) {
+      let app = this;
+      if (!url || url=='') {
+        app.$message.warning('请检查模型地址');
+        //app.handleClose()
+        return;
+      }
+      let modelObj = new SkyScenery.singleModelBindClick(viewer, {
+        url: url,
+        lon: systemConfig.mapCenter.lon,
+        lat: systemConfig.mapCenter.lat,
+        height: 10,
+        heading: 0,
+        pitch: -90,
+        roll: 0,
+        info: {}
+      })
+      let origin = SkyScenery.Cartesian3.fromDegrees(systemConfig.mapCenter.lon, systemConfig.mapCenter.lat, 10);
+      viewer.camera.flyTo({
+        destination: origin,
+        orientation: {
+          heading: SkyScenery.Math.toRadians(0), // 方向
+          pitch: SkyScenery.Math.toRadians(-90), // 倾斜角度
+          roll: SkyScenery.Math.toRadians(0),
+        },
+      });
+      return modelObj;
+    },
+    flyToPrimitive(obj) {
+      let east = obj.geometryInstances.geometry.rectangle.east;
+      let north = obj.geometryInstances.geometry.rectangle.north;
+      let west = obj.geometryInstances.geometry.rectangle.west;
+      let south = obj.geometryInstances.geometry.rectangle.south;
+      let lon = (east+west)/2;
+      let lat = (north+south)/2;
+      viewer.camera.flyTo({
+        destination: SkyScenery.Cartesian3.fromDegrees(SkyScenery.Math.toDegrees(lon),SkyScenery.Math.toDegrees(lat), 338.8293456247198),
+        orientation: {
+          heading: SkyScenery.Math.toRadians(0),
+          pitch: SkyScenery.Math.toRadians(-90),
+          roll: 0,
+        }
+      })
+    },
+    handleClose() {
+      this.close(false)
+    }
+  }
+}
+</script>
+
+<style scoped>
+#AmapBox {
+  width: 100%;
+  height: 100%;
+  position: relative;
+}
+
+#AmapContainer {
+  width: 100%;
+  height: 100%;
+}
+
+#AnavItem{
+  position: absolute;
+  top: 18%;
+  left: 1%;
+  width: 20%;
+  height: 65%;
+  color: white;
+  border: 1px solid grey;
+  border-radius: 10px;
+  background-color: #393939;
+}
+</style>
+
+<style>
+/*隐藏 cesium logo*/
+.cesium-widget-credits {
+  display: none !important;
+}
+
+.el-dialog__body {
+  padding-top: 10px;
+}
+</style>

+ 242 - 0
src/components/dataPublish/dialog/CesiumMap.vue

@@ -0,0 +1,242 @@
+<template>
+  <el-dialog v-if="isShow"
+             :model-value="isShow"
+             title="地理信息"
+             :width="1200"
+             :close-on-click-modal="false"
+             :before-close="handleClose"
+
+  >
+    <div id="mapBox">
+      <div id="mapContainer"></div>
+    </div>
+
+  </el-dialog>
+</template>
+
+<script>
+
+let viewer = null;
+export default {
+  data() {
+    return {
+      viewer: '',
+      centerPoint: {},
+      cesiumConfig: {
+        animation: false, //动画控制不显示
+        timeline: false, //时间线不显示
+        fullscreenButton: false, //全屏按钮不显示
+        imageryProvider: new SkyScenery.SingleTileImageryProvider({
+          url: (function createColorCanvas(color) {
+            let width = 1,
+                height = 1;
+            let canvas = document.createElement("canvas");
+            canvas.width = width;
+            canvas.height = height;
+            let ctx = canvas.getContext("2d");
+            ctx.fillStyle = color;
+            ctx.fillRect(0, 0, width, height);
+            return canvas.toDataURL();
+          })("#ffffff00"),
+          rectangle: SkyScenery.Rectangle.fromDegrees(-180.0, -90.0, 180.0, 90.0),
+        }),
+        infoBox: false,
+        baseLayerPicker: false, //地图切换不显示
+        geocoder: false,
+        homeButton: false,
+        selectionIndicator: false, // 去除绿色选择框
+        sceneModePicker: false,
+        navigationHelpButton: false,
+        navigationInstructionsInitiallyVisible: false,
+        scene3DOnly: true, // 仅以3D渲染以节省GPU内存
+        useBrowserRecommendedResolution: true, // 以浏览器建议的分辨率渲染
+      },
+    }
+  },
+  props: {
+    isShow: Boolean,
+    type: Number, // 0-GeoJson、1-3DTiles、2-gltf、3-水面、4-地图
+    item: Object,
+    close: Function
+  },
+  watch: {
+    "isShow": function (val) {
+      this.initMap();
+    }
+  },
+  mounted() {
+    let app = this;
+    this.$nextTick(() => {
+      app.initMap();
+    })
+  },
+  methods: {
+    initMap() {
+      let app = this;
+      viewer = new SkyScenery.Viewer('mapContainer', app.cesiumConfig);
+      // 加载底图
+      if (app.type!==4) {
+        viewer.imageryLayers.addImageryProvider(
+            new SkyScenery.ArcGisMapServerImageryProvider({
+              url: 'https://server.arcgisonline.com/arcgis/rest/services/World_Imagery/MapServer',
+            })
+        )
+      }
+      window.viewer = viewer
+      // 加载模型
+      app.loadingEntities(app.type);
+    },
+    loadingEntities(type) {
+      let app = this;
+      if (!type || type === '') {
+        return;
+      }
+      // 加载GeoJson
+      if (type === 0) {
+        let obj = {"type": "Feature", "geometry": JSON.parse(app.item), "properties": {}}
+        this.addGeoJson(obj);
+      }
+      // 加载3DTiles
+      else if (type === 1) {
+        let url = app.item.url+'/tileset.json'
+        app.add3DTiles(url)
+      }
+      // 加载gltf
+      else if (type === 2) {
+        app.addGltf(app.item.url)
+      }
+      // 加载底图
+      else if (type === 4) {
+        app.addMap(app.item.url);
+      }
+    },
+    // 加载GeoJson
+    addGeoJson(obj) {
+      let app = this;
+      let res = SkyScenery.GeoJsonDataSource.load(obj, {
+        stroke: SkyScenery.Color.fromCssColorString('#ff0000'),
+        fill: SkyScenery.Color.RED.withAlpha(0.3),
+        strokeWidth: 5,
+        clampToGround: true,
+      })
+      viewer.dataSources.add(res);
+      res.then(() => {
+        viewer.zoomTo(res, {heading: 2.718565, pitch: -0.415366, roll: 0.0,});
+      }).catch(() => {
+        app.$message({message: '加载失败', type: 'error'})
+      })
+    },
+    // 添加模型
+    add3DTiles(url) {
+      let app = this;
+      let tile = undefined;
+      if (!url || url=='') {
+        app.$message.warning('请检查模型地址');
+        app.handleClose()
+        return;
+      }
+      tile = SkyScenery.add3DTilesData(url, viewer);
+      tile.tileFailed.addEventListener(function (err) {
+        app.$message({message: '模型加载失败', type: 'error'});
+        app.handleClose()
+      })
+      tile.readyPromise.then(function () {
+        viewer.zoomTo(tile, {
+          heading: 2.718565,
+          pitch: -0.415366,
+          roll: 0.0,
+        });
+      }).catch(err => {
+        app.$message({
+          dangerouslyUseHTMLString: true,
+          message: '模型加载失败,' + err.statusCode + ':' + err.response,
+          type: 'error'
+        });
+        app.handleClose()
+      });
+      return tile;
+    },
+    // 添加gltf
+    addGltf(url) {
+      let app = this;
+      if (!url || url=='') {
+        app.$message.warning('请检查模型地址');
+        app.handleClose()
+        return;
+      }
+      let modelObj = new SkyScenery.singleModelBindClick(viewer, {
+        url: url,
+        lon: systemConfig.mapCenter.lon,
+        lat: systemConfig.mapCenter.lat,
+        height: 10,
+        heading: 0,
+        pitch: -90,
+        roll: 0,
+        info: {}
+      })
+      let origin = SkyScenery.Cartesian3.fromDegrees(systemConfig.mapCenter.lon, systemConfig.mapCenter.lat, 10);
+      viewer.camera.flyTo({
+        destination: origin,
+        orientation: {
+          heading: SkyScenery.Math.toRadians(0), // 方向
+          pitch: SkyScenery.Math.toRadians(-90), // 倾斜角度
+          roll: SkyScenery.Math.toRadians(0),
+        },
+      });
+    },
+    addMap(url) {
+      viewer.imageryLayers.removeAll(true);
+      viewer.imageryLayers.addImageryProvider(
+          new SkyScenery.ArcGisMapServerImageryProvider({
+            url: url,
+          })
+      )},
+    flyToPrimitive(obj) {
+      let east = obj.geometryInstances.geometry.rectangle.east;
+      let north = obj.geometryInstances.geometry.rectangle.north;
+      let west = obj.geometryInstances.geometry.rectangle.west;
+      let south = obj.geometryInstances.geometry.rectangle.south;
+      let lon = (east+west)/2;
+      let lat = (north+south)/2;
+      viewer.camera.flyTo({
+        destination: SkyScenery.Cartesian3.fromDegrees(SkyScenery.Math.toDegrees(lon),SkyScenery.Math.toDegrees(lat), 338.8293456247198),
+        orientation: {
+          heading: SkyScenery.Math.toRadians(0),
+          pitch: SkyScenery.Math.toRadians(-90),
+          roll: 0,
+        }
+      })
+    },
+    handleClose() {
+      this.close(false)
+    }
+  }
+}
+</script>
+
+<style scoped>
+#mapBox {
+  width: 100%;
+  height: 100%;
+}
+
+#mapContainer {
+  width: 100%;
+  height: 100%;
+}
+
+#mapOperation {
+  margin-bottom: 10px;
+}
+</style>
+
+<style>
+/*隐藏 cesium logo*/
+.cesium-widget-credits {
+  display: none !important;
+}
+
+.el-dialog__body {
+  padding-top: 10px;
+}
+</style>

+ 226 - 0
src/components/dataPublish/dialog/ConfigDetail.vue

@@ -0,0 +1,226 @@
+<template>
+  <el-dialog
+    :model-value="show"
+    :title="title"
+    :width="500"
+    :close-on-click-modal="false"
+    :destroy-on-close="true"
+    :before-close="closeDialog"
+  >
+    <el-form
+      ref="form"
+      :model="formData"
+      :rules="formDataRules"
+      style="margin: 0 3%"
+      :label-width="80"
+    >
+      <el-form-item
+        label="ID:"
+        v-show="false"
+      >
+        <el-input
+          v-model="formData.id"
+          :disabled="true"
+        />
+      </el-form-item>
+      <el-form-item
+        label="类型:"
+        prop="type"
+      >
+        <el-select
+          v-model="formData.type"
+          placeholder="请选择类型"
+          style="margin-right: 12px"
+          default-first-option
+        >
+          <template
+            v-for="(item, index) in selectOptions"
+            :key="index"
+          >
+            <el-option
+              :label="item.label"
+              :value="item.value"
+              v-show="item.value!='ALL'"
+            ></el-option>
+          </template>
+        </el-select>
+      </el-form-item>
+      <el-form-item
+        label="标题:"
+        prop="key"
+      >
+        <el-input
+          v-model="formData.key"
+          placeholder="请输入标题"
+        />
+      </el-form-item>
+      <el-form-item
+        label="描述:"
+        prop="content"
+      >
+        <el-input
+          v-model="formData.content"
+          placeholder="请输入标题"
+        />
+      </el-form-item>
+      <el-form-item
+        label="链接:"
+        prop="url"
+      >
+        <el-input
+          v-model="formData.url"
+          placeholder="请输入链接"
+        />
+      </el-form-item>
+    </el-form>
+
+    <template #footer>
+      <el-button @click="closeDialog">取消</el-button>
+      <el-button
+        type="primary"
+        @click="save"
+      >保存</el-button>
+    </template>
+  </el-dialog>
+</template>
+
+<script> 
+import api from "@/api/data/publish"
+
+export default {
+  data() {
+    return {
+      title: "",
+      formData: {
+        id: "",
+        title: "",
+        url: "",
+      },
+      formDataRules: {
+        key: [
+          { required: true, message: "请输入标题", trigger: "blur" },
+          { required: true, message: "请输入标题", trigger: "change" },
+        ],
+        type: [
+          { required: true, message: "请选择类型", trigger: "blur" },
+          { required: true, message: "请选择类型", trigger: "change" },
+        ],
+        url: [
+          { required: true, message: "请输入链接", trigger: "blur" },
+          { required: true, message: "请输入链接", trigger: "change" },
+        ],
+      },
+      operations: {
+        isEdit: false,
+        isAdd: false,
+      },
+    };
+  },
+  props: {
+    show: Boolean,
+    item: Object,
+    proxyType: String,
+    dataType: String,
+    operation: String,
+    selectOptions: Array,
+    refresh: Function,
+    isEdit: Boolean,
+  },
+  emits: ["update:show"],
+  setup(props, context) {
+    // let app = getCurrentInstance();
+    const methods = {
+      updateShow(val) {
+        context.emit("update:show", val);
+      },
+    };
+    return methods;
+  },
+  watch: {
+    item: function (val) {
+      if (val) {
+        this.updateOperation(this.operation);
+        this.formData.type = this.dataType;
+      }
+    },
+  },
+  methods: { 
+    closeDialog() {
+      this.updateShow(false);
+    },
+    updateOperation(val) {
+      this.formData = this.$options.data().formData;
+      this.operations.isAdd = val === "Add";
+      this.operations.isEdit = val === "Edit";
+      if (this.operations.isAdd) {
+        this.title = "添加配置";
+      }
+      if (this.operations.isEdit) {
+        this.title = "修改配置";
+        this.formData = JSON.parse(JSON.stringify(this.item));
+      }
+    },
+    save() {
+      let that = this;
+      this.$refs.form.validate((valid) => {
+        if (that.operations.isAdd) {
+          that.addConfig();
+        } else if (that.operations.isEdit) {
+          that.updateConfig();
+        }
+      });
+    },
+    addConfig() {
+      let that = this;
+      let params = {
+        proxyType: this.proxyType,
+        dataType: this.formData.type,
+        key: this.formData.key,
+        content: this.formData.content,
+        url: this.formData.url,
+      };
+      api.addItem(params)
+        .then((res) => {
+          if (res.code === 200) {
+            that.$message({ message: "添加成功", type: "success" });
+            that.refresh();
+            that.closeDialog();
+          } else {
+            that.$message({ message: res.content, type: "error" });
+          }
+        })
+        .catch((err) => {
+          that.$message({ message: err.message, type: "error" });
+        });
+    },
+    updateConfig() {
+      let that = this;
+      let params = {
+        proxyType: this.proxyType,
+        dataType: this.dataType,
+        newDataType: this.formData.type,
+        key: this.formData.key,
+        content: this.formData.content,
+        index: this.formData.id,
+        url: this.formData.url,
+      };
+      api.updateItem(params)
+        .then((res) => {
+          if (res.code === 200) {
+            that.$message({ message: "修改成功", type: "success" });
+            that.refresh();
+            that.closeDialog();
+          } else {
+            that.$message({ message: res.content, type: "error" });
+          }
+        })
+        .catch((err) => {
+          that.$message({ message: err.message, type: "error" });
+        });
+    },
+  },
+};
+</script>
+
+<style lang="less" scoped>
+</style>

+ 57 - 21
src/components/home/DataPublish.vue

@@ -1,58 +1,88 @@
 <template>
   <div id="dataPublish">
-    <br/>
+    <br />
     <div class="left">
       <el-scrollbar :max-height="menuHeight">
-        <el-menu default-active="0" class="dataPublish-menu" @select="handleServiceSelect">
-          <el-menu-item v-for="(item,index) of serviceList" :key="index" :index="index+''" >
+        <el-menu
+          default-active="0"
+          class="dataPublish-menu"
+          @select="handleServiceSelect"
+        >
+          <el-menu-item :index="0">
             <el-icon>
-              <IconPark-server/>
+              <IconPark-server />
+            </el-icon>
+            <span>{{ "地图服务发布" }}</span>
+          </el-menu-item>
+          <el-menu-item
+            v-for="(item,index) of serviceList"
+            :key="index"
+            :index="index+1+''"
+          >
+            <el-icon>
+              <IconPark-server />
             </el-icon>
             <span>{{ item.serviceName }}</span>
           </el-menu-item>
         </el-menu>
-        <el-empty description="无服务/权限" v-if="!serviceList || serviceList.length<1"></el-empty>
+        <el-empty
+          description="无服务/权限"
+          v-if="!serviceList || serviceList.length<1"
+        ></el-empty>
       </el-scrollbar>
 
     </div>
     <div class="content">
-      <PublishDetail :data="currService" v-if="isDetailShow"/>
+      <Publish v-if="menuIndex==0" />
+      <PublishDetail
+        :data="currService"
+        v-if="isDetailShow && menuIndex!=0"
+      />
     </div>
   </div>
 </template>
 
 <script>
-import PublishDetail from '@/components/dataPublish/PublishDetail'
+import Publish from "@/components/dataPublish/Publish";
+import PublishDetail from "@/components/dataPublish/PublishDetail";
 import ServiceData from "@/static/datas/ServiceData";
 
 export default {
   data() {
     return {
-      menuHeight: '',
+      menuHeight: "",
       serviceList: [],
       currService: {},
       pageShow: {},
       isDetailShow: true,
-    }
+
+      menuIndex: "0",
+    };
   },
   props: {
-    height: Object
+    height: Object,
   },
   components: {
-    PublishDetail
+    Publish,
+    PublishDetail,
   },
   created() {
     let app = this;
     this.pageShow = this.$store.state.pageShow;
     this.menuHeight = this.height * 0.7;
-    this.serviceList = JSON.parse(JSON.stringify(ServiceData))
-    this.serviceList = this.serviceList.filter(item=>app.pageShow[item.authKey])
+    this.serviceList = JSON.parse(JSON.stringify(ServiceData));
+    this.serviceList.unshift({
+      serviceName: "地图服务发布",
+    });
+
+    this.serviceList = this.serviceList.filter(
+      (item) => app.pageShow[item.authKey]
+    );
     if (this.serviceList.length > 0) {
-      this.currService = this.serviceList[0]
+      this.currService = this.serviceList[0];
     }
   },
-  mounted() {
-  },
+  mounted() {},
   methods: {
     handleServiceSelect(val) {
       let app = this;
@@ -60,14 +90,19 @@ export default {
       // setTimeout(function () {
       //   app.isDetailShow = true;
       // }, 200)
-      app.currService = app.serviceList[Number(val)]
+      this.menuIndex = val;
+      app.currService = app.serviceList[Number(val - 1)];
     },
-  }
-}
-
+  },
+};
 </script>
 
 <style scoped>
+#dataPublish {
+  width: 100%;
+  height: 100%;
+}
+
 #dataPublish .left {
   display: inline-block;
   width: 20%;
@@ -83,7 +118,8 @@ export default {
 </style>
 
 <style>
-#dataPublish .el-menu-item,.el-sub-menu__title {
+#dataPublish .el-menu-item,
+.el-sub-menu__title {
   font-size: 17px !important;
   font-weight: 600;
   color: #373737;

+ 1 - 1
src/main.js

@@ -7,7 +7,7 @@ import store from './store'
 import ElementPlus from 'element-plus'
 import zhCn from 'element-plus/dist/locale/zh-cn.mjs'
 import 'element-plus/dist/index.css'
-import '@/style/element-variables.scss'
+import '@/style/element-variables.less'
 import * as ElementPlusIconsVue from '@element-plus/icons-vue'
 //iconpark
 import {install} from '@icon-park/vue-next/es/all';

+ 0 - 0
src/style/element-variables.scss → src/style/element-variables.less


この差分においてかなりの量のファイルが変更されているため、一部のファイルを表示していません