Browse Source

区域管理

master
xuhuajiao 2 weeks ago
parent
commit
2fc2b1092b
  1. 10
      src/assets/iconfonts/light/iconfont.css
  2. 2
      src/assets/iconfonts/light/iconfont.js
  3. 7
      src/assets/iconfonts/light/iconfont.json
  4. BIN
      src/assets/iconfonts/light/iconfont.ttf
  5. BIN
      src/assets/iconfonts/light/iconfont.woff
  6. BIN
      src/assets/iconfonts/light/iconfont.woff2
  7. 4
      src/components/Crud/crud.js
  8. 6
      src/views/deviceManage/area/areaClassifyRelated.vue
  9. 280
      src/views/deviceManage/area/index.vue
  10. 10
      src/views/deviceManage/floor/index.vue
  11. 49
      src/views/deviceManage/map3d/map.vue
  12. 29
      src/views/deviceManage/map3d/mapRight.vue

10
src/assets/iconfonts/light/iconfont.css

@ -1,8 +1,8 @@
@font-face {
font-family: "iconfont"; /* Project id 3966148 */
src: url('iconfont.woff2?t=1757381540478') format('woff2'),
url('iconfont.woff?t=1757381540478') format('woff'),
url('iconfont.ttf?t=1757381540478') format('truetype');
src: url('iconfont.woff2?t=1760517327121') format('woff2'),
url('iconfont.woff?t=1760517327121') format('woff'),
url('iconfont.ttf?t=1760517327121') format('truetype');
}
.iconfont {
@ -13,6 +13,10 @@
-moz-osx-font-smoothing: grayscale;
}
.icon-d:before {
content: "\e6a0";
}
.icon-yooxi:before {
content: "\e69d";
}

2
src/assets/iconfonts/light/iconfont.js
File diff suppressed because it is too large
View File

7
src/assets/iconfonts/light/iconfont.json

@ -5,6 +5,13 @@
"css_prefix_text": "icon-",
"description": "",
"glyphs": [
{
"icon_id": "13302910",
"name": "3d",
"font_class": "d",
"unicode": "e6a0",
"unicode_decimal": 59040
},
{
"icon_id": "778898",
"name": "vip",

BIN
src/assets/iconfonts/light/iconfont.ttf

BIN
src/assets/iconfonts/light/iconfont.woff

BIN
src/assets/iconfonts/light/iconfont.woff2

4
src/components/Crud/crud.js

@ -276,7 +276,9 @@ function CRUD(options) {
crud.crudMethod.add(crud.form).then((res) => {
crud.status.add = CRUD.STATUS.NORMAL
crud.resetForm()
if (res && (res !== 'SUCCESS' || res !== '保存成功' || res.code !== 500)) {
console.log('res', res)
// if (res && res !== 'SUCCESS' || res !== '保存成功' || res.code !== 500) {
if (res === 'SUCCESS' || res === '保存成功' || res.code !== 500) {
crud.addSuccessNotify()
callVmHook(crud, CRUD.HOOK.afterSubmit, res)
} else {

6
src/views/deviceManage/area/areaClassifyRelated.vue

@ -1,7 +1,7 @@
<template>
<div class="app-container">
<div class="venue-header">
<h4><i class="iconfont icon-hangzhengquyuguanli" />区域列表</h4>
<h4><i class="iconfont icon-hangzhengquyuguanli" />区域分类关联</h4>
<p><i class="iconfont icon-gongsi" />{{ user.fonds.fondsName }}</p>
</div>
<div class="venue-content">
@ -26,13 +26,13 @@
@selection-change="crud.selectionChangeHandler"
@row-click="clickRowHandler"
>
<el-table-column type="selection" align="center" width="55" />
<!-- <el-table-column type="selection" align="center" width="55" /> -->
<el-table-column type="index" label="排序" />
<el-table-column prop="regionName" label="区域名称" />
<el-table-column prop="regionCode" label="区域编码" />
<el-table-column prop="floorName" label="所在楼层" />
<el-table-column prop="booksheflCount" label="书架" />
<el-table-column prop="signPoint" label="关联分类" />
<el-table-column prop="data" label="关联分类" />
</el-table>
<!--分页组件-->
<pagination v-if="crud.data.length!==0" />

280
src/views/deviceManage/area/index.vue

@ -47,11 +47,22 @@
<el-table-column prop="regionName" label="区域名称" />
<el-table-column prop="regionCode" label="区域编码" />
<el-table-column prop="floorName" label="所在楼层" />
<el-table-column prop="booksheflCount" label="书架" />
<el-table-column prop="signPoint" label="标注">
<el-table-column prop="booksheflCount" label="书架" width="70" />
<el-table-column prop="mapType" label="地图类型">
<template slot-scope="scope">
<span>{{ scope.row.mapType === 1 ? '2D' : '3D' }}</span>
</template>
</el-table-column>
<!-- <el-table-column prop="signPoint" label="标注">
<template slot-scope="scope">
<span :class="['row-state', scope.row.signPoint ? 'end-state' : 'cancel-state' ]">{{ scope.row.signPoint ? '已标注': '未标注' }}</span>
</template>
</el-table-column> -->
<el-table-column prop="signPoint" label="标注" width="70">
<template slot-scope="scope">
<span v-if="scope.row.mapType === 1" :class="['row-state', scope.row.signPoint ? 'end-state' : 'cancel-state' ]">{{ scope.row.signPoint ? '已上传': '未上传' }}</span>
<span v-else :class="['row-state', scope.row.fid ? 'end-state' : 'cancel-state' ]">{{ scope.row.fid ? '已绑定': '未绑定' }}</span>
</template>
</el-table-column>
</el-table>
<!--分页组件-->
@ -62,16 +73,21 @@
<div class="container-right tab-content">
<span class="right-top-line" />
<span class="left-bottom-line" />
<ul class="tab-nav">
<ul v-if="currentMarkData && currentMarkData.mapType===2" class="tab-nav">
<li :class="{ 'active-tab-nav': activeIndex == 2 }" @click="changeActiveTab(2)">3D楼层区域预览<i /></li>
<span class="tab-right-img" />
</ul>
<ul v-else class="tab-nav">
<li :class="{ 'active-tab-nav': activeIndex == 0 }" @click="changeActiveTab(0)">楼层区域<i /></li>
<li :class="{ 'active-tab-nav': activeIndex == 1 }" @click="changeActiveTab(1)">区域预览<i /></li>
<!-- 最右侧装饰img -->
<span class="tab-right-img" />
<el-button size="mini" class="venue-mark" :disabled="crud.selections.length !== 1" @click="handleMark">
<el-button v-if="currentMarkData && currentMarkData.mapType===1" size="mini" class="venue-mark" :disabled="crud.selections.length !== 1" @click="handleMark">
<i class="el-icon-edit" />
区域标注
</el-button>
</ul>
<div v-show="activeIndex == 0" class="venue-preview">
<!-- <MarkCover v-if="currentMarkData && currentMarkData.signPoint" ref="markRefs2" :is-canvas-show="true" :current-mark-data="currentMarkData" :image-floor-url="imageUrl" /> -->
<div v-show="currentMarkData && currentMarkData.signPoint ">
@ -83,6 +99,9 @@
<div v-if="activeIndex == 1" class="venue-preview">
<img :src="imageRegionUrl" :onerror="defaultImg" alt="">
</div>
<div v-if="activeIndex == 2" class="venue-preview">
<PreviewMapRight ref="rightMap" :map-data="currentMapData" />
</div>
</div>
</div>
</div>
@ -112,7 +131,35 @@
<el-form-item label="描述信息" prop="regionDescription">
<el-input v-model="form.regionDescription" placeholder="请输入" type="textarea" rows="3" style="width: 580px;" />
</el-form-item>
<UploadCover ref="uploadCoverRefs" :label-name="labelName" :form="form" @childCover="handleCover" />
<el-form-item label="地图类型" prop="mapType">
<el-radio-group v-model="form.mapType" :disabled="true">
<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" ref="uploadCoverRefs" :label-name="labelName" :form="form" @childCover="handleCover" />
<el-form-item v-if="form.mapType===2" label="选择3D地图" prop="mapData">
<el-select v-model="form.mapData" placeholder="请选择" value-key="id" style="width: 580px;" :disabled="true">
<el-option
v-for="(item,index) in mapOptions"
:key="index"
:label="item.appName"
:value="item"
/>
</el-select>
</el-form-item>
<el-form-item v-if="form.mapType===2" label="区域绑定" prop="fid">
<!-- <p v-if="mapLevelName">当前已选择{{ mapLevelName }}</p> -->
<el-button v-if="form.fid" size="mini" @click="handleBindMapFloor">
<i class="iconfont icon-sulan" />
已绑定点击查看/重新绑定
</el-button>
<el-button v-else size="mini" style="color: #fff; background-color: #0348f3;" @click="handleBindMapFloor">
<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>
@ -149,11 +196,23 @@
<MarkCover ref="markRefs" :is-book-shelf="false" :current-mark-data="currentMarkData" :image-url="imageUrl" @handleCloseDialog="handleCloseDialog" />
</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="form.mapData" @refreshAreaFid="handleAreaFid" />
</div>
<div slot="footer" class="dialog-footer">
<el-button type="primary" @click.native="saveAreaFid">确定</el-button>
</div>
</el-dialog>
</div>
</template>
<script>
import { FetchLibraryFloorListAll } from '@/api/floor/index'
import { FetchMapTree, FetchMapDetails } from '@/api/map/index'
import crudRegion from '@/api/area/index'
import CRUD, { presenter, header, form, crud } from '@crud/crud'
import crudOperation from '@crud/CRUD.operation'
@ -166,10 +225,13 @@ import { mapGetters } from 'vuex'
import defaultImg from '@/assets/images/system/default-img.jpg'
import { fabric } from 'fabric'
const defaultForm = { id: null, floorId: null, regionName: null, regionCode: null, regionDescription: null, regionMap: null, signPoint: null }
import PreviewMap from '../map3d/map'
import PreviewMapRight from '../map3d/mapRight'
const defaultForm = { id: null, floorId: null, regionName: null, regionCode: null, regionDescription: null, regionMap: null, signPoint: null, mapId: null, mapAppId: null, mapType: null, mapData: null, mapLevel: null, fid: null }
export default {
name: 'Bookshelf',
components: { crudOperation, rrOperation, pagination, UploadCover, MarkCover },
components: { crudOperation, rrOperation, pagination, UploadCover, MarkCover, PreviewMap, PreviewMapRight },
cruds() {
return CRUD({ title: '区域', url: 'api/libraryRegion/initLibraryRegionList', crudMethod: { ...crudRegion }, sort: [], optShow: {
add: true,
@ -215,7 +277,14 @@ export default {
canvasPreview: {},
width: 900,
height: 600,
drawWidth: 2 //
drawWidth: 2, //
floorInfo: {},
mapOptions: [],
mapPreviewVisible: false,
mapPreviewTitle: '3D地图绑定',
mapLevelName: null,
currentMapData: null
}
},
computed: {
@ -235,6 +304,9 @@ export default {
beforeDestroy() {
window.removeEventListener('beforeunload', this.clearLocalStorage)
},
mounted() {
this.getMapTree()
},
methods: {
clearLocalStorage() {
const key = 'formFloor'
@ -256,19 +328,54 @@ export default {
console.log('crud.data', crud.data)
if (crud.data.length !== 0) {
this.clickRowHandler(crud.data[0])
this.activeIndex = 0
if (crud.data[0].mapType === 1) {
this.activeIndex = 0
} else {
this.activeIndex = 2
}
} else {
this.activeIndex = 0
this.currentMarkData = null
this.imageUrl = this.defaultImg
this.imageRegionUrl = this.defaultImg
}
},
//
[CRUD.HOOK.beforeToAdd](crud, form) {
this.mapLevelName = null
},
//
[CRUD.HOOK.beforeToEdit](crud, form) {
this.changeFloorValue(form.floorId)
// if (form.mapId) {
// const matchedItem = this.mapOptions.find(item => item.id === form.mapId)
// if (matchedItem) {
// this.form.mapData = matchedItem
// }
// } else {
// this.form.mapData = null
// }
},
//
[CRUD.HOOK.afterValidateCU](crud) {
this.$refs.uploadCoverRefs.fileNames = ''
if (crud.form.mapType === 1 && this.$refs.uploadCoverRefs) {
this.$refs.uploadCoverRefs.fileNames = ''
}
if (crud.form.mapType === 2 && crud.form.mapData) {
crud.form.mapId = crud.form.mapData.id
crud.form.mapAppId = crud.form.mapData.appId
delete this.crud.form.mapData
}
this.mapLevelName = null
console.log('crud.form', crud.form)
return true
},
handleAreaFid(areaFid) {
this.crud.form.fid = areaFid
// this.mapLevelName = levelName
console.log('mapAreaFid', areaFid)
},
//
getLibraryFloorListAll() {
FetchLibraryFloorListAll().then(res => {
@ -276,6 +383,16 @@ export default {
}).catch(() => {
})
},
getMapTree() {
const params = {
'libcode': this.user.fonds.fondsNo
}
FetchMapTree(params).then(res => {
this.mapOptions = res
}).catch(() => {
})
},
handleCover(value) {
console.log(value)
this.crud.form.regionMap = value
@ -290,34 +407,54 @@ export default {
console.log('value', value)
},
changeFloorValue(value) {
console.log('value', value)
const matchedItem = this.floorOptions.find(item => item.id === value)
if (matchedItem) {
this.floorInfo = matchedItem
this.crud.form.mapType = matchedItem.mapType
const matchedMapItem = this.mapOptions.find(item => item.id === matchedItem.mapId)
if (matchedItem) {
this.crud.form.mapData = matchedMapItem
}
} else {
this.floorInfo = {}
this.crud.form.mapType = null
this.crud.form.mapData = null
}
},
clickRowHandler(row) {
this.$refs.table.clearSelection()
this.$refs.table.toggleRowSelection(row)
// http://192.168.99.67:12010/api/fileRelevant/getImg?imgType=1&imgId=f6d3ecea-0456-4429-ba77-1a4921d5c806
this.currentMarkData = row
if (this.canvasPreview.lowerCanvasEl) {
this.canvasPreview.clear()
this.canvasPreview.dispose()
}
if (this.activeIndex === 0) {
if (row.floorMap) {
this.imageUrl = this.baseApi + '/api/fileRelevant/getImg?imgType=1&imgId=' + row.floorMap
if (row.signPoint) {
this.$nextTick(() => {
const drawinfo = JSON.parse(row.signPoint)
this.initCanvasPreview(drawinfo)
})
if (row.mapType === 1) {
this.changeActiveTab(0)
if (this.canvasPreview.lowerCanvasEl) {
this.canvasPreview.clear()
this.canvasPreview.dispose()
}
if (this.activeIndex === 0) {
if (row.floorMap) {
this.imageUrl = this.baseApi + '/api/fileRelevant/getImg?imgType=1&imgId=' + row.floorMap
if (row.signPoint) {
this.$nextTick(() => {
const drawinfo = JSON.parse(row.signPoint)
this.initCanvasPreview(drawinfo)
})
}
} else {
this.imageUrl = this.defaultImg
}
} else {
this.imageUrl = this.defaultImg
if (row.regionMap) {
this.imageRegionUrl = this.baseApi + '/api/fileRelevant/getImg?imgType=1&imgId=' + row.regionMap
} else {
this.imageRegionUrl = this.defaultImg
}
}
} else {
if (row.regionMap) {
this.imageRegionUrl = this.baseApi + '/api/fileRelevant/getImg?imgType=1&imgId=' + row.regionMap
} else {
this.imageRegionUrl = this.defaultImg
}
console.log('3D地图')
this.changeActiveTab(2)
}
},
onRowDblclick(row) {
@ -341,13 +478,18 @@ export default {
if (this.activeIndex === 0) {
if (this.crud.selections[0].signPoint) {
console.log('1111')
this.$nextTick(() => {
const drawinfo = JSON.parse(this.crud.selections[0].signPoint)
this.initCanvasPreview(drawinfo)
})
}
}
if (this.activeIndex === 2) {
this.$nextTick(() => {
this.getMapDetails(this.crud.selections[0].mapId)
})
}
}
},
async handleMark() {
@ -516,6 +658,76 @@ export default {
})
})
self.canvasPreview.renderAll()
},
getMapDetails(id) {
const params = {
'id': id
}
FetchMapDetails(params).then(res => {
this.currentMapData = res
this.$nextTick(() => {
if (this.$refs.rightMap) {
this.$refs.rightMap.dispose()
}
console.log('this.currentMarkData', this.currentMarkData)
if (this.currentMarkData.mapLevel) {
this.$refs.rightMap.level = Number(this.currentMarkData.mapLevel)
} else {
this.$refs.rightMap.level = 1
}
if (this.currentMarkData.fid) {
this.$refs.rightMap.areaFid = this.currentMarkData.fid
} else {
this.$refs.rightMap.areaFid = null
}
this.$refs.rightMap.initMap()
})
}).catch(() => {
})
},
handleBindMapFloor() {
console.log('this.crud.form', this.crud.form)
console.log('this.floorInfo', this.floorInfo)
if (this.crud.form.floorId && this.floorInfo) {
this.crud.form.mapLevel = Number(this.floorInfo.mapLevel)
if (this.crud.form.mapData) {
const row = this.crud.form.mapData
this.mapPreviewTitle = '3D地图绑定 - 【' + row.appId + '】 ' + row.appName
this.mapPreviewVisible = true
this.$nextTick(() => {
console.log('this.crud.form.mapLevel', this.crud.form.mapLevel)
if (this.crud.form.mapLevel) {
this.$refs.map.level = this.crud.form.mapLevel
} else {
this.$refs.map.level = 1
}
if (this.crud.form.fid) {
this.$refs.map.areaFid = this.crud.form.fid
} else {
this.$refs.map.areaFid = null
}
this.$refs.map.initMap()
})
} else {
this.$message({ message: '请先选择3D地图', type: 'error', offset: 8 })
}
} else {
this.$message({ message: '请先选择所属楼层', type: 'error', offset: 8 })
}
},
saveAreaFid() {
if (this.$refs.map) {
this.$refs.map.getCurrentAreaFid()
this.handleClose()
}
},
handleClose() {
this.mapPreviewVisible = false
this.mapData = {}
if (this.$refs.map) {
this.$refs.map.dispose()
}
}
}
}
@ -525,4 +737,12 @@ export default {
.tab-content{
min-height: calc(100vh - 232px) !important;
}
.map-dialog{
::v-deep .el-dialog__footer{
padding: 0;
.dialog-footer{
margin-top: 0;
}
}
}
</style>

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

@ -446,10 +446,12 @@ export default {
.tab-content{
min-height: calc(100vh - 232px) !important;
}
::v-deep .el-dialog__footer{
padding: 0;
.dialog-footer{
margin-top: 0;
.map-dialog{
::v-deep .el-dialog__footer{
padding: 0;
.dialog-footer{
margin-top: 0;
}
}
}
</style>

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

@ -8,6 +8,8 @@
<script>
import fengmap from '@/assets/fengmap/fengmap.map.min'
import { FMControlPosition, FMToolbar, FMScaleBar } from '@/assets/fengmap/fengmap.plugin.ui.min.js'
import '@/assets/fengmap/fengmap.effect.min'
import locationIcon from '@/assets/images/red.png'
export default {
name: 'FengMap',
@ -28,7 +30,9 @@ export default {
levels: null,
marker: null,
scrollFloorControl: null,
scaleBar: null
scaleBar: null,
areaFid: null,
areaModel: null
}
},
watch: {
@ -114,12 +118,44 @@ export default {
this.scaleBar = new FMScaleBar(scrollScaleBarCtlOpt)
this.scaleBar.addTo(this.map)
window.vueInstance = this
// FID
if (this.areaFid) {
const floor = this.map.getFloor(this.level)
console.log('floor', floor)
this.areaModel = floor.getLayers(fengmap.FMType.MODEL_LAYER)[0].getFeatures().find(item => item.FID === this.areaFid)
console.log('model', this.areaModel)
console.log('model', this.areaModel.getData())
// const feature = model.getData()
this.marker = new fengmap.FMImageMarker({
url: locationIcon,
x: this.areaModel.x,
y: this.areaModel.y,
anchor: fengmap.FMMarkerAnchor.BOTTOM
})
this.marker.addTo(floor)
this.areaModel.setColor('#FF6633')
// this.map.setCenter({ x: this.areaModel.x, y: this.areaModel.y })
// model.flash('red')
}
console.log('Vue实例已全局挂载:', window.vueInstance)
}, { passive: true })
this.map.on('click', (e) => {
const target = e.targets[0]
this.marker && this.marker.remove()
this.marker = null
this.areaFid = null
this.areaModel.resetColor()
console.log('event:', e)
console.log('拾取模型对象:', target)
console.log('name:', target?.name)
console.log('FID:', target?.FID)
this.areaFid = target?.FID
}, { passive: true })
this.map.on('mapInitError', (err) => {
@ -146,6 +182,17 @@ export default {
//
console.log('getFloorInfos', this.map.getFloorInfos())
window.vueInstance.$emit('refreshLevel', this.level, this.levelName)
},
getCurrentAreaFid() {
window.vueInstance.$emit('refreshAreaFid', this.areaFid)
},
fromFidToSearch() {
// FID
const floor = this.map.getFloor(this.level)
const model = floor.getLayers(fengmap.FMType.MODEL_LAYER)[0].getFeatures().find(item => item.FID === '1026050201310')
console.log('model', model.getData())
model.setColor('red')
model.flash('red')
}
}

29
src/views/deviceManage/map3d/mapRight.vue

@ -8,6 +8,8 @@
<script>
import fengmap from '@/assets/fengmap/fengmap.map.min'
import { FMControlPosition, FMToolbar, FMScaleBar } from '@/assets/fengmap/fengmap.plugin.ui.min.js'
import '@/assets/fengmap/fengmap.effect.min'
import locationIcon from '@/assets/images/red.png'
export default {
name: 'FengMap',
@ -28,7 +30,8 @@ export default {
levels: null,
marker: null,
scrollFloorControl: null,
scaleBar: null
scaleBar: null,
areaFid: null
}
},
watch: {
@ -113,6 +116,30 @@ export default {
}
this.scaleBar = new FMScaleBar(scrollScaleBarCtlOpt)
this.scaleBar.addTo(this.map)
// FID
if (this.areaFid) {
const floor = this.map.getFloor(this.level)
console.log('floor', floor)
const model = floor.getLayers(fengmap.FMType.MODEL_LAYER)[0].getFeatures().find(item => item.FID === this.areaFid)
console.log('model', model)
console.log('model', model.getData())
// const feature = model.getData()
this.marker = new fengmap.FMImageMarker({
url: locationIcon,
x: model.x,
y: model.y,
anchor: fengmap.FMMarkerAnchor.BOTTOM
})
model.setColor('#FF6633')
this.marker.addTo(floor)
this.map.setCenter({ x: model.x, y: model.y })
this.map.setZoom({ 'zoom': 21 })
// model.flash('red')
}
window.vueInstance = this
console.log('Vue实例已全局挂载:', window.vueInstance)
}, { passive: true })

Loading…
Cancel
Save