Browse Source

区域/书架api页面调试

master
xuhuajiao 6 months ago
parent
commit
063ecf4d1b
  1. 10
      src/api/area/index.js
  2. 11
      src/api/floor/index.js
  3. 45
      src/api/shelf/index.js
  4. 180
      src/views/components/mark.vue
  5. 40
      src/views/visualCheck/venueDevice/area/index.vue
  6. 505
      src/views/visualCheck/venueDevice/bookshelf/index.vue
  7. 37
      src/views/visualCheck/venueDevice/bookshelfPosition/index.vue
  8. 2
      vue.config.js

10
src/api/area/index.js

@ -1,4 +1,12 @@
import request from '@/utils/request'
import qs from 'qs'
export function FetchInitLibraryRegionList(params) {
return request({
url: 'api/libraryRegion/initLibraryRegionList' + '?' + qs.stringify(params, { indices: false }),
method: 'get'
})
}
export function add(data) {
return request({
@ -40,4 +48,4 @@ export function saveLibraryRegionSignPoint(parameter) {
})
}
export default { add, edit, del, sort, saveLibraryRegionSignPoint }
export default { add, edit, del, sort, saveLibraryRegionSignPoint, FetchInitLibraryRegionList }

11
src/api/floor/index.js

@ -1,4 +1,5 @@
import request from '@/utils/request'
import qs from 'qs'
export function FetchLibraryFloorListAll() {
return request({
@ -39,4 +40,12 @@ export function sort(parameter) {
})
}
export default { add, edit, del, sort, FetchLibraryFloorListAll }
// 根据楼层id获取楼层详细信息
export function FetchLibraryFloorDetails(params) {
return request({
url: 'api/libraryFloor/getLibraryFloorDetails' + '?' + qs.stringify(params, { indices: false }),
method: 'get'
})
}
export default { add, edit, del, sort, FetchLibraryFloorListAll, FetchLibraryFloorDetails }

45
src/api/shelf/index.js

@ -0,0 +1,45 @@
import request from '@/utils/request'
import qs from 'qs'
export function add(data) {
return request({
url: 'api/bookShelf/editBookShelf',
method: 'post',
data
})
}
export function edit(data) {
return request({
url: 'api/bookShelf/editBookShelf',
method: 'post',
data
})
}
export function del(ids) {
return request({
url: '',
method: 'post',
data: ids
})
}
// 根据书架id查看书架详情 shelfId
export function FetchBookShelfDetails(params) {
return request({
url: 'api/bookShelf/getBookShelfDetails' + '?' + qs.stringify(params, { indices: false }),
method: 'get'
})
}
// 保存书架标注点位
export function saveBookShelfSignPoint(parameter) {
return request({
url: 'api/bookShelf/saveBookShelfSignPoint',
method: 'post',
data: parameter
})
}
export default { add, edit, del, FetchBookShelfDetails, saveBookShelfSignPoint }

180
src/views/components/mark.vue

@ -1,11 +1,13 @@
<template>
<div class="mark-handle">
<div class="mark-img">
<!-- <img :src="imageFloorUrl" :onerror="defaultImg" alt=""> -->
<canvas id="canvas" :width="width" :height="height" />
<div v-if="isBookShelf && currentMarkData && currentMarkData.shelfId !== undefined" class="mark-img">
<canvas :id="'canvas' + currentMarkData.shelfId" :width="width" :height="height" />
</div>
<div v-else-if="!isBookShelf && currentMarkData && currentMarkData.id !== undefined" class="mark-img">
<canvas :id="'canvas' + currentMarkData.id" :width="width" :height="height" />
</div>
<div class="mark-right">
<ul class="mark-info">
<ul v-if="!isBookShelf" class="mark-info">
<li>
<p>所属机构</p>
<span>{{ user.fonds.fondsName }}</span>
@ -20,18 +22,42 @@
</li>
<li><span :class="['row-state', currentMarkData && currentMarkData.signPoint ? 'end-state' : 'cancel-state' ]">{{ currentMarkData && currentMarkData.signPoint ? '已标注': '未标注' }}</span></li>
</ul>
<ul v-else class="mark-info">
<li>
<p>所属机构</p>
<span>{{ user.fonds.fondsName }}</span>
</li>
<li>
<p>所属楼层</p>
<span>{{ currentMarkData && currentMarkData.floorName }}</span>
</li>
<li>
<p>所属区域</p>
<span>{{ currentMarkData && currentMarkData.regionName }}</span>
</li>
<li>
<p>/双面</p>
<span>{{ currentMarkData && currentMarkData.rowType === 1 ? '单面' :'双面' }}</span>
</li>
<li>
<p>书架规格</p>
<span>{{ currentMarkData && currentMarkData.shelfShelf + ' X ' + currentMarkData.shelfFloor }}</span>
</li>
<li><span :class="['row-state', true ? 'end-state' : 'cancel-state' ]">{{ true ? '已标注': '未标注' }}</span></li>
</ul>
<div class="mark-button">
<el-button type="primary" :disabled="!isDrawing" @click="clean"><i class="iconfont icon-shanchu" />清空</el-button>
<el-button type="primary" :disabled="isDrawing" @click="drawPolygon"><i class="el-icon-edit" style="font-weight: bold; padding-right: 4px; font-size: 16px;" />标注</el-button>
<el-button type="primary" :disabled="!isDrawing" @click="submitDraw"><i class="el-icon-folder-checked" style="font-weight: bold; padding-right: 4px; font-size: 16px;" />保存</el-button>
</div>
</div>
<img id="expImg" :src="imageFloorUrl">
<img id="expImg" :src="imageUrl">
</div>
</template>
<script>
import { saveLibraryRegionSignPoint } from '@/api/area/index'
import { saveBookShelfSignPoint } from '@/api/shelf/index'
import { fabric } from 'fabric'
import { mapGetters } from 'vuex'
export default {
@ -44,15 +70,19 @@ export default {
return {}
}
},
imageFloorUrl: {
imageUrl: {
type: String,
default: ''
},
isBookShelf: {
type: Boolean,
default: false
}
},
data() {
return {
bgImgFlag: true,
bgImgSrc: this.imageFloorUrl,
bgImgSrc: this.imageUrl,
width: 900,
height: 600,
canvas: {},
@ -90,24 +120,38 @@ export default {
},
currentMarkData: {
handler(newVal, oldVal) {
if (newVal.id !== oldVal.id) {
console.log('id has changed')
console.log('handler')
this.canvas.clear()
this.canvas.dispose()
if (newVal.signPoint !== '' || newVal.signPoint !== null) {
this.drawinfo = JSON.parse(newVal.signPoint)
} else {
this.drawinfo = null
// newVal null undefined
if (!newVal) {
console.log('newVal is null or undefined')
return
}
//
const handleIdChange = (newId, oldId, idKey) => {
if (newId !== oldId) {
console.log('id has changed')
console.log('handler')
this.canvas.clear()
this.canvas.dispose()
this.drawinfo = newVal.signPoint ? JSON.parse(newVal.signPoint) : null
this.$nextTick(() => {
this.$refs.markRefs.initCanvas()
})
}
this.initCanvas()
}
if (this.isBookShelf && oldVal && oldVal.shelfId !== undefined) {
handleIdChange(newVal.shelfId, oldVal.shelfId, 'shelfId')
} else if (!this.isBookShelf && oldVal && oldVal.id !== undefined) {
handleIdChange(newVal.id, oldVal.id, 'id')
}
},
deep: true
},
imageFloorUrl(newVal, oldVal) {
imageUrl(newVal, oldVal) {
if (newVal !== oldVal) {
console.log('imageFloorUrl')
console.log('imageUrl')
}
}
},
@ -115,11 +159,11 @@ export default {
},
mounted() {
this.$nextTick(() => {
console.log('mounted')
this.drawinfo = this.currentMarkData && this.currentMarkData.signPoint ? JSON.parse(this.currentMarkData.signPoint) : null
this.initCanvas()
})
// this.$nextTick(() => {
// console.log('mounted')
// this.drawinfo = this.currentMarkData && this.currentMarkData.signPoint ? JSON.parse(this.currentMarkData.signPoint) : null
// this.initCanvas()
// })
},
beforeDestroy() {
if (this.canvas) {
@ -129,15 +173,24 @@ export default {
},
methods: {
initCanvas() {
this.canvas = new fabric.Canvas('canvas', {
skipTargetFind: false, //
selectable: false, // false
selection: false //
// currentMarkData
if (!this.currentMarkData) {
console.error('currentMarkData is null or undefined')
return
}
const canvasId = `canvas${this.isBookShelf ? this.currentMarkData.shelfId : this.currentMarkData.id}`
// fabric.js
this.canvas = new fabric.Canvas(canvasId, {
skipTargetFind: false,
selectable: false,
selection: false
})
this.canvas.selectionColor = 'rgba(0,0,0,0.05)'
// this.canvas.on('mouse:down', this.mousedown)
// this.canvas.on('mouse:move', this.mousemove)
// this.canvas.on('object:moving', this.objectMoving)
this.canvas.on('mouse:down', this.mousedown)
this.canvas.on('mouse:move', this.mousemove)
this.canvas.on('object:moving', this.objectMoving)
console.log('this.drawinfo', this.drawinfo)
console.log('this.canvas', this.canvas)
if (this.drawinfo) {
@ -148,7 +201,7 @@ export default {
this.isDrawing = false
this.bgImgFlag = true
const imgElement = document.getElementById('expImg')
imgElement.src = this.imageFloorUrl
imgElement.src = this.imageUrl
this.loadExpImg()
}
},
@ -246,16 +299,34 @@ export default {
})
console.log('saveCanvasData', saveCanvasData)
const params = {
'id': this.currentMarkData.id,
'signPoint': JSON.stringify(saveCanvasData)
if (this.isBookShelf) {
const params = {
'id': this.currentMarkData.shelfId,
'signPoint': JSON.stringify(saveCanvasData)
}
saveBookShelfSignPoint(params).then(res => {
console.log(res)
if (res) {
this.$message({ message: '当前书架标注成功', type: 'success', offset: 8 })
this.$emit('handleCloseDialog')
}
}).catch(err => {
console.log(err)
})
} else {
const params = {
'id': this.currentMarkData.id,
'signPoint': JSON.stringify(saveCanvasData)
}
saveLibraryRegionSignPoint(params).then(res => {
if (res) {
this.$message({ message: '当前区域标注成功', type: 'success', offset: 8 })
this.$emit('handleCloseDialog')
}
}).catch(err => {
console.log(err)
})
}
console.log('params', params)
saveLibraryRegionSignPoint(params).then(res => {
console.log(res)
}).catch(err => {
console.log(err)
})
},
//
mousedown(e) {
@ -367,6 +438,7 @@ export default {
},
//
drawPolygon() {
console.log(1111)
if (this.bgImgFlag) {
this.canvas.getObjects().forEach((obj) => {
if (obj.isBgImg) {
@ -527,7 +599,9 @@ export default {
this.canvas.clear()
this.bgImgFlag = true
const imgElement = document.getElementById('expImg')
imgElement.src = this.imageFloorUrl
imgElement.src = this.imageUrl
this.isDrawing = false
this.bgImgFlag = true
this.loadExpImg()
}
@ -561,15 +635,11 @@ export default {
},
//
loadDraw() {
this.canvas.clear()
const self = this
// if (this.drawinfo.id === '') return
// const pointGroup = JSON.parse(self.drawinfo.pointInfo);
// const imgInfo = JSON.parse(self.drawinfo.imgInfo);
if (this.currentMarkData.id === '') return
const pointGroup = self.drawinfo.pointInfo
const imgInfo = self.drawinfo.imgInfo
// self.imageFloorUrl = self.drawinfo.img
imgInfo.src = self.imageFloorUrl
imgInfo.src = self.imageUrl
this.isDrawing = true
//
@ -604,14 +674,14 @@ export default {
self.doDrawing = false
polygon.on('mousedown', function(e) {
console.log('Rect ' + (index + 1) + ' clicked', e)
console.log('e.target.name', e.target.name)
console.log('Rect222' + (index + 1) + ' clicked', e)
console.log('e.target.name222', 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)
console.log('e22', e)
console.log('e.target22', e.target)
console.log('e.target.name22', e.target.name)
// var delta = new fabric.Point(e.e.movementX, e.e.movementY)
// if(e.target&&e.target.name){
// // that.showDialog(e.target.name)
@ -645,7 +715,7 @@ export default {
}
})
})
self.canvas.renderAll()
this.canvas.renderAll()
},
//
clean() {
@ -658,7 +728,7 @@ export default {
this.isDrawing = false
this.bgImgFlag = true
const imgElement = document.getElementById('expImg')
imgElement.src = this.imageFloorUrl
imgElement.src = this.imageUrl
this.loadExpImg()
}).catch(() => {
console.log('取消清空标注')

40
src/views/visualCheck/venueDevice/area/index.vue

@ -71,11 +71,11 @@
</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="imageFloorUrl" /> -->
<!-- <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="imageFloorUrl" :onerror="defaultImg" alt="">
<img v-if="currentMarkData && !currentMarkData.signPoint" :src="imageUrl" :onerror="defaultImg" alt="">
</div>
<div v-if="activeIndex == 1" class="venue-preview">
<img :src="imageRegionUrl" :onerror="defaultImg" alt="">
@ -143,7 +143,7 @@
<span class="dialog-right-top" />
<span class="dialog-left-bottom" />
<div class="setting-dialog">
<MarkCover ref="markRefs" :current-mark-data="currentMarkData" :image-floor-url="imageFloorUrl" />
<MarkCover ref="markRefs" :is-book-shelf="false" :current-mark-data="currentMarkData" :image-url="imageUrl" />
</div>
</el-dialog>
</div>
@ -180,7 +180,6 @@ export default {
mixins: [presenter(), header(), form(defaultForm), crud()],
data() {
return {
canvasPreview: {},
floorOptions: [],
labelName: '区域地图',
permission: {
@ -201,7 +200,7 @@ export default {
},
activeIndex: 0,
defaultImg: defaultImg,
imageFloorUrl: defaultImg,
imageUrl: defaultImg,
imageRegionUrl: defaultImg,
sortTableData: [], // data
sortVisible: false, // dialog
@ -209,6 +208,7 @@ export default {
titleMark: '区域标注',
currentMarkData: null,
canvasPreview: {},
width: 900,
height: 600,
drawWidth: 2 //
@ -233,6 +233,13 @@ export default {
this.getLibraryFloorListAll()
},
[CRUD.HOOK.afterRefresh](crud) {
if (crud.data.length !== 0) {
this.clickRowHandler(crud.data[0])
this.activeIndex = 0
} else {
this.imageUrl = this.defaultImg
this.imageRegionUrl = this.defaultImg
}
},
//
[CRUD.HOOK.afterValidateCU](crud) {
@ -259,13 +266,13 @@ export default {
this.currentMarkData = row
if (this.activeIndex === 0) {
if (row.floorMap) {
this.imageFloorUrl = this.baseApi + '/api/fileRelevant/getImg?imgId=' + 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.imageFloorUrl = this.defaultImg
this.imageUrl = this.defaultImg
}
} else {
if (row.regionMap) {
@ -284,9 +291,9 @@ export default {
// }
if (this.crud.selections[0].floorMap) {
this.currentMarkData = this.crud.selections[0]
this.imageFloorUrl = this.baseApi + '/api/fileRelevant/getImg?imgId=' + this.crud.selections[0].floorMap
this.imageUrl = this.baseApi + '/api/fileRelevant/getImg?imgId=' + this.crud.selections[0].floorMap
} else {
this.imageFloorUrl = this.defaultImg
this.imageUrl = this.defaultImg
}
if (this.crud.selections[0].regionMap) {
this.imageRegionUrl = this.baseApi + '/api/fileRelevant/getImg?imgId=' + this.crud.selections[0].regionMap
@ -308,6 +315,10 @@ export default {
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 })
}
@ -374,9 +385,12 @@ export default {
})
},
handleCloseDialog() {
// this.$refs.markRefs.canvas.clear()
// this.$refs.markRefs.canvas.dispose()
// 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', {
@ -405,7 +419,7 @@ export default {
const self = this
const pointGroup = drawinfo.pointInfo
const imgInfo = drawinfo.imgInfo
imgInfo.src = self.imageFloorUrl
imgInfo.src = self.imageUrl
//
fabric.util.enlivenObjects([imgInfo], objects => {
objects.forEach(o => {
@ -429,7 +443,7 @@ export default {
originX: 'left', //
originY: 'top' //
})
polygon.index = index
// polygon.index = index
self.canvasPreview.add(polygon)
polygon.on('mousedown', function(e) {

505
src/views/visualCheck/venueDevice/bookshelf/index.vue

@ -9,11 +9,11 @@
<div class="head-container">
<div class="head-search">
<!-- 搜索 -->
<el-select v-model="query.floorId" clearable size="small" placeholder="楼层" class="filter-item" style="width: 80px" @change="crud.toQuery">
<el-option v-for="item in floorOptions" :key="item.key" :label="item.floorName" :value="item.key" />
<el-select v-model="selectFloorVal" clearable size="small" placeholder="楼层" class="filter-item" style="width: 80px" value-key="id" @change="changeBeforeFloor">
<el-option v-for="(item,index) in floorOptions" :key="index" :label="item.floorName" :value="item" />
</el-select>
<el-select v-model="query.floorId" clearable size="small" placeholder="区域" class="filter-item" style="width: 80px" @change="crud.toQuery">
<el-option v-for="item in floorOptions" :key="item.key" :label="item.floorName" :value="item.key" />
<el-select v-model="selectRegionVal" clearable size="small" placeholder="区域" class="filter-item" style="width: 120px" value-key="id" @change="changeBeforeRegion">
<el-option v-for="(item,index) in regionOptions" :key="index" :label="item.regionName" :value="item" />
</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 /> -->
@ -34,19 +34,27 @@
:data="crud.data"
style="width: 100%;"
height="540"
@selection-change="crud.selectionChangeHandler"
@selection-change="selectionChangeHandler"
@row-click="clickRowHandler"
>
<el-table-column type="selection" align="center" width="55" />
<!-- <el-table-column type="index" label="排序" /> -->
<el-table-column prop="shelfName" label="书架名称" />
<el-table-column prop="collectionFloor" label="书架规格" />
<el-table-column prop="floorName" label="单/双面" />
<el-table-column prop="shelfShelf" label="书架规格">
<template slot-scope="scope">
<span>{{ scope.row.shelfShelf + ' X ' + scope.row.shelfFloor }}</span>
</template>
</el-table-column>
<el-table-column prop="rowType" label="单/双面">
<template slot-scope="scope">
<span>{{ scope.row.rowType === 1 ? '单面' :'双面' }}</span>
</template>
</el-table-column>
<el-table-column prop="floorName" label="所属楼层" />
<el-table-column prop="floorName" label="所属区域" />
<el-table-column prop="floorMap" label="标注">
<el-table-column prop="regionName" label="所属区域" />
<el-table-column prop="signPoint" label="标注">
<template slot-scope="scope">
<span :class="['row-state', scope.row.floorMap ? 'end-state' : 'cancel-state' ]">{{ scope.row.floorMap ? '已标注': '未标注' }}</span>
<span :class="['row-state', scope.row.signPoint ? 'end-state' : 'cancel-state' ]">{{ scope.row.signPoint ? '已标注': '未标注' }}</span>
</template>
</el-table-column>
</el-table>
@ -62,13 +70,18 @@
<li class="active-tab-nav">区域书架<i /></li>
<!-- 最右侧装饰img -->
<span class="tab-right-img" />
<el-button size="mini" class="venue-mark" :disabled="crud.selections.length === 0" @click="markVisible = true">
<el-button size="mini" class="venue-mark" :disabled="crud.selections.length !== 1" @click="handleMark">
<i class="el-icon-edit" />
书架标注
</el-button>
</ul>
<div class="venue-preview">
<img :src="imageUrl" :onerror="defaultImg" alt="">
<!-- <img :src="imageUrl" :onerror="defaultImg" alt=""> -->
<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>
</div>
@ -80,49 +93,49 @@
<span class="dialog-left-bottom" />
<div class="setting-dialog">
<el-form ref="form" :rules="rules" :model="form" inline size="small" label-width="90px">
<el-form-item label="所属楼层" prop="floorId">
<el-input v-model="form.floorId" disabled />
<el-form-item label="所属楼层" prop="floorName">
<el-input v-model="form.floorName" disabled />
</el-form-item>
<el-form-item label="所属区域" prop="areaName">
<el-input v-model="form.areaName" disabled />
<el-form-item label="所属区域" prop="regionName">
<el-input v-model="form.regionName" disabled />
</el-form-item>
<el-row>
<el-form-item label="单/双排" prop="singleOrDouble">
<el-radio-group v-model="form.singleOrDouble" v-removeAriaHidden size="mini" @change="changeSingleOrDouble($event)">
<el-form-item label="单/双排" prop="rowType">
<el-radio-group v-model="form.rowType" v-removeAriaHidden size="mini" @change="changeSingleOrDouble($event)">
<el-radio :label="1">单排</el-radio>
<el-radio :label="2">双排</el-radio>
</el-radio-group>
</el-form-item>
<el-form-item v-if="form.singleOrDouble===1" label="A/B面" prop="ab">
<el-select v-model="form.ab" placeholder="请选择" style="width: 225px;" @change="changeAB($event)">
<el-form-item v-if="form.rowType===1" label="A/B面" prop="toward">
<el-select v-model="form.toward" placeholder="请选择" style="width: 225px;" @change="changeAB($event)">
<el-option
v-for="(item,index) in abOptions"
:key="index"
:label="item.name"
:value="item.key"
:value="item.value"
/>
</el-select>
</el-form-item>
</el-row>
<el-row>
<el-form-item label="书架排号" prop="rackNum">
<el-input v-model="form.rackNum" />
<el-form-item label="书架排号" prop="shelfRow">
<el-input v-model="form.shelfRow" />
</el-form-item>
<el-form-item label="书架名称" prop="rackName">
<el-input v-model="form.rackName" disabled />
<el-form-item label="书架名称" prop="shelfName">
<el-input v-model="computedShelfName" disabled />
</el-form-item>
</el-row>
<el-form-item label="书架规格" prop="rackSpecs">
<el-input-number v-model.number="form.rackSpecsMin" :min="0" :max="999" controls-position="right" style="width: 90px;" />
<el-input-number v-model.number="form.shelfShelf" :min="1" :max="999" controls-position="right" style="width: 90px;" />
<span style="padding:0 12px;"></span>
<el-input-number v-model.number="form.rackSpecsMax" :min="0" :max="999" controls-position="right" style="width: 90px;" />
<el-input-number v-model.number="form.shelfFloor" :min="1" :max="999" controls-position="right" style="width: 90px;" />
</el-form-item>
<el-form-item label="架起始标" prop="rackStartNum">
<el-input-number v-model.number="form.rackStartNum" :min="0" :max="999" controls-position="right" />
<el-form-item label="架起始标" prop="startShelf">
<el-input-number v-model.number="form.startShelf" :min="0" :max="999" controls-position="right" />
</el-form-item>
<el-row>
<el-form-item label="架号顺序" prop="rackOrder">
<el-select v-model="form.rackOrder" placeholder="请选择" style="width: 586px;" @change="changeOrder($event)">
<el-form-item label="架号顺序" prop="shelfType">
<el-select v-model="form.shelfType" placeholder="请选择" style="width: 586px;" @change="changeOrder($event)">
<el-option
v-for="(item,index) in rackOrderOptions"
:key="index"
@ -133,8 +146,8 @@
</el-form-item>
</el-row>
<el-row>
<el-form-item label="层号顺序" prop="layerSeq">
<el-select v-model="form.layerSeq" placeholder="请选择" style="width: 586px;" @change="changeLayerSeq($event)">
<el-form-item label="层号顺序" prop="floorType">
<el-select v-model="form.floorType" placeholder="请选择" style="width: 586px;" @change="changeLayerSeq($event)">
<el-option
v-for="(item,index) in layerSeqOptions"
:key="index"
@ -144,14 +157,14 @@
</el-select>
</el-form-item>
</el-row>
<el-form-item label="倒架规则" prop="invRules">
<el-radio-group v-model="form.invRules" v-removeAriaHidden size="mini">
<el-form-item label="倒架规则" prop="shelfRule">
<el-radio-group v-model="form.shelfRule" v-removeAriaHidden size="mini">
<el-radio :label="1">无序</el-radio>
<el-radio :label="2">有序</el-radio>
</el-radio-group>
</el-form-item>
<el-form-item label="错架判断" prop="wrongJudge">
<el-radio-group v-model="form.wrongJudge" v-removeAriaHidden size="mini">
<el-form-item label="错架判断" prop="shelfErrorJudge">
<el-radio-group v-model="form.shelfErrorJudge" v-removeAriaHidden size="mini">
<el-radio :label="1">书架</el-radio>
<el-radio :label="2">格子</el-radio>
</el-radio-group>
@ -165,160 +178,279 @@
</el-dialog>
<!-- 标注 -->
<el-dialog class="mark-dialog" :close-on-click-modal="false" :append-to-body="true" title="001排A面-书架标注" :visible.sync="markVisible">
<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 mark-handle">
<div class="mark-img">
<img :src="imageUrl" :onerror="defaultImg" alt="">
</div>
<div class="mark-right">
<ul class="mark-info">
<li>
<p>所属机构</p>
<span>机构A</span>
</li>
<li>
<p>所属楼层</p>
<span>五楼</span>
</li>
<li>
<p>所属区域</p>
<span>A楼</span>
</li>
<li>
<p>/双面</p>
<span>单面</span>
</li>
<li>
<p>书架规格</p>
<span>68</span>
</li>
<li><span :class="['row-state', true ? 'end-state' : 'cancel-state' ]">{{ true ? '已标注': '未标注' }}</span></li>
</ul>
<div class="mark-button">
<el-button type="primary" disabled><i class="iconfont icon-shanchu" />清空</el-button>
<el-button type="primary"><i class="el-icon-edit" style="font-weight: bold; padding-right: 4px; font-size: 16px;" />标注</el-button>
<el-button type="primary" disabled><i class="el-icon-folder-checked" style="font-weight: bold; padding-right: 4px; font-size: 16px;" />保存</el-button>
</div>
</div>
<div class="setting-dialog">
<MarkCover ref="markRefs" :is-book-shelf="true" :current-mark-data="currentMarkData" :image-url="imageUrl" @handleCloseDialog="handleCloseDialog" />
</div>
</el-dialog>
</div>
</template>
<script>
import crudFloor from '@/api/floor/index'
import { FetchLibraryFloorListAll } from '@/api/floor/index'
import { FetchInitLibraryRegionList } from '@/api/area/index'
import crudShelf from '@/api/shelf/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 { mapGetters } from 'vuex'
import defaultImg from '@/assets/images/system/default-img.jpg'
import MarkCover from '@/views/components/mark.vue'
import { fabric } from 'fabric'
const defaultForm = { id: null, floorId: null, areaName: null, singleOrDouble: null, ab: null, rackNum: null, rackName: null, rackSpecsMin: null, rackSpecsMax: null, rackStartNum: null, rackOrder: null, layerSeq: null, invRules: null, wrongJudge: null }
const defaultForm = { id: null, floorName: null, floorId: null, regionName: null, rowType: 1, toward: 1, shelfRow: '', shelfName: '', shelfShelf: null, shelfFloor: null, startShelf: null, shelfType: null, floorType: null, shelfRule: null, shelfErrorJudge: null, signPoint: '' }
export default {
name: 'Bookshelf',
components: { crudOperation, pagination },
components: { crudOperation, pagination, MarkCover },
cruds() {
return CRUD({ title: '书架', url: 'api/libraryFloor/initLibraryFloorList', crudMethod: { ...crudFloor }, sort: [], optShow: {
return CRUD({ title: '书架', idField: 'shelfId', url: 'api/bookShelf/initBookShelfList', crudMethod: { ...crudShelf }, sort: [], optShow: {
add: true,
edit: true,
del: false,
download: false,
group: false,
reset: false
}})
},
queryOnPresenterCreated: false
})
},
mixins: [presenter(), header(), form(defaultForm), crud()],
data() {
return {
permission: {
add: ['admin', 'floor:add'],
edit: ['admin', 'floor:edit'],
del: ['admin', 'floor:del']
},
floorOptions: [],
regionOptions: [],
selectFloorVal: null,
selectRegionVal: null,
abOptions: [
{ key: '1', name: 'A面' },
{ key: '0', name: 'B面' }
],
floorOptions: [
{ key: '1', floorName: '一楼' },
{ key: '0', floorName: '二楼' }
{ value: 1, name: 'A面' },
{ value: 2, name: 'B面' }
],
rackOrderOptions: [
{ key: 0, name: '始终最左边为第1架(S型排架)' },
{ key: 1, name: 'A面最左为第1架(B面最左为最后1架)' },
{ key: 2, name: 'B面最左为第1架(A面最左为最后1架)' }
{ key: 1, name: '始终最左边为第1架(S型排架)' },
{ key: 2, name: 'A面最左为第1架(B面最左为最后1架)' },
{ key: 3, name: 'B面最左为第1架(A面最左为最后1架)' }
],
layerSeqOptions: [
{ key: 0, name: '最顶层为第一层(从上至下)' },
{ key: 1, name: '最底层为第一层(从下至上)' }
{ key: 1, name: '最顶层为第一层(从上至下)' },
{ key: 2, name: '最底层为第一层(从下至上)' }
],
permission: {
add: ['admin', 'floor:add'],
edit: ['admin', 'floor:edit'],
del: ['admin', 'floor:del']
},
rules: {
floorId: [
floorName: [
{ required: true, message: '所属楼层不可为空', trigger: 'blur' }
],
areaName: [
regionName: [
{ required: true, message: '所属区域不可为空', trigger: 'blur' }
],
singleOrDouble: [
rowType: [
{ required: true, message: '请选择单双排', trigger: 'change' }
],
rackNum: [
shelfRow: [
{ required: true, message: '书架排号不可为空', trigger: 'blur' }
],
rackName: [
{ required: true, message: '书架名称不可为空', trigger: 'blur' }
shelfName: [
{ validator: this.validateShelfName, trigger: 'blur' }
],
rackSpecs: [
{ required: true, message: '书架规格不可为空', trigger: 'blur' }
{ validator: this.validateRackSpecs, trigger: 'blur' }
],
rackStartNum: [
startShelf: [
{ required: true, message: '架起始标不可为空', trigger: 'blur' }
],
rackOrder: [
shelfType: [
{ required: true, message: '请选择架号顺序', trigger: 'change' }
],
layerSeq: [
floorType: [
{ required: true, message: '请选择层号顺序', trigger: 'change' }
],
invRules: [
shelfRule: [
{ required: true, message: '请选择倒架规则', trigger: 'change' }
],
wrongJudge: [
shelfErrorJudge: [
{ required: true, message: '请选择错架判断', trigger: 'change' }
]
},
defaultImg: defaultImg,
imageUrl: defaultImg,
markVisible: false //
markVisible: false, //
titleMark: '书架标注',
currentMarkData: null,
canvasPreview: {},
width: 900,
height: 600,
drawWidth: 2 //
}
},
computed: {
...mapGetters([
'user',
'baseApi'
])
]),
computedShelfName() {
const { shelfRow, rowType, toward } = this.form
if (!shelfRow) {
return ''
}
const baseName = `${shelfRow}`
if (rowType === 1 && toward !== null) {
return `${baseName}${this.abOptions.find(option => option.value === toward).name}`
} else if (rowType === 2) {
return baseName
}
return ''
}
},
watch: {
computedShelfName(newVal) {
this.form.shelfName = newVal
},
width() {
this.canvasPreview.setWidth(this.width)
},
height() {
this.canvasPreview.setHeight(this.height)
}
},
created() {
this.getLibraryFloorListAll()
},
mounted() {
},
methods: {
validateShelfName(rule, value, callback) {
if (this.form.shelfRow) {
if (!value) {
callback(new Error('书架名称不能为空'))
} else {
callback()
}
} else {
callback()
}
},
validateRackSpecs(rule, value, callback) {
// shelfShelf shelfFloor
if (!this.form.shelfShelf) {
callback(new Error('请输入书架规格中书架架数'))
} else if (!this.form.shelfFloor) {
callback(new Error('请输入书架规格中书架层数'))
} else {
callback()
}
},
[CRUD.HOOK.beforeRefresh]() {
},
[CRUD.HOOK.afterRefresh](crud) {
console.log(crud.data)
if (crud.data.length !== 0) {
// this.$nextTick(() => {
// this.$refs.table.toggleRowSelection(crud.data[0], true)
// })
if (this.selectRegionVal && this.selectRegionVal.regionMap) {
this.imageUrl = this.baseApi + '/api/fileRelevant/getImg?imgId=' + this.selectRegionVal.regionMap
} else {
this.imageUrl = defaultImg
}
},
//
[CRUD.HOOK.afterToCU](crud, form) {
console.log(form)
console.log('crud.query.floorId', crud.query.floorId)
console.log('selectFloorVal', this.selectFloorVal)
console.log('crud.query.regionId', crud.query.regionId)
console.log('selectRegionVal', this.selectRegionVal)
form.floorId = this.selectFloorVal.id
form.floorName = this.selectFloorVal.floorName
form.regionId = this.selectRegionVal.id
form.regionName = this.selectRegionVal.regionName
},
//
[CRUD.HOOK.beforeToEdit](crud, form) {
const params = {
'shelfId': this.crud.selections[0].shelfId
}
crudShelf.FetchBookShelfDetails(params).then(res => {
form.id = res.id
// / 1 2
form.rowType = res.rowType
// A/B 1 A 2 B
form.toward = res.toward
//
form.shelfRow = res.shelfRow
//
form.shelfName = res.shelfName
//
form.shelfShelf = res.shelfShelf
//
form.shelfFloor = res.shelfFloor
//
form.startShelf = res.startShelf
//
form.shelfType = res.shelfType
//
form.floorType = res.floorType
// 1 2
form.shelfRule = res.shelfRule
// 1 2
form.shelfErrorJudge = res.shelfErrorJudge
}).catch(() => {
})
},
//
[CRUD.HOOK.afterValidateCU](crud) {
console.log(crud.form)
delete crud.form.floorName
delete crud.form.regionName
return true
},
//
getLibraryFloorListAll() {
FetchLibraryFloorListAll().then(res => {
this.floorOptions = res
if (this.floorOptions.length > 0) {
this.selectFloorVal = this.floorOptions[0]
this.crud.query.floorId = this.selectFloorVal.id
if (this.crud.query.floorId) {
this.getInitLibraryRegionList(this.crud.query.floorId)
}
}
}).catch(() => {
})
},
getInitLibraryRegionList(val) {
const params = {
'floorId': val
}
FetchInitLibraryRegionList(params).then(res => {
this.regionOptions = res.content
if (this.regionOptions.length > 0) {
this.selectRegionVal = this.regionOptions[0]
this.crud.query.regionId = this.selectRegionVal.id
this.crud.toQuery()
}
}).catch(() => {
})
},
changeBeforeFloor(val) {
if (val) {
this.selectFloorVal = val
this.crud.query.floorId = val.id
this.getInitLibraryRegionList(val.id)
}
},
changeBeforeRegion(val) {
if (val) {
this.selectRegionVal = val
this.crud.query.regionId = val.id
this.crud.toQuery()
}
},
changeSingleOrDouble(value) {
console.log(value)
},
@ -334,16 +466,70 @@ export default {
changeLayerSeq(value) {
console.log(value)
},
selectionChangeHandler(val) {
this.crud.selections = val
// 1
if (this.crud.selections.length === 1 && this.crud.selections[0].signPoint) {
this.currentMarkData = val[0]
try {
const drawinfo = JSON.parse(this.crud.selections[0].signPoint)
this.initCanvasPreview(drawinfo)
} catch (error) {
console.error(error)
this.resetImageUrl()
}
} else {
// 10
this.currentMarkData = null
this.setImageUrlBasedOnRegionMap()
}
},
setImageUrlBasedOnRegionMap() {
if (this.selectRegionVal && this.selectRegionVal.regionMap) {
this.imageUrl = `${this.baseApi}/api/fileRelevant/getImg?imgId=${this.selectRegionVal.regionMap}`
} else {
this.resetImageUrl()
}
},
resetImageUrl() {
this.imageUrl = this.defaultImg
},
async handleMark() {
if (this.crud.selections.length === 1) {
const selection = this.crud.selections[0]
if (selection && this.selectRegionVal.regionMap) {
this.markVisible = true
this.currentMarkData = selection
this.titleMark = this.currentMarkData.shelfName + ' - 书架标注'
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 })
}
} else {
console.error('666')
}
},
handleCloseDialog() {
// if (this.$refs.markRefs.canvas) {
// this.$refs.markRefs.canvas.clear()
// this.$refs.markRefs.canvas.dispose()
// }
this.markVisible = false
this.crud.refresh()
},
clickRowHandler(row) {
this.$router.push({ path: '/bookshelf/bookshelfPosition', query: { }})
console.log(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
if (row.floorMap) {
this.imageUrl = this.baseApi + '/api/fileRelevant/getImg?imgId=' + row.floorMap
} else {
this.imageUrl = this.defaultImg
}
crudShelf.FetchBookShelfDetails({ 'shelfId': row.shelfId }).then(res => {
this.$router.push({ path: '/bookshelf/bookshelfPosition', query: { 'bookShelfDetails': res }})
}).catch(() => {
})
},
toDelete(datas) {
this.$confirm('此操作将删除当前所选书架<span>你是否还要继续?</span>', '提示', {
@ -358,7 +544,7 @@ export default {
ids.push(val.id)
})
console.log(ids)
crudFloor.del(ids).then(res => {
crudShelf.del(ids).then(res => {
console.log(res)
this.$message({ message: res, type: 'success', offset: 8 })
this.crud.delAllLoading = false
@ -370,6 +556,83 @@ export default {
}).catch(() => {
this.crud.delAllLoading = false
})
},
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()
}
}
}

37
src/views/visualCheck/venueDevice/bookshelfPosition/index.vue

@ -8,11 +8,11 @@
<div class="bookshelf-main">
<div class="bookshelf-top">
<ul class="bookshelf-info">
<li><p>书架名称</p><span>001排A面</span></li>
<li><p>书架规格</p><span>6 x 8</span></li>
<li><p>/双面</p><span>单面</span></li>
<li><p>倒架规则</p><span>无序0</span></li>
<li><p>判断</p><span>书架</span></li>
<li><p>书架名称</p><span>{{ bookShelfDetails && bookShelfDetails.shelfName }}</span></li>
<li><p>书架规格</p><span>{{ bookShelfDetails && bookShelfDetails.shelfShelf + ' X ' + bookShelfDetails.shelfFloor }}</span></li>
<li><p>/双面</p><span>{{ bookShelfDetails && bookShelfDetails.rowType === 1 ? '单面' :'双面' }}</span></li>
<li><p>倒架规则</p><span>{{ bookShelfDetails && bookShelfDetails.shelfRule === 1 ? '无序' :'有序' }}</span></li>
<li><p>判断</p><span>{{ bookShelfDetails && bookShelfDetails.shelfErrorJudge === 1 ? '书架' :'格子' }}</span></li>
</ul>
<div class="bookshelf-button">
<el-button size="mini" @click="doExport(crud.selections)">
@ -67,9 +67,8 @@
class="swiper-slide-content"
>
<ul class="cabinet-row">
<!-- layerNum*rackNum -->
<li v-for="(item,index) in layerNum*rackNum" :key="index" class="cabinet-cell" :style="cellStyle" :class="{ active: index === cellIndex }" @click="handleCellCurrent(index)">
<span>{{ index+1 }}</span>
<span>{{ bookShelfDetails && bookShelfDetails.shelfName +''+ (index+1) }}</span>
</li>
</ul>
</swiper-slide>
@ -77,11 +76,11 @@
</div>
<div class="bookshelf-right-info">
<div class="layer-status">
<span class="row-state end-state">正常盘点</span>
<!-- <span class="row-state soon-state">待初始化</span>
<span class="row-state soon-state">待初始化</span>
<!-- <span class="row-state end-state">正常盘点</span>
<span class="row-state cancel-state">停止盘点</span> -->
<!-- <span class="row-state other-state">无序倒架</span> -->
<span class="row-state ing-state">有序倒架</span>
<span v-if="bookShelfDetails.shelfRule === 1" class="row-state other-state">无序倒架</span>
<span v-else class="row-state ing-state">有序倒架</span>
</div>
<h5 class="layer-name">001排A面01架1层</h5>
<div class="layer-code-sort">
@ -174,10 +173,11 @@ export default {
data() {
const _this = this
return {
bookShelfDetails: null,
isBindCarme: false,
callNumVisible: false,
layerNum: 6,
rackNum: 8,
layerNum: 0,
rackNum: 0,
checkValue: 'true',
bookSortValue: 'true',
swiperActiveIndex: 0,
@ -260,9 +260,18 @@ export default {
// return { width: `calc(${w} - 10px)` }
// }
},
watch: {
'$route'(val, from) { //
if (this.$route.query) {
this.bookShelfDetails = this.$route.query.bookShelfDetails
}
}
},
methods: {
[CRUD.HOOK.beforeRefresh]() {
this.bookShelfDetails = this.$route.query.bookShelfDetails
this.layerNum = this.bookShelfDetails.shelfShelf
this.rackNum = this.bookShelfDetails.shelfFloor
},
[CRUD.HOOK.afterRefresh](crud) {
},

2
vue.config.js

@ -6,7 +6,7 @@ function resolve(dir) {
return path.join(__dirname, dir)
}
const name = defaultSettings.title // 网址标题
const port = 8013 // 端口配置
const port = 8015 // 端口配置
// All configuration item explanations can be find in https://cli.vuejs.org/config/
// const GenerateAssetPlugin = require('generate-asset-webpack-plugin')

Loading…
Cancel
Save