|
|
<template> <div class="app-container"> <div class="venue-header"> <h4><i class="iconfont icon-hangzhengquyuguanli" />区域列表</h4> <p><i class="iconfont icon-gongsi" />{{ user.fonds.fondsName }}</p> </div> <div class="venue-content"> <div class="venue-left"> <div class="head-container"> <div class="head-search"> <!-- 搜索 --> <el-select v-model="setfloorId" clearable size="small" placeholder="楼层" class="filter-item" style="width: 80px" @change="crud.toQuery"> <el-option v-for="item in floorOptions" :key="item.id" :label="item.floorName" :value="item.id" /> </el-select> <el-input v-model="query.search" clearable size="small" placeholder="输入关键字搜索" prefix-icon="el-icon-search" style="width: 200px;" class="filter-item" @clear="crud.toQuery" @keyup.enter.native="crud.toQuery" /> <rrOperation /> </div> <crudOperation :permission="permission"> <template v-slot:middle> <el-button slot="reference" size="mini" :loading="crud.delAllLoading" :disabled="crud.selections.length === 0" @click="toDelete(crud.selections)"> <i class="iconfont icon-shanchu" /> 删除 </el-button> </template> <template v-slot:right> <el-button :loading="crud.downloadLoading" size="mini" :disabled="crud.selections.length <= 1" @click="showSort"> <i class="iconfont icon-paixu" /> 排序 </el-button> </template> </crudOperation> </div> <div> <el-table ref="table" v-loading="crud.loading" :data="crud.data" style="width: 100%;" height="540" @selection-change="crud.selectionChangeHandler" @row-click="clickRowHandler" > <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="标注"> <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> <!--分页组件--> <pagination v-if="crud.data.length!==0" /> </div> </div> <div class="venue-right"> <div class="container-right tab-content"> <span class="right-top-line" /> <span class="left-bottom-line" /> <ul 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"> <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"> <canvas id="canvasPreview" :width="width" :height="height" /> </div> <img v-if="currentMarkData && !currentMarkData.signPoint" :src="imageUrl" :onerror="defaultImg" alt=""> <img v-if="!currentMarkData" :src="imageUrl" :onerror="defaultImg" alt=""> </div> <div v-if="activeIndex == 1" class="venue-preview"> <img :src="imageRegionUrl" :onerror="defaultImg" alt=""> </div> </div> </div> </div>
<!-- form --> <el-dialog append-to-body :close-on-click-modal="false" :modal-append-to-body="false" :before-close="crud.cancelCU" :visible="crud.status.cu > 0" :title="crud.status.title"> <span class="dialog-right-top" /> <span class="dialog-left-bottom" /> <div class="setting-dialog"> <el-form ref="form" :rules="rules" :model="form" size="small" label-width="100px"> <el-form-item label="所属楼层" prop="floorId"> <el-select v-model="form.floorId" placeholder="请选择" style="width: 225px;" @change="changeFloorValue($event)"> <el-option v-for="(item,index) in floorOptions" :key="index" :label="item.floorName" :value="item.id" /> </el-select> </el-form-item> <el-form-item label="区域名称" prop="regionName"> <el-input v-model="form.regionName" style="width: 580px;" /> </el-form-item> <el-form-item label="区域编码" prop="regionCode"> <el-input v-model="form.regionCode" style="width: 580px;" /> </el-form-item> <el-form-item label="描述信息" prop="regionDescription"> <el-input v-model="form.regionDescription" placeholder="请输入" type="textarea" rows="3" style="width: 580px;" /> </el-form-item> <UploadCover :label-name="labelName" :form="form" @childCover="handleCover" /> </el-form> <div slot="footer" class="dialog-footer"> <el-button type="text" @click="crud.cancelCU">取消</el-button> <el-button :loading="crud.status.cu === 2" type="primary" @click="crud.submitCU">保存</el-button> </div> </div> </el-dialog>
<!-- 排序 --> <el-dialog :close-on-click-modal="false" :append-to-body="true" title="排序" :visible.sync="sortVisible" @opened="opened"> <span class="dialog-right-top" /> <span class="dialog-left-bottom" /> <div class="setting-dialog"> <i class="drag-tip">提示:请通过拖动鼠标来调整当前顺序</i> <el-table :data="sortTableData" class="file-sort" style="width: 100%;max-height: 70vh;" row-key="id"> <el-table-column type="index" label="序号" width="100" align="center" /> <el-table-column prop="regionName" label="区域名称"> <template slot-scope="scope"> <span>{{ scope.row.regionName +' [ '+ scope.row.floorName+' ] ' }}</span> </template> </el-table-column> </el-table> <div slot="footer" class="dialog-footer"> <el-button type="primary" @click.native="handleSort">保存</el-button> </div> </div> </el-dialog>
<!-- 标注 --> <el-dialog class="mark-dialog" :close-on-click-modal="false" :append-to-body="true" :title="titleMark" :visible.sync="markVisible" :before-close="handleCloseDialog"> <span class="dialog-right-top" /> <span class="dialog-left-bottom" /> <div class="setting-dialog"> <MarkCover ref="markRefs" :is-book-shelf="false" :current-mark-data="currentMarkData" :image-url="imageUrl" @handleCloseDialog="handleCloseDialog" /> </div> </el-dialog> </div> </template>
<script> import { FetchLibraryFloorListAll } from '@/api/floor/index' import crudRegion from '@/api/area/index' import CRUD, { presenter, header, form, crud } from '@crud/crud' import crudOperation from '@crud/CRUD.operation' import rrOperation from '@crud/RR.operation' import pagination from '@crud/Pagination' import UploadCover from '@/views/components/upload.vue' import MarkCover from '@/views/components/mark.vue' import Sortable from 'sortablejs' 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 } export default { name: 'Bookshelf', components: { crudOperation, rrOperation, pagination, UploadCover, MarkCover }, cruds() { return CRUD({ title: '区域', url: 'api/libraryRegion/initLibraryRegionList', crudMethod: { ...crudRegion }, sort: [], optShow: { add: true, edit: true, del: false, download: false, group: false, reset: false }}) }, mixins: [presenter(), header(), form(defaultForm), crud()], data() { return { setfloorId: null, floorOptions: [], labelName: '区域地图', permission: { add: ['admin', 'floor:add'], edit: ['admin', 'floor:edit'], del: ['admin', 'floor:del'] }, rules: { floorId: [ { required: true, message: '请选择所属楼层', trigger: 'change' } ], regionName: [ { required: true, message: '区域名称不可为空', trigger: 'blur' } ], regionCode: [ { required: true, message: '区域编码不可为空', trigger: 'blur' } ] }, activeIndex: 0, defaultImg: defaultImg, imageUrl: defaultImg, imageRegionUrl: defaultImg, sortTableData: [], // 排序data
sortVisible: false, // 排序dialog
markVisible: false, // 区域标注
titleMark: '区域标注', currentMarkData: null,
canvasPreview: {}, width: 900, height: 600, drawWidth: 2 // 笔触宽度
} }, computed: { ...mapGetters([ 'user', 'baseApi' ]) }, watch: { width() { this.canvasPreview.setWidth(this.width) }, height() { this.canvasPreview.setHeight(this.height) } }, beforeDestroy() { window.removeEventListener('beforeunload', this.clearLocalStorage) }, methods: { clearLocalStorage() { const key = 'formFloor' if (localStorage.getItem(key)) { localStorage.removeItem(key) } }, [CRUD.HOOK.beforeRefresh]() { this.getLibraryFloorListAll() console.log('this.setfloorId', this.setfloorId) this.crud.query.floorId = this.setfloorId // const formFloor = JSON.parse(localStorage.getItem('formFloor'))
// if (formFloor) {
// this.crud.query.floorId = formFloor.id
// } else {
// this.crud.query.floorId = null
// }
}, [CRUD.HOOK.afterRefresh](crud) { console.log('crud.data', crud.data) if (crud.data.length !== 0) { this.clickRowHandler(crud.data[0]) this.activeIndex = 0 } else { this.currentMarkData = null this.imageUrl = this.defaultImg this.imageRegionUrl = this.defaultImg } }, // 提交前的验证
[CRUD.HOOK.afterValidateCU](crud) { return true }, // 获取楼层数据
getLibraryFloorListAll() { FetchLibraryFloorListAll().then(res => { this.floorOptions = res }).catch(() => { }) }, handleCover(value) { console.log(value) this.crud.form.regionMap = value }, changeFloorValue(value) { console.log(value) }, clickRowHandler(row) { this.$refs.table.clearSelection() this.$refs.table.toggleRowSelection(row) // http://192.168.99.67:12010/api/fileRelevant/getImg?imgId=f6d3ecea-0456-4429-ba77-1a4921d5c806
this.currentMarkData = row if (this.activeIndex === 0) { if (row.floorMap) { this.imageUrl = this.baseApi + '/api/fileRelevant/getImg?imgId=' + row.floorMap if (row.signPoint) { const drawinfo = JSON.parse(row.signPoint) this.initCanvasPreview(drawinfo) } } else { this.imageUrl = this.defaultImg } } else { if (row.regionMap) { this.imageRegionUrl = this.baseApi + '/api/fileRelevant/getImg?imgId=' + row.regionMap } else { this.imageRegionUrl = this.defaultImg } } }, changeActiveTab(data) { this.activeIndex = data if (this.crud.selections.length === 1) { // if (this.canvasPreview) {
// this.canvasPreview.clear()
// this.canvasPreview.dispose()
// }
if (this.crud.selections[0].floorMap) { this.currentMarkData = this.crud.selections[0] this.imageUrl = this.baseApi + '/api/fileRelevant/getImg?imgId=' + this.crud.selections[0].floorMap } else { this.imageUrl = this.defaultImg } if (this.crud.selections[0].regionMap) { this.imageRegionUrl = this.baseApi + '/api/fileRelevant/getImg?imgId=' + this.crud.selections[0].regionMap } else { this.imageRegionUrl = this.defaultImg }
if (this.activeIndex === 0) { if (this.crud.selections[0].signPoint) { console.log('1111') const drawinfo = JSON.parse(this.crud.selections[0].signPoint) this.initCanvasPreview(drawinfo) } } } }, async handleMark() { if (this.crud.selections[0].floorMap) { this.markVisible = true this.currentMarkData = this.crud.selections[0] this.titleMark = this.currentMarkData.regionName + ' - 区域标注' this.$nextTick(() => { this.$refs.markRefs.drawinfo = this.currentMarkData && this.currentMarkData.signPoint ? JSON.parse(this.currentMarkData.signPoint) : null this.$refs.markRefs.initCanvas() }) } else { this.$message({ message: '请先上传当前楼层图', type: 'error', offset: 8 }) } }, toDelete(datas) { this.$confirm('此操作将删除当前所选区域<span>你是否还要继续?</span>', '提示', { confirmButtonText: '继续', cancelButtonText: '取消', type: 'warning', dangerouslyUseHTMLString: true }).then(() => { this.crud.delAllLoading = true const ids = [] datas.forEach(val => { ids.push(val.id) }) console.log(ids) crudRegion.del(ids).then(res => { console.log(res) this.$message({ message: res, type: 'success', offset: 8 }) this.crud.delAllLoading = false this.crud.refresh() }).catch(err => { this.crud.delAllLoading = false console.log(err) }) }).catch(() => { this.crud.delAllLoading = false }) }, // 排序 - 行拖拽
rowDrop(className, targetName) { // 此时找到的元素是要拖拽元素的父容器
const tbody = document.querySelector('.' + className + ' .el-table__body-wrapper tbody') const that = this Sortable.create(tbody, { // 指定父元素下可被拖拽的子元素
draggable: '.el-table__row', onEnd({ newIndex, oldIndex }) { if (newIndex === oldIndex) return that[targetName].splice(newIndex, 0, that[targetName].splice(oldIndex, 1)[0]) } }) }, // 排序
opened() { this.rowDrop('file-sort', 'sortTableData') }, showSort() { this.sortVisible = true this.sortTableData = JSON.parse(JSON.stringify(this.crud.selections)) }, handleSort() { const data = this.sortTableData.map((value, index) => { return { id: value.id, isSequence: index + 1 } }) this.sortTableData.forEach((item, index) => { item.isSequence = index + 1 }) crudRegion.sort(data).then(() => { this.sortVisible = false this.$message({ message: '保存成功', type: 'success', offset: 8 }) this.crud.refresh() }) }, handleCloseDialog() { // if (this.$refs.markRefs.canvas) {
// this.$refs.markRefs.canvas.clear()
// this.$refs.markRefs.canvas.dispose()
// }
this.markVisible = false this.crud.refresh() }, initCanvasPreview(drawinfo) { this.canvasPreview = new fabric.Canvas('canvasPreview', { skipTargetFind: false, selectable: false, selection: false })
this.canvasPreview.selectionColor = 'rgba(0,0,0,0.05)' this.loadDrawPreview(drawinfo) this.canvasPreview.on('mouse:wheel', this.mouse) }, // 鼠标滚轮放大缩小
mouse(e) { if (undefined === e) return let zoom = (e.e.deltaY > 0 ? -0.1 : 0.1) + this.canvasPreview.getZoom() zoom = Math.max(0.8, zoom) // 最小为原来的1/10
zoom = Math.min(3, zoom) // 最大是原来的3倍
const zoomPoint = new fabric.Point(e.e.pageX, e.e.pageY) this.canvasPreview.zoomToPoint(zoomPoint, zoom) }, // 回显详情信息
loadDrawPreview(drawinfo) { const self = this const pointGroup = drawinfo.pointInfo const imgInfo = drawinfo.imgInfo imgInfo.src = self.imageUrl // 加载底图
fabric.util.enlivenObjects([imgInfo], objects => { objects.forEach(o => { o.selectable = false o.hasControls = false o.centeredScaling = false self.canvasPreview.add(o) }) // 处理多边形绘制回显操作
pointGroup.forEach(async(item, index) => { if (item.pointInfo !== '') { const polygon = new fabric.Polygon(item.pointInfo, { name: item.name, stroke: 'rgba(196,43, 1, 1)', strokeWidth: self.drawWidth, fill: 'rgba(196,43, 1, 0.3)', opacity: 1, selectable: false, hasBorders: false, hasControls: false, originX: 'left', // 设置原点为左上角
originY: 'top' // 设置原点为左上角
}) // polygon.index = index
self.canvasPreview.add(polygon)
polygon.on('mousedown', function(e) { console.log('Rect ' + (index + 1) + ' clicked', e) console.log('e.target.name', e.target.name) })
polygon.on('mouseover', function(e) { console.log('e', e) console.log('e.target', e.target) console.log('e.target.name', e.target.name) this.set({ opacity: 0.3, hoverCursor: 'pointer' }) self.canvasPreview.renderAll() })
// 监听鼠标移出事件
polygon.on('mouseout', function() { this.set({ opacity: 1 }) self.canvasPreview.renderAll() }) } }) }) self.canvasPreview.renderAll() } } } </script>
<style lang="scss" scoped> </style>
|