Browse Source

3D地图管理

master
xuhuajiao 2 weeks ago
parent
commit
d2d2715875
  1. 36
      src/api/map/index.js
  2. 37
      src/views/deviceManage/floor/index.vue
  3. 129
      src/views/deviceManage/map3d/index.vue
  4. 150
      src/views/deviceManage/map3d/map.vue

36
src/api/map/index.js

@ -0,0 +1,36 @@
import request from '@/utils/request'
import qs from 'qs'
export function add(data) {
return request({
url: 'api/fengmap/editMap',
method: 'post',
data
})
}
export function edit(data) {
return request({
url: 'api/fengmap/editMap',
method: 'post',
data
})
}
// export function del(ids) {
// return request({
// url: 'api/libraryRegion/delLibraryRegion',
// method: 'post',
// data: ids
// })
// }
// 根据id查询地图详情
export function FetchMapDetails(params) {
return request({
url: 'api/fengmap/getMapDetails' + '?' + qs.stringify(params, { indices: false }),
method: 'get'
})
}
export default { add, edit, FetchMapDetails }

37
src/views/deviceManage/floor/index.vue

@ -93,7 +93,34 @@
<el-form-item label="描述信息" prop="floorDescription">
<el-input v-model="form.floorDescription" placeholder="请输入" type="textarea" rows="3" style="width: 580px;" />
</el-form-item>
<UploadCover :label-name="labelName" :form="form" upload-type="other" @childCover="handleCover" />
<el-form-item label="地图类型" prop="mapType">
<el-radio-group v-model="form.mapType">
<el-radio :label="1">2D</el-radio>
<el-radio :label="2">3D</el-radio>
</el-radio-group>
</el-form-item>
<UploadCover v-if="form.mapType===1" :label-name="labelName" :form="form" upload-type="other" @childCover="handleCover" />
<el-form-item v-if="form.mapType===2" label="选择3D地图" prop="appID">
<el-select v-model="form.appID" placeholder="请选择" style="width: 580px;">
<el-option
v-for="(item,index) in mapOptions"
:key="index"
:label="item.name"
:value="item.id"
/>
</el-select>
</el-form-item>
<el-form-item v-if="form.mapType===2" label="楼层绑定" prop="bindFloor">
<el-button size="mini">
<i class="iconfont icon-sulan" />
已绑定点击查看/重新绑定
</el-button>
<el-button size="mini" style="color: #fff; background-color: #0348f3;">
<i class="iconfont icon-bendiguajie" />
未绑定点击按钮完成绑定
</el-button>
</el-form-item>
</el-form>
<div slot="footer" class="dialog-footer">
<el-button type="text" @click="crud.cancelCU">取消</el-button>
@ -131,7 +158,7 @@ import Sortable from 'sortablejs'
import { mapGetters } from 'vuex'
import defaultImg from '@/assets/images/system/default-img.jpg'
const defaultForm = { id: null, floorName: null, floorDescription: null, floorMap: null }
const defaultForm = { id: null, floorName: null, floorDescription: null, floorMap: null, mapType: 1, appID: null }
export default {
name: 'Floor',
components: { crudOperation, rrOperation, pagination, UploadCover },
@ -158,12 +185,16 @@ export default {
rules: {
floorName: [
{ required: true, message: '所在楼层不可为空', trigger: 'blur' }
],
mapType: [
{ required: true, message: '请选择地图类型', trigger: 'change' }
]
},
defaultImg: defaultImg,
imageUrl: defaultImg,
sortTableData: [], // data
sortVisible: false // dialog
sortVisible: false, // dialog
mapOptions: []
}
},
computed: {

129
src/views/deviceManage/map3d/index.vue

@ -6,7 +6,7 @@
</div>
<div class="head-container">
<div class="head-search" style="align-items: center;">
<el-input v-model="query.title" size="small" clearable placeholder="输入appName关键字搜索" prefix-icon="el-icon-search" style="width: 200px;" class="filter-item" @keyup.enter.native="crud.toQuery" />
<el-input v-model="query.appName" size="small" clearable placeholder="输入appName关键字搜索" prefix-icon="el-icon-search" style="width: 200px;" class="filter-item" @keyup.enter.native="crud.toQuery" />
<rrOperation />
</div>
<crudOperation :permission="permission">
@ -24,15 +24,17 @@
<el-table ref="table" v-loading="crud.loading" highlight-current-row style="width: 100%;" height="calc(100vh - 400px)" :data="crud.data" @selection-change="crud.selectionChangeHandler">
<el-table-column type="selection" align="center" width="55" />
<el-table-column prop="appName" label="appName" />
<el-table-column prop="appID" label="appID" />
<el-table-column prop="key" label="Key" />
<el-table-column prop="seqencing" label="访问方式" align="center" />
<el-table-column prop="status" label="离线地图包" align="center" />
<el-table-column prop="appId" label="appId" />
<el-table-column prop="mapKey" label="mapKey" />
<el-table-column prop="isOnline" label="访问方式" align="center">
<template slot-scope="scope">
<el-tag v-if="scope.row.isOnline" type="success">在线</el-tag>
<el-tag v-else type="danger">离线</el-tag>
</template>
</el-table-column>
<el-table-column prop="createTime" label="操作">
<!-- slot-scope="scope" -->
<template>
<!-- @click="handlePosition(scope.row)" -->
<el-button size="mini">
<template slot-scope="scope">
<el-button size="mini" @click="handlePreviewMap(scope.row)">
<i class="iconfont icon-yulan" />
地图预览
</el-button>
@ -56,15 +58,19 @@
<el-form-item label="appId" prop="appId">
<el-input v-model="form.appId" style="width: 486px;" placeholder="请输入,注意:输入错误将无法正常解析" />
</el-form-item>
<el-form-item label="Key" prop="key">
<el-input v-model="form.key" style="width: 486px;" placeholder="请输入,注意:输入错误将无法正常解析" />
<el-form-item label="Key" prop="mapKey">
<el-input v-model="form.mapKey" style="width: 486px;" placeholder="请输入,注意:输入错误将无法正常解析" />
</el-form-item>
<el-form-item label="访问方式" prop="type">
<el-radio-group v-model="form.type">
<el-form-item label="访问方式" prop="isOnline">
<el-radio-group v-model="form.isOnline">
<el-radio :label="1">在线</el-radio>
<el-radio :label="0">离线</el-radio>
</el-radio-group>
</el-form-item>
<div v-if="form.isOnline===0" class="setting-tip">
<i class="iconfont icon-zhuyi-lan" />
<span>请确保管理员已将地图离线数据包上传到服务器指定路径否则无法成功加载地图信息<br> 注意离线地图数据包的文件夹名需与AppID保持一致</span>
</div>
</el-form>
<div slot="footer" class="dialog-footer">
<el-button type="text" @click="crud.cancelCU">取消</el-button>
@ -73,23 +79,32 @@
</div>
</el-dialog>
<el-dialog class="map-dialog" :close-on-click-modal="false" :modal-append-to-body="false" append-to-body :before-close="handleClose" :visible.sync="mapPreviewVisible" :title="mapPreviewTitle">
<span class="dialog-right-top" />
<span class="dialog-left-bottom" />
<div class="setting-dialog">
<PreviewMap ref="map" :map-data="mapData" />
</div>
</el-dialog>
</div>
</template>
<script>
import crudColumn from '@/api/inquiryMachine/column'
import crudMap from '@/api/map/index'
import CRUD, { presenter, header, form, crud } from '@crud/crud'
import rrOperation from '@crud/RR.operation'
import crudOperation from '@crud/CRUD.operation'
import pagination from '@crud/Pagination'
import { mapGetters } from 'vuex'
import PreviewMap from './map'
const defaultForm = { id: null, appName: null, appId: null, type: 1, key: null }
const defaultForm = { id: null, appName: null, appId: null, isOnline: 1, mapKey: null }
export default {
name: 'Column',
components: { pagination, crudOperation, rrOperation },
components: { pagination, crudOperation, rrOperation, PreviewMap },
cruds() {
return CRUD({ title: '3D地图配置', url: 'api/queryMachine/initQueryTopic', crudMethod: { ...crudColumn }, optShow: {
return CRUD({ title: '3D地图配置', url: 'api/fengmap/initMapList', crudMethod: { ...crudMap }, optShow: {
add: true,
edit: true,
del: false,
@ -115,13 +130,16 @@ export default {
appId: [
{ required: true, message: '请输入AppID', trigger: 'blur' }
],
key: [
mapKey: [
{ required: true, message: '请输入Key', trigger: 'blur' }
],
type: [
isOnline: [
{ required: true, message: '请选择访问方式', trigger: 'change' }
]
}
},
mapPreviewVisible: false,
mapPreviewTitle: '3D地图预览',
mapData: {}
}
},
computed: {
@ -145,12 +163,26 @@ export default {
},
//
[CRUD.HOOK.beforeToEdit](crud, form) {
console.log(form)
if (form.isOnline) {
form.isOnline = 1
} else {
form.isOnline = 0
}
},
//
[CRUD.HOOK.afterValidateCU](crud) {
console.log(crud.form)
return true
},
handlePreviewMap(row) {
console.log('row', row)
this.mapPreviewVisible = true
this.mapData = row
this.$nextTick(() => {
this.$refs.map.initMap()
})
},
toDelete(datas) {
this.$confirm('此操作将删除当前所选' + this.crud.title + '<span>你是否还要继续?</span>', '提示', {
confirmButtonText: '继续',
@ -163,24 +195,57 @@ export default {
datas.forEach(val => {
ids.push(val.id)
})
crudColumn.del(ids).then((res) => {
if (res.code !== 500) {
this.$message({ message: '删除成功', type: 'success', offset: 8 })
this.crud.refresh()
} else {
this.$message({ message: '删除失败', type: 'error', offset: 8 })
}
this.crud.delAllLoading = false
}).catch(err => {
this.crud.delAllLoading = false
console.log(err)
})
// crudColumn.del(ids).then((res) => {
// if (res.code !== 500) {
// this.$message({ message: '', type: 'success', offset: 8 })
// this.crud.refresh()
// } else {
// this.$message({ message: '', type: 'error', offset: 8 })
// }
// this.crud.delAllLoading = false
// }).catch(err => {
// this.crud.delAllLoading = false
// console.log(err)
// })
}).catch(() => {
})
},
handleClose() {
this.mapPreviewVisible = false
this.mapData = {}
if (this.$refs.map) {
this.$refs.map.dispose()
}
}
}
}
</script>
<style lang="scss" scoped>
.setting-tip{
display: flex;
justify-content: flex-start;
line-height: 26px;
margin-bottom: 15px;
padding-left: 110px;
span{
display: inline-block;
font-size: 12px;
color: #545B65;
}
i{
display: inline-block;
color: #0348F3;
}
}
.map-dialog{
::v-deep .el-dialog{
width: 1200px;
height: 800px;
.el-dialog__body{
padding: 0 !important;
}
}
}
</style>

150
src/views/deviceManage/map3d/map.vue

@ -0,0 +1,150 @@
<template>
<div style="position: relative; width: 100%; height: 720px; ">
<div id="fengmap" />
<div class="rightMask" />
</div>
</template>
<script>
import fengmap from '@/assets/fengmap/fengmap.map.min'
import { FMControlPosition, FMToolbar, FMScaleBar } from '@/assets/fengmap/fengmap.plugin.ui.min.js'
export default {
name: 'FengMap',
props: {
mapData: {
type: Object,
require: true,
default: function() {
return {}
}
}
},
data() {
return {
map: null,
level: null,
levels: null,
marker: null,
scrollFloorControl: null,
scaleBar: null
}
},
watch: {
mapData: {
handler(newVal, oldVal) {
if (!newVal) {
console.log('newVal-null')
return
}
},
deep: true
}
},
mounted() {
console.log('mapData', this.mapData)
},
methods: {
dispose() {
this.scrollFloorControl.remove()
this.map.dispose()
this.map = null
},
initMap() {
window.vueInstance = null
try {
console.log('开始初始化地图')
const options = {
container: document.getElementById('fengmap'),
appName: this.mapData && this.mapData.appName,
key: this.mapData && this.mapData.mapKey,
mapID: this.mapData && this.mapData.appId,
// mapURL: '/fengmap/data/',
// themeID: '1574346301450625025',
// themeURL: '/fengmap/data/theme/',
mapZoom: 19.5,
backgroundColor: '#fff'
}
console.log('地图配置:', options)
this.map = new fengmap.FMMap(options)
console.log('地图实例已创建')
// this.map.on('loadingProcess', (event) => {
// console.log(':', event.progress)
// this.debugInfo = `: ${event.progress}%`
// })
this.map.on('loaded', () => {
console.log('地图加载完成')
this.map.setViewMode(fengmap.FMViewMode.MODE_3D)
//
const scrollFloorCtlOpt = {
position: FMControlPosition.RIGHT_TOP,
floorButtonCount: 5,
offset: {
x: -20,
y: 150
},
viewModeControl: true,
floorModeControl: true,
needAllLayerBtn: true
}
this.scrollFloorControl = new FMToolbar(scrollFloorCtlOpt)
this.scrollFloorControl.addTo(this.map)
//
const scrollScaleBarCtlOpt = {
fontSize: 18,
height: 30,
position: FMControlPosition.LEFT_BOTTOM,
offset: {
x: 20,
y: -20
}
}
this.scaleBar = new FMScaleBar(scrollScaleBarCtlOpt)
this.scaleBar.addTo(this.map)
window.vueInstance = this
console.log('Vue实例已全局挂载:', window.vueInstance)
}, { passive: true })
this.map.on('click', (e) => {
this.marker && this.marker.remove()
this.marker = null
}, { passive: true })
this.map.on('mapInitError', (err) => {
console.error('地图初始化错误:', err)
this.debugInfo = `地图初始化错误: ${err.message}`
})
} catch (error) {
console.error('初始化地图失败:', error)
this.debugInfo = `初始化失败: ${error.message}`
}
}
}
}
</script>
<style scoped lang="scss">
@import "~@/assets/fengmap/toolBarStyle.css";
#fengmap {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
background: #f5f5f5;
}
.rightMask{
width: 162px;
height: 42px;
position: absolute;
bottom: 0;
right: 0;
background: #fff;
}
</style>
Loading…
Cancel
Save