|
|
<template> <div class="app-container"> <div class="venue-header"> <h4><i class="iconfont icon-shujia" />架位列表</h4> <span class="bookshelf-area">{{ floorName }} - {{ regionName }}</span> <p><i class="iconfont icon-gongsi" />{{ user.fonds.fondsName }}</p> </div> <div class="bookshelf-main"> <div class="bookshelf-top"> <ul class="bookshelf-info"> <li><p>书架名称:</p><span>{{ bookShelfDetails && bookShelfDetails.shelfName }}</span></li> <li><p>书架规格:</p><span>{{ bookShelfDetails && bookShelfDetails.shelfFloor + ' X ' + bookShelfDetails.shelfShelf }}</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> <!-- <li><p>前端测试用-架号顺序:</p><span>{{ bookShelfDetails && bookShelfDetails.shelfType === 1 ? '始终最左边为第1架(S型排架)' : (bookShelfDetails.shelfType === 2 ? 'A面最左为第1架(B面最左为最后1架)' : 'B面最左为第1架(A面最左为最后1架)') }}</span></li> <li><p>前端测试用-层号顺序:</p><span>{{ bookShelfDetails && bookShelfDetails.floorType === 1 ? '最顶层为第一层(从上至下)' :'最底层为第一层(从下至上)' }}</span></li> --> </ul> <div class="bookshelf-button"> <el-button size="mini" @click="doExport"> <i class="iconfont icon-daochu" /> 导出层位编码 </el-button> <el-button size="mini" :disabled="!cellInfo.cameraId" @click="handleViewVideo(cellInfo.cameraId)"> <i class="iconfont icon-yulan" /> {{ cellInfo.cameraId ? '摄像头预览' : '未绑定摄像头' }} </el-button> </div> </div> <div class="bookshelf-layer-info"> <div class="bookshelf-left"> <swiper ref="swiperTitle" class="swiper-title" :options="swiperOptionTitle" :auto-update="true" :auto-destroy="true" :delete-instance-on-destroy="true" :cleanup-styles-on-destroy="true" > <swiper-slide v-for="(item, index) of tabListData" ref="swiperSlideItem" :key="'name' + index" :iname="item.name" class="swiper-slide-title" > <div class="tab-name" :class="{ active: index === swiperActiveIndex }" @click="handleSlidClickFun(index)" > {{ item.name }} </div> </swiper-slide> </swiper> <swiper ref="swiperContent" class="swiper-content" :style="rowStyle" :options="swiperOptionContent" :auto-update="true" :auto-destroy="true" :delete-instance-on-destroy="true" :cleanup-styles-on-destroy="true" > <swiper-slide v-for="(item, index) of tabListData" :key="'content' + index" class="swiper-slide-content" > <ul class="cabinet-row" :style="rowStyle"> <li v-for="(shelf,i) in booShelfGrid" :key="i" class="cabinet-cell" :style="cellStyle" :class="{ active: i === cellIndex }" @click="handleCellCurrent(shelf,i)"> <span>{{ shelf.gridName | removeQUPrefix }}</span> </li> </ul> </swiper-slide> </swiper> </div> <div class="bookshelf-right-info"> <div class="layer-status"> <span v-if="cellInfo.startSortmark && cellInfo.endSortmark && checkValue === 'true'" class="row-state end-state">正常盘点</span> <span v-if="!cellInfo.startSortmark && !cellInfo.endSortmark && checkValue === 'true'" class="row-state soon-state">待初始化</span> <span v-if="checkValue === 'false'" class="row-state cancel-state">停止盘点</span> <span v-if="bookSortValue === 'false'" class="row-state other-state">无序倒架</span> <span v-else class="row-state ing-state">有序倒架</span> </div> <h5 class="layer-name">{{ cellInfo.gridName | removeQUPrefix }}</h5> <div class="layer-code-sort"> <ul> <!-- I247.58/586 --> <li><p>起始索书号</p><span>{{ cellInfo.startSortmark ? cellInfo.startSortmark : '-' }}</span></li> <li><p>结束索书号</p><span>{{ cellInfo.endSortmark? cellInfo.endSortmark : '-' }}</span></li> </ul> <el-button size="mini" class="edit-callNumber" @click="handleEditGridNum"> <!-- <i class="iconfont icon-yulan" /> --> <!-- <i>编 辑</i> <i>索书号</i> --> 编辑索书号 </el-button> </div> <ul class="layer-handle"> <li> <p>层位盘点开关</p> <el-switch v-model="checkValue" active-color="#13ce66" inactive-color="#ff4949" active-value="true" inactive-value="false" @change="changeCheckSwitch" /> </li> <li> <p>图书有序检查</p> <el-switch v-model="bookSortValue" active-color="#13ce66" inactive-color="#ff4949" active-value="true" inactive-value="false" @change="changeBookSortSwitch" /> </li> </ul> </div> </div> </div>
<!-- 编辑索书号 --> <el-dialog append-to-body :close-on-click-modal="false" :modal-append-to-body="false" :visible="callNumVisible" title="编辑索书号范围" :before-close="handleClose"> <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="gridName"> <el-input v-model="form.gridName" disabled style="width: 580px;" /> </el-form-item> <el-form-item label="起始索书号" prop="startSortmark"> <el-input v-model="form.startSortmark" style="width: 580px;" /> </el-form-item> <el-form-item label="结束索书号" prop="endSortmark"> <el-input v-model="form.endSortmark" style="width: 580px;" /> </el-form-item> </el-form> <div slot="footer" class="dialog-footer"> <el-button type="text" @click.native="handleClose">取消</el-button> <el-button type="primary" @click.native="handleSaveCallNum">保存</el-button> </div> </div> </el-dialog>
<!-- 查看监控视频 --> <el-dialog class="view-video" append-to-body :close-on-click-modal="false" :modal-append-to-body="false" :visible="hkVideoVisible" title="查看监控视频" :before-close="handleClose"> <span class="dialog-right-top" /> <span class="dialog-left-bottom" /> <div class="setting-dialog"> <hkVideo :hk-config="hkConfig" /> </div> </el-dialog>
</div> </template>
<script> // https://blog.csdn.net/qq_37236395/article/details/119737898
import { FetchInitShelfGridByShelfId, FetcheEditSortmarkByGrid, FetchChangeOrderByGrid, FetchChangeCheckByGrid } from '@/api/shelf/index' import { FetchDeviceById } from '@/api/deviceVI/index' import { mapGetters } from 'vuex' import { swiper, swiperSlide } from 'vue-awesome-swiper' import 'swiper/dist/css/swiper.css' import { parseTime, saveAs, getBlob } from '@/utils/index' import qs from 'qs' import hkVideo from '@/views/components/hkVideo.vue'
export default { name: 'BookshelfPosition', components: { swiper, swiperSlide, hkVideo }, data() { const _this = this return { floorName: null, regionName: null, bookShelfDetails: null, booShelfGrid: null, cellInfo: { gridName: null, startSortmark: null, endSortmark: null, cameraId: null }, callNumVisible: false, layerNum: 0, rackNum: 0, checkValue: 'true', bookSortValue: 'true', swiperActiveIndex: 0, cellIndex: null, swiperOptionContent: { slidesPerView: 'auto', on: { slideChangeTransitionStart: function() { _this.cellIndex = null _this.swiperActiveIndex = this.activeIndex console.log('activeIndexffff', this.swiperActiveIndex) _this.swiperTitle.slideTo(this.activeIndex, 500, false) } } }, swiperOptionTitle: { slidesPerView: 'auto', freeMode: true }, tabListData: [], form: { id: null, gridName: null, startSortmark: null, endSortmark: null, check: null, order: null, cameraId: null }, rules: { gridName: [ { required: true, message: '所属架位不可为空', trigger: 'blur' } ], startSortmark: [ { required: true, message: '起始索书号不可为空', trigger: 'blur' } ], endSortmark: [ { required: true, message: '结束索书号不可为空', trigger: 'blur' } ] }, hkVideoVisible: false, hkConfig: { 'username': null, 'password': null, 'ip': null, 'port': null } } }, computed: { ...mapGetters([ 'user', 'baseApi' ]), swiperContent() { return this.$refs.swiperContent.$el.swiper }, swiperTitle() { return this.$refs.swiperTitle.$el.swiper }, cellStyle: function() { // const h = '100%/' + this.layerNum
// const w = '100%/' + this.rackNum
const h = '60px' const w = '146px' return { width: `calc(${w} - 4px )`, height: `calc(${h} - 2px)` } }, rowStyle: function() { const w = 146 * this.rackNum + 'px' return { width: `calc(${w})` } } }, watch: { '$route'(val, from) { // 监听到路由(参数)改变
if (this.$route.query) { this.floorName = this.$route.query.floorName this.regionName = this.$route.query.regionName } } }, async created() { if (this.$route.query) { this.floorName = this.$route.query.floorName this.regionName = this.$route.query.regionName } if (localStorage.getItem('bookShelfDetails')) { this.bookShelfDetails = JSON.parse(localStorage.getItem('bookShelfDetails')) this.layerNum = this.bookShelfDetails.shelfFloor this.rackNum = this.bookShelfDetails.shelfShelf
// 单面/双面
this.tabListData = this.bookShelfDetails.rowType === 1 ? this.bookShelfDetails.toward === 1 ? [{ name: 'A面' }] : [{ name: 'B面' }] : [{ name: 'A面' }, { name: 'B面' }]
// 层数据
this.getInitShelfGridByShelfId(this.bookShelfDetails.toward) } }, mounted() { }, methods: { removeAreaPrefix(gridNames) { const index = gridNames.indexOf('区') if (index !== -1) { return gridNames.substring(index + 1) } return gridNames }, getInitShelfGridByShelfId(toward) { // rowType 1 单 2 双
// toward 1 A面 2 B面
// shelfType 1 '始终最左边为第1架(S型排架)'
// shelfType 2 'A面最左为第1架(B面最左为最后1架)'
// shelfType 3 'B面最左为第1架(A面最左为最后1架)'
// floorType 1 '最顶层为第一层(从上至下)'
// floorType 2 '最底层为第一层(从下至上)'
FetchInitShelfGridByShelfId({ 'shelfId': this.bookShelfDetails.id, 'toward': toward }).then(res => { const sortFunction = toward === 1 ? { 1: { 1: 'sortBookshelvesLeftTop', 2: 'sortBookshelvesLeftBottom' }, 2: { 1: 'sortBookshelvesLeftTop', 2: 'sortBookshelvesLeftBottom' }, 3: { 1: 'sortBookshelvesRightTop', 2: 'sortBookshelvesRightBottom' } } : { 1: { 1: 'sortBookshelvesLeftTop', 2: 'sortBookshelvesLeftBottom' }, 2: { 1: 'sortBookshelvesRightTop', 2: 'sortBookshelvesRightBottom' }, 3: { 1: 'sortBookshelvesLeftTop', 2: 'sortBookshelvesLeftBottom' } } const shelfType = this.bookShelfDetails.shelfType const floorType = this.bookShelfDetails.floorType const sortMethod = sortFunction[shelfType][floorType] this.booShelfGrid = this[sortMethod](res) }).catch(() => { }) }, // 最左为第一架, 最顶层为第一层 从上往下
sortBookshelvesLeftTop(data) { const sortedData = [] const maxFloor = Math.max(...data.map(item => parseInt(item.gridFloor))) const maxShelf = Math.max(...data.map(item => parseInt(item.gridShelf.slice(-1))))
for (let i = 1; i <= maxFloor; i++) { for (let j = 1; j <= maxShelf; j++) { const currentShelf = data.find(item => parseInt(item.gridFloor) === i && parseInt(item.gridShelf.slice(-1)) === j) if (currentShelf) { sortedData.push(currentShelf) } } } return sortedData }, // 最右为第一架,最左为最后一架, 最顶层为第一层 从上往下
sortBookshelvesRightTop(data) { const sortedData = [] // 获取最大的楼层数
const maxFloor = Math.max(...data.map(item => parseInt(item.gridFloor))) const maxShelf = Math.max(...data.map(item => parseInt(item.gridShelf.match(/\d+$/)[0]))) for (let i = 1; i <= maxFloor; i++) { // 从最大的书架层数开始,向下排序
for (let j = maxShelf; j >= 1; j--) { const currentShelf = data.find(item => parseInt(item.gridFloor) === i && parseInt(item.gridShelf.match(/\d+$/)[0]) === j) if (currentShelf) { sortedData.push(currentShelf) } } } return sortedData }, // 最左为第一架, 最底层为第一层 从下往上
sortBookshelvesLeftBottom(data) { const sortedData = [] // 获取最大的楼层数
const maxFloor = Math.max(...data.map(item => parseInt(item.gridFloor))) // 获取最大的书架层数
const maxShelf = Math.max(...data.map(item => parseInt(item.gridShelf.slice(-1)))) for (let i = maxFloor; i >= 1; i--) { for (let j = 1; j <= maxShelf; j++) { const currentShelf = data.find(item => parseInt(item.gridFloor) === i && parseInt(item.gridShelf.slice(-1)) === j) if (currentShelf) { sortedData.push(currentShelf) } } } return sortedData }, // 最左为最后一架, 最底层为第一层 从下往上
sortBookshelvesRightBottom(data) { const sortedData = [] // 获取最大的楼层数
const maxFloor = Math.max(...data.map(item => parseInt(item.gridFloor))) const maxShelfPerFloor = data.map(item => parseInt(item.gridShelf.match(/\d+$/)[0])) .reduce((acc, curr, index, arr) => { const floor = parseInt(data[index].gridFloor) if (!acc[floor]) acc[floor] = 1 if (acc[floor] < curr) acc[floor] = curr return acc }, {}) // 从最大的楼层开始向下遍历
for (let i = maxFloor; i >= 1; i--) { // 从最大的书架编号开始向左遍历
for (let j = maxShelfPerFloor[i] || 1; j >= 1; j--) { const currentShelf = data.find(item => parseInt(item.gridFloor) === i && parseInt(item.gridShelf.match(/\d+$/)[0]) === j) if (currentShelf) { sortedData.push(currentShelf) } } } return sortedData }, handleSlidClickFun(index) { this.cellIndex = null this.handleSlideToFun(index) if (localStorage.getItem('bookShelfDetails')) { this.getInitShelfGridByShelfId(index + 1) } }, handleSlideToFun(index) { this.swiperActiveIndex = index this.swiperContent.slideTo(index, 500, false) this.swiperTitle.slideTo(index, 500, false) }, handleCellCurrent(item, index) { this.cellIndex = index this.cellInfo = { id: item.id, gridName: item.gridName, startSortmark: item.startSortmark, endSortmark: item.endSortmark, cameraId: item.cameraId, check: item.isCheck, order: item.isOrder } this.checkValue = `${item.isCheck}` this.bookSortValue = `${item.isOrder}` }, handleEditGridNum() { console.log(this.cellIndex) if (this.cellIndex !== null) { this.callNumVisible = true this.form = this.cellInfo console.log(this.cellInfo) } else { this.$message({ message: '请选择需要操作得层位', type: 'error', offset: 8 }) } }, handleSaveCallNum() { if (this.$refs['form']) { this.$refs['form'].validate((valid) => { if (valid) { console.log(this.form) FetcheEditSortmarkByGrid(this.form).then(res => { console.log(res) if (res) { this.$message({ message: '编辑索书号范围成功', type: 'success', offset: 8 }) this.callNumVisible = false } }).catch(() => { }) } }) } }, handleClose() { if (this.callNumVisible) { this.$refs['form'].resetFields() this.callNumVisible = false } this.hkVideoVisible = false }, handleViewVideo(data) { console.log('data', data) FetchDeviceById({ 'deviceId': data }).then(res => { if (res) { console.log(res) this.hkConfig = { 'username': res.account, 'password': res.password, 'ip': res.ipv4, 'port': res.rtsp } this.hkVideoVisible = true } }) }, // 盘点
changeCheckSwitch(data) { console.log(data) if (this.cellIndex !== null) { this.$confirm('此操作将开启/关闭该层位的盘点功能' + '<span>你是否还要继续?</span>', '提示', { confirmButtonText: '继续', cancelButtonText: '取消', type: 'warning', dangerouslyUseHTMLString: true }).then(() => { this.cellInfo.check = JSON.parse(data) console.log(this.cellInfo) FetchChangeCheckByGrid(this.cellInfo).then(res => { this.$message({ message: '修改层位盘点状态成功', type: 'success', offset: 8 }) if (localStorage.getItem('bookShelfDetails')) { this.getInitShelfGridByShelfId(this.swiperActiveIndex + 1) } }).catch(() => { this.checkValue = data === 'true' ? 'false' : 'true' }) }).catch(() => { this.checkValue = data === 'true' ? 'false' : 'true' }) } else { this.$message({ message: '请选择需要操作得层位', type: 'error', offset: 8 }) this.checkValue = data === 'true' ? 'false' : 'true' return false } }, changeBookSortSwitch(data) { console.log(data) if (this.cellIndex !== null) { this.$confirm('此操作将开启/关闭该层位的图书顺序检查' + '<span>你是否还要继续?</span>', '提示', { confirmButtonText: '继续', cancelButtonText: '取消', type: 'warning', dangerouslyUseHTMLString: true }).then(() => { this.cellInfo.order = JSON.parse(data) FetchChangeOrderByGrid(this.cellInfo).then(res => { this.$message({ message: '修改图书有序检查状态成功', type: 'success', offset: 8 }) if (localStorage.getItem('bookShelfDetails')) { this.getInitShelfGridByShelfId(this.swiperActiveIndex + 1) } }).catch(() => { this.bookSortValue = data === 'true' ? 'false' : 'true' }) }).catch(() => { this.bookSortValue = data === 'true' ? 'false' : 'true' }) } else { this.$message({ message: '请选择需要操作得层位', type: 'error', offset: 8 }) this.bookSortValue = data === 'true' ? 'false' : 'true' return false } }, doExport() { console.log(this.bookShelfDetails) this.$confirm('此操作将导出所选数据' + '<span>你是否还要继续?</span>', '提示', { confirmButtonText: '继续', cancelButtonText: '取消', type: 'warning', dangerouslyUseHTMLString: true }).then(() => { const params = { 'shelfId': this.bookShelfDetails.id, 'toward': this.bookShelfDetails.toward } console.log(params) const fileName = '层位编码-' + parseTime(new Date()) + '.xlsx' getBlob(this.baseApi + '/api/bookShelf/exportShelfGridLabel' + '?' + qs.stringify(params, { indices: false }), function(blob) { saveAs(blob, fileName) }) }).catch(() => { }) } } } </script>
<style lang="scss" scoped> .swiper-title{ ::v-deep .swiper-wrapper{ margin: 10px 0; border-bottom: 1px solid #EDEFF3; } } .swiper-slide-title { width: auto !important; margin-right: 20px; cursor: pointer; .tab-name { padding: 10px; &.active { color: #0348F3; border-bottom: 3px solid #0348F3; } } }
.swiper-content{ height: 544px; } .swiper-slide-content { // padding: 0 10px;
// margin: 0 10px 0 0;
} .view-video{ ::v-deep .el-dialog{ width: 1000px !important; } } .swiper-container{ margin: 0 !important; } </style>
|