Procházet zdrojové kódy

feat: 地图数据管理功能页面开发

 地图数据管理功能页面开发
hong.yang před 1 rokem
rodič
revize
5fbd906269

+ 6 - 0
data-room-ui/packages/Layout/BigScreenHomeLayout/index.vue

@@ -113,6 +113,12 @@ export default {
           name: '数据集管理',
           path: window?.BS_CONFIG?.routers?.dataSetUrl || '/big-screen-dataSet',
           icon: 'icon-data'
+        },
+        {
+          id: 5,
+          name: '地图数据管理',
+          path: '/big-screen-map-data',
+          icon: 'icon-data'
         }
       ]
     }

+ 7 - 0
data-room-ui/packages/MapDataManagement/index.js

@@ -0,0 +1,7 @@
+import MapDataManagement from './src/index.vue'
+
+MapDataManagement.install = function (Vue) {
+  Vue.component(MapDataManagement.name, MapDataManagement)
+}
+
+export default MapDataManagement

+ 338 - 0
data-room-ui/packages/MapDataManagement/src/AddForm.vue

@@ -0,0 +1,338 @@
+<template>
+  <div>
+    <el-dialog
+      :append-to-body="true"
+      :before-close="handleClose"
+      :close-on-click-modal="false"
+      :title="title"
+      :visible.sync="mapFormVisible"
+      class="bs-dialog-wrap bs-el-dialog"
+      width="700px"
+    >
+      <el-form
+        ref="mapForm"
+        :model="mapForm"
+        :rules="rules"
+        class="bs-el-form"
+        label-width="120px"
+      >
+        <el-form-item
+          label="上级地图"
+          prop="parentCode"
+        >
+          <el-input
+            v-model="parentName"
+            class="bs-el-input"
+            disabled
+          />
+        </el-form-item>
+        <el-form-item
+          label="地图名称"
+          prop="name"
+        >
+          <el-input
+            v-model="mapForm.name"
+            class="bs-el-input"
+            placeholder="请输入"
+          />
+        </el-form-item>
+        <el-form-item
+          label="地图编码"
+          prop="mapCode"
+        >
+          <el-input
+            v-if="mapForm.parentCode === '0'"
+            v-model="mapForm.mapCode"
+            class="bs-el-input"
+            placeholder="请输入地图编码"
+          />
+          <el-select
+            v-else
+            v-model="mapForm.mapCode"
+            class="bs-el-select"
+            placeholder="请选择地图编码"
+            popper-class="bs-el-select"
+          >
+            <el-option
+              v-for="mapCode in mapCodeList"
+              :key="mapCode.name"
+              :disabled="mapCode.exist"
+              :label="mapCode.name"
+              :value="mapCode.name"
+            >
+              <span style="float: left">{{ mapCode.name }}</span>
+              <span style="float: right; color: #8492a6; font-size: 13px">{{ mapCode.exist ? '已存在' : '' }}</span>
+            </el-option>
+          </el-select>
+        </el-form-item>
+        <el-form-item
+          label="地图级别"
+          prop="level"
+        >
+          <el-select
+            v-model="mapForm.level"
+            :disabled="mapForm.parentCode !== '0'"
+            class="bs-el-select"
+            placeholder="请选择地图级别"
+            popper-class="bs-el-select"
+          >
+            <el-option
+              v-for="level in levelList"
+              :key="level.value"
+              :label="level.label"
+              :value="level.value"
+            />
+          </el-select>
+        </el-form-item>
+        <el-form-item
+          label="开启下钻"
+          prop="enableDown"
+        >
+          <el-switch
+            v-model="mapForm.enableDown"
+            :active-value="1"
+            :inactive-value="0"
+            class="bs-el-switch"
+          />
+        </el-form-item>
+        <el-form-item
+          label="geoJson上传"
+        >
+          <vue-json-viewer
+            v-model="mapForm.geoJson"
+            theme="dark"
+            :show-btns="false"
+            mode="code"
+          />
+          <el-button
+            class="bs-el-button-default"
+            @click="upload"
+          >
+            <i class="el-icon-upload2" />
+            上传
+          </el-button>
+        </el-form-item>
+        <el-form-item
+          v-if="autoParseNextLevelShow"
+          label="自动解析下一级"
+          prop="autoParseNextLevel"
+        >
+          <el-switch
+            v-model="mapForm.autoParseNextLevel"
+            :active-value="1"
+            :inactive-value="0"
+            class="bs-el-switch"
+          />
+        </el-form-item>
+
+      </el-form>
+      <span
+        slot="footer"
+        class="dialog-footer"
+      >
+      <el-button
+        class="bs-el-button-default"
+        @click="handleClose"
+      >
+        取消
+      </el-button>
+      <el-button
+        type="primary"
+        @click="submitForm"
+      >
+        确定
+      </el-button>
+    </span>
+    </el-dialog>
+    <input
+      ref="geoJsonFile"
+      accept=".json"
+      name="file"
+      style="display: none"
+      type="file"
+      @change="handleBatchUpload"
+    >
+  </div>
+</template>
+
+<script>
+import vueJsonViewer from 'vue-json-viewer'
+import {getMapChildFromGeoJson, mapAdd, repeatCheck} from 'data-room-ui/js/utils/mapDataService'
+
+export default {
+  name: "AddForm",
+  components: {
+    vueJsonViewer
+  },
+  computed: {
+    autoParseNextLevelShow() {
+      // geoJson 不为空,且支持下钻
+      return !this.isEmpty(this.mapForm.geoJson) && this.mapForm.enableDown === 1
+    }
+  },
+  data() {
+    const validateCode = (rule, value, callback) => {
+      console.log(value)
+      if (this.mapForm.parentCode !== '0') {
+        // 不需要校验
+        callback()
+      }
+      repeatCheck({
+        parentCode: this.mapForm.parentCode,
+        mapCode: value
+      }).then(res => {
+        if (res) {
+          callback(new Error('地图编码已存在'))
+        } else {
+          callback()
+        }
+      })
+
+    }
+    return {
+      mapFormVisible: false,
+      geoJsonVisible: false,
+      uploadLoading: false,
+      title: '新增地图数据',
+      parentName: '顶级',
+      mapForm: {
+        parentId: '0',
+        parentCode: '0',
+        mapCode: '',
+        name: '',
+        level: 0,
+        enableDown: 0,
+        geoJson: {},
+        uploadedGeoJson: 0,
+        autoParseNextLevel: 0
+      },
+      rules: {
+        mapCode: [
+          {required: true, message: '请选择地图编码', trigger: 'blur'},
+          {validator: validateCode, trigger: 'blur'}
+        ],
+        name: [
+          {required: true, message: '请输入地图名称', trigger: 'blur'}
+        ],
+        level: [
+          {required: true, message: '请选择地图级别', trigger: 'change'}
+        ]
+      },
+      levelList: [
+        {value: 0, label: '世界'},
+        {value: 1, label: '国家'},
+        {value: 2, label: '省份'},
+        {value: 3, label: '城市'},
+        {value: 4, label: '区县'}
+      ],
+      mapCodeList: []
+    }
+  },
+  methods: {
+    init(parentMap) {
+      this.mapForm = {
+        parentId: '0',
+        parentCode: '0',
+        mapCode: `map-${new Date().getTime()}`,
+        name: '',
+        level: 0,
+        enableDown: 0,
+        geoJson: {},
+        uploadedGeoJson: 0,
+        autoParseNextLevel: 0
+      }
+      this.parentName = '顶级'
+      if (parentMap) {
+        this.mapForm.parentId = parentMap.id
+        this.mapForm.parentCode = parentMap.mapCode
+        this.parentName = parentMap.name
+        this.mapForm.level = parentMap.level + 1
+        this.mapForm.mapCode = ''
+        this.getMapCodeList()
+      }
+    },
+    handleClose() {
+      this.mapFormVisible = false
+    },
+    submitForm() {
+      this.$refs.mapForm.validate(valid => {
+        if (!valid) {
+          return false
+        }
+        let geoJson
+        // 如果geoJson是空的,包括空字符串,纯空格、空对象,空数组,都不允许提交
+        if (this.isEmpty(this.mapForm.geoJson)) {
+          geoJson = ''
+        } else {
+          geoJson = JSON.stringify(this.mapForm.geoJson)
+        }
+        mapAdd({
+          ...this.mapForm,
+          geoJson: geoJson
+        }).then(res => {
+          this.mapFormVisible = false
+          this.$emit('refresh')
+        })
+
+      })
+    },
+    isEmpty(obj) {
+      if (typeof obj === 'object') {
+        return Object.keys(obj).length === 0 && obj.constructor === Object;
+      }
+      if (typeof obj === 'string') {
+        return /^\s*$/.test(obj);
+      }
+      return Array.isArray(obj) && obj.length === 0;
+    },
+    getMapCodeList() {
+      this.mapCodeList = []
+      if (this.mapForm.parentCode === '0') {
+        this.mapCodeList = [{
+          name: `map-${new Date().getTime()}`,
+          exist: false
+        }]
+      } else {
+        getMapChildFromGeoJson(this.mapForm.parentCode).then(res => {
+          this.mapCodeList = res
+        })
+      }
+    },
+    upload() {
+      this.$refs.geoJsonFile.click()
+    },
+    handleBatchUpload(source) {
+      this.uploadLoading = true
+      const file = source.target.files
+      const reader = new FileReader() // 新建一个FileReader
+      reader.readAsText(file[0], 'UTF-8') // 读取文件
+
+      reader.onload = (event) => {
+        let jsonStr = event.target.result
+        // 读取文件内容
+        try {
+          this.mapForm.geoJson = JSON.parse(jsonStr)
+        } catch (e) {
+          this.uploadLoading = false
+          this.$message.error('JSON文件格式错误')
+          return false
+        }
+        this.uploadLoading = false
+        // input通过onchange事件来触发js代码的,由于两次文件是重复的,所以这个时候onchange事件是没有触发到的,所以需要手动清空input的值
+        source.target.value = ''
+      }
+    },
+
+  }
+}
+</script>
+
+
+<style lang="scss" scoped>
+@import '../../assets/style/bsTheme.scss';
+
+.jv-container.dark {
+  color: aliceblue;
+  background: #161A26;
+}
+</style>

+ 273 - 0
data-room-ui/packages/MapDataManagement/src/EditForm.vue

@@ -0,0 +1,273 @@
+<template>
+  <div>
+    <el-dialog
+      :append-to-body="true"
+      :before-close="handleClose"
+      :close-on-click-modal="false"
+      :title="title"
+      :visible.sync="mapFormVisible"
+      class="bs-dialog-wrap bs-el-dialog"
+      width="700px"
+    >
+      <el-form
+        ref="mapForm"
+        :model="mapForm"
+        :rules="rules"
+        class="bs-el-form"
+        label-width="120px"
+      >
+        <el-form-item
+          label="上级地图"
+          prop="parentCode"
+        >
+          <el-input
+            v-model="parentName"
+            class="bs-el-input"
+            disabled
+          />
+        </el-form-item>
+        <el-form-item
+          label="地图名称"
+          prop="name"
+        >
+          <el-input
+            v-model="mapForm.name"
+            class="bs-el-input"
+            placeholder="请输入"
+          />
+        </el-form-item>
+        <el-form-item
+          label="地图编码"
+          prop="mapCode"
+        >
+          <el-input
+            v-model="mapForm.mapCode"
+            class="bs-el-input"
+            disabled
+            placeholder="请输入地图编码"
+          />
+        </el-form-item>
+        <el-form-item
+          label="地图级别"
+          prop="level"
+        >
+          <el-select
+            v-model="mapForm.level"
+            disabled
+            class="bs-el-select"
+            placeholder="请选择地图级别"
+            popper-class="bs-el-select"
+          >
+            <el-option
+              v-for="level in levelList"
+              :key="level.value"
+              :label="level.label"
+              :value="level.value"
+            />
+          </el-select>
+        </el-form-item>
+        <el-form-item
+          label="开启下钻"
+          prop="enableDown"
+        >
+          <el-switch
+            v-model="mapForm.enableDown"
+            :active-value="1"
+            :inactive-value="0"
+            class="bs-el-switch"
+          />
+        </el-form-item>
+        <el-form-item
+          label="geoJson"
+        >
+          <vue-json-viewer
+            v-model="mapForm.geoJson"
+            theme="dark"
+            :show-btns="false"
+            mode="code"
+          />
+          <el-button
+            v-if="mapForm.uploadedGeoJson !== 1"
+            class="bs-el-button-default"
+            @click="upload"
+          >
+            <i class="el-icon-upload2" />
+            上传
+          </el-button>
+        </el-form-item>
+        <el-form-item
+          v-if="autoParseNextLevelShow"
+          label="自动解析下一级"
+          prop="autoParseNextLevel"
+        >
+          <el-switch
+            v-model="mapForm.autoParseNextLevel"
+            :active-value="1"
+            :inactive-value="0"
+            class="bs-el-switch"
+          />
+        </el-form-item>
+      </el-form>
+      <span
+        slot="footer"
+        class="dialog-footer"
+      >
+      <el-button
+        class="bs-el-button-default"
+        @click="handleClose"
+      >
+        取消
+      </el-button>
+      <el-button
+        type="primary"
+        @click="submitForm"
+      >
+        确定
+      </el-button>
+    </span>
+    </el-dialog>
+    <input
+      ref="geoJsonFile"
+      accept=".json"
+      name="file"
+      style="display: none"
+      type="file"
+      @change="handleBatchUpload"
+    >
+  </div>
+</template>
+
+<script>
+import _ from 'lodash'
+import vueJsonViewer from 'vue-json-viewer'
+import {mapUpdate} from 'data-room-ui/js/utils/mapDataService'
+
+export default {
+  name: "EditForm",
+  components: {
+    vueJsonViewer
+  },
+  computed: {
+    autoParseNextLevelShow() {
+      // geoJson 不为空,且支持下钻,且未上传过(说明是刚上传的)
+      return !this.isWhitespace(this.mapForm.geoJson) && this.mapForm.enableDown === 1 && this.mapForm.uploadedGeoJson === 0
+    }
+  },
+  data() {
+    return {
+      mapFormVisible: false,
+      geoJsonVisible: false,
+      uploadLoading: false,
+      title: '编辑地图数据',
+      parentName: '顶级',
+      mapForm: {
+        parentId: '0',
+        parentCode: '0',
+        mapCode: '',
+        name: '',
+        level: 0,
+        enableDown: 0,
+        geoJson: '',
+        uploadedGeoJson: 0,
+        autoParseNextLevel: 0
+      },
+      rules: {
+        mapCode: [
+          {required: true, message: '请输入地图编码', trigger: 'blur'}
+        ],
+        name: [
+          {required: true, message: '请输入地图名称', trigger: 'blur'}
+        ],
+        level: [
+          {required: true, message: '请选择地图级别', trigger: 'change'}
+        ],
+        geoJson: [
+          {required: true, message: '请上传地图数据', trigger: 'change'}
+        ]
+      },
+      levelList: [
+        {value: 0, label: '世界'},
+        {value: 1, label: '国家'},
+        {value: 2, label: '省份'},
+        {value: 3, label: '城市'},
+        {value: 4, label: '区县'}
+      ],
+      mapCodeList: []
+    }
+  },
+  methods: {
+    init(map) {
+      this.mapForm = _.cloneDeep(map)
+      if (!this.isWhitespace(this.mapForm.geoJson)) {
+        this.mapForm.geoJson = JSON.parse(this.mapForm.geoJson)
+      }
+    },
+    handleClose() {
+      this.mapFormVisible = false
+    },
+    submitForm() {
+      this.$refs.mapForm.validate(valid => {
+        if (!valid) {
+          return false
+        }
+        let geoJson
+        // 如果geoJson是空的,包括空字符串,纯空格、空对象,空数组,都不允许提交
+        if (this.isWhitespace(this.mapForm.geoJson) || this.mapForm.geoJson === '{}' || this.mapForm.geoJson === '[]') {
+          geoJson = ''
+        } else {
+          geoJson = JSON.stringify(this.mapForm.geoJson)
+        }
+        mapUpdate({
+          ...this.mapForm,
+          geoJson: geoJson
+        }).then(res => {
+          this.mapFormVisible = false
+          this.$emit('refresh')
+        })
+
+      })
+    },
+    isWhitespace(str) {
+      // 如果是null、undefined,返回true
+      if (str == null) {
+        return true
+      }
+      return /^\s*$/.test(str);
+    },
+    upload() {
+      this.$refs.geoJsonFile.click()
+    },
+    handleBatchUpload(source) {
+      this.uploadLoading = true
+      const file = source.target.files
+      const reader = new FileReader() // 新建一个FileReader
+      reader.readAsText(file[0], 'UTF-8') // 读取文件
+
+      reader.onload = (event) => {
+        let jsonStr = event.target.result
+        // 读取文件内容
+        try {
+          this.mapForm.geoJson = JSON.parse(jsonStr)
+        } catch (e) {
+          this.uploadLoading = false
+          this.$message.error('JSON文件格式错误')
+          return false
+        }
+        this.uploadLoading = false
+        // input通过onchange事件来触发js代码的,由于两次文件是重复的,所以这个时候onchange事件是没有触发到的,所以需要手动清空input的值
+        source.target.value = ''
+      }
+    },
+  }
+}
+</script>
+
+
+<style lang="scss" scoped>
+@import '../../assets/style/bsTheme.scss';
+
+.jv-container.dark {
+  color: aliceblue;
+  background: #161A26;
+}
+</style>

+ 426 - 0
data-room-ui/packages/MapDataManagement/src/index.vue

@@ -0,0 +1,426 @@
+<template>
+  <div class="bs-container">
+    <div class="inner-container">
+      <el-form
+        :inline="true"
+        class="filter-container"
+      >
+        <el-form-item class="filter-input filter-item">
+          <el-input
+            v-model="searchForm.searchKey"
+            class="bs-el-input"
+            clearable
+            maxlength="200"
+            placeholder="请输入地图名称或编码"
+          />
+        </el-form-item>
+        <el-form-item class="filter-item">
+          <el-select
+            v-model="searchForm.level"
+            class="bs-el-select"
+            clearable
+            placeholder="请选择地图级别"
+            popper-class="bs-el-select"
+            @change="getDataList"
+          >
+            <el-option
+              v-for="level in levelList"
+              :key="level.value"
+              :label="level.label"
+              :value="level.value"
+            />
+          </el-select>
+        </el-form-item>
+        <el-form-item class="filter-item">
+          <el-button
+            :loading="searchLoading"
+            icon="el-icon-search"
+            type="primary"
+            @click="getDataList"
+          >
+            查询
+          </el-button>
+        </el-form-item>
+        <el-form-item class="filter-item">
+          <el-button
+            class="bs-el-button-default"
+            @click="addMap"
+          >
+            新增
+          </el-button>
+        </el-form-item>
+      </el-form>
+      <div class="bs-table-box">
+        <el-table
+          v-loading="searchLoading"
+          ref="table"
+          v-table
+          :data="mapList"
+          :element-loading-text="loadingText"
+          :load="load"
+          :tree-props="{children: 'children', hasChildren: 'hasChildren'}"
+          class="bs-el-table bs-scrollbar"
+          height="0"
+          lazy
+          row-key="id"
+        >
+          <el-empty slot="empty"/>
+          <el-table-column
+            align="left"
+            label="名称"
+            prop="name"
+            show-overflow-tooltip
+          />
+          <el-table-column
+            align="center"
+            label="编码"
+            prop="mapCode"
+            show-overflow-tooltip
+          />
+          <el-table-column
+            align="center"
+            label="级别"
+            prop="level"
+            show-overflow-tooltip
+          >
+            <template slot-scope="scope">
+              <span v-if="scope.row.level === 0">世界</span>
+              <span v-else-if="scope.row.level === 1">国家</span>
+              <span v-else-if="scope.row.level === 2">省份</span>
+              <span v-else-if="scope.row.level === 3">城市</span>
+              <span v-else-if="scope.row.level === 4">区县</span>
+            </template>
+          </el-table-column>
+          <el-table-column
+            align="center"
+            label="开启下钻"
+            prop="enableDown"
+            show-overflow-tooltip
+          >
+            <template slot-scope="scope">
+              <span v-if="scope.row.enableDown === 1">是</span>
+              <span v-else>否</span>
+            </template>
+          </el-table-column>
+          <el-table-column
+            align="center"
+            label="已上传配置JSON"
+            prop="uploadedGeoJson"
+            show-overflow-tooltip
+          >
+            <template slot-scope="scope">
+              <span v-if="scope.row.uploadedGeoJson === 1">是</span>
+              <span v-else>否</span>
+            </template>
+          </el-table-column>
+          <el-table-column
+            align="center"
+            label="操作"
+            width="200"
+          >
+            <template slot-scope="scope">
+              <el-button
+                class="bs-el-button-default"
+                @click="editMap(scope.row)"
+              >
+                编辑
+              </el-button>
+              <el-button
+                class="bs-el-button-default"
+                @click="deleteMap(scope.row)"
+              >
+                删除
+              </el-button>
+              <el-button
+                v-if="scope.row.uploadedGeoJson === 1"
+                class="bs-el-button-default"
+                @click="addChild(scope.row)"
+              >
+                添加下级
+              </el-button>
+              <el-button
+                v-if="scope.row.uploadedGeoJson === 0"
+                class="bs-el-button-default"
+                @click="uploadGeoJson(scope.row)"
+              >
+                上传配置
+              </el-button>
+            </template>
+          </el-table-column>
+
+        </el-table>
+      </div>
+    </div>
+    <add-form
+      ref="addForm"
+      @refresh="getDataList"
+    />
+    <edit-form
+      ref="editForm"
+      @refresh="getDataList"
+    />
+    <el-dialog
+      :close-on-click-modal="false"
+      :visible.sync="geoJsonVisible"
+      append-to-body
+      class="bs-dialog-wrap bs-el-dialog"
+      height="1000px"
+      title="geoJson数据"
+      width="1000px"
+    >
+      <vue-json-viewer
+        v-model="currentMapGeoJSon"
+        theme="dark"
+        :show-btns="false"
+        mode="code"
+      />
+      <el-button
+        class="bs-el-button-default"
+        @click="upload()"
+      >
+        <i class="el-icon-upload2"></i>
+        上传
+      </el-button>
+      <span
+        slot="footer"
+        class="dialog-footer"
+      >
+        <el-button
+          class="bs-el-button-default"
+          @click="submitUpload"
+        >提交</el-button>
+        </span>
+    </el-dialog>
+    <input
+      ref="geoJsonFileUpload"
+      accept=".json"
+      name="file"
+      style="display: none"
+      type="file"
+      @change="handleBatchUpload"
+    >
+  </div>
+</template>
+
+<script>
+import table from 'data-room-ui/js/utils/table.js'
+import {mapList, mapDelete, uploadGeoJson, mapCascadeDelete} from 'data-room-ui/js/utils/mapDataService'
+import AddForm from "./AddForm"
+import EditForm from "./EditForm"
+import vueJsonViewer from 'vue-json-viewer'
+
+export default {
+  name: "MapManagement",
+  directives: {
+    table // 注册自定义指令
+  },
+  components: {
+    AddForm,
+    EditForm,
+    vueJsonViewer
+  },
+  data() {
+    return {
+      currentMap: {}, // 当前操作的地图
+      currentMapGeoJSon: {}, // 当前操作的地图geoJson
+      loadingText: '',
+      searchLoading: false,
+      geoJsonVisible: false,
+      lazyResolveIds: [],
+      searchForm: {
+        searchKey: '',
+        level: null,
+        enableDown: null,
+        uploadedGeoJson: null,
+        parentCode: '0'
+      },
+      levelList: [
+        {
+          label: '世界',
+          value: 0
+        },
+        {
+          label: '国家',
+          value: 1
+        },
+        {
+          label: '省份',
+          value: 2
+        },
+        {
+          label: '城市',
+          value: 3
+        },
+        {
+          label: '区县',
+          value: 4
+        }
+      ],
+      mapList: []
+    }
+  },
+  mounted() {
+    this.init()
+
+  },
+  methods: {
+    init() {
+      this.searchLoading = true
+      this.loadingText = '正在加载地图数据...'
+      mapList(this.searchForm).then(res => {
+        this.mapList = res
+        this.searchLoading = false
+      }).catch(err => {
+        this.searchLoading = false
+      })
+    },
+    getDataList() {
+      this.searchLoading = true
+      this.loadingText = '正在加载地图数据...'
+      mapList(this.searchForm).then(res => {
+        this.mapList = res
+        this.searchLoading = false
+      }).catch(err => {
+        this.searchLoading = false
+      })
+      // 清除展开状态
+      for (let i = 0; i < this.lazyResolveIds.length; i++) {
+        this.$refs.table.store.states.treeData[this.lazyResolveIds[i]].loaded = false;
+        this.$refs.table.store.states.treeData[this.lazyResolveIds[i]].expanded = false
+      }
+    },
+    addMap() {
+      this.$refs.addForm.mapFormVisible = true
+      this.$refs.addForm.init()
+    },
+    load(data, treeNode, resolve) {
+      this.lazyResolveIds.push(data.id)
+      mapList({
+        parentCode: data.mapCode
+      }).then(res => {
+        resolve(res)
+      }).catch(err => {
+        resolve([])
+      })
+    },
+    deleteMap(map) {
+      this.$confirm('确定删除该地图?', '提示', {
+        confirmButtonText: '确定',
+        cancelButtonText: '取消',
+        type: 'warning',
+        customClass: 'bs-el-message-box'
+      }).then(async () => {
+        mapDelete(map.id).then(() => {
+          this.$message({
+            type: 'success',
+            message: '删除成功'
+          })
+          this.getDataList()
+        }).catch(() => {
+          this.deleteMapCascade(map)
+        })
+      }).catch(() => {
+      })
+    },
+    deleteMapCascade(map) {
+      this.$confirm('该地图存在子级,是否直接删除该地图以及其所有子级?', '提示', {
+        confirmButtonText: '确定',
+        cancelButtonText: '取消',
+        type: 'warning',
+        customClass: 'bs-el-message-box'
+      }).then(async () => {
+        mapCascadeDelete(map.id).then(() => {
+          this.$message({
+            type: 'success',
+            message: '删除成功'
+          })
+          this.getDataList()
+        }).catch(() => {
+        })
+      }).catch(() => {
+      })
+    },
+    addChild(map) {
+      this.$refs.addForm.mapFormVisible = true
+      this.$refs.addForm.init(map)
+    },
+    editMap(map) {
+      this.$refs.editForm.mapFormVisible = true
+      this.$refs.editForm.init(map)
+    },
+    uploadGeoJson(map) {
+      this.currentMap = map
+      this.currentMapGeoJSon = {}
+      this.geoJsonVisible = true
+    },
+    upload() {
+      this.$refs.geoJsonFileUpload.click()
+    },
+    handleBatchUpload(source) {
+      this.uploadLoading = true
+      const file = source.target.files
+      const reader = new FileReader() // 新建一个FileReader
+      reader.readAsText(file[0], 'UTF-8') // 读取文件
+
+      reader.onload = (event) => {
+        let jsonStr = event.target.result
+        // 读取文件内容
+        try {
+          this.currentMapGeoJSon = JSON.parse(jsonStr)
+        } catch (e) {
+          this.uploadLoading = false
+          this.$message.error('JSON文件格式错误')
+          return false
+        }
+        this.uploadLoading = false
+        // input通过onchange事件来触发js代码的,由于两次文件是重复的,所以这个时候onchange事件是没有触发到的,所以需要手动清空input的值
+        source.target.value = ''
+      }
+    },
+    submitUpload() {
+      // 先检查JSON是否合法
+      if (typeof this.currentMapGeoJSon === 'string') {
+        this.$message.error('JSON文件格式错误')
+        return false
+      }
+      if (this.currentMapGeoJSon === {}) {
+        this.$message.error('JSON数据不能为空')
+        return false
+      }
+      // 调接口保存
+      uploadGeoJson({
+        id: this.currentMap.id,
+        geoJson: JSON.stringify(this.currentMapGeoJSon)
+      }).then(res => {
+        this.$message({
+          type: 'success',
+          message: '上传成功'
+        })
+        this.geoJsonVisible = false
+        this.getDataList()
+      }).catch(err => {
+        this.$message({
+          type: 'error',
+          message: '上传失败'
+        })
+      })
+      this.geoJsonVisible = false
+    },
+    isWhitespace(str) {
+      // 如果是null、undefined,返回true
+      if (str == null) {
+        return true
+      }
+      return /^\s*$/.test(str);
+    },
+  },
+}
+</script>
+
+<style lang="scss" scoped>
+@import '../../assets/style/bsTheme.scss';
+.jv-container.dark {
+  color: aliceblue;
+  background: #161A26;
+}
+</style>

+ 1 - 0
data-room-ui/packages/assets/style/bsTheme.scss

@@ -610,6 +610,7 @@
   .el-switch__core {
     background: var(--bs-el-background-1);
     background-color: var(--bs-el-background-1);
+    border-color: var(--bs-el-border);
   }
 }
 

+ 71 - 0
data-room-ui/packages/js/utils/mapDataService.js

@@ -0,0 +1,71 @@
+/*!
+ * 地图数据管理
+ */
+import Vue from 'vue'
+
+/**
+ * 获取地图列表
+ * @param params
+ * @param flag
+ * @returns {*}
+ */
+const mapList = (params = {}, flag = false) => Vue.prototype.$dataRoomAxios.get('/bigScreen/map/list', params, flag)
+
+/**
+ * 新增地图
+ * @param params
+ * @param flag
+ * @returns {*}
+ */
+const mapAdd = (params = {}, flag = false) => Vue.prototype.$dataRoomAxios.post('/bigScreen/map/add', params, flag)
+
+/**
+ * 更新地图
+ * @param params
+ * @param flag
+ * @returns {*}
+ */
+const mapUpdate = (params = {}, flag = false) => Vue.prototype.$dataRoomAxios.post('/bigScreen/map/update', params, flag)
+
+/**
+ * 删除地图
+ * @param id
+ */
+const mapDelete = (id = '-1') => Vue.prototype.$dataRoomAxios.post(`/bigScreen/map/delete/${id}`)
+
+/**
+ * 级联删除地图
+ * @param id
+ */
+const mapCascadeDelete = (id = '-1') => Vue.prototype.$dataRoomAxios.post(`/bigScreen/map/cascadeDelete/${id}`)
+
+/**
+ * 根据父编码解析父级json中的子级
+ * @param code
+ */
+const getMapChildFromGeoJson = (code = '-1') => Vue.prototype.$dataRoomAxios.get(`/bigScreen/map/getMapChildFromGeoJson/${code}`)
+
+/**
+ * 上传地图json
+ * @param params
+ * @param flag
+ */
+const uploadGeoJson = (params = {}, flag = false) => Vue.prototype.$dataRoomAxios.post('/bigScreen/map/upload', params, flag)
+
+/**
+ * 编码重复校验
+ * @param params
+ * @param flag
+ */
+const repeatCheck = (params = {}, flag = false) => Vue.prototype.$dataRoomAxios.post('/bigScreen/map/repeat', params, flag)
+
+export {
+  mapList,
+  mapAdd,
+  mapUpdate,
+  mapDelete,
+  mapCascadeDelete,
+  getMapChildFromGeoJson,
+  uploadGeoJson,
+  repeatCheck
+}

+ 7 - 0
data-room-ui/packages/js/utils/registerConfig.js

@@ -72,6 +72,13 @@ function registerRouters (config, router) {
             title: '数据集管理'
           }
         },
+        {
+          path: '/big-screen-map-data',
+          component: () => import('data-room-ui/MapDataManagement'),
+          meta: {
+            title: '地图数据管理'
+          }
+        },
         {
           path: config?.routers?.SourceUrl || '/big-screen-source',
           component: () => import('data-room-ui/SourceManagement'),