Browse Source

初始化框架

tianyabing 2 years ago
parent
commit
e621d7f8dd
56 changed files with 4154 additions and 111 deletions
  1. 3 0
      .env.dev
  2. 3 0
      .env.prod
  3. 4 1
      .eslintrc.js
  4. 20 3
      package.json
  5. 24 18
      src/App.vue
  6. 26 0
      src/api/data/BusinessData.js
  7. 10 0
      src/api/data/MenuData.js
  8. 31 0
      src/api/data/MetaData.js
  9. 31 0
      src/api/data/ModelData.js
  10. 31 0
      src/api/data/ThreeDimensionalData.js
  11. 31 0
      src/api/data/TwoDimensionalData.js
  12. 10 0
      src/api/login.js
  13. BIN
      src/assets/img/bg.jpg
  14. 0 60
      src/components/HelloWorld.vue
  15. 29 0
      src/components/dataManage/ImportData.vue
  16. 6 0
      src/components/dataManage/SyncInterface.vue
  17. 225 0
      src/components/dataManage/dataDetail/BusinessDataDetail.vue
  18. 225 0
      src/components/dataManage/dataDetail/ModelDataDetail.vue
  19. 225 0
      src/components/dataManage/dataDetail/ThreeDimensionalDataDetail.vue
  20. 225 0
      src/components/dataManage/dataDetail/TwoDimensionalDataDetail.vue
  21. 223 0
      src/components/dataManage/dataShow/BusinessData.vue
  22. 95 0
      src/components/dataManage/dataShow/IotData.vue
  23. 223 0
      src/components/dataManage/dataShow/MetaData.vue
  24. 226 0
      src/components/dataManage/dataShow/ModelData.vue
  25. 243 0
      src/components/dataManage/dataShow/ThreeDimensionalData.vue
  26. 250 0
      src/components/dataManage/dataShow/TwoDimensionalData.vue
  27. 93 0
      src/components/dataPublish/PublishDetail.vue
  28. 131 0
      src/components/home/DataManage.vue
  29. 71 0
      src/components/home/DataPublish.vue
  30. 90 0
      src/components/home/HomeIndex.vue
  31. 69 0
      src/components/home/PluginManage.vue
  32. 3 0
      src/components/home/SystemManage.vue
  33. 51 0
      src/components/json/JsonDataView.vue
  34. 159 0
      src/components/map/CesiumMap.vue
  35. 194 0
      src/components/map/OlMap.vue
  36. 97 0
      src/components/pluginManage/PluginDetail.vue
  37. 34 1
      src/main.js
  38. 5 5
      src/router/index.js
  39. 34 0
      src/static/datas/PluginData.json
  40. 44 0
      src/static/datas/ServiceData.json
  41. 39 0
      src/static/files/mockData.json
  42. 24 0
      src/static/js/CesiumMarker.js
  43. 0 0
      src/store/actions.js
  44. 11 0
      src/store/getters.js
  45. 21 9
      src/store/index.js
  46. 16 0
      src/store/mutations.js
  47. 4 0
      src/store/state.js
  48. 12 0
      src/utils/clipboard.js
  49. 6 0
      src/utils/constant.js
  50. 29 0
      src/utils/datetime.js
  51. 11 0
      src/utils/index.js
  52. 20 0
      src/utils/loading.js
  53. 106 0
      src/utils/request.js
  54. 0 5
      src/views/AboutView.vue
  55. 276 7
      src/views/HomeView.vue
  56. 85 2
      vue.config.js

+ 3 - 0
.env.dev

@@ -0,0 +1,3 @@
+NODE_ENV=development
+VUE_APP_BASEURL=http://121.43.55.7:10091/dtbservice
+VUE_APP_OAUTHURL=http://121.43.55.7:8888/oauth

+ 3 - 0
.env.prod

@@ -0,0 +1,3 @@
+NODE_ENV=production
+VUE_APP_BASEURL=http://121.43.55.7:10091/dtbservice
+VUE_APP_OAUTHURL=http://121.43.55.7:8888/oauth

+ 4 - 1
.eslintrc.js

@@ -12,6 +12,9 @@ module.exports = {
   },
   },
   rules: {
   rules: {
     'no-console': process.env.NODE_ENV === 'production' ? 'warn' : 'off',
     'no-console': process.env.NODE_ENV === 'production' ? 'warn' : 'off',
-    'no-debugger': process.env.NODE_ENV === 'production' ? 'warn' : 'off'
+    'no-debugger': process.env.NODE_ENV === 'production' ? 'warn' : 'off',
+    "no-unused-vars": 'off',
+    "vue/no-unused-components": "off",
+    "no-undef": "off",
   }
   }
 }
 }

+ 20 - 3
package.json

@@ -3,15 +3,32 @@
   "version": "0.1.0",
   "version": "0.1.0",
   "private": true,
   "private": true,
   "scripts": {
   "scripts": {
-    "serve": "vue-cli-service serve",
-    "build": "vue-cli-service build",
+    "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"
     "lint": "vue-cli-service lint"
   },
   },
   "dependencies": {
   "dependencies": {
+    "@icon-park/vue-next": "^1.4.2",
+    "axios": "^1.1.3",
+    "cesium": "^1.98.1",
+    "copy-webpack-plugin": "^11.0.0",
     "core-js": "^3.8.3",
     "core-js": "^3.8.3",
+    "dayjs": "^1.11.5",
+    "element-plus": "^2.2.18",
+    "element-resize-detector": "^1.2.4",
+    "node-polyfill-webpack-plugin": "^2.0.1",
+    "ol": "^7.1.0",
+    "path": "^0.12.7",
+    "qs": "^6.11.0",
     "vue": "^3.2.13",
     "vue": "^3.2.13",
+    "vue-clipboard3": "^2.0.0",
+    "vue-json-viewer": "^3.0.4",
     "vue-router": "^4.0.3",
     "vue-router": "^4.0.3",
-    "vuex": "^4.0.0"
+    "vuex": "^4.0.0",
+    "vuex-persistedstate": "^4.1.0",
+    "webpack": "^5.74.0"
   },
   },
   "devDependencies": {
   "devDependencies": {
     "@babel/core": "^7.12.16",
     "@babel/core": "^7.12.16",

+ 24 - 18
src/App.vue

@@ -1,30 +1,36 @@
 <template>
 <template>
-  <nav>
-    <router-link to="/">Home</router-link> |
-    <router-link to="/about">About</router-link>
-  </nav>
-  <router-view/>
+  <div id="app">
+    <HomeView />
+  </div>
 </template>
 </template>
 
 
+<script>
+import HomeView from '@/views/HomeView.vue'
+
+export default {
+  name: 'APP',
+  components: {
+    HomeView
+  }
+}
+</script>
+
 <style lang="scss">
 <style lang="scss">
+* {
+  margin: 0;
+  padding: 0;
+}
+html,body {
+  width: 100%;
+  height: 100%;
+  margin: auto;
+}
 #app {
 #app {
   font-family: Avenir, Helvetica, Arial, sans-serif;
   font-family: Avenir, Helvetica, Arial, sans-serif;
   -webkit-font-smoothing: antialiased;
   -webkit-font-smoothing: antialiased;
   -moz-osx-font-smoothing: grayscale;
   -moz-osx-font-smoothing: grayscale;
-  text-align: center;
   color: #2c3e50;
   color: #2c3e50;
+  height: 99.5%;
 }
 }
 
 
-nav {
-  padding: 30px;
-
-  a {
-    font-weight: bold;
-    color: #2c3e50;
-
-    &.router-link-exact-active {
-      color: #42b983;
-    }
-  }
-}
 </style>
 </style>

+ 26 - 0
src/api/data/BusinessData.js

@@ -0,0 +1,26 @@
+import request from "@/utils/request";
+import constant from "@/utils/constant";
+
+// 分页查询业务数据
+const getData = (params) => {
+    return request.postForm(constant.dtbserverProxy + '/baseData/getBasedata', params);
+}
+// 新增业务数据
+const addData = (params) => {
+    return request.postForm(constant.dtbserverProxy + '/baseData/addBaseData', params);
+}
+// 修改业务数据
+const updateData = (params) => {
+    return request.postForm(constant.dtbserverProxy + '/baseData/addBaseData', params);
+}
+// 删除业务数据
+const deleteData = (params) => {
+    return request.postForm(constant.dtbserverProxy + '/baseData/deleteBaseDataById', params)
+}
+
+export default {
+    getData,
+    addData,
+    updateData,
+    deleteData,
+}

+ 10 - 0
src/api/data/MenuData.js

@@ -0,0 +1,10 @@
+import request from "@/utils/request";
+import constant from "@/utils/constant";
+
+const getMenuData = (params) => {
+    return request.postForm(constant.dtbserverProxy + '/menu/getMenuDataList', params)
+}
+
+export default {
+    getMenuData,
+}

+ 31 - 0
src/api/data/MetaData.js

@@ -0,0 +1,31 @@
+import request from "@/utils/request";
+import constant from "@/utils/constant";
+
+// 分页查询元数据
+const getData = (params) => {
+    return request.postForm(constant.dtbserverProxy + '/metadata/selectMetadtaDataPage', params);
+}
+// 通过ID查询元数据
+const getDataById = (params) => {
+    return request.postForm(constant.dtbserverProxy + '/metadata/selectMetadataDataById', params)
+}
+// 新增元数据
+const addData = (params) => {
+    return request.postForm(constant.dtbserverProxy + '/metadata/addMetadataData', params);
+}
+// 修改元数据
+const updateData = (params) => {
+    return request.postForm(constant.dtbserverProxy + '/metadata/addMetadataData', params);
+}
+// 删除元数据
+const deleteData = (params) => {
+    return request.postForm(constant.dtbserverProxy + '/metadata/deleteMetadataData', params)
+}
+
+export default {
+    getData,
+    getDataById,
+    addData,
+    updateData,
+    deleteData,
+}

+ 31 - 0
src/api/data/ModelData.js

@@ -0,0 +1,31 @@
+import request from "@/utils/request";
+import constant from "@/utils/constant";
+
+// 分页查询模型数据
+const getData = (params) => {
+    return request.postForm(constant.dtbserverProxy + '/model/getModelData', params);
+}
+// 通过ID查询模型数据
+const getDataById = (params) => {
+    return request.postForm(constant.dtbserverProxy + '/latlon/getLonlatById', params)
+}
+// 新增模型数据
+const addData = (params) => {
+    return request.postForm(constant.dtbserverProxy + '/model/addModelData', params);
+}
+// 修改模型数据
+const updateData = (params) => {
+    return request.postForm(constant.dtbserverProxy + '/model/addModelData', params);
+}
+// 删除模型数据
+const deleteData = (params) => {
+    return request.postForm(constant.dtbserverProxy + '/model/deleteModelData', params)
+}
+
+export default {
+    getData,
+    getDataById,
+    addData,
+    updateData,
+    deleteData,
+}

+ 31 - 0
src/api/data/ThreeDimensionalData.js

@@ -0,0 +1,31 @@
+import request from "@/utils/request";
+import constant from "@/utils/constant";
+
+// 分页查询三维数据
+const getData = (params) => {
+    return request.postForm(constant.dtbserverProxy + '/threeD/getThreeDData', params);
+}
+// 通过ID查询三维数据
+const getDataById = (params) => {
+    return request.postForm(constant.dtbserverProxy + '/threeD/getThreeDDataById', params)
+}
+// 新增三维数据
+const addData = (params) => {
+    return request.postForm(constant.dtbserverProxy + '/threeD/addThreeDData', params);
+}
+// 修改三维数据
+const updateData = (params) => {
+    return request.postForm(constant.dtbserverProxy + '/threeD/addThreeDData', params);
+}
+// 删除三维数据
+const deleteData = (params) => {
+    return request.postForm(constant.dtbserverProxy + '/threeD/deleteThreeDData/', params)
+}
+
+export default {
+    getData,
+    getDataById,
+    addData,
+    updateData,
+    deleteData,
+}

+ 31 - 0
src/api/data/TwoDimensionalData.js

@@ -0,0 +1,31 @@
+import request from "@/utils/request";
+import constant from "@/utils/constant";
+
+// 分页查询二维数据
+const getData = (params) => {
+    return request.postForm(constant.dtbserverProxy + '/latlon/getLatlonData', params);
+}
+// 通过ID查询二维数据
+const getDataById = (params) => {
+    return request.postForm(constant.dtbserverProxy + '/latlon/getLonlatById', params)
+}
+// 新增二维数据
+const addData = (params) => {
+    return request.postForm(constant.dtbserverProxy + '/latlon/addLatlonData', params);
+}
+// 修改二维数据
+const updateData = (params) => {
+    return request.postForm(constant.dtbserverProxy + '/latlon/addLatlonData', params);
+}
+// 删除二维数据
+const deleteData = (params) => {
+    return request.postForm(constant.dtbserverProxy + '/latlon/deleteLatlonDataById', params)
+}
+
+export default {
+    getData,
+    getDataById,
+    addData,
+    updateData,
+    deleteData,
+}

+ 10 - 0
src/api/login.js

@@ -0,0 +1,10 @@
+import request from "@/utils/request";
+import constant from "@/utils/constant";
+
+const userLogin = (params) => {
+    return request.postForm(constant.oauthProxy + '/api/user/login', params);
+}
+
+export default {
+    userLogin,
+}

BIN
src/assets/img/bg.jpg


+ 0 - 60
src/components/HelloWorld.vue

@@ -1,60 +0,0 @@
-<template>
-  <div class="hello">
-    <h1>{{ msg }}</h1>
-    <p>
-      For a guide and recipes on how to configure / customize this project,<br>
-      check out the
-      <a href="https://cli.vuejs.org" target="_blank" rel="noopener">vue-cli documentation</a>.
-    </p>
-    <h3>Installed CLI Plugins</h3>
-    <ul>
-      <li><a href="https://github.com/vuejs/vue-cli/tree/dev/packages/%40vue/cli-plugin-babel" target="_blank" rel="noopener">babel</a></li>
-      <li><a href="https://github.com/vuejs/vue-cli/tree/dev/packages/%40vue/cli-plugin-router" target="_blank" rel="noopener">router</a></li>
-      <li><a href="https://github.com/vuejs/vue-cli/tree/dev/packages/%40vue/cli-plugin-vuex" target="_blank" rel="noopener">vuex</a></li>
-      <li><a href="https://github.com/vuejs/vue-cli/tree/dev/packages/%40vue/cli-plugin-eslint" target="_blank" rel="noopener">eslint</a></li>
-    </ul>
-    <h3>Essential Links</h3>
-    <ul>
-      <li><a href="https://vuejs.org" target="_blank" rel="noopener">Core Docs</a></li>
-      <li><a href="https://forum.vuejs.org" target="_blank" rel="noopener">Forum</a></li>
-      <li><a href="https://chat.vuejs.org" target="_blank" rel="noopener">Community Chat</a></li>
-      <li><a href="https://twitter.com/vuejs" target="_blank" rel="noopener">Twitter</a></li>
-      <li><a href="https://news.vuejs.org" target="_blank" rel="noopener">News</a></li>
-    </ul>
-    <h3>Ecosystem</h3>
-    <ul>
-      <li><a href="https://router.vuejs.org" target="_blank" rel="noopener">vue-router</a></li>
-      <li><a href="https://vuex.vuejs.org" target="_blank" rel="noopener">vuex</a></li>
-      <li><a href="https://github.com/vuejs/vue-devtools#vue-devtools" target="_blank" rel="noopener">vue-devtools</a></li>
-      <li><a href="https://vue-loader.vuejs.org" target="_blank" rel="noopener">vue-loader</a></li>
-      <li><a href="https://github.com/vuejs/awesome-vue" target="_blank" rel="noopener">awesome-vue</a></li>
-    </ul>
-  </div>
-</template>
-
-<script>
-export default {
-  name: 'HelloWorld',
-  props: {
-    msg: String
-  }
-}
-</script>
-
-<!-- Add "scoped" attribute to limit CSS to this component only -->
-<style scoped lang="scss">
-h3 {
-  margin: 40px 0 0;
-}
-ul {
-  list-style-type: none;
-  padding: 0;
-}
-li {
-  display: inline-block;
-  margin: 0 10px;
-}
-a {
-  color: #42b983;
-}
-</style>

+ 29 - 0
src/components/dataManage/ImportData.vue

@@ -0,0 +1,29 @@
+<template>
+  <div id="ImportData">
+    <h2>数据导入</h2>
+    <el-divider></el-divider>
+    <el-form>
+      <el-form-item>
+        <el-upload></el-upload>
+      </el-form-item>
+    </el-form>
+  </div>
+</template>
+
+<script>
+export default {
+  data() {
+
+  },
+  props: {
+
+  },
+  created() {
+  },
+  mounted() {
+  },
+  methods: {
+
+  }
+}
+</script>

+ 6 - 0
src/components/dataManage/SyncInterface.vue

@@ -0,0 +1,6 @@
+<template>
+    <div id="SyncInterface">
+        <h2>接口同步</h2>
+        <el-divider></el-divider>
+    </div>
+</template>

+ 225 - 0
src/components/dataManage/dataDetail/BusinessDataDetail.vue

@@ -0,0 +1,225 @@
+<template>
+  <el-dialog v-if="isShow"
+             :model-value="isShow"
+             title="编辑数据"
+             :width="700"
+             :close-on-click-modal="false"
+             :before-close="handleClose"
+  >
+    <div id="addData">
+      <el-form ref="form" :model="formData" :rules="formDataRules" style="margin: 0 15px" :label-width="110">
+        <el-form-item label="ID:" v-show="false">
+          <el-input v-model="formData.id" />
+        </el-form-item>
+        <el-form-item label="标题:" prop="title" >
+          <el-input v-model="formData.title" placeholder="请输入标题" :disabled="formData.isDataView" />
+        </el-form-item>
+        <el-form-item label="描述:" prop="content">
+          <el-input v-model="formData.content" placeholder="请输入描述" :disabled="formData.isDataView" />
+        </el-form-item>
+        <el-form-item label="类别:" prop="menuId">
+          <el-select v-model="formData.menuId" placeholder="请选择类别" :disabled="formData.isDataView" >
+            <el-option
+                v-for="item in category"
+                :key="item.value"
+                :label="item.label"
+                :value="item.value"
+            />
+          </el-select>
+        </el-form-item>
+        <el-form-item label="地理信息:" prop="geometryStr" >
+          <el-input v-model="formData.geometryStr" placeholder="请设置地理信息" :disabled="true" >
+            <template #prepend>
+              <el-button @click="handleMapShow(true)">
+                <span v-if="formData.isDataView">查看</span>
+                <span v-else>设置</span>
+                地理信息
+              </el-button>
+            </template>
+            <template #append>
+              <el-button @click="handleJsonDataView(true)">
+                查看GeoJson
+              </el-button>
+            </template>
+          </el-input>
+        </el-form-item>
+        <el-form-item label="地名地址库:" prop="address" >
+          <el-input v-model="formData.address" placeholder="请输入地名地址库名称" :disabled="formData.isDataView" />
+        </el-form-item>
+      </el-form>
+    </div>
+    <template #footer>
+      <el-button type="primary" @click="submit" v-show="!formData.isDataView">保存</el-button>
+    </template>
+  </el-dialog>
+  <OlMap v-if="isMapShow"
+         :is-show="isMapShow"
+         :is-view="formData.isDataView"
+         :menuId="formData.menuId"
+         :geometryStr="formData.geometryStr"
+         :callback="setMapData"
+         :close="handleMapShow">
+  </OlMap>
+
+  <JsonDataView v-if="isJsonDataView"
+                :is-show="isJsonDataView"
+                :title="'地理数据预览'"
+                :data="formData.geometryStr"
+                :close="handleJsonDataView"
+  >
+  </JsonDataView>
+</template>
+
+<script>
+import OlMap from "@/components/map/OlMap";
+import JsonDataView from "@/components/json/JsonDataView";
+import api from "@/api/data/BusinessData";
+import menuApi from "@/api/data/MenuData";
+
+export default {
+  data() {
+    return {
+      formData: {},
+      oriFormData: {},
+      formDataRules: {
+        title: [
+          { required: true, message: '请输入标题', trigger: 'change' },
+        ],
+        content: [
+          { required: true, message: '请输入描述', trigger: 'change' },
+        ],
+        menuId: [
+          { required: true, message: '请选择类别', trigger: 'change' },
+        ],
+        geometryStr: [
+          { required: true, message: '请输入Geojson数据', trigger: 'blur' },
+        ],
+        address: [
+          { required: true, message: '请输入地名地址库名称', trigger: 'change' },
+        ]
+      },
+      category: [],
+      isMapShow: false,
+
+      isJsonDataView: false,
+
+    }
+  },
+  props: {
+    isShow: Boolean,
+    item: Object,
+    close: Function
+  },
+  watch: {
+    "formData.menuId": function (newVal, oldVal) {
+      let app = this;
+      if (app.formData.isEdit) {
+        if (newVal!==app.oriFormData.menuId) {
+          app.$msgbox.confirm('修改类型需重新设置地理信息,确定要修改吗?','Warning', {
+            confirmButtonText: '确认修改',
+            cancelButtonText: '恢复原始类别及地理信息',
+            type: 'warning',
+          }).then(()=>{
+            app.formData.geometryStr = ''
+          }).catch(()=>{
+            app.formData.menuId = app.oriFormData.menuId;
+            app.formData.geometryStr = app.oriFormData.geometryStr;
+          })
+        } else {
+          app.formData.geometryStr = app.oriFormData.geometryStr;
+        }
+
+      }
+    }
+  },
+  mounted() {
+    this.getMenuData()
+    this.formData = this.item;
+    this.oriFormData = JSON.parse(JSON.stringify(this.formData))
+  },
+  components: {
+    OlMap,
+    JsonDataView,
+  },
+  methods: {
+    handleMapShow(flag) {
+      if (flag) {
+        if (this.formData.menuId) {
+          this.isMapShow = true
+        } else {
+          this.$message({message: '请先选择类别', type: 'warning'})
+        }
+      } else {
+        this.isMapShow = false
+      }
+    },
+    getMenuData() {
+      let app = this;
+      let params = {
+        type: "1",
+        parentId: "3",
+      }
+      menuApi.getMenuData(params).then(res=>{
+        if (res.code===200) {
+          app.category = res.content
+        }
+      })
+    },
+    setMapData(geometry) {
+      this.formData.geometryStr = JSON.stringify(geometry)
+    },
+    handleClose() {
+      this.close();
+    },
+    submit() {
+      let app = this;
+      app.$refs.form.validate(valid=>{
+        if (valid) {
+          if (app.formData.isEdit){
+            app.updateData();
+          } else {
+            app.addData();
+          }
+        } else {
+          app.$message({message: '请完善数据', type: 'warning'})
+        }
+      })
+    },
+    // 数据录入
+    addData() {
+      let app = this;
+      let params = JSON.parse(JSON.stringify(app.formData));
+      params['menuNameOne'] = '二维数据'
+      api.addData(params).then(res=>{
+        if (res.code===200) {
+          app.$message({message: '录入成功', type: 'success'})
+          app.close(true);
+        }
+      })
+    },
+    // 编辑数据
+    updateData() {
+      let app = this;
+      let params = JSON.parse(JSON.stringify(app.formData));
+      delete params.createDate;
+      delete params.updateDate;
+      api.updateData(params).then(res=>{
+        if (res.code===200) {
+          app.$message({message: '修改成功', type: 'success'})
+          app.close(true);
+        }
+      })
+    },
+    handleJsonDataView(flag) {
+      this.isJsonDataView = flag;
+    }
+  }
+}
+</script>
+
+<style>
+#addData {
+  width: 100%;
+  height: 100%;
+}
+</style>

+ 225 - 0
src/components/dataManage/dataDetail/ModelDataDetail.vue

@@ -0,0 +1,225 @@
+<template>
+  <el-dialog v-if="isShow"
+             :model-value="isShow"
+             title="编辑数据"
+             :width="700"
+             :close-on-click-modal="false"
+             :before-close="handleClose"
+  >
+    <div id="addData">
+      <el-form ref="form" :model="formData" :rules="formDataRules" style="margin: 0 15px" :label-width="110">
+        <el-form-item label="ID:" v-show="false">
+          <el-input v-model="formData.id" />
+        </el-form-item>
+        <el-form-item label="标题:" prop="title" >
+          <el-input v-model="formData.title" placeholder="请输入标题" :disabled="formData.isDataView" />
+        </el-form-item>
+        <el-form-item label="描述:" prop="content">
+          <el-input v-model="formData.content" placeholder="请输入描述" :disabled="formData.isDataView" />
+        </el-form-item>
+        <el-form-item label="类型:" prop="modelType">
+          <el-input v-model="formData.modelType" placeholder="请输入类型" :disabled="formData.isDataView" />
+        </el-form-item>
+        <el-form-item label="类别:" prop="menuId">
+          <el-select v-model="formData.menuId" placeholder="请选择类别" :disabled="formData.isDataView" >
+            <el-option
+                v-for="item in category"
+                :key="item.id"
+                :label="item.title"
+                :value="item.id"
+            />
+          </el-select>
+        </el-form-item>
+        <el-form-item label="位置" v-if="formData.isDataView" >
+          <el-input :model-value="formData.lon+', '+formData.lat" :disabled="true" >
+          </el-input>
+        </el-form-item>
+        <el-form-item label="模型数据:" prop="url" >
+          <el-input v-model="formData.url" placeholder="请设置模型地址" :disabled="formData.isDataView" >
+            <template #append>
+              <el-button @click="handleMapShow(true)">
+                查看模型
+              </el-button>
+            </template>
+          </el-input>
+        </el-form-item>
+        <el-form-item label="地名地址库:" prop="address" >
+          <el-input v-model="formData.address" placeholder="请输入地名地址库名称" :disabled="formData.isDataView" />
+        </el-form-item>
+      </el-form>
+    </div>
+    <template #footer>
+      <el-button type="primary" @click="submit" v-show="!formData.isDataView">保存</el-button>
+    </template>
+  </el-dialog>
+    <CesiumMap v-if="isMapShow"
+           :is-show="isMapShow"
+           :item="formData"
+           :close="handleMapShow">
+    </CesiumMap>
+
+  <JsonDataView v-if="isJsonDataView"
+                :is-show="isJsonDataView"
+                :title="'地理数据预览'"
+                :data="formData.geometryStr"
+                :close="handleJsonDataView"
+  >
+  </JsonDataView>
+</template>
+
+<script>
+import CesiumMap from "@/components/map/CesiumMap";
+import JsonDataView from "@/components/json/JsonDataView";
+import api from "@/api/data/ModelData";
+import menuApi from "@/api/data/MenuData";
+
+export default {
+  data() {
+    return {
+      formData: {},
+      oriFormData: {},
+      formDataRules: {
+        title: [
+          { required: true, message: '请输入标题', trigger: 'change' },
+        ],
+        content: [
+          { required: true, message: '请输入描述', trigger: 'change' },
+        ],
+        modelType: [
+          { required: true, message: '请输入类型', trigger: 'change' },
+        ],
+        menuId: [
+          { required: true, message: '请选择类别', trigger: 'change' },
+        ],
+        geometryStr: [
+          { required: true, message: '请输入Geojson数据', trigger: 'blur' },
+        ],
+        address1: [
+          { required: true, message: '请输入地名地址库名称', trigger: 'change' },
+        ]
+      },
+      category: [],
+      isMapShow: false,
+
+      isJsonDataView: false,
+
+    }
+  },
+  props: {
+    isShow: Boolean,
+    item: Object,
+    close: Function
+  },
+  watch: {
+    "formData.menuId": function (newVal, oldVal) {
+      let app = this;
+      if (app.formData.isEdit) {
+        if (oldVal && newVal!==app.oriFormData.menuId) {
+          app.$msgbox.confirm('修改类型需重新设置地理信息,确定要修改吗?','Warning', {
+            confirmButtonText: '确认修改',
+            cancelButtonText: '恢复原始类别及地理信息',
+            type: 'warning',
+          }).then(()=>{
+            app.formData.geometryStr = ''
+          }).catch(()=>{
+            app.formData.menuId = app.oriFormData.menuId;
+            app.formData.geometryStr = app.oriFormData.geometryStr;
+          })
+        } else {
+          app.formData.geometryStr = app.oriFormData.geometryStr;
+        }
+
+      }
+    }
+  },
+  mounted() {
+    this.getMenuData();
+    this.formData = this.item;
+    this.oriFormData = JSON.parse(JSON.stringify(this.formData))
+  },
+  components: {
+    CesiumMap,
+    JsonDataView,
+  },
+  methods: {
+    handleMapShow(flag) {
+      if (flag) {
+        if (this.formData.menuId) {
+          this.isMapShow = true
+        } else {
+          this.$message({message: '请先选择类别', type: 'warning'})
+        }
+      } else {
+        this.isMapShow = false
+      }
+    },
+    getMenuData() {
+      let app = this;
+      let params = {
+        type: "1",
+        parentId: "4",
+      }
+      menuApi.getMenuData(params).then(res=>{
+        if (res.code===200) {
+          app.category = res.content
+        }
+      })
+    },
+    setMapData(geometry) {
+      this.formData.geometryStr = JSON.stringify(geometry)
+    },
+    handleClose() {
+      this.close();
+    },
+    submit() {
+      let app = this;
+      app.$refs.form.validate(valid=>{
+        if (valid) {
+          if (app.formData.isEdit){
+            app.updateData();
+          } else {
+            app.addData();
+          }
+        } else {
+          app.$message({message: '请完善数据', type: 'warning'})
+        }
+      })
+    },
+    // 数据录入
+    addData() {
+      let app = this;
+      let params = JSON.parse(JSON.stringify(app.formData));
+      params['menuNameOne'] = '二维数据'
+      api.addData(params).then(res=>{
+        if (res.code===200) {
+          app.$message({message: '录入成功', type: 'success'})
+          app.close(true);
+        }
+      })
+    },
+    // 编辑数据
+    updateData() {
+      let app = this;
+      let params = JSON.parse(JSON.stringify(app.formData));
+      delete params.createDate;
+      delete params.updateDate;
+      api.updateData(params).then(res=>{
+        if (res.code===200) {
+          app.$message({message: '修改成功', type: 'success'})
+          app.close(true);
+        }
+      })
+    },
+    handleJsonDataView(flag) {
+      this.isJsonDataView = flag;
+    }
+  }
+}
+</script>
+
+<style>
+#addData {
+  width: 100%;
+  height: 100%;
+}
+</style>

+ 225 - 0
src/components/dataManage/dataDetail/ThreeDimensionalDataDetail.vue

@@ -0,0 +1,225 @@
+<template>
+  <el-dialog v-if="isShow"
+             :model-value="isShow"
+             title="编辑数据"
+             :width="700"
+             :close-on-click-modal="false"
+             :before-close="handleClose"
+  >
+    <div id="addData">
+      <el-form ref="form" :model="formData" :rules="formDataRules" style="margin: 0 15px" :label-width="110">
+        <el-form-item label="ID:" v-show="false">
+          <el-input v-model="formData.id" />
+        </el-form-item>
+        <el-form-item label="标题:" prop="title" >
+          <el-input v-model="formData.title" placeholder="请输入标题" :disabled="formData.isDataView" />
+        </el-form-item>
+        <el-form-item label="描述:" prop="content">
+          <el-input v-model="formData.content" placeholder="请输入描述" :disabled="formData.isDataView" />
+        </el-form-item>
+        <el-form-item label="类别:" prop="menuId">
+          <el-select v-model="formData.menuId" placeholder="请选择类别" :disabled="formData.isDataView" >
+            <el-option
+                v-for="item in category"
+                :key="item.id"
+                :label="item.title"
+                :value="item.id"
+            />
+          </el-select>
+        </el-form-item>
+        <el-form-item label="地理信息:" prop="geometryStr" >
+          <el-input v-model="formData.geometryStr" placeholder="请设置地理信息" :disabled="true" >
+            <template #prepend>
+              <el-button @click="handleMapShow(true)">
+                <span v-if="formData.isDataView">查看</span>
+                <span v-else>设置</span>
+                地理信息
+              </el-button>
+            </template>
+            <template #append>
+              <el-button @click="handleJsonDataView(true)">
+                查看GeoJson
+              </el-button>
+            </template>
+          </el-input>
+        </el-form-item>
+        <el-form-item label="地名地址库:" prop="address" >
+          <el-input v-model="formData.address" placeholder="请输入地名地址库名称" :disabled="formData.isDataView" />
+        </el-form-item>
+      </el-form>
+    </div>
+    <template #footer>
+      <el-button type="primary" @click="submit" v-show="!formData.isDataView">保存</el-button>
+    </template>
+  </el-dialog>
+    <OlMap v-if="isMapShow"
+           :is-show="isMapShow"
+           :is-view="formData.isDataView"
+           :menuId="formData.menuId"
+           :geometryStr="formData.geometryStr"
+           :callback="setMapData"
+           :close="handleMapShow">
+    </OlMap>
+
+  <JsonDataView v-if="isJsonDataView"
+                :is-show="isJsonDataView"
+                :title="'地理数据预览'"
+                :data="formData.geometryStr"
+                :close="handleJsonDataView"
+  >
+  </JsonDataView>
+</template>
+
+<script>
+import OlMap from "@/components/map/OlMap";
+import JsonDataView from "@/components/json/JsonDataView";
+import api from "@/api/data/TwoDimensionalData";
+import menuApi from "@/api/data/MenuData";
+
+export default {
+  data() {
+    return {
+      formData: {},
+      oriFormData: {},
+      formDataRules: {
+        title: [
+          { required: true, message: '请输入标题', trigger: 'change' },
+        ],
+        content: [
+          { required: true, message: '请输入描述', trigger: 'change' },
+        ],
+        menuId: [
+          { required: true, message: '请选择类别', trigger: 'change' },
+        ],
+        geometryStr: [
+          { required: true, message: '请输入Geojson数据', trigger: 'blur' },
+        ],
+        address: [
+          { required: true, message: '请输入地名地址库名称', trigger: 'change' },
+        ]
+      },
+      category: [],
+      isMapShow: false,
+
+      isJsonDataView: false,
+
+    }
+  },
+  props: {
+    isShow: Boolean,
+    item: Object,
+    close: Function
+  },
+  watch: {
+    "formData.menuId": function (newVal, oldVal) {
+      let app = this;
+      if (app.formData.isEdit) {
+        if (newVal!==app.oriFormData.menuId) {
+          app.$msgbox.confirm('修改类型需重新设置地理信息,确定要修改吗?','Warning', {
+            confirmButtonText: '确认修改',
+            cancelButtonText: '恢复原始类别及地理信息',
+            type: 'warning',
+          }).then(()=>{
+            app.formData.geometryStr = ''
+          }).catch(()=>{
+            app.formData.menuId = app.oriFormData.menuId;
+            app.formData.geometryStr = app.oriFormData.geometryStr;
+          })
+        } else {
+          app.formData.geometryStr = app.oriFormData.geometryStr;
+        }
+
+      }
+    }
+  },
+  mounted() {
+    this.getMenuData()
+    this.formData = this.item;
+    this.oriFormData = JSON.parse(JSON.stringify(this.formData))
+  },
+  components: {
+    OlMap,
+    JsonDataView,
+  },
+  methods: {
+    handleMapShow(flag) {
+      if (flag) {
+        if (this.formData.menuId) {
+          this.isMapShow = true
+        } else {
+          this.$message({message: '请先选择类别', type: 'warning'})
+        }
+      } else {
+        this.isMapShow = false
+      }
+    },
+    getMenuData() {
+      let app = this;
+      let params = {
+        type: "1",
+        parentId: "2",
+      }
+      menuApi.getMenuData(params).then(res=>{
+        if (res.code===200) {
+          app.category = res.content
+        }
+      })
+    },
+    setMapData(geometry) {
+      this.formData.geometryStr = JSON.stringify(geometry)
+    },
+    handleClose() {
+      this.close();
+    },
+    submit() {
+      let app = this;
+      app.$refs.form.validate(valid=>{
+        if (valid) {
+          if (app.formData.isEdit){
+            app.updateData();
+          } else {
+            app.addData();
+          }
+        } else {
+          app.$message({message: '请完善数据', type: 'warning'})
+        }
+      })
+    },
+    // 数据录入
+    addData() {
+      let app = this;
+      let params = JSON.parse(JSON.stringify(app.formData));
+      params['menuNameOne'] = '二维数据'
+      api.addData(params).then(res=>{
+        if (res.code===200) {
+          app.$message({message: '录入成功', type: 'success'})
+          app.close(true);
+        }
+      })
+    },
+    // 编辑数据
+    updateData() {
+      let app = this;
+      let params = JSON.parse(JSON.stringify(app.formData));
+      delete params.createDate;
+      delete params.updateDate;
+      api.updateData(params).then(res=>{
+        if (res.code===200) {
+          app.$message({message: '修改成功', type: 'success'})
+          app.close(true);
+        }
+      })
+    },
+    handleJsonDataView(flag) {
+      this.isJsonDataView = flag;
+    }
+  }
+}
+</script>
+
+<style>
+#addData {
+  width: 100%;
+  height: 100%;
+}
+</style>

+ 225 - 0
src/components/dataManage/dataDetail/TwoDimensionalDataDetail.vue

@@ -0,0 +1,225 @@
+<template>
+  <el-dialog v-if="isShow"
+             :model-value="isShow"
+             title="编辑数据"
+             :width="700"
+             :close-on-click-modal="false"
+             :before-close="handleClose"
+  >
+    <div id="addData">
+      <el-form ref="form" :model="formData" :rules="formDataRules" style="margin: 0 15px" :label-width="110">
+        <el-form-item label="ID:" v-show="false">
+          <el-input v-model="formData.id" />
+        </el-form-item>
+        <el-form-item label="标题:" prop="title" >
+          <el-input v-model="formData.title" placeholder="请输入标题" :disabled="formData.isDataView" />
+        </el-form-item>
+        <el-form-item label="描述:" prop="content">
+          <el-input v-model="formData.content" placeholder="请输入描述" :disabled="formData.isDataView" />
+        </el-form-item>
+        <el-form-item label="类别:" prop="menuId">
+          <el-select v-model="formData.menuId" placeholder="请选择类别" :disabled="formData.isDataView" >
+            <el-option
+                v-for="item in category"
+                :key="item.id"
+                :label="item.title"
+                :value="item.id"
+            />
+          </el-select>
+        </el-form-item>
+        <el-form-item label="地理信息:" prop="geometryStr" >
+          <el-input v-model="formData.geometryStr" placeholder="请设置地理信息" :disabled="true" >
+            <template #prepend>
+              <el-button @click="handleMapShow(true)">
+                <span v-if="formData.isDataView">查看</span>
+                <span v-else>设置</span>
+                地理信息
+              </el-button>
+            </template>
+            <template #append>
+              <el-button @click="handleJsonDataView(true)">
+                查看GeoJson
+              </el-button>
+            </template>
+          </el-input>
+        </el-form-item>
+        <el-form-item label="地名地址库:" prop="address" >
+          <el-input v-model="formData.address" placeholder="请输入地名地址库名称" :disabled="formData.isDataView" />
+        </el-form-item>
+      </el-form>
+    </div>
+    <template #footer>
+      <el-button type="primary" @click="submit" v-show="!formData.isDataView">保存</el-button>
+    </template>
+  </el-dialog>
+    <OlMap v-if="isMapShow"
+           :is-show="isMapShow"
+           :is-view="formData.isDataView"
+           :menuId="formData.menuId"
+           :geometryStr="formData.geometryStr"
+           :callback="setMapData"
+           :close="handleMapShow">
+    </OlMap>
+
+  <JsonDataView v-if="isJsonDataView"
+                :is-show="isJsonDataView"
+                :title="'地理数据预览'"
+                :data="formData.geometryStr"
+                :close="handleJsonDataView"
+  >
+  </JsonDataView>
+</template>
+
+<script>
+import OlMap from "@/components/map/OlMap";
+import JsonDataView from "@/components/json/JsonDataView";
+import api from "@/api/data/TwoDimensionalData";
+import menuApi from "@/api/data/MenuData";
+
+export default {
+  data() {
+    return {
+      formData: {},
+      oriFormData: {},
+      formDataRules: {
+        title: [
+          { required: true, message: '请输入标题', trigger: 'change' },
+        ],
+        content: [
+          { required: true, message: '请输入描述', trigger: 'change' },
+        ],
+        menuId: [
+          { required: true, message: '请选择类别', trigger: 'change' },
+        ],
+        geometryStr: [
+          { required: true, message: '请输入Geojson数据', trigger: 'blur' },
+        ],
+        address: [
+          { required: true, message: '请输入地名地址库名称', trigger: 'change' },
+        ]
+      },
+      category: [],
+      isMapShow: false,
+
+      isJsonDataView: false,
+
+    }
+  },
+  props: {
+    isShow: Boolean,
+    item: Object,
+    close: Function
+  },
+  watch: {
+    "formData.menuId": function (newVal, oldVal) {
+      let app = this;
+      if (app.formData.isEdit) {
+        if (newVal!==app.oriFormData.menuId) {
+          app.$msgbox.confirm('修改类型需重新设置地理信息,确定要修改吗?','Warning', {
+            confirmButtonText: '确认修改',
+            cancelButtonText: '恢复原始类别及地理信息',
+            type: 'warning',
+          }).then(()=>{
+            app.formData.geometryStr = ''
+          }).catch(()=>{
+            app.formData.menuId = app.oriFormData.menuId;
+            app.formData.geometryStr = app.oriFormData.geometryStr;
+          })
+        } else {
+          app.formData.geometryStr = app.oriFormData.geometryStr;
+        }
+
+      }
+    }
+  },
+  mounted() {
+    this.getMenuData()
+    this.formData = this.item;
+    this.oriFormData = JSON.parse(JSON.stringify(this.formData))
+  },
+  components: {
+    OlMap,
+    JsonDataView,
+  },
+  methods: {
+    handleMapShow(flag) {
+      if (flag) {
+        if (this.formData.menuId) {
+          this.isMapShow = true
+        } else {
+          this.$message({message: '请先选择类别', type: 'warning'})
+        }
+      } else {
+        this.isMapShow = false
+      }
+    },
+    getMenuData() {
+      let app = this;
+      let params = {
+        type: "1",
+        parentId: "1",
+      }
+      menuApi.getMenuData(params).then(res=>{
+        if (res.code===200) {
+          app.category = res.content
+        }
+      })
+    },
+    setMapData(geometry) {
+      this.formData.geometryStr = JSON.stringify(geometry)
+    },
+    handleClose() {
+      this.close();
+    },
+    submit() {
+      let app = this;
+      app.$refs.form.validate(valid=>{
+        if (valid) {
+          if (app.formData.isEdit){
+            app.updateData();
+          } else {
+            app.addData();
+          }
+        } else {
+          app.$message({message: '请完善数据', type: 'warning'})
+        }
+      })
+    },
+    // 数据录入
+    addData() {
+      let app = this;
+      let params = JSON.parse(JSON.stringify(app.formData));
+      params['menuNameOne'] = '二维数据'
+      api.addData(params).then(res=>{
+        if (res.code===200) {
+          app.$message({message: '录入成功', type: 'success'})
+          app.close(true);
+        }
+      })
+    },
+    // 编辑数据
+    updateData() {
+      let app = this;
+      let params = JSON.parse(JSON.stringify(app.formData));
+      delete params.createDate;
+      delete params.updateDate;
+      api.updateData(params).then(res=>{
+        if (res.code===200) {
+          app.$message({message: '修改成功', type: 'success'})
+          app.close(true);
+        }
+      })
+    },
+    handleJsonDataView(flag) {
+      this.isJsonDataView = flag;
+    }
+  }
+}
+</script>
+
+<style>
+#addData {
+  width: 100%;
+  height: 100%;
+}
+</style>

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

@@ -0,0 +1,223 @@
+<!-- 业务数据 -->
+<template>
+  <div id="data">
+    <el-button type="primary" @click="addDataClick">录入业务数据</el-button>
+    <el-button type="warning" @click="batchDelete">批量删除</el-button>
+    <div class="operation">
+      <el-form :model="filterForm" :inline="true">
+        <el-form-item label="地名地址库名称:">
+          <el-input v-model="filterForm.name" placeholder="请输入地名地址库名称"></el-input>
+        </el-form-item>
+        <el-form-item>
+          <el-button type="primary" @click="search">搜索</el-button>
+        </el-form-item>
+      </el-form>
+    </div>
+    <div class="list">
+      <el-table ref="dataTable" v-loading="loading" element-loading-text="正在加载,请稍后..." :data="tableData"
+                :border="true" :stripe="true" :height="440" style="width: 100%;margin-bottom: 15px;"
+                @selection-change="handleTableSelect">
+        <el-table-column type="selection" width="55"/>
+        <el-table-column prop="id" label="ID" width="100" :show-overflow-tooltip="true">
+          <template #default="scope">
+            <span style="cursor: pointer" @click="$util.clipboard.copyText(scope.row.id)"> {{ scope.row.id }} </span>
+          </template>
+        </el-table-column>
+        <el-table-column prop="title" label="标题" width="200"/>
+        <el-table-column prop="content" label="描述" width="250"/>
+        <el-table-column prop="menuNameTwo" label="类别" width="80"/>
+        <el-table-column prop="importType" label="导入类型" width="150"/>
+        <el-table-column prop="updator" label="修改人"/>
+        <el-table-column prop="updateDate" label="修改时间" width="160">
+          <template #default="scope">
+            {{ $util.datetime.format(scope.row.updateDate) }}
+          </template>
+        </el-table-column>
+        <el-table-column prop="creator" label="创建人"/>
+        <el-table-column prop="createDate" label="创建时间" width="160">
+          <template #default="scope">
+            {{ $util.datetime.format(scope.row.createDate) }}
+          </template>
+        </el-table-column>
+        <el-table-column prop="operation" label="操作" width="150" fixed="right">
+          <template #default="scope">
+            <el-tooltip class="box-item" effect="dark" content="查看详情" placement="top-start">
+              <el-button type="default" @click="viewData(scope.row)" circle>
+                <el-icon>
+                  <ElIconView/>
+                </el-icon>
+              </el-button>
+            </el-tooltip>
+
+            <el-tooltip class="box-item" effect="dark" content="编辑" placement="top-start">
+              <el-button type="primary" @click="editData(scope.row)" circle>
+                <el-icon>
+                  <ElIconEdit/>
+                </el-icon>
+              </el-button>
+            </el-tooltip>
+
+            <el-tooltip class="box-item" effect="dark" content="删除" placement="top-start">
+              <el-button type="danger" @click="deleteData(scope.row)" circle>
+                <el-icon>
+                  <ElIconDelete/>
+                </el-icon>
+              </el-button>
+            </el-tooltip>
+
+          </template>
+        </el-table-column>
+      </el-table>
+      <el-pagination style="float:right" background layout="sizes, prev, pager, next, jumper, total"
+                     v-model:current-page="pageInfo.page" v-model:page-size="pageInfo.pageSize"
+                     v-model:total="pageInfo.total"/>
+    </div>
+  </div>
+
+  <BusinessDataDetail v-if="isDetailShow" :is-show="isDetailShow" :item="currRow" :close="handleDetailShow"></BusinessDataDetail>
+</template>
+
+<script>
+import api from '@/api/data/BusinessData'
+import BusinessDataDetail from "@/components/dataManage/dataDetail/BusinessDataDetail";
+import menuApi from "@/api/data/MenuData";
+
+export default {
+  data() {
+    return {
+      loading: false,
+      filterForm: {},
+      tableData: [],
+      currRow: {},
+      selectedRows: [],
+      pageInfo: {
+        page: 1,
+        pageSize: 10,
+        total: 0,
+      },
+
+      isDetailShow: false,
+    }
+  },
+  components: {
+    BusinessDataDetail
+  },
+  created() {
+  },
+  mounted() {
+    this.getData();
+  },
+  watch: {
+    "pageInfo.page": function (val) {
+      if (val > 0) {
+        this.getData();
+      }
+    },
+    "pageInfo.pageSize": function () {
+      let app = this;
+      this.pageInfo.page = -1;
+      setTimeout(function () {
+        app.pageInfo.page = 1;
+      }, 50)
+    },
+  },
+  methods: {
+    handleLoading(flag) {
+      let app = this;
+      if (flag) {
+        app.loading = true;
+      } else {
+        setTimeout(() => {
+          app.loading = false;
+        }, 500);
+      }
+    },
+    getData() {
+      let app = this;
+      let params = {
+        page: app.pageInfo.page,
+        pageSize: app.pageInfo.pageSize
+      }
+      app.handleLoading(true)
+      api.getData(params).then(res => {
+        if (res.code === 200) {
+          app.pageInfo.total = res.total;
+          app.tableData = res.content
+        }
+        app.handleLoading(false)
+      }).catch(err => {
+        app.handleLoading(false)
+      })
+    },
+    search() {
+
+    },
+    handleTableSelect(val) {
+      this.selectedRows = val;
+    },
+    handleDetailShow(flag) {
+      if (flag) {
+        this.getData()
+      }
+      this.isDetailShow = false
+    },
+    // 录入数据
+    addDataClick() {
+      this.currRow = {};
+      this.isDetailShow = true;
+    },
+    // 批量删除数据
+    batchDelete() {
+      if (!this.selectedRows) {
+        return;
+      }
+      let ids = this.selectedRows.map(i=> {return i.id}).join(',');
+    },
+    // 查看详情
+    viewData(item) {
+      let app = this;
+      if (item.menuId) {
+        item.menuId = Number(item.menuId);
+      }
+      app.currRow = JSON.parse(JSON.stringify(item))
+      app.currRow.geometryStr = JSON.stringify(item.geometry)
+      delete app.currRow.geometry
+      this.currRow.isDataView = true;
+      app.isDetailShow = true
+    },
+    // 编辑数据
+    editData(item) {
+      let app = this;
+      if (item.menuId) {
+        item.menuId = Number(item.menuId);
+      }
+      app.currRow = JSON.parse(JSON.stringify(item))
+      app.currRow.geometryStr = JSON.stringify(item.geometry)
+      delete app.currRow.geometry
+      this.currRow.isEdit = true;
+      app.isDetailShow = true
+    },
+    // 删除数据
+    deleteData(item) {
+      let app = this;
+      let params = {
+        baseDataId: item.id
+      }
+      app.$msgbox.confirm('确认要删除此条数据吗?').then(()=>{
+        api.deleteData(params).then(res=>{
+          if (res.code === 200) {
+            app.getData();
+            app.$message({message: '删除成功', type: 'success'});
+          }
+        })
+      })
+    },
+  }
+}
+</script>
+
+<style>
+#data .operation {
+  float: right;
+}
+</style>

+ 95 - 0
src/components/dataManage/dataShow/IotData.vue

@@ -0,0 +1,95 @@
+<!-- 物联感知数据 -->
+<template>
+    <div id="data">
+        <el-button type="primary">录入物联感知数据</el-button>
+        <el-button type="warning">批量删除</el-button>
+        <div class="operation" >
+            <el-form :model="filterForm" :inline="true">
+                <el-form-item label="地名地址库名称:">
+                    <el-input v-model="filterForm.name" placeholder="请输入地名地址库名称"></el-input>
+                </el-form-item>
+                <el-form-item>
+                    <el-button type="primary">搜索</el-button>
+                </el-form-item>
+            </el-form>
+        </div>
+        <div class="list">
+            <el-table ref="dataTable" :data="tableData" :border="true" :stripe="true" :height="440" style="width: 100%;margin-bottom: 15px;" @selection-change="handleTableSelect">
+                <el-table-column type="selection" width="55" />
+                <el-table-column prop="id" label="ID" />
+                <el-table-column prop="title" label="标题" />
+                <el-table-column prop="desc" label="描述" />
+                <el-table-column prop="createTime" label="创建时间" />
+                <el-table-column prop="creator" label="创建人" />
+                <el-table-column prop="updateTime" label="修改时间" />
+                <el-table-column prop="updator" label="修改人" />
+                <el-table-column prop="operation" label="操作" width="150">
+                    <template #default="scope">
+                        <el-tooltip class="box-item" effect="dark" content="查看详情" placement="top-start">
+                            <el-button type="default" circle>
+                                <el-icon>
+                                    <ElIconView />
+                                </el-icon>
+                            </el-button>
+                        </el-tooltip>
+
+                        <el-tooltip class="box-item" effect="dark" content="编辑" placement="top-start">
+                            <el-button type="primary" circle>
+                                <el-icon>
+                                    <ElIconEdit />
+                                </el-icon>
+                            </el-button>
+                        </el-tooltip>
+
+                        <el-tooltip class="box-item" effect="dark" content="删除" placement="top-start">
+                            <el-button type="danger" circle>
+                                <el-icon>
+                                    <ElIconDelete />
+                                </el-icon>
+                            </el-button>
+                        </el-tooltip>
+
+                    </template>
+                </el-table-column>
+            </el-table>
+            <el-pagination style="float:right" background layout="sizes, prev, pager, next, jumper, totle"
+                v-model:current-page="pageInfo.page" :total="1000" />
+        </div>
+    </div>
+</template>
+
+<script>
+import mockData from '@/static/files/mockData'
+
+export default {
+    data() {
+        return {
+            filterForm: {},
+            tableData: [],
+            pageInfo: {
+                page: 1,
+                pageSize: 10
+            }
+        }
+    },
+    created() {
+        this.getData();
+    },
+    mounted() {
+
+    },
+    methods: {
+        getData() {
+            this.tableData = mockData;
+        },
+        handleTableSelect(val) {
+        }
+    }
+}
+</script>
+
+<style>
+#data .operation {
+    float: right;
+}
+</style>

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

@@ -0,0 +1,223 @@
+<!-- 业务数据 -->
+<template>
+  <div id="data">
+    <el-button type="primary" @click="addDataClick">录入元数据</el-button>
+    <el-button type="warning" @click="batchDelete">批量删除</el-button>
+    <div class="operation">
+      <el-form :model="filterForm" :inline="true">
+        <el-form-item label="地名地址库名称:">
+          <el-input v-model="filterForm.name" placeholder="请输入地名地址库名称"></el-input>
+        </el-form-item>
+        <el-form-item>
+          <el-button type="primary" @click="search">搜索</el-button>
+        </el-form-item>
+      </el-form>
+    </div>
+    <div class="list">
+      <el-table ref="dataTable" v-loading="loading" element-loading-text="正在加载,请稍后..." :data="tableData"
+                :border="true" :stripe="true" :height="440" style="width: 100%;margin-bottom: 15px;"
+                @selection-change="handleTableSelect">
+        <el-table-column type="selection" width="55"/>
+        <el-table-column prop="id" label="ID" width="100" :show-overflow-tooltip="true">
+          <template #default="scope">
+            <span style="cursor: pointer" @click="$util.clipboard.copyText(scope.row.id)"> {{ scope.row.id }} </span>
+          </template>
+        </el-table-column>
+        <el-table-column prop="title" label="标题" width="200"/>
+        <el-table-column prop="content" label="描述" width="250"/>
+        <el-table-column prop="menuNameTwo" label="类别" width="80"/>
+        <el-table-column prop="importType" label="导入类型" width="150"/>
+        <el-table-column prop="updator" label="修改人"/>
+        <el-table-column prop="updateDate" label="修改时间" width="160">
+          <template #default="scope">
+            {{ $util.datetime.format(scope.row.updateDate) }}
+          </template>
+        </el-table-column>
+        <el-table-column prop="creator" label="创建人"/>
+        <el-table-column prop="createDate" label="创建时间" width="160">
+          <template #default="scope">
+            {{ $util.datetime.format(scope.row.createDate) }}
+          </template>
+        </el-table-column>
+        <el-table-column prop="operation" label="操作" width="150" fixed="right">
+          <template #default="scope">
+            <el-tooltip class="box-item" effect="dark" content="查看详情" placement="top-start">
+              <el-button type="default" @click="viewData(scope.row)" circle>
+                <el-icon>
+                  <ElIconView/>
+                </el-icon>
+              </el-button>
+            </el-tooltip>
+
+            <el-tooltip class="box-item" effect="dark" content="编辑" placement="top-start">
+              <el-button type="primary" @click="editData(scope.row)" circle>
+                <el-icon>
+                  <ElIconEdit/>
+                </el-icon>
+              </el-button>
+            </el-tooltip>
+
+            <el-tooltip class="box-item" effect="dark" content="删除" placement="top-start">
+              <el-button type="danger" @click="deleteData(scope.row)" circle>
+                <el-icon>
+                  <ElIconDelete/>
+                </el-icon>
+              </el-button>
+            </el-tooltip>
+
+          </template>
+        </el-table-column>
+      </el-table>
+      <el-pagination style="float:right" background layout="sizes, prev, pager, next, jumper, total"
+                     v-model:current-page="pageInfo.page" v-model:page-size="pageInfo.pageSize"
+                     v-model:total="pageInfo.total"/>
+    </div>
+  </div>
+
+  <BusinessDataDetail v-if="isDetailShow" :is-show="isDetailShow" :item="currRow" :close="handleDetailShow"></BusinessDataDetail>
+</template>
+
+<script>
+import api from '@/api/data/BusinessData'
+import BusinessDataDetail from "@/components/dataManage/dataDetail/BusinessDataDetail";
+import menuApi from "@/api/data/MenuData";
+
+export default {
+  data() {
+    return {
+      loading: false,
+      filterForm: {},
+      tableData: [],
+      currRow: {},
+      selectedRows: [],
+      pageInfo: {
+        page: 1,
+        pageSize: 10,
+        total: 0,
+      },
+
+      isDetailShow: false,
+    }
+  },
+  components: {
+    BusinessDataDetail
+  },
+  created() {
+  },
+  mounted() {
+    this.getData();
+  },
+  watch: {
+    "pageInfo.page": function (val) {
+      if (val > 0) {
+        this.getData();
+      }
+    },
+    "pageInfo.pageSize": function () {
+      let app = this;
+      this.pageInfo.page = -1;
+      setTimeout(function () {
+        app.pageInfo.page = 1;
+      }, 50)
+    },
+  },
+  methods: {
+    handleLoading(flag) {
+      let app = this;
+      if (flag) {
+        app.loading = true;
+      } else {
+        setTimeout(() => {
+          app.loading = false;
+        }, 500);
+      }
+    },
+    getData() {
+      let app = this;
+      let params = {
+        page: app.pageInfo.page,
+        pageSize: app.pageInfo.pageSize
+      }
+      app.handleLoading(true)
+      api.getData(params).then(res => {
+        if (res.code === 200) {
+          app.pageInfo.total = res.total;
+          app.tableData = res.content
+        }
+        app.handleLoading(false)
+      }).catch(err => {
+        app.handleLoading(false)
+      })
+    },
+    search() {
+
+    },
+    handleTableSelect(val) {
+      this.selectedRows = val;
+    },
+    handleDetailShow(flag) {
+      if (flag) {
+        this.getData()
+      }
+      this.isDetailShow = false
+    },
+    // 录入数据
+    addDataClick() {
+      this.currRow = {};
+      this.isDetailShow = true;
+    },
+    // 批量删除数据
+    batchDelete() {
+      if (!this.selectedRows) {
+        return;
+      }
+      let ids = this.selectedRows.map(i=> {return i.id}).join(',');
+    },
+    // 查看详情
+    viewData(item) {
+      let app = this;
+      if (item.menuId) {
+        item.menuId = Number(item.menuId);
+      }
+      app.currRow = JSON.parse(JSON.stringify(item))
+      app.currRow.geometryStr = JSON.stringify(item.geometry)
+      delete app.currRow.geometry
+      this.currRow.isDataView = true;
+      app.isDetailShow = true
+    },
+    // 编辑数据
+    editData(item) {
+      let app = this;
+      if (item.menuId) {
+        item.menuId = Number(item.menuId);
+      }
+      app.currRow = JSON.parse(JSON.stringify(item))
+      app.currRow.geometryStr = JSON.stringify(item.geometry)
+      delete app.currRow.geometry
+      this.currRow.isEdit = true;
+      app.isDetailShow = true
+    },
+    // 删除数据
+    deleteData(item) {
+      let app = this;
+      let params = {
+        metadataId: item.id
+      }
+      app.$msgbox.confirm('确认要删除此条数据吗?').then(()=>{
+        api.deleteData(params).then(res=>{
+          if (res.code === 200) {
+            app.getData();
+            app.$message({message: '删除成功', type: 'success'});
+          }
+        })
+      })
+    },
+  }
+}
+</script>
+
+<style>
+#data .operation {
+  float: right;
+}
+</style>

+ 226 - 0
src/components/dataManage/dataShow/ModelData.vue

@@ -0,0 +1,226 @@
+<!-- 模型数据 -->
+<template>
+  <div id="data">
+    <el-button type="primary" @click="addDataClick">录入模型数据</el-button>
+    <el-button type="warning" @click="batchDelete">批量删除</el-button>
+    <div class="operation">
+      <el-form :model="filterForm" :inline="true">
+        <el-form-item label="地名地址库名称:">
+          <el-input v-model="filterForm.name" placeholder="请输入地名地址库名称"></el-input>
+        </el-form-item>
+        <el-form-item>
+          <el-button type="primary" @click="search">搜索</el-button>
+        </el-form-item>
+      </el-form>
+    </div>
+    <div class="list">
+      <el-table ref="dataTable" v-loading="loading" element-loading-text="正在加载,请稍后..." :data="tableData"
+                :border="true" :stripe="true" :height="440" style="width: 100%;margin-bottom: 15px;"
+                @selection-change="handleTableSelect">
+        <el-table-column type="selection" width="55"/>
+        <el-table-column prop="id" label="ID" width="100" :show-overflow-tooltip="true">
+          <template #default="scope">
+            <span style="cursor: pointer" @click="$util.clipboard.copyText(scope.row.id)"> {{ scope.row.id }} </span>
+          </template>
+        </el-table-column>
+        <el-table-column prop="title" label="标题" width="200"/>
+        <el-table-column prop="content" label="描述" width="250"/>
+        <el-table-column prop="modelType" label="类型" width="120"/>
+        <el-table-column prop="menuNameTwo" label="类别" width="120"/>
+        <el-table-column prop="lon" label="位置" width="130">
+          <template #default="scope">
+            [
+            <span v-if="scope.row.lon && scope.row.lon!=='' && scope.row.lat && scope.row.lat!==''">
+              {{ scope.row.lon }},<br/> {{ scope.row.lat }}
+            </span>
+            ]
+          </template>
+        </el-table-column>
+        <el-table-column prop="address" label="地名地址库" width="150"/>
+        <el-table-column prop="updator" label="修改人"/>
+        <el-table-column prop="updateDate" label="修改时间" width="160">
+          <template #default="scope">
+            {{ $util.datetime.format(scope.row.updateDate) }}
+          </template>
+        </el-table-column>
+        <el-table-column prop="creator" label="创建人"/>
+        <el-table-column prop="createDate" label="创建时间" width="160">
+          <template #default="scope">
+            {{ $util.datetime.format(scope.row.createDate) }}
+          </template>
+        </el-table-column>
+        <el-table-column prop="operation" label="操作" width="150" fixed="right">
+          <template #default="scope">
+            <el-tooltip class="box-item" effect="dark" content="查看详情" placement="top-start">
+              <el-button type="default" @click="viewData(scope.row)" circle>
+                <el-icon>
+                  <ElIconView/>
+                </el-icon>
+              </el-button>
+            </el-tooltip>
+
+            <el-tooltip class="box-item" effect="dark" content="编辑" placement="top-start">
+              <el-button type="primary" @click="editData(scope.row)" circle>
+                <el-icon>
+                  <ElIconEdit/>
+                </el-icon>
+              </el-button>
+            </el-tooltip>
+
+            <el-tooltip class="box-item" effect="dark" content="删除" placement="top-start">
+              <el-button type="danger" @click="deleteData(scope.row)" circle>
+                <el-icon>
+                  <ElIconDelete/>
+                </el-icon>
+              </el-button>
+            </el-tooltip>
+
+          </template>
+        </el-table-column>
+      </el-table>
+      <el-pagination style="float:right" background layout="sizes, prev, pager, next, jumper, total"
+                     v-model:current-page="pageInfo.page" v-model:page-size="pageInfo.pageSize"
+                     v-model:total="pageInfo.total"/>
+    </div>
+  </div>
+
+  <ModelDataDetail v-if="isDetailShow" :is-show="isDetailShow" :item="currRow" :close="handleDetailShow"></ModelDataDetail>
+</template>
+
+<script>
+import api from '@/api/data/ModelData'
+import ModelDataDetail from "@/components/dataManage/dataDetail/ModelDataDetail";
+
+export default {
+  data() {
+    return {
+      loading: false,
+      filterForm: {},
+      tableData: [],
+      currRow: {},
+      selectedRows: [],
+      pageInfo: {
+        page: 1,
+        pageSize: 10,
+        total: 0,
+      },
+
+      isDetailShow: false,
+    }
+  },
+  components: {
+    ModelDataDetail
+  },
+  created() {
+  },
+  mounted() {
+    this.getData();
+  },
+  watch: {
+    "pageInfo.page": function (val) {
+      if (val > 0) {
+        this.getData();
+      }
+    },
+    "pageInfo.pageSize": function () {
+      let app = this;
+      this.pageInfo.page = -1;
+      setTimeout(function () {
+        app.pageInfo.page = 1;
+      }, 50)
+    },
+  },
+  methods: {
+    handleLoading(flag) {
+      let app = this;
+      if (flag) {
+        app.loading = true;
+      } else {
+        setTimeout(() => {
+          app.loading = false;
+        }, 500);
+      }
+    },
+    getData() {
+      let app = this;
+      let params = {
+        page: app.pageInfo.page,
+        pageSize: app.pageInfo.pageSize
+      }
+      app.handleLoading(true)
+      api.getData(params).then(res => {
+        if (res.code === 200) {
+          app.pageInfo.total = res.total;
+          app.tableData = res.content
+        }
+        app.handleLoading(false)
+      }).catch(err => {
+        app.handleLoading(false)
+      })
+    },
+    search() {
+
+    },
+    handleTableSelect(val) {
+      this.selectedRows = val;
+    },
+    handleDetailShow(flag) {
+      if (flag) {
+        this.getData()
+      }
+      this.isDetailShow = false
+    },
+    // 录入数据
+    addDataClick() {
+      this.currRow = {};
+      this.isDetailShow = true;
+    },
+    // 批量删除数据
+    batchDelete() {
+      if (!this.selectedRows) {
+        return;
+      }
+      let ids = this.selectedRows.map(i=> {return i.id}).join(',');
+    },
+    // 查看详情
+    viewData(item) {
+      let app = this;
+      app.currRow = JSON.parse(JSON.stringify(item))
+      if (app.currRow.menuId) {
+        app.currRow.menuId = Number(app.currRow.menuId)
+      }
+      this.currRow.isDataView = true;
+      app.isDetailShow = true
+    },
+    // 编辑数据
+    editData(item) {
+      let app = this;
+      app.currRow = JSON.parse(JSON.stringify(item))
+      console.log(app.currRow)
+      if (app.currRow.menuId) {
+        app.currRow.menuId = Number(app.currRow.menuId)
+      }
+      app.currRow.isEdit = true;
+      app.isDetailShow = true
+    },
+    // 删除数据
+    deleteData(item) {
+      let app = this;
+      app.$msgbox.confirm('确认要删除此条数据吗?').then(()=>{
+        api.deleteData({modelId	: item.id}).then(res=>{
+          if (res.code === 200) {
+            app.getData();
+            app.$message({message: '删除成功', type: 'success'});
+          }
+        })
+      })
+    },
+  }
+}
+</script>
+
+<style>
+#data .operation {
+  float: right;
+}
+</style>

+ 243 - 0
src/components/dataManage/dataShow/ThreeDimensionalData.vue

@@ -0,0 +1,243 @@
+<!-- 三维数据 -->
+<template>
+  <div id="data">
+    <el-button type="primary" @click="addDataClick">录入三维数据</el-button>
+    <el-button type="warning" @click="batchDelete">批量删除</el-button>
+    <div class="operation">
+      <el-form :model="filterForm" :inline="true">
+        <el-form-item label="地名地址库名称:">
+          <el-input v-model="filterForm.name" placeholder="请输入地名地址库名称"></el-input>
+        </el-form-item>
+        <el-form-item>
+          <el-button type="primary" @click="search">搜索</el-button>
+        </el-form-item>
+      </el-form>
+    </div>
+    <div class="list">
+      <el-table ref="dataTable" v-loading="loading" element-loading-text="正在加载,请稍后..." :data="tableData"
+                :border="true" :stripe="true" :height="440" style="width: 100%;margin-bottom: 15px;"
+                @selection-change="handleTableSelect">
+        <el-table-column type="selection" width="55"/>
+        <el-table-column prop="id" label="ID" width="100" :show-overflow-tooltip="true">
+          <template #default="scope">
+            <span style="cursor: pointer" @click="$util.clipboard.copyText(scope.row.id)"> {{ scope.row.id }} </span>
+          </template>
+        </el-table-column>
+        <el-table-column prop="title" label="标题" width="200"/>
+        <el-table-column prop="content" label="描述" width="250"/>
+        <el-table-column prop="address" label="地名地址库" width="150"/>
+        <el-table-column prop="updator" label="修改人"/>
+        <el-table-column prop="updateDate" label="修改时间" width="160">
+          <template #default="scope">
+            {{ $util.datetime.format(scope.row.updateDate) }}
+          </template>
+        </el-table-column>
+        <el-table-column prop="creator" label="创建人"/>
+        <el-table-column prop="createDate" label="创建时间" width="160">
+          <template #default="scope">
+            {{ $util.datetime.format(scope.row.createDate) }}
+          </template>
+        </el-table-column>
+        <el-table-column prop="operation" label="操作" width="150" fixed="right">
+          <template #default="scope">
+            <el-tooltip class="box-item" effect="dark" content="查看详情" placement="top-start">
+              <el-button type="default" @click="viewData(scope.row)" circle>
+                <el-icon>
+                  <ElIconView/>
+                </el-icon>
+              </el-button>
+            </el-tooltip>
+
+            <el-tooltip class="box-item" effect="dark" content="编辑" placement="top-start">
+              <el-button type="primary" @click="editData(scope.row)" circle>
+                <el-icon>
+                  <ElIconEdit/>
+                </el-icon>
+              </el-button>
+            </el-tooltip>
+
+            <el-tooltip class="box-item" effect="dark" content="删除" placement="top-start">
+              <el-button type="danger" @click="deleteData(scope.row)" circle>
+                <el-icon>
+                  <ElIconDelete/>
+                </el-icon>
+              </el-button>
+            </el-tooltip>
+
+          </template>
+        </el-table-column>
+      </el-table>
+      <el-pagination style="float:right" background layout="sizes, prev, pager, next, jumper, total"
+                     v-model:current-page="pageInfo.page" v-model:page-size="pageInfo.pageSize"
+                     v-model:total="pageInfo.total"/>
+    </div>
+  </div>
+
+  <ThreeDimensionalDataDetail v-if="isDetailShow" :is-show="isDetailShow" :item="currRow" :close="handleDetailShow"></ThreeDimensionalDataDetail>
+</template>
+
+<script>
+import api from '@/api/data/ThreeDimensionalData'
+import ThreeDimensionalDataDetail from "@/components/dataManage/dataDetail/ThreeDimensionalDataDetail";
+
+export default {
+  data() {
+    return {
+      loading: false,
+      filterForm: {},
+      tableData: [],
+      currRow: {},
+      selectedRows: [],
+      pageInfo: {
+        page: 1,
+        pageSize: 10,
+        total: 0,
+      },
+
+      isDetailShow: false,
+    }
+  },
+  components: {
+    ThreeDimensionalDataDetail
+  },
+  created() {
+  },
+  mounted() {
+    this.getData();
+  },
+  watch: {
+    "pageInfo.page": function (val) {
+      if (val > 0) {
+        this.getData();
+      }
+    },
+    "pageInfo.pageSize": function () {
+      let app = this;
+      this.pageInfo.page = -1;
+      setTimeout(function () {
+        app.pageInfo.page = 1;
+      }, 50)
+    },
+  },
+  methods: {
+    handleLoading(flag) {
+      let app = this;
+      if (flag) {
+        app.loading = true;
+      } else {
+        setTimeout(() => {
+          app.loading = false;
+        }, 500);
+      }
+    },
+    getData() {
+      let app = this;
+      // app.tableData = mockData;
+      // return;
+      let params = {
+        page: app.pageInfo.page,
+        pageSize: app.pageInfo.pageSize
+      }
+      app.handleLoading(true)
+      api.getData(params).then(res => {
+        if (res.code === 200) {
+          app.pageInfo.total = res.total;
+          app.tableData = res.content
+        }
+        app.handleLoading(false)
+      }).catch(err => {
+        app.handleLoading(false)
+      })
+    },
+    search() {
+
+    },
+    handleTableSelect(val) {
+      this.selectedRows = val;
+    },
+    handleDetailShow(flag) {
+      if (flag) {
+        this.getData()
+      }
+      this.isDetailShow = false
+    },
+    // 录入数据
+    addDataClick() {
+      this.currRow = {};
+      this.isDetailShow = true;
+    },
+    // 批量删除数据
+    batchDelete() {
+      if (!this.selectedRows) {
+        return;
+      }
+      let ids = this.selectedRows.map(i=> {return i.id}).join(',');
+    },
+    // 查看详情
+    viewData(item) {
+      let app = this;
+      let params = {
+        latlonDataId: item.id
+      }
+      api.getDataById(params).then(res=>{
+        if (res.code===200) {
+          if (!res.content.id || res.content.id==='') {
+            app.$message({message: '该数据不存在', type: 'error'})
+            return;
+          }
+          if (res.content.menuId) {
+            res.content.menuId = Number(res.content.menuId);
+            res.content.geometryStr = JSON.stringify(res.content.geometry);
+            delete res.content.geometry;
+          }
+          app.currRow = JSON.parse(JSON.stringify(res.content))
+          this.currRow.isDataView = true;
+          app.isDetailShow = true
+        }
+      })
+    },
+    // 编辑数据
+    editData(item) {
+      let app = this;
+      let params = {
+        latlonDataId: item.id
+      }
+      api.getDataById(params).then(res=>{
+        if (!res.content.id || res.content.id==='') {
+          app.$message({message: '该数据不存在', type: 'error'})
+          return;
+        }
+        if (res.code===200) {
+          if (res.content.menuId) {
+            res.content.menuId = Number(res.content.menuId);
+            res.content.geometryStr = JSON.stringify(res.content.geometry);
+            delete res.content.geometry;
+          }
+          app.currRow = JSON.parse(JSON.stringify(res.content))
+          app.currRow.isEdit = true;
+          app.isDetailShow = true
+        }
+      })
+
+    },
+    // 删除数据
+    deleteData(item) {
+      let app = this;
+      app.$msgbox.confirm('确认要删除此条数据吗?').then(()=>{
+        api.deleteData({latlonDataId: item.id}).then(res=>{
+          if (res.code === 200) {
+            app.getData();
+            app.$message({message: '删除成功', type: 'success'});
+          }
+        })
+      })
+    },
+  }
+}
+</script>
+
+<style>
+#data .operation {
+  float: right;
+}
+</style>

+ 250 - 0
src/components/dataManage/dataShow/TwoDimensionalData.vue

@@ -0,0 +1,250 @@
+<!-- 二维数据 -->
+<template>
+  <div id="data">
+    <el-button type="primary" @click="addDataClick">录入二维数据</el-button>
+    <el-button type="warning" @click="batchDelete">批量删除</el-button>
+    <div class="operation">
+      <el-form :model="filterForm" :inline="true">
+        <el-form-item label="地名地址库名称:">
+          <el-input v-model="filterForm.name" placeholder="请输入地名地址库名称"></el-input>
+        </el-form-item>
+        <el-form-item>
+          <el-button type="primary" @click="search">搜索</el-button>
+        </el-form-item>
+      </el-form>
+    </div>
+    <div class="list">
+      <el-table ref="dataTable" v-loading="loading" element-loading-text="正在加载,请稍后..." :data="tableData"
+                :border="true" :stripe="true" :height="440" style="width: 100%;margin-bottom: 15px;"
+                @selection-change="handleTableSelect">
+        <el-table-column type="selection" width="55"/>
+        <el-table-column prop="id" label="ID" width="100" :show-overflow-tooltip="true">
+          <template #default="scope">
+            <span style="cursor: pointer" @click="$util.clipboard.copyText(scope.row.id)"> {{ scope.row.id }} </span>
+          </template>
+        </el-table-column>
+        <el-table-column prop="title" label="标题" width="200"/>
+        <el-table-column prop="content" label="描述" width="250"/>
+        <el-table-column prop="menuNameTwo" label="类别" width="80"/>
+        <el-table-column prop="importType" label="导入类型" width="150"/>
+        <el-table-column prop="address" label="地名地址库" width="150"/>
+        <el-table-column prop="updator" label="修改人"/>
+        <el-table-column prop="updateDate" label="修改时间" width="160">
+          <template #default="scope">
+            {{ $util.datetime.format(scope.row.updateDate) }}
+          </template>
+        </el-table-column>
+        <el-table-column prop="creator" label="创建人"/>
+        <el-table-column prop="createDate" label="创建时间" width="160">
+          <template #default="scope">
+            {{ $util.datetime.format(scope.row.createDate) }}
+          </template>
+        </el-table-column>
+        <el-table-column prop="operation" label="操作" width="150" fixed="right">
+          <template #default="scope">
+            <el-tooltip class="box-item" effect="dark" content="查看详情" placement="top-start">
+              <el-button type="default" @click="viewData(scope.row)" circle>
+                <el-icon>
+                  <ElIconView/>
+                </el-icon>
+              </el-button>
+            </el-tooltip>
+
+            <el-tooltip class="box-item" effect="dark" content="编辑" placement="top-start">
+              <el-button type="primary" @click="editData(scope.row)" circle>
+                <el-icon>
+                  <ElIconEdit/>
+                </el-icon>
+              </el-button>
+            </el-tooltip>
+
+            <el-tooltip class="box-item" effect="dark" content="删除" placement="top-start">
+              <el-button type="danger" @click="deleteData(scope.row)" circle>
+                <el-icon>
+                  <ElIconDelete/>
+                </el-icon>
+              </el-button>
+            </el-tooltip>
+
+          </template>
+        </el-table-column>
+      </el-table>
+      <el-pagination style="float:right" background layout="sizes, prev, pager, next, jumper, total"
+                     v-model:current-page="pageInfo.page" v-model:page-size="pageInfo.pageSize"
+                     v-model:total="pageInfo.total"/>
+    </div>
+  </div>
+
+  <TwoDimensionalDataDetail v-if="isDetailShow" :is-show="isDetailShow" :item="currRow" :close="handleDetailShow"></TwoDimensionalDataDetail>
+</template>
+
+<script>
+import api from '@/api/data/TwoDimensionalData'
+import mockData from '@/static/files/mockData'
+import TwoDimensionalDataDetail from "@/components/dataManage/dataDetail/TwoDimensionalDataDetail";
+
+export default {
+  data() {
+    return {
+      loading: false,
+      filterForm: {},
+      tableData: [],
+      currRow: {},
+      selectedRows: [],
+      pageInfo: {
+        page: 1,
+        pageSize: 10,
+        total: 0,
+      },
+
+      isDetailShow: false,
+    }
+  },
+  components: {
+    TwoDimensionalDataDetail
+  },
+  created() {
+  },
+  mounted() {
+    this.getData();
+  },
+  watch: {
+    "pageInfo.page": function (val) {
+      if (val > 0) {
+        this.getData();
+      }
+    },
+    "pageInfo.pageSize": function () {
+      let app = this;
+      this.pageInfo.page = -1;
+      setTimeout(function () {
+        app.pageInfo.page = 1;
+      }, 50)
+    },
+  },
+  methods: {
+    handleLoading(flag) {
+      let app = this;
+      if (flag) {
+        app.loading = true;
+      } else {
+        setTimeout(() => {
+          app.loading = false;
+        }, 500);
+      }
+    },
+    getData() {
+      let app = this;
+      // app.tableData = mockData;
+      // return;
+      let params = {
+        page: app.pageInfo.page,
+        pageSize: app.pageInfo.pageSize
+      }
+      app.handleLoading(true)
+      api.getData(params).then(res => {
+        if (res.code === 200) {
+          app.pageInfo.total = res.total;
+          app.tableData = res.content
+        }
+        app.handleLoading(false)
+      }).catch(err => {
+        app.handleLoading(false)
+      })
+    },
+    search() {
+
+    },
+    handleTableSelect(val) {
+      this.selectedRows = val;
+    },
+    handleDetailShow(flag) {
+      if (flag) {
+        this.getData()
+      }
+      this.isDetailShow = false
+    },
+    // 录入数据
+    addDataClick() {
+      this.currRow = {};
+      this.isDetailShow = true;
+    },
+    // 批量删除数据
+    batchDelete() {
+      if (!this.selectedRows) {
+        return;
+      }
+      let ids = this.selectedRows.map(i=> {return i.id}).join(',');
+    },
+    // 查看详情
+    viewData(item) {
+      let app = this;
+      let params = {
+        latlonDataId: item.id
+      }
+      app.$util.loading.handleLoading(true);
+      api.getDataById(params).then(res=>{
+        if (res.code===200) {
+          if (!res.content.id || res.content.id==='') {
+            app.$message({message: '该数据不存在', type: 'error'})
+            return;
+          }
+          if (res.content.menuId) {
+            res.content.menuId = Number(res.content.menuId);
+            res.content.geometryStr = JSON.stringify(res.content.geometry);
+            delete res.content.geometry;
+          }
+          app.currRow = JSON.parse(JSON.stringify(res.content))
+          this.currRow.isDataView = true;
+          app.isDetailShow = true
+        }
+        app.$util.loading.handleLoading(false);
+      })
+    },
+    // 编辑数据
+    editData(item) {
+      let app = this;
+      let params = {
+        latlonDataId: item.id
+      }
+      app.$util.loading.handleLoading(true);
+      api.getDataById(params).then(res=>{
+        if (!res.content.id || res.content.id==='') {
+          app.$message({message: '该数据不存在', type: 'error'})
+          return;
+        }
+        if (res.code===200) {
+          if (res.content.menuId) {
+            res.content.menuId = Number(res.content.menuId);
+            res.content.geometryStr = JSON.stringify(res.content.geometry);
+            delete res.content.geometry;
+          }
+          app.currRow = JSON.parse(JSON.stringify(res.content))
+          app.currRow.isEdit = true;
+          app.isDetailShow = true
+        }
+        app.$util.loading.handleLoading(false);
+      })
+
+    },
+    // 删除数据
+    deleteData(item) {
+      let app = this;
+      app.$msgbox.confirm('确认要删除此条数据吗?').then(()=>{
+        api.deleteData({latlonDataId: item.id}).then(res=>{
+          if (res.code === 200) {
+            app.getData();
+            app.$message({message: '删除成功', type: 'success'});
+          }
+        })
+      })
+    },
+  }
+}
+</script>
+
+<style>
+#data .operation {
+  float: right;
+}
+</style>

+ 93 - 0
src/components/dataPublish/PublishDetail.vue

@@ -0,0 +1,93 @@
+<template>
+    <div id="PublishDetail">
+        <h2>{{ data.serviceName }}</h2>
+        <el-divider />
+        <div class="itemList">
+            <el-table :data="tableData" style="width: 100%" :show-header="false">
+                <el-table-column prop="title" label="标题" width="120" className="vertical-align-top">
+                    <template #default="scope">
+                        <span class="title">{{ scope.row.title }}</span>
+                    </template>
+                </el-table-column>
+                <el-table-column prop="content" label="内容" />
+            </el-table>
+        </div>
+    </div>
+</template>
+
+<script>
+
+
+export default {
+    data() {
+        return {
+            tableData: []
+        }
+    },
+    props: {
+        data: Number
+    },
+    watch: {
+        "data": function (params) {
+            this.renderTable();
+        }
+    },
+    created() {
+
+    },
+    mounted() {
+        let app = this;
+        this.renderTable();
+    },
+    methods: {
+        renderTable() {
+            this.tableData = []
+            let url = {
+                title: '服务地址:',
+                content: this.data.url
+            }
+            let type = {
+                title: '服务类型:',
+                content: this.data.type
+            }
+            let desc = {
+                title: '服务描述:',
+                content: this.data.desc
+            }
+            let standard = {
+                title: '服务规范:',
+                content: this.data.standard
+            }
+            this.tableData.push(url)
+            this.tableData.push(type)
+            this.tableData.push(desc)
+            this.tableData.push(standard)
+        }
+    }
+}
+</script>
+
+<style scoped>
+#PublishDetail {
+    width: 100%;
+    height: 100%;
+    padding-left: 1%;
+}
+
+#PublishDetail .itemList {
+    width: 100%;
+}
+
+#PublishDetail .itemList .title {
+    display: inline-block;
+    margin-left: 10px;
+    font-size: 15px;
+    font-weight: bold;
+}
+</style>
+
+<style>
+.vertical-align-top {
+    vertical-align: top !important;
+}
+</style>

+ 131 - 0
src/components/home/DataManage.vue

@@ -0,0 +1,131 @@
+<template>
+    <div id="dataManage">
+        <div class="left">
+            <el-menu default-active="1-1" class="dataManage-menu" @select="handleMenuSelect">
+                <el-sub-menu index="1">
+                    <template #title>
+                        <el-icon>
+                            <IconPark-table-file />
+                        </el-icon>
+                        <span>数据管理</span>
+                    </template>
+                    <el-menu-item index="1-1">
+                        <el-icon>
+                            <IconPark-multi-triangular />
+                        </el-icon>
+                        <span>二维数据</span>
+                    </el-menu-item>
+                    <el-menu-item index="1-2">
+                        <el-icon>
+                            <IconPark-sphere />
+                        </el-icon>
+                        <span>三维数据</span>
+                    </el-menu-item>
+                    <el-menu-item index="1-3">
+                        <el-icon>
+                            <IconPark-internal-data />
+                        </el-icon>
+                        <span>业务数据</span>
+                    </el-menu-item>
+                    <el-menu-item index="1-4">
+                        <el-icon>
+                            <IconPark-graphic-stitching />
+                        </el-icon>
+                        <span>模型数据</span>
+                    </el-menu-item>
+                    <el-menu-item index="1-5">
+                        <el-icon :color="'#303133'">
+                            <IconPark-data />
+                        </el-icon>
+                        <span>元数据</span>
+                    </el-menu-item>
+                    <el-menu-item index="1-6">
+                        <el-icon>
+                            <IconPark-connection-point />
+                        </el-icon>
+                        <span>物联感知数据</span>
+                    </el-menu-item>
+                </el-sub-menu>
+                <el-menu-item index="2">
+                    <el-icon>
+                        <IconPark-external-transmission />
+                    </el-icon>
+                    <span>数据导入</span>
+                </el-menu-item>
+                <el-menu-item index="3">
+                    <el-icon>
+                        <IconPark-refresh />
+                    </el-icon>
+                    <span>接口同步</span>
+                </el-menu-item>
+            </el-menu>
+        </div>
+        <div class="content">
+            <TwoDimensionalData v-if="activeName==='1-1'" />
+            <ThreeDimensionalData v-if="activeName==='1-2'" />
+            <BusinessData v-if="activeName==='1-3'" />
+            <ModelData v-if="activeName==='1-4'" />
+            <MetaData v-if="activeName==='1-5'" />
+            <IotData v-if="activeName==='1-6'" />
+
+            <ImportData v-if="activeName==='2'" />
+            <SyncInterface v-if="activeName==='3'" />
+        </div>
+    </div>
+</template>
+
+<script>
+import { defineAsyncComponent } from "vue";
+
+export default {
+    data() {
+        return {
+            activeName: '1-1',
+        }
+    },
+    components: {
+        TwoDimensionalData: defineAsyncComponent(() => import("@/components/dataManage/dataShow/TwoDimensionalData.vue")),
+        ThreeDimensionalData: defineAsyncComponent(() => import("@/components/dataManage/dataShow/ThreeDimensionalData.vue")),
+        BusinessData: defineAsyncComponent(() => import("@/components/dataManage/dataShow/BusinessData.vue")),
+        ModelData: defineAsyncComponent(() => import("@/components/dataManage/dataShow/ModelData.vue")),
+        MetaData: defineAsyncComponent(() => import("@/components/dataManage/dataShow/MetaData.vue")),
+        IotData: defineAsyncComponent(() => import("@/components/dataManage/dataShow/IotData.vue")),
+
+        ImportData: defineAsyncComponent(() => import("@/components/dataManage/ImportData.vue")),
+        SyncInterface: defineAsyncComponent(() => import("@/components/dataManage/SyncInterface.vue")),
+    },
+    created() {
+
+    },
+    mounted() {
+
+    },
+    methods: {
+        handleMenuSelect(val) {
+            this.activeName = '-1';
+            setTimeout(() => {
+                this.activeName = val;
+            }, 10);
+            
+        }
+    }
+}
+</script>
+
+<style scoped>
+#dataManage {
+    width: 100%;
+    height: 100%;
+}
+#dataManage .left {
+    width: 20%;
+    display: inline-block;
+}
+#dataManage .content {
+    width: 78%;
+    height: 100%;
+    display: inline-block;
+    vertical-align: top;
+    margin-left: 2%;
+}
+</style>

+ 71 - 0
src/components/home/DataPublish.vue

@@ -0,0 +1,71 @@
+<template>
+    <div id="dataPublish">
+        <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-icon>
+                            <IconPark-server />
+                        </el-icon>
+                        <span>{{ item.serviceName }}</span>
+                    </el-menu-item>
+                </el-menu>
+            </el-scrollbar>
+
+        </div>
+        <div class="content">
+            <PublishDetail :data="currService" />
+        </div>
+    </div>
+</template>
+
+<script>
+import PublishDetail from '@/components/dataPublish/PublishDetail'
+import ServiceData from "@/static/datas/ServiceData";
+
+export default {
+    data() {
+        return {
+            menuHeight: '',
+            serviceList: [],
+            currService: {}
+        }
+    },
+    props: {
+        height: Object
+    },
+    components: {
+        PublishDetail
+    },
+    created() {
+        this.menuHeight = this.height*0.7;
+        this.serviceList = JSON.parse(JSON.stringify(ServiceData))
+        if (this.serviceList.length>0) {
+            this.currService = this.serviceList[0]
+        }
+    },
+    mounted() {
+    },
+    methods: {
+        handleServiceSelect(val) {
+            this.currService = this.serviceList[Number(val)]
+        }
+    }
+}
+
+</script>
+
+<style scoped>
+#dataPublish .left {
+    display: inline-block;
+    width: 20%;
+    height: 100%;
+}
+
+#dataPublish .content {
+    display: inline-block;
+    width: 79%;
+    vertical-align: top;
+    height: 100%;
+}
+</style>

+ 90 - 0
src/components/home/HomeIndex.vue

@@ -0,0 +1,90 @@
+<template>
+    <div id="HomeContainer">
+        <el-row :gutter="30">
+            <el-col :span="12" >
+                <el-card class="box-card">
+                    <template #header>
+                        <div class="card-header">
+                            <span class="cardTitle">平台介绍</span>
+                        </div>
+                    </template>
+                    <div >平台介绍内容</div>
+                </el-card>
+            </el-col>
+            <el-col :span="12">
+                <el-card class="box-card">
+                    <template #header>
+                        <div class="card-header">
+                            <span class="cardTitle">专项介绍</span>
+                        </div>
+                    </template>
+                    <div >专项介绍内容</div>
+                </el-card>
+            </el-col>
+            <el-col :span="24" ><br/></el-col>
+            <el-col :span="24" ><br/></el-col>
+            <el-col :span="12">
+                <el-card class="box-card">
+                    <template #header>
+                        <div class="card-header">
+                            <span class="cardTitle">系统概览</span>
+                        </div>
+                    </template>
+                    <div >系统信息</div>
+                </el-card>
+            </el-col>
+            <el-col :span="12">
+                <el-card class="box-card">
+                    <template #header>
+                        <div class="card-header">
+                            <span class="cardTitle">数据明细</span>
+                        </div>
+                    </template>
+                    <div >数据明细内容</div>
+                </el-card>
+            </el-col>
+        </el-row>
+
+
+    </div>
+</template>
+
+<script>
+export default {
+    name: 'HomeIndex',
+    data() {
+        return {
+
+        }
+    },
+    created() {
+
+    },
+    mounted() {
+
+    },
+    methods: {
+
+    }
+}
+</script>
+
+<style scoped>
+#HomeContainer {
+    width: 100%;
+    height: 100%;
+}
+
+.box-card {
+    width: 100%;
+    margin: 1%;
+    height: 100%;
+    min-height: 200px;
+    display: inline-block;
+}
+
+.box-card .cardTitle {
+    font-weight: bold;
+    font-size: 25px;
+}
+</style>

+ 69 - 0
src/components/home/PluginManage.vue

@@ -0,0 +1,69 @@
+<template>
+    <div id="pluginManage">
+        <div class="left">
+            <el-scrollbar :max-height="menuHeight">
+                <el-menu default-active="0" class="pluginManage-menu" @select="handlePluginSelect">
+                    <el-menu-item v-for="(item,index) of pluginList" :key="index" :index="index+''">
+                        <el-icon><ElIconMagicStick /></el-icon>
+                        <span>{{ item.pluginName }}</span>
+                    </el-menu-item>
+                </el-menu>
+            </el-scrollbar>
+
+        </div>
+        <div class="content">
+            <PluginDetail :data="currPlugin" />
+        </div>
+    </div>
+</template>
+
+<script>
+import PluginDetail from '@/components/pluginManage/PluginDetail'
+import PluginData from '@/static/datas/PluginData'
+
+export default {
+    data() {
+        return {
+            menuHeight: '',
+            pluginList: [],
+            currPlugin: {}
+        }
+    },
+    props: {
+        height: Object
+    },
+    components: {
+        PluginDetail
+    },
+    created() {
+        this.menuHeight = this.height*0.7;
+        this.pluginList = JSON.parse(JSON.stringify(PluginData))
+        if (this.pluginList.length>0) {
+            this.currPlugin = this.pluginList[0]
+        }
+    },
+    mounted() {
+    },
+    methods: {
+        handlePluginSelect(val) {
+            this.currPlugin = this.pluginList[Number(val)]
+        }
+    }
+}
+
+</script>
+
+<style scoped>
+#pluginManage .left {
+    display: inline-block;
+    width: 20%;
+    height: 100%;
+}
+
+#pluginManage .content {
+    display: inline-block;
+    width: 79%;
+    vertical-align: top;
+    height: 100%;
+}
+</style>

+ 3 - 0
src/components/home/SystemManage.vue

@@ -0,0 +1,3 @@
+<template>
+    
+</template>

+ 51 - 0
src/components/json/JsonDataView.vue

@@ -0,0 +1,51 @@
+<template>
+  <el-drawer
+      v-if="isShow"
+      v-model="isJsonViewShow"
+      title="Json数据预览"
+      direction="rtl"
+      :before-close="handleClose"
+  >
+    <json-viewer :value="jsonData" :expand-depth="4" copyable ></json-viewer>
+  </el-drawer>
+</template>
+
+<script>
+import JsonViewer from 'vue-json-viewer'
+
+export default {
+  data() {
+    return {
+      isJsonViewShow: true,
+      jsonData: {},
+    }
+  },
+  components: {
+    JsonViewer
+  },
+  props: {
+    isShow: Boolean,
+    title: String,
+    data: String,
+    close: Function,
+  },
+  mounted() {
+    if (this.data) {
+      this.jsonData = JSON.parse(this.data)
+    } else {
+      this.$message({message: '数据为空, 不支持预览', type: 'warning'})
+      this.handleClose()
+    }
+
+  },
+  methods: {
+    handleClose() {
+      this.close();
+    }
+  }
+}
+</script>
+
+<style>
+
+</style>

+ 159 - 0
src/components/map/CesiumMap.vue

@@ -0,0 +1,159 @@
+<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="mapOperation">-->
+      <!--  <el-button>点标记</el-button>-->
+      <!--  <el-button>线标记</el-button>-->
+      <!--  <el-button>面标记</el-button>-->
+      <!--</div>-->
+      <div id="mapContainer">
+
+      </div>
+    </div>
+
+    <template #footer>
+      <el-button type="primary">确认</el-button>
+    </template>
+  </el-dialog>
+</template>
+
+<script>
+import 'cesium/Widgets/widgets.css'
+import CesiumMarker from "@/static/js/CesiumMarker";
+
+export default {
+  data() {
+    return {
+      viewer: '',
+      drawData: {
+        points: [],
+        lines: [],
+        polygons: []
+      },
+      cesiumConfig: {
+        animation: false, //动画控制不显示
+        timeline: false, //时间线不显示
+        fullscreenButton: false, //全屏按钮不显示
+        imageryProvider: new Cesium.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: Cesium.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,
+    item: Object,
+    close: Function
+  },
+  watch: {
+    "isShow": function (val) {
+      this.initMap();
+    }
+  },
+  mounted() {
+    this.$util.loading.handleLoading(true)
+    this.initMap();
+  },
+  methods: {
+    initMap() {
+      let app = this;
+      this.$nextTick(()=>{
+        app.viewer = new Cesium.Viewer('mapContainer', app.cesiumConfig);
+        app.viewer.scene.preRender.addEventListener(function () {
+          app.loading = true;
+        })
+        app.viewer.scene.postRender.addEventListener(function () {
+          app.loading = false;
+        })
+        // 加载模型
+        if (app.item.url && app.item.url!=='') {
+          app.add3DTiles(app.viewer, app.item.url, true)
+        } else {
+          app.$util.loading.handleLoading(false)
+        }
+      });
+    },
+    // 添加模型
+    add3DTiles(viewer, url, flyto){
+      let app = this;
+      let tileset = new Cesium.Cesium3DTileset({
+        url: url,
+        skipLevelOfDetail: true, //开启跳级加载
+        maximumScreenSpaceError: 16,
+        maximumNumberOfLoadedTiles: 2000,
+        maximumMemoryUsage: 512,//tileset可以使用的最大内存
+        show: true,
+        immediatelyLoadDesiredLevelOfDetail: true,
+        // showOutLine : true, // 是否使用 CESIUM_primitive_outline 扩展显示模型的轮廓。为 true 时,将显示轮廓。如果为 false,则不显示轮廓。
+        // debugColorizeTiles : true, // 仅用于调试。如果为 true,则为每个图块分配随机颜色。
+        // debugShowBoundingVolume : true, // 仅用于调试。如果为 true,则为每个图块渲染边界体积。
+        // debugShowContentBoundingVolume : true, // 仅用于调试。如果为 true,则为每个图块的内容渲染边界体积。
+        // lightColor : new Cesium.Cartesian3(100.0,100.0, 100.0),  // 调整模型亮度
+      });
+      tileset.allTilesLoaded.addEventListener(function() {
+        app.$util.loading.handleLoading(false)
+      });
+      viewer.scene.primitives.add(tileset);
+      tileset.show=true;
+      if(flyto){
+        tileset.readyPromise.then(function () {
+          viewer.zoomTo(tileset);
+        });
+      }
+      return tileset;
+    },
+    handleClose() {
+      this.close(false)
+    }
+  }
+}
+</script>
+
+<style>
+#mapBox {
+  width: 100%;
+  height: 100%;
+}
+#mapContainer {
+  width: 100%;
+  height: 100%;
+}
+#mapOperation {
+  margin-bottom: 10px;
+}
+/*隐藏 cesium logo*/
+.cesium-widget-credits{
+  display: none !important;
+}
+.el-dialog__body {
+  padding-top: 10px;
+}
+</style>

+ 194 - 0
src/components/map/OlMap.vue

@@ -0,0 +1,194 @@
+<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="mapOperation" v-if="!isView">
+        <el-tooltip class="box-item" effect="dark" content="清空标记" placement="right-start">
+          <el-button @click="clearMapDraw"><el-icon><ElIconDelete /></el-icon></el-button>
+        </el-tooltip>
+      </div>
+      <div id="mapContainer" ref="map">
+      </div>
+    </div>
+
+    <template #footer v-if="!isView">
+      <el-button type="primary" @click="sure">确认</el-button>
+    </template>
+  </el-dialog>
+</template>
+
+<script>
+import 'ol/ol.css'
+import { Map, View, Feature } from 'ol'
+import * as Style from 'ol/style.js'
+import * as Source from 'ol/source.js'
+import * as Layer from 'ol/layer.js'
+import TileLayer from 'ol/layer/Tile'
+import OSM from 'ol/source/OSM'
+import {GeoJSON} from "ol/format";
+import {Draw} from "ol/interaction";
+
+export default {
+  data() {
+    return {
+      map: null,
+      type: '',
+      geometry: {},
+      category: {
+        7: 'MultiPoint',
+        8: 'MultiLineString',
+        9: 'MultiPolygon'
+      },
+      drawStyle: new Style.Style({
+        // 将点设置成圆形样式
+        image: new Style.Circle({
+          // 点的颜色
+          fill: new Style.Fill({
+            color: '#F00'
+          }),
+          // 圆形半径
+          radius: 5
+        }),
+        // 线样式
+        stroke: new Style.Stroke({
+          color: '#F00',
+          lineCap: 'round',       // 设置线的两端为圆头
+          width: 3
+        }),
+        // 填充样式
+        fill: new Style.Fill({
+          color: 'rgba(248,152,152,0.5)'
+        })
+      })
+    }
+  },
+  props: {
+    isShow: Boolean,
+    menuId: Number,
+    geometryStr: String,
+    isView: Boolean,
+    callback: Function,
+    close: Function
+  },
+  created() {
+    let app = this;
+    if (app.isView) {
+      if (app.geometryStr && app.geometryStr!=='') {
+      } else {
+        app.$message({message: '数据为空,不支持查看', type: 'warning'});
+        app.handleClose()
+      }
+    }
+    this.$nextTick(()=>{
+      setTimeout(app.initMap(), 100)
+    })
+    if (app.geometryStr) {
+      app.geometry = JSON.parse(app.geometryStr)
+    }
+    if (app.menuId) {
+      app.type = app.category[app.menuId]
+    }
+  },
+  methods: {
+    initMap() {
+      let app = this;
+      app.map = new Map({
+        target: app.$refs.map,
+        layers: [
+          new TileLayer({
+            source: new OSM()
+          })
+        ],
+        view: new View({
+          projection: 'EPSG:4326', // 使用这个坐标系
+          center: [120.91634045937181, 27.943677724068422], // 中心点
+          zoom: 14
+        })
+      })
+      app.markerLayer = new Layer.Vector({
+        source: new Source.Vector()
+      });
+      app.map.addLayer(app.markerLayer)
+      if (!app.isView && app.type && app.type!=='') {
+        app.draw(app.type);
+      }
+      if (app.geometry && app.geometry.type) {
+        let feature = new GeoJSON().readFeature(app.geometry);
+        feature.setStyle(app.drawStyle)
+        app.markerLayer.getSource().addFeature(feature)
+        app.map.getView().fit(feature.getGeometry().getExtent(), {size: app.map.getSize(),maxZoom: 14})
+      }
+    },
+    clearMapDraw() {
+      let source = this.markerLayer.getSource();
+      source.getFeatures().forEach(i=>{
+        source.removeFeature(i)
+      })
+    },
+    draw(type) {
+      let app = this;
+      this.draw = new Draw({
+        source: app.markerLayer.getSource(),
+        type: type,
+        style: app.drawStyle
+      })
+      app.map.addInteraction(app.draw)
+      app.draw.on('drawend', e=>{
+        e.feature.setStyle(app.drawStyle);
+      })
+    },
+    getGeoJson() {
+      let features = this.markerLayer.getSource().getFeatures();
+      if (features.length>1) {
+        let geoTool = new GeoJSON();
+        let geometry = geoTool.writeFeatureObject(features[0]).geometry;
+        for (let i = 1; i < features.length; i++) {
+          geometry.coordinates.push(geoTool.writeFeatureObject(features[i]).geometry.coordinates[0])
+        }
+        return geometry;
+      } else if (features.length===1) {
+        let geometry = new GeoJSON().writeFeatureObject(features[0]).geometry;
+        geometry.type = geometry.type.substring(5);
+        geometry.coordinates = geometry.coordinates[0];
+        return geometry;
+      } else {
+        return '';
+      }
+    },
+    sure() {
+      this.callback(this.getGeoJson());
+      this.handleClose();
+    },
+    handleClose() {
+      this.close(false)
+    }
+  }
+}
+</script>
+
+<style>
+#mapBox {
+  width: 100%;
+  height: 100%;
+  position: relative;
+}
+#mapContainer {
+  width: 100%;
+  height: 450px;
+}
+#mapOperation {
+  position: absolute;
+  right: 1%;
+  top: 5%;
+  z-index: 10;
+}
+.el-dialog__body {
+  padding-top: 10px;
+}
+</style>

+ 97 - 0
src/components/pluginManage/PluginDetail.vue

@@ -0,0 +1,97 @@
+<template>
+    <div id="PluginDetail">
+        <h2>{{ data.pluginName }}</h2>
+        <el-divider />
+        <div class="itemList">
+            <el-table :data="tableData" style="width: 100%" :show-header="false">
+                <el-table-column prop="title" label="标题" width="160" className="vertical-align-top">
+                    <template #default="scope">
+                        <span class="title">{{ scope.row.title }}</span>
+                    </template>
+                </el-table-column>
+                <el-table-column prop="content" label="内容" />
+            </el-table>
+        </div>
+    </div>
+</template>
+
+<script>
+
+export default {
+    data() {
+        return {
+            tableData: []
+        }
+    },
+    props: {
+        data: Number
+    },
+    watch: {
+        "data": function (params) {
+            this.renderTable();
+        }
+    },
+    created() {
+
+    },
+    mounted() {
+        let app = this;
+        this.renderTable();
+    },
+    methods: {
+        renderTable() {
+            this.tableData = []
+            let methods = {
+                title: '集成方式和步骤:',
+                content: this.data.methods
+            }
+            let params = {
+                title: '参数说明:',
+                content: this.data.params
+            }
+            let example = {
+                title: '调用示例:',
+                content: this.data.example
+            }
+            let response = {
+                title: '返回值示例:',
+                content: this.data.response
+            }
+            let display = {
+                title: '效果展示:',
+                content: this.data.display
+            }
+            this.tableData.push(methods)
+            this.tableData.push(params)
+            this.tableData.push(example)
+            this.tableData.push(response)
+            this.tableData.push(display)
+        }
+    }
+}
+</script>
+
+<style scoped>
+#PluginDetail {
+    width: 100%;
+    height: 100%;
+    padding-left: 1%;
+}
+
+#PluginDetail .itemList {
+    width: 100%;
+}
+
+#PluginDetail .itemList .title {
+    display: inline-block;
+    margin-left: 10px;
+    font-size: 15px;
+    font-weight: bold;
+}
+</style>
+
+<style>
+.vertical-align-top {
+    vertical-align: top !important;
+}
+</style>

+ 34 - 1
src/main.js

@@ -3,4 +3,37 @@ import App from './App.vue'
 import router from './router'
 import router from './router'
 import store from './store'
 import store from './store'
 
 
-createApp(App).use(store).use(router).mount('#app')
+// ElementPlus
+import ElementPlus from 'element-plus'
+import zhCn from 'element-plus/dist/locale/zh-cn.mjs'
+import 'element-plus/dist/index.css'
+import * as ElementPlusIconsVue from '@element-plus/icons-vue'
+//iconpark
+import {install} from '@icon-park/vue-next/es/all';
+
+
+const app = createApp(App);
+
+app.use(store);
+app.use(router);
+app.use(ElementPlus, {
+  locale: zhCn,
+})
+
+// element-plus icon, 以ElIcon开头,例如ElIconEdit
+for (const [key, component] of Object.entries(ElementPlusIconsVue)) {
+  app.component('ElIcon' + key, component)
+}
+// iconpark, 以IconPark开头, 例如IconPark-people
+install(app, 'IconPark')
+
+// 全局方法
+import util from '@/utils/index'
+app.config.globalProperties.$util = util
+// 常量
+import constant from '@/utils/constant'
+app.config.globalProperties.$constant = constant
+
+app.mount('#app');
+
+

+ 5 - 5
src/router/index.js

@@ -7,14 +7,14 @@ const routes = [
     name: 'home',
     name: 'home',
     component: HomeView
     component: HomeView
   },
   },
-  {
-    path: '/about',
-    name: 'about',
+  // {
+    // path: '/about',
+    // name: 'about',
     // route level code-splitting
     // route level code-splitting
     // this generates a separate chunk (about.[hash].js) for this route
     // this generates a separate chunk (about.[hash].js) for this route
     // which is lazy-loaded when the route is visited.
     // which is lazy-loaded when the route is visited.
-    component: () => import(/* webpackChunkName: "about" */ '../views/AboutView.vue')
-  }
+    // component: () => import(/* webpackChunkName: "about" */ '../views/AboutView.vue')
+  // }
 ]
 ]
 
 
 const router = createRouter({
 const router = createRouter({

+ 34 - 0
src/static/datas/PluginData.json

@@ -0,0 +1,34 @@
+[
+    {
+        "pluginName": "水面模拟插件",
+        "methods": "测试",
+        "params": "测试",
+        "example": "测试",
+        "response": "测试",
+        "display": "测试"
+    },
+    {
+        "pluginName": "地质模拟插件",
+        "methods": "测试",
+        "params": "",
+        "example": "",
+        "response": "",
+        "display": ""
+    },
+    {
+        "pluginName": "树木加载插件",
+        "methods": "",
+        "params": "",
+        "example": "",
+        "response": "",
+        "display": ""
+    },
+    {
+        "pluginName": "抬升插件",
+        "methods": "",
+        "params": "",
+        "example": "",
+        "response": "",
+        "display": ""
+    }
+]

+ 44 - 0
src/static/datas/ServiceData.json

@@ -0,0 +1,44 @@
+[
+    {
+        "serviceName": "业务数据对外服务",
+        "url": "http://localhost:8080",
+        "type": "对外",
+        "desc": "服务描述1234",
+        "standard": "测试1111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111"
+    },
+    {
+        "serviceName": "空间数据对外服务",
+        "url": "",
+        "type": "",
+        "desc": "",
+        "standard": ""
+    },
+    {
+        "serviceName": "模型数据对外服务",
+        "url": "",
+        "type": "",
+        "desc": "",
+        "standard": ""
+    },
+    {
+        "serviceName": "地名地址服务",
+        "url": "",
+        "type": "",
+        "desc": "",
+        "standard": ""
+    },
+    {
+        "serviceName": "授权服务",
+        "url": "",
+        "type": "",
+        "desc": "",
+        "standard": ""
+    },
+    {
+        "serviceName": "接口检测服务",
+        "url": "",
+        "type": "",
+        "desc": "",
+        "standard": ""
+    }
+]

+ 39 - 0
src/static/files/mockData.json

@@ -0,0 +1,39 @@
+[
+    {
+        "id": "1",
+        "title": "测试标题",
+        "desc": "测试描述",
+        "menuId": 7,
+        "geometryStr": "测试"
+    },
+    {
+        "id": "2",
+        "title": "测试标题",
+        "desc": "测试描述"
+    },
+    {
+        "id": "3",
+        "title": "测试标题",
+        "desc": "测试描述"
+    },
+    {
+        "id": "4",
+        "title": "测试标题",
+        "desc": "测试描述"
+    },
+    {
+        "id": "5",
+        "title": "测试标题",
+        "desc": "测试描述"
+    },
+    {
+        "id": "6",
+        "title": "测试标题",
+        "desc": "测试描述"
+    },
+    {
+        "id": "7",
+        "title": "测试标题",
+        "desc": "测试描述"
+    }
+]

+ 24 - 0
src/static/js/CesiumMarker.js

@@ -0,0 +1,24 @@
+export default {
+    point: {
+        positions: []
+    },
+    // 绘制点
+    drawPoint(viewer, callback) {
+        let that = this;
+        viewer.cesiumWidget.screenSpaceEventHandler.removeInputAction(Cesium.ScreenSpaceEventType.LEFT_CLICK);
+        let handler = new Cesium.ScreenSpaceEventHandler(viewer.scene.canvas);
+        handler.setInputAction(function (event) {
+            let clickPosition = viewer.scene.camera.pickEllipsoid(event.position);
+            let point = viewer.entities.add({
+                position: clickPosition,
+                point: {
+                    color: Cesium.Color.RED,
+                    pixelSize: 10
+                }
+            });
+            if (callback) {
+                callback(point)
+            }
+        }, Cesium.ScreenSpaceEventType.LEFT_CLICK);
+    },
+}

+ 0 - 0
src/store/actions.js


+ 11 - 0
src/store/getters.js

@@ -0,0 +1,11 @@
+export default {
+    getUserInfo: (state) => {
+        return state.userInfo;
+    },
+    getUserName: (state) => {
+        return state.userInfo.username || '';
+    },
+    getToken: (state) => {
+        return state.token || '';
+    }
+}

+ 21 - 9
src/store/index.js

@@ -1,14 +1,26 @@
 import { createStore } from 'vuex'
 import { createStore } from 'vuex'
+import createPersistedState from "vuex-persistedstate";
+
+import state from '@/store/state'
+import getters from '@/store/getters'
+import actions from '@/store/actions'
+import mutations from '@/store/mutations'
 
 
 export default createStore({
 export default createStore({
-  state: {
-  },
-  getters: {
-  },
-  mutations: {
-  },
-  actions: {
-  },
+  state: state,
+  getters: getters,
+  mutations: mutations,
+  actions: actions,
   modules: {
   modules: {
-  }
+  },
+  // 配置插件
+  plugins: [
+    // 默认储存在localstorage
+    createPersistedState({
+      // 存储方法
+      storage: Window.localStorage,
+      // 本地储存名
+      key: 'disgital-twin-base',
+    })
+],
 })
 })

+ 16 - 0
src/store/mutations.js

@@ -0,0 +1,16 @@
+import initState from "./state";
+
+export default {
+    setToken: (state, token) => {
+        state.token = token;
+    },
+    setUserInfo: (state, userInfo) => {
+        state.userInfo = userInfo;
+    },
+    resetState: (state) => {
+        for (const key in initState) {
+            state[key] = initState[key]
+        }
+    },
+    
+}

+ 4 - 0
src/store/state.js

@@ -0,0 +1,4 @@
+export default {
+    userInfo: {},
+    token: '',
+}

+ 12 - 0
src/utils/clipboard.js

@@ -0,0 +1,12 @@
+import useClipboard from 'vue-clipboard3'
+import { ElMessage } from 'element-plus';
+
+const copyText = (text) => {
+  try {
+    useClipboard().toClipboard(text);
+    ElMessage({message: '已复制到剪切板:'+text, type: 'success'})
+  } catch (e){ console.error(e) }
+}
+ export default {
+  copyText
+ }

+ 6 - 0
src/utils/constant.js

@@ -0,0 +1,6 @@
+// 常量
+
+export default {
+    oauthProxy: '/proxy_oauth', // oauth 代理地址前缀
+    dtbserverProxy: '/proxy_dtbserver' // dtbserver 代理地址前缀
+}

+ 29 - 0
src/utils/datetime.js

@@ -0,0 +1,29 @@
+// 时间处理
+import dayjs from 'dayjs'
+
+// 获取当前时间
+const now = () => {
+    return dayjs();
+}
+
+// 获取当前时间戳
+const nowTimestamp = () => {
+    return dayjs().valueOf();
+}
+
+// 格式化时间
+const format = (str, pattern) => {
+    if(!pattern || pattern==='') {
+        pattern = 'YYYY-MM-DD HH:mm:ss'; //默认格式
+    }
+    if(str && str!=='') {
+        return dayjs(str).format(pattern)
+    }
+    return '';
+}
+
+export default {
+    now,
+    nowTimestamp,
+    format,
+}

+ 11 - 0
src/utils/index.js

@@ -0,0 +1,11 @@
+import datetime from "@/utils/datetime";
+import request from "@/utils/request";
+import clipboard from '@/utils/clipboard'
+import loading from '@/utils/loading'
+
+export default {
+    request,
+    datetime,
+    clipboard,
+    loading,
+}

+ 20 - 0
src/utils/loading.js

@@ -0,0 +1,20 @@
+import { ElLoading } from 'element-plus'
+
+let fullscreenLoading = null;
+let handleLoading = (flag) => {
+    if (flag) {
+        fullscreenLoading = ElLoading.service({
+            lock: true,
+            text: '正在处理,请稍后。。。',
+            background: 'rgba(0, 0, 0, 0.7)',
+        })
+    } else {
+        setTimeout(function () {
+            fullscreenLoading.close();
+        }, 200);
+    }
+}
+
+export default {
+    handleLoading,
+}

+ 106 - 0
src/utils/request.js

@@ -0,0 +1,106 @@
+import axios from 'axios'
+import qs from 'qs'
+import { ElMessage, ElMessageBox } from 'element-plus'
+
+import store from '@/store/index'
+
+// 服务接口地址
+// axios.defaults.baseURL = process.env.VUE_APP_BASEURL
+// 携带 cookie
+axios.defaults.withCredentials = true
+
+// 默认 post 请求,使用 multipart/form-data 形式
+axios.defaults.headers.post["Content-Type"] = "application/x-www-form-urlencoded";
+
+// 创建 axios 实例
+const service = axios.create({
+    timeout: 6000000, // 请求超时时间,
+})
+
+// 结果拦截
+const userFailCodes = [206, 207] // 用户失效code
+const loginFailCodes = [208, 212] // 登录失效code
+const noDataCodes = [202, 205] // 无数据
+service.interceptors.response.use(response => {
+    let code = response.data.code
+    if (code && loginFailCodes.indexOf(code) > -1) {
+        ElMessage({ message: '登录失效,请重新登录', type: 'error' })
+    } else if (code && userFailCodes.indexOf(code) > -1) {
+        ElMessage({ message: '用户状态失效,请联系管理员', type: 'error' })
+    } else if (code && noDataCodes.indexOf(code) > -1) {
+        ElMessage({ message: '未查询到相关数据', type: 'warning' })
+    } else if (code !== 200) {
+        ElMessage({ message: response.data.content || '请求出错', type: 'error' })
+    }
+    return response
+})
+
+// 普通请求
+function req(method, url, params) {
+    return new Promise((resolve, reject) => {
+        service({
+            method: method,
+            url,
+            data: params,
+            headers: {
+                'token': store.state.token || ''
+            }
+        }).then(response => {
+            resolve(response.data)
+        }).catch(err => {
+            reject(err)
+        })
+    })
+}
+// 表单请求
+function formReq(method, url, params) {
+    return new Promise((resolve, reject) => {
+        service({
+            method: method,
+            url,
+            data: qs.stringify(params),
+            headers: {
+                'Content-Type': 'application/x-www-form-urlencoded',
+                'token': store.state.token || ''
+            }
+        }).then(response => {
+            resolve(response.data)
+        }).catch(err => {
+            reject(err)
+        })
+    })
+}
+
+// 请求方法
+export default {
+    get(url, params) {
+        return req('GET', url, params);
+    },
+    post(url, params) {
+        return req('POST', url, params);
+    },
+    put(url, params) {
+        return req('PUT', url, params);
+    },
+    delete(url, params) {
+        return req('DELETE', url, params);
+    },
+    getForm(url, params) {
+        return formReq('GET', url, params)
+    },
+    postForm(url, params) {
+        return formReq('POST', url, params)
+    },
+    putForm(url, params) {
+        return formReq('PUT', url, params)
+    },
+    deleteForm(url, params) {
+        return formReq('DELETE', url, params)
+    },
+    getFile(url, params) {
+
+    },
+    postWithFile(url, params) {
+
+    }
+}

+ 0 - 5
src/views/AboutView.vue

@@ -1,5 +0,0 @@
-<template>
-  <div class="about">
-    <h1>This is an about page</h1>
-  </div>
-</template>

+ 276 - 7
src/views/HomeView.vue

@@ -1,18 +1,287 @@
 <template>
 <template>
-  <div class="home">
-    <img alt="Vue logo" src="../assets/logo.png">
-    <HelloWorld msg="Welcome to Your Vue.js App"/>
+  <div id="home">
+    <div id="Header">
+      <div class="loginForm" v-if="isLogin">
+        用户名:
+        <span style="display: inline-block; padding: 0 20px 0 0">{{ $store.getters.getUserName || '未登录' }}</span>
+        <el-link type="warning" :underline="false" class="logout" @click="logout"> 退出登录 </el-link>
+      </div>
+      <div class="loginForm" v-else>
+        <el-form :inline="true" :model="loginForm" :rules="loginFormRules" ref="loginForm">
+          <el-form-item prop="userName">
+            <template #label>
+              <span class="formLabel">用户名:</span>
+            </template>
+            <el-input v-model="loginForm.userName" placeholder="请输入用户名"></el-input>
+          </el-form-item>
+          <el-form-item prop="password">
+            <template #label>
+              <span class="formLabel">密码:</span>
+            </template>
+            <el-input type="password" v-model="loginForm.password" placeholder="请输入密码"></el-input>
+          </el-form-item>
+          <el-form-item>
+            <el-button type="default" @click="login">登录</el-button>
+          </el-form-item>
+        </el-form>
+      </div>
+      <div class="title">可视化数据管理平台</div>
+    </div>
+    <div id="Menu" :style="{height: contentHeight+'px'}">
+      <div id="Tags">
+        <el-tabs v-model="activeName" type="card" @tab-click="handleMenuClick" style="margin: auto;" stretch>
+          <div class="content">
+            <el-tab-pane label="综合展示" name="homeIndex">
+                <div class="tabPanel">
+                  <HomeIndex v-if="activeName==='homeIndex'" />
+                </div>
+              </el-tab-pane>
+              <span v-if="isLogin">
+                <el-tab-pane label="数据管理" name="dataManage">
+                  <div class="tabPanel">
+                    <DataManage :height="contentHeight" v-if="activeName==='dataManage'" />
+                  </div>
+                </el-tab-pane>
+                <el-tab-pane label="数据发布" name="datePublish">
+                  <div class="tabPanel">
+                    <DataPublish :height="contentHeight" v-if="activeName==='datePublish'" />
+                  </div>
+                </el-tab-pane>
+                <el-tab-pane label="插件管理" name="pluginManage">
+                  <div class="tabPanel">
+                    <PluginManage v-if="activeName==='pluginManage'" />
+                  </div>
+                </el-tab-pane>
+                <el-tab-pane label="系统管理" name="systemManage">
+                  <div class="tabPanel">
+                    <SystemManage v-if="activeName==='systemManage'" />
+                  </div>
+                </el-tab-pane>
+              </span>
+          </div>
+        </el-tabs>
+      </div>
+    </div>
   </div>
   </div>
 </template>
 </template>
 
 
 <script>
 <script>
-// @ is an alias to /src
-import HelloWorld from '@/components/HelloWorld.vue'
+import { defineAsyncComponent } from "vue";
+import loginApi from "@/api/login";
+import elementResizeDetectorMaker from "element-resize-detector";
+
 
 
 export default {
 export default {
-  name: 'HomeView',
+  name: 'homeIndex',
   components: {
   components: {
-    HelloWorld
+    HomeIndex: defineAsyncComponent(() => import("@/components/home/HomeIndex.vue")),
+    DataManage: defineAsyncComponent(() => import("@/components/home/DataManage.vue")),
+    DataPublish: defineAsyncComponent(() => import("@/components/home/DataPublish.vue")),
+    PluginManage: defineAsyncComponent(() => import("@/components/home/PluginManage.vue")),
+    SystemManage: defineAsyncComponent(() => import("@/components/home/SystemManage.vue")),
+  },
+  data() {
+    return {
+      activeName: 'homeIndex',
+      fullscreenLoading: null,
+      contentHeight: '',
+      isLogin: false,
+      loginForm: {
+        userName: 'user001',
+        password: '1234567890',
+        clientId: '0',
+      },
+      loginFormRules: {
+        userName: [
+          { required: true, message: '请输入用户名', trigger: 'blur' },
+          { required: true, message: '请输入用户名', trigger: 'change' }
+        ],
+        password: [
+          { required: true, message: '请输入用户名', trigger: 'blur' },
+          { required: true, message: '请输入用户名', trigger: 'change' }
+        ]
+      }
+    }
+  },
+  created() {
+
+  },
+  mounted() {
+    this.judgeLogin();
+    // 监听高度变化
+    let app = this;
+    let erd = elementResizeDetectorMaker();
+    let minHeight = document.getElementById('home').scrollHeight * 0.779;
+    erd.listenTo(document.getElementsByClassName('content'), e => {
+      if (e.scrollHeight && e.scrollHeight >= minHeight - 70) {
+        app.contentHeight = e.scrollHeight + 70
+      } else {
+        app.contentHeight = minHeight;
+      }
+    })
+  },
+  methods: {
+    judgeLogin() {
+      let token = this.$store.getters.getToken;
+      this.isLogin = token && token !== '';
+      this.activeName = 'homeIndex'
+    },
+    handleMenuClick(panel, event) {
+      this.activeName = panel.paneName;
+    },
+    login() {
+      let app = this;
+      this.$refs.loginForm.validate((valid) => {
+        if (valid) {
+          app.$util.loading.handleLoading(true)
+          loginApi.userLogin(app.loginForm).then(res => {
+            app.$store.state.token = res.message
+            app.$store.commit('setUserInfo', res.content);
+            app.$store.commit('setToken', res.message);
+            app.$util.loading.handleLoading(false);
+            app.judgeLogin()
+          }).catch(err => {
+            app.$util.loading.handleLoading(false);
+            app.judgeLogin();
+          })
+        }
+      })
+
+    },
+    logout() {
+      this.$util.loading.handleLoading(true);
+      this.$store.commit('resetState', {});
+      this.$util.loading.handleLoading(false);
+      this.judgeLogin();
+    },
   }
   }
 }
 }
 </script>
 </script>
+
+<style scoped>
+.custom-loading .circular {
+  margin-right: 6px;
+  width: 18px;
+  height: 18px;
+  animation: loading-rotate 2s linear infinite;
+}
+
+.custom-loading .circular .path {
+  animation: loading-dash 1.5s ease-in-out infinite;
+  stroke-dasharray: 90, 150;
+  stroke-dashoffset: 0;
+  stroke-width: 2;
+  stroke: var(--el-button-text-color);
+  stroke-linecap: round;
+}
+
+#home {
+  width: 100%;
+  height: 100%;
+  min-height: 100%;
+}
+
+#Header {
+  /* background-image: linear-gradient(#90e2fc, white); */
+  background-image: url('@/assets/img/bg.jpg');
+  background-size: 100% 180%;
+  height: 22%;
+}
+
+#Menu {
+  height: 76%;
+  overflow: visible;
+  background-image: linear-gradient(white 93%, #2970d8);
+}
+
+#Tags {
+  /* background-color: #02a7f0; */
+  margin-top: 10px;
+  width: 100%;
+  height: 100%;
+  /* color: white; */
+  /* height: 8%; */
+}
+
+#Header .title {
+  /* color: #0d8ee9; */
+  color: white;
+  height: 100%;
+  padding: 4% 0 0 10%;
+  font-size: 40px;
+  font-weight: bold;
+}
+
+#Header .loginForm {
+  float: right;
+  margin-top: 1%;
+  color: white;
+}
+
+.logout {
+  color: #e1e1e1;
+  padding: 0 15px 5px
+}
+
+.logout:hover {
+  color: orange;
+}
+
+.formLabel {
+  color: white;
+}
+
+.content {
+  width: 100%;
+  height: 100%;
+  padding-top: 1%;
+}
+
+.tabPanel {
+  width: 70%;
+  margin: 0 auto;
+}
+
+/* tabs 样式 start */
+:deep .el-tabs__nav-scroll {
+  width: 50%;
+  background-color: #0d8ee9;
+  margin: 0 auto
+}
+
+:deep .el-tabs__content {
+  overflow: visible;
+}
+
+:deep .el-tabs__item {
+  color: white;
+  font-size: 15px;
+}
+
+:deep .el-tabs__item:hover {
+  color: white;
+  background-color: #2ba7ff;
+  font-size: 15px;
+}
+
+:deep .el-tabs__item.is-active {
+  color: white;
+  font-weight: bolder;
+  font-size: 18px;
+  background-color: #2ba7ff;
+}
+
+:deep .el-tabs__active-bar {
+  border-radius: 30px;
+  background-color: #0d8ee9;
+}
+
+/* tabs 样式 end */
+
+</style>
+
+<style>
+.el-dialog__body {
+  padding-top: 10px;
+}
+</style>

+ 85 - 2
vue.config.js

@@ -1,4 +1,87 @@
-const { defineConfig } = require('@vue/cli-service')
+const {defineConfig} = require('@vue/cli-service')
+const NodePolyfillPlugin = require('node-polyfill-webpack-plugin')
+const path = require("path")
+const webpack = require("webpack")
+const CopyWebpackPlugin = require("copy-webpack-plugin")
+const cesiumSource = "node_modules/cesium/Source"
+const cesiumWorkers = "../Build/Cesium/Workers"
+
 module.exports = defineConfig({
 module.exports = defineConfig({
-  transpileDependencies: true
+    transpileDependencies: true,
+    lintOnSave: false,
+    configureWebpack: {
+        resolve: {
+            alias: {
+                // 添加一个cesium别名,以便我们在项目中轻松的引入它
+                cesium: path.resolve(cesiumSource)
+            }
+        },
+        amd: {
+            // Cesium源码模块化使用的requireJs
+            // 此配置允许webpack友好地在铯中使用require,使webpack打包cesium
+            // 告诉Cesium, AMD的webpack版本用来评估要求的声明是不符合标准的toUrl功能
+            toUrlUndefined: true
+        },
+        module: {
+            // 解决require引入警告
+            unknownContextCritical: false
+        },
+        plugins: [
+            new webpack.DefinePlugin({
+                // 在cesium中定义用于加载资源的相对基路径
+                CESIUM_BASE_URL: JSON.stringify("/")
+            }),
+            // 对build生效,拷贝到dist目录下。如:dist/Assets
+            new CopyWebpackPlugin({
+                patterns: [
+                    {
+                        from: path.join(cesiumSource, cesiumWorkers),
+                        to: "Workers"
+                    },
+                    {
+                        from: path.join(cesiumSource, "Assets"),
+                        to: "Assets"
+                    },
+                    {
+                        from: path.join(cesiumSource, "Widgets"),
+                        to: "Widgets"
+                    },
+                    {
+                        from: path.join(cesiumSource, "ThirdParty"),
+                        to: "ThirdParty"
+                    }
+                ]
+            }),
+            // 使Cesium对象实例可在每个js中使用而无须import
+            new webpack.ProvidePlugin({
+                Cesium: ["cesium/Cesium"]
+            }),
+            new NodePolyfillPlugin()
+        ],
+        optimization: {
+            // 抽取公共模块执行压缩
+            minimize: process.env.NODE_ENV === "production"
+        },
+        // sourcemap生成
+        devtool: process.env.NODE_ENV === "production" ? false : "source-map"
+    },
+    devServer: {
+        port: 8080,
+        proxy: {
+            '/proxy_oauth/': {
+                target: process.env.VUE_APP_OAUTHURL,
+                changeOrigin: true,
+                pathRewrite: {
+                    '^/proxy_oauth': ''
+                }
+            },
+            '/proxy_dtbserver/': {
+                target: process.env.VUE_APP_BASEURL,
+                changeOrigin: true,
+                pathRewrite: {
+                    '^/proxy_dtbserver': ''
+                }
+            },
+        }
+    }
 })
 })