Browse Source

0109

master
xuhuajiao 6 months ago
parent
commit
262415ecdf
  1. 19
      src/api/book/index.js
  2. 12
      src/api/shelf/index.js
  3. 27
      src/api/stockTask/index.js
  4. 132
      src/assets/styles/manage.scss
  5. 11
      src/components/Crud/crud.js
  6. 2
      src/views/components/bookSwiper.vue
  7. 14
      src/views/components/canvasPreview.vue
  8. 16
      src/views/components/mark.vue
  9. 8
      src/views/dashboard/PanelGroup.vue
  10. 215
      src/views/home.vue
  11. 236
      src/views/visualCheck/checkManage/bookSearch/index.vue
  12. 595
      src/views/visualCheck/checkManage/bookshelfSearch/index.vue
  13. 2
      src/views/visualCheck/checkManage/dataScreening/girdList.vue
  14. 33
      src/views/visualCheck/checkManage/dataScreening/index.vue
  15. 2
      src/views/visualCheck/checkManage/dataScreening/regionsList.vue
  16. 18
      src/views/visualCheck/checkManage/dataScreening/shelfList.vue
  17. 44
      src/views/visualCheck/checkManage/paramSetting/index.vue
  18. 334
      src/views/visualCheck/checkManage/positionMixins/index.js
  19. 42
      src/views/visualCheck/checkManage/statistic/seqShelf/index.vue
  20. 80
      src/views/visualCheck/checkManage/upDownLog/index.vue
  21. 8
      src/views/visualCheck/venueDevice/area/index.vue
  22. 13
      src/views/visualCheck/venueDevice/bookshelf/index.vue

19
src/api/book/index.js

@ -40,4 +40,21 @@ export function FetchBookBasiceByISBN(params) {
})
}
export default { add, edit, del, FetchInitBookBasiceList, FetchBookBasiceByISBN }
// 一键下架
export function FetchFastDownShelf(ids) {
return request({
url: 'api/bookBasice/fastDownShelf',
method: 'post',
data: ids
})
}
// 盘点管理-图书检索-图书详情
export function FetchInitBookDetailsSearchInto(params) {
return request({
url: 'api/bookBasice/initBookDetailsSearchInto' + '?' + qs.stringify(params, { indices: false }),
method: 'get'
})
}
export default { add, edit, del, FetchInitBookBasiceList, FetchBookBasiceByISBN, FetchFastDownShelf, FetchInitBookDetailsSearchInto }

12
src/api/shelf/index.js

@ -100,4 +100,14 @@ export function FetchShelfAllByRegionId(params) {
})
}
export default { add, edit, del, FetchInitBookShelfList, FetchBookShelfDetails, saveBookShelfSignPoint, FetchInitShelfGridByShelfId, FetcheEditSortmarkByGrid, FetchChangeOrderByGrid, FetchChangeCheckByGrid, FetchShelfGridAllByShelfId, FetchShelfAllByRegionId }
// 书架/一键下架
export function FetchFastDownShelf(ids) {
return request({
url: 'api/bookShelf/fastDownShelf',
method: 'post',
data: ids
})
}
export default { add, edit, del, FetchInitBookShelfList, FetchBookShelfDetails, saveBookShelfSignPoint, FetchInitShelfGridByShelfId, FetcheEditSortmarkByGrid, FetchChangeOrderByGrid, FetchChangeCheckByGrid, FetchShelfGridAllByShelfId, FetchShelfAllByRegionId, FetchFastDownShelf }

27
src/api/stockTask/index.js

@ -42,4 +42,29 @@ export function FetchInitSuggestTilting(params) {
})
}
export default { add, edit, del, FetchUpdateStockTaskStatus, FetchInitSuggestTilting }
// 盘点管理-初始化参数
export function FetchInitSetting(params) {
return request({
url: 'api/stocktask-task/initSetting' + '?' + qs.stringify(params, { indices: false }),
method: 'get'
})
}
// 盘点管理-编辑初始化参数
export function FetchEditSetting(data) {
return request({
url: 'api/stocktask-task/editSetting',
method: 'post',
data
})
}
// 初始化统计基础数据
export function FetchInitHomeInfo(params) {
return request({
url: 'api/stocktask-task/initHomeInfo' + '?' + qs.stringify(params, { indices: false }),
method: 'get'
})
}
export default { add, edit, del, FetchUpdateStockTaskStatus, FetchInitSuggestTilting, FetchInitSetting, FetchEditSetting, FetchInitHomeInfo }

132
src/assets/styles/manage.scss

@ -638,4 +638,136 @@
background-color: #E6E8ED !important;
}
}
}
.positionDialog{
.el-dialog{
width: 1300px !important;
.el-dialog__body{
padding: 0 !important;
}
}
.book-detail{
position: relative;
display: flex;
justify-content: flex-start;
padding: 10px 30px !important;
background-color: #F6F8FC;
li{
line-height: 40px;
margin-right: 20px;
span{
display: inline-block;
width: 60px;
text-align: right;
margin-right: 20px;
color: #0C0E1E;
}
i{
font-style: normal;
padding: 0 8px;
}
// &:last-child{
// width: 30%;
// text-align: right;
// }
}
}
.position-content{
display: flex;
justify-content: space-between;
align-items: flex-start;
padding: 20px 0 !important;
h5{
font-size: 18px;
color: #0C0E1E;
}
.position-left{
width: 600px;
overflow: hidden;
::v-deep .venue-preview{
height: 500px;
}
}
.position-right{
width: 640px;
margin-left: 20px;
}
}
.shelf-top{
display: flex;
justify-content: space-around;
align-items: center;
text-align: center;
margin-top: 30px;
p{
font-size: 12px;
color: #fff;
height: 30px;
line-height: 26px;
background: url('~@/assets/images/shelf04.png') no-repeat center top;
background-size: auto 100%;
}
}
.data-shelf-row{
display: flex;
flex: 1;
flex-wrap: wrap;
text-align: center;
.data-shelf-cell{
position: relative;
font-size: 12px;
color: #0C0E1E;
background: url('~@/assets/images/shelf02.png') repeat-x left top;
background-size: 20% 100%;
border-radius: 3px;
cursor: pointer;
&::before{
content: "";
position: absolute;
left: 0;
top: 0;
width: 6px;
height: 38px;
background: url('~@/assets/images/shelf01.png') no-repeat left top;
background-size: 100% 100%;
}
&::after{
content: "";
position: absolute;
right: -4px;
top: 0;
width: 6px;
height: 38px;
background: url('~@/assets/images/shelf01.png') no-repeat left top;
background-size: 100% 100%;
}
.cell-name{
display: block;
width: 100%;
line-height: 38px;
}
&.active{
color: #fff;
span{
position: relative;
display: block;
&::before{
position: absolute;
top: 0;
left: 6px;
content: '';
width: 98%;
height: 100%;
background-color: rgba(255,0,0,.3);
}
}
}
}
}
}

11
src/components/Crud/crud.js

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

2
src/views/components/bookSwiper.vue

@ -90,7 +90,7 @@ export default {
slidesPerView: 'auto',
freeMode: true
},
tabListData: [{ name: '热门图书' }, { name: '热门架位' }, { name: '冷门图书' }],
tabListData: [{ name: '热门图书' }, { name: '热门架位' }],
bookList: [
{ 'id': 1, 'name': '女帝英雄传', 'num': 10 },
{ 'id': 2, 'name': 'NBA赛场', 'num': 9 },

14
src/views/components/canvasPreview.vue

@ -137,6 +137,7 @@ export default {
})
//
pointGroup.forEach(async(item, index) => {
console.log('item', item)
if (item.pointInfo !== '') {
const polygon = new fabric.Polygon(item.pointInfo, {
id: item.id,
@ -148,8 +149,8 @@ export default {
regionName: item.regionName,
stroke: 'rgba(196,43, 1, 1)',
strokeWidth: self.drawWidth,
fill: 'rgba(196,43, 1, 0.3)',
opacity: 1,
fill: 'rgba(196,43, 1, 1)',
opacity: 0.5,
selectable: false,
hasBorders: false,
hasControls: false,
@ -190,13 +191,14 @@ export default {
console.log('e', e)
console.log('e.target', e.target)
console.log('e.target.name', e.target.name)
console.log('e.target.rowType', e.target.rowType)
this.tooltipInfo = {
'id': e.target.id,
'name': e.target.name
'name': e.target.name,
'rowType': e.target.rowType
}
console.log('this.tooltipInfo', this.tooltipInfo)
// this.set({ opacity: 0.3, hoverCursor: 'pointer' })
this.set({ opacity: 0.8, hoverCursor: 'pointer' })
if (self.pagePreview === 'floor') {
document.getElementById('tooltip').innerHTML =
@ -234,7 +236,7 @@ export default {
})
polygon.on('mouseout', function() {
this.set({ opacity: 1 })
this.set({ opacity: 0.5 })
document.getElementById('tooltip').style.display = 'none'
self.canvasPreview.renderAll()
})

16
src/views/components/mark.vue

@ -129,10 +129,10 @@ export default {
//
const handleIdChange = (newId, oldId, idKey) => {
if (newId !== oldId) {
console.log('id has changed')
console.log('handler')
this.canvas.clear()
this.canvas.dispose()
// 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()
@ -654,8 +654,8 @@ export default {
name: item.name,
stroke: 'rgba(196,43, 1, 1)',
strokeWidth: self.drawWidth,
fill: 'rgba(196,43, 1, 0.3)',
opacity: 1,
fill: 'rgba(196,43, 1, 1)',
opacity: 0.5,
selectable: false,
hasBorders: false,
hasControls: false,
@ -683,13 +683,13 @@ export default {
// if(e.target&&e.target.name){
// // that.showDialog(e.target.name)
// }
this.set({ opacity: 0.3, hoverCursor: 'pointer' })
this.set({ opacity: 0.8, hoverCursor: 'pointer' })
this.canvas.renderAll()
})
//
polygon.on('mouseout', function() {
this.set({ opacity: 1 })
this.set({ opacity: 0.5 })
this.canvas.renderAll()
})

8
src/views/dashboard/PanelGroup.vue

@ -8,7 +8,7 @@
<div class="card-panel-description">
盘点区域
<div class="card-panel-text">
<count-to :start-val="0" :end-val="topObjectNum && topObjectNum.caseNum" :duration="3200" class="card-panel-num" />
<count-to :start-val="0" :end-val="topObjectNum && topObjectNum.regionCount" :duration="3200" class="card-panel-num" />
</div>
</div>
</div>
@ -21,7 +21,7 @@
<div class="card-panel-description">
盘点书架
<div class="card-panel-text">
<count-to :start-val="0" :end-val="topObjectNum && topObjectNum.archivesNum" :duration="3200" class="card-panel-num" />
<count-to :start-val="0" :end-val="topObjectNum && topObjectNum.shelfCount" :duration="3200" class="card-panel-num" />
</div>
</div>
</div>
@ -34,7 +34,7 @@
<div class="card-panel-description">
盘点层位
<div class="card-panel-text">
<count-to :start-val="0" :end-val="topObjectNum && topObjectNum.documentNum" :duration="3200" class="card-panel-num" />
<count-to :start-val="0" :end-val="topObjectNum && topObjectNum.gridCount" :duration="3200" class="card-panel-num" />
</div>
</div>
</div>
@ -47,7 +47,7 @@
<div class="card-panel-description">
盘点设备
<div class="card-panel-text">
<count-to :start-val="0" :end-val="topObjectNum && topObjectNum.fileNum" :duration="3200" class="card-panel-num" />
<count-to :start-val="0" :end-val="topObjectNum && topObjectNum.deviceCount" :duration="3200" class="card-panel-num" />
</div>
</div>
</div>

215
src/views/home.vue

@ -8,24 +8,40 @@
<span class="right-top-line" />
<span class="left-bottom-line" />
<h3 class="home-item-title">
盘点任务
盘点日志
<router-link :to="{ path: '/check/check/checkLog'}">
<div style="position: absolute; right: 20px; top: 20px; color: #999;" class="el-icon-more" />
</router-link>
</h3>
<div class="home-flowable" style="height: calc(100% - 54px); overflow-x: hidden;">
<div class="home-tab">
<span :class="{'home-tab-active': flowableTabIndex == 0}">全部任务({{ flowableData.length !==0? flowableData.length: 0 }})</span>
<span :class="{'home-tab-active': flowableTabIndex == 1}">进行中({{ flowableData.length !==0? flowableData.length: 0 }})</span>
<span :class="{'home-tab-active': flowableTabIndex == 2}">已完成({{ flowableData.length !==0? flowableData.length: 0 }})</span>
<span :class="{'home-tab-active': flowableTabIndex == 3}" @click="toMoreProcess">更多任务</span>
<span :class="{'home-tab-active': flowableTabIndex == 0}">未完成({{ stockLogIncompleteData.length !==0? stockLogIncompleteData.length: 0 }})</span>
<span :class="{'home-tab-active': flowableTabIndex == 1}">已完成({{ stockLogCompletedData.length !==0? stockLogCompletedData.length: 0 }})</span>
<!-- <span :class="{'home-tab-active': flowableTabIndex == 2}">已完成({{ flowableData.length !==0? flowableData.length: 0 }})</span>
<span :class="{'home-tab-active': flowableTabIndex == 3}" @click="toMoreProcess">更多任务</span> -->
</div>
<div class="home-flowable-list" style="height: calc(100% - 45px); overflow-y: auto; overflow-x: hidden;">
<el-table v-if="flowableData.length !== 0" height="calc(100%)" :data="flowableData" stripe style="width: 100%">
<el-table-column prop="title" label="标题" />
<el-table-column prop="applicant" label="申请人" width="100" />
<el-table-column prop="createTime" label="申请时间" width="180">
<el-table v-if="stockLogIncompleteData.length !== 0" height="calc(100%)" :data="stockLogIncompleteData" class="archives-table" stripe style="width: 100%">
<el-table-column prop="stockBill" label="盘点单号" />
<el-table-column prop="stockRegion" label="目标位置" />
<el-table-column prop="stockGridNum" label="目标数量" align="right">
<template slot-scope="scope">
<div>{{ scope.row.createTime | parseTime }}</div>
<div>{{ scope.row.stockGridNum + ' / '+ (scope.row.totalGridNum?scope.row.totalGridNum:'0') +' 层位' }}</div>
</template>
</el-table-column>
<el-table-column prop="state" label="盘点状态" align="center">
<template slot-scope="scope">
<span v-if="scope.row.state === 0" class="row-state row-lending state-active">已终止</span>
<span v-if="scope.row.state === 1" class="row-state row-warehousing state-active">排队中</span>
<span v-if="scope.row.state === 2" class="row-state row-binding state-active">盘点中</span>
<span v-if="scope.row.state === 3" class="row-state row-physical state-active">已完成</span>
</template>
</el-table-column>
<!-- <el-table-column prop="createTime" label="申请时间" width="180"> -->
<!-- <template slot-scope="scope"> -->
<!-- <div>{{ scope.row.createTime | parseTime }}</div> -->
<!-- </template> -->
<!-- </el-table-column> -->
</el-table>
<div v-else class="empty-main" style="height: 100%;">
<svg-icon icon-class="empty" class-name="empty-img" />
@ -41,6 +57,7 @@
<span class="left-bottom-line" />
<h3 class="home-item-title">
服务器监控
<div style="position: absolute; right: 20px; top: 20px; color: #999; cursor: pointer;" class="el-icon-refresh" @click="refreshSystemData" />
</h3>
<!-- <div class="chart-wrapper"> -->
<serverProgress :system-data="systemData" />
@ -109,7 +126,8 @@ import lendAcross from '@/views/components/echarts/lendAcross.vue'
import typePie from '@/views/components/echarts/typePie.vue'
import bookSwiper from '@/views/components/bookSwiper.vue'
import serverProgress from '@/views/components/echarts/serverProgress.vue'
import { FetchMainData } from '@/api/archivesManage/library'
import { FetchInitHomeInfo } from '@/api/stockTask/index'
import { FetchInitStockLogList } from '@/api/stockTaskLog/index'
import { FetchSystemInfo } from '@/api/home/cpu/index'
import { mapGetters } from 'vuex'
@ -126,10 +144,10 @@ export default {
data() {
return {
topObjectNum: {
archivesNum: 0,
caseNum: 0,
documentNum: 0,
fileNum: 0
regionCount: 0,
shelfCount: 0,
gridCount: 0,
deviceCount: 0
},
archivesTotalNum: 0,
flowableData: [],
@ -153,7 +171,9 @@ export default {
cpuPercentage: 0,
memPercentage: 0,
sysFilesPercentage: 0
}
},
stockLogCompletedData: [],
stockLogIncompleteData: []
}
},
computed: {
@ -164,7 +184,7 @@ export default {
created() {
this.handleMainData()
this.getSystemInfo()
// this.get()
this.getStockLog()
},
mounted() {
// const _this = this
@ -214,97 +234,111 @@ export default {
this.systemData.sysFilesPercentage = Math.round((sysFilesTotalUsed / sysFilesTotal) * 100)
})
},
refreshSystemData() {
this.systemData = {
cpuPercentage: 0,
memPercentage: 0,
sysFilesPercentage: 0
}
this.getSystemInfo()
},
getStockLog() {
FetchInitStockLogList().then(res => {
this.stockLogCompletedData = res.content.filter(item => [0, 3].includes(item.state))
this.stockLogIncompleteData = res.content.filter(item => [1, 2].includes(item.state))
})
},
toMoreProcess() {
this.$router.push({ path: '/user/center?activeIndex=2' })
},
handleMainData() {
const fondsAffiliation = []
fondsAffiliation.push(this.user.fonds.id.toString())
const params = {
fondsAffiliations: fondsAffiliation
}
FetchMainData(params).then(data => {
// const fondsAffiliation = []
// fondsAffiliation.push(this.user.fonds.id.toString())
// const params = {
// fondsAffiliations: fondsAffiliation
// }
FetchInitHomeInfo().then(data => {
this.topObjectNum = {
archivesNum: data.archivesNum,
caseNum: data.caseNum,
documentNum: data.documentNum,
fileNum: data.fileNum
regionCount: data.regionCount,
shelfCount: data.shelfCount,
gridCount: data.gridCount,
deviceCount: data.deviceCount
}
this.flowableData = data.flows
// this.flowableData = data.flows
// '', '', '', '', '', '', ''
// "archivesTotalNum archivesTagNum installNum storageNum borrowNum openNum entityNum approveNum
//
this.lendData.archivesTotalNum = data.archivesTotalNum
this.lendData.otherData = [
data.archivesTagNum, data.installNum, data.storageNum, data.borrowNum, data.openNum, data.entityNum, data.approveNum
]
// this.lendData.archivesTotalNum = data.archivesTotalNum
// this.lendData.otherData = [
// data.archivesTagNum, data.installNum, data.storageNum, data.borrowNum, data.openNum, data.entityNum, data.approveNum
// ]
//
let maxCount = 0
data.statisNumJSON.archives.forEach(archive => {
if (archive.count > maxCount) {
maxCount = archive.count
}
})
// //
// let maxCount = 0
// data.statisNumJSON.archives.forEach(archive => {
// if (archive.count > maxCount) {
// maxCount = archive.count
// }
// })
data.statisNumJSON.singles.forEach(single => {
if (single.count > maxCount) {
maxCount = single.count
}
})
this.addArcivesData.addArcivesMaxCount = maxCount
// data.statisNumJSON.singles.forEach(single => {
// if (single.count > maxCount) {
// maxCount = single.count
// }
// })
// this.addArcivesData.addArcivesMaxCount = maxCount
const currentDate = new Date() //
const currentYear = currentDate.getFullYear() //
const currentMonth = currentDate.getMonth() // 0 11 1
// const currentDate = new Date() //
// const currentYear = currentDate.getFullYear() //
// const currentMonth = currentDate.getMonth() // 0 11 1
let startYear = currentYear - 1 //
let startMonth = currentMonth + 1 // 1
// let startYear = currentYear - 1 //
// let startMonth = currentMonth + 1 // 1
const result = [] //
const xResult = []
while (startYear < currentYear || startMonth <= currentMonth) {
xResult.push(startYear + '/' + startMonth)
result.push({ year: startYear, month: startMonth, archivesCount: 0, singlesCount: 0 })
//
startMonth += 1
if (startMonth > 12) {
startYear += 1
startMonth = 1
}
}
// const result = [] //
// const xResult = []
// while (startYear < currentYear || startMonth <= currentMonth) {
// xResult.push(startYear + '/' + startMonth)
// result.push({ year: startYear, month: startMonth, archivesCount: 0, singlesCount: 0 })
// //
// startMonth += 1
// if (startMonth > 12) {
// startYear += 1
// startMonth = 1
// }
// }
result.forEach(yearMonthObj => {
data.statisNumJSON.archives.forEach(archive => {
if (parseInt(archive.month) === yearMonthObj.month) {
yearMonthObj.archivesCount = archive.count
return
}
})
// result.forEach(yearMonthObj => {
// data.statisNumJSON.archives.forEach(archive => {
// if (parseInt(archive.month) === yearMonthObj.month) {
// yearMonthObj.archivesCount = archive.count
// return
// }
// })
data.statisNumJSON.singles.forEach(single => {
if (parseInt(single.month) === yearMonthObj.month) {
yearMonthObj.singlesCount = single.count
return
}
})
})
// data.statisNumJSON.singles.forEach(single => {
// if (parseInt(single.month) === yearMonthObj.month) {
// yearMonthObj.singlesCount = single.count
// return
// }
// })
// })
this.addArcivesData.addArcivesMonth = xResult
this.addArcivesData.addArcivesNum = result.map(function(obj) {
return obj.archivesCount
})
this.addArcivesData.addArcivesNumFile = result.map(function(obj) {
return obj.singlesCount
})
// this.addArcivesData.addArcivesMonth = xResult
// this.addArcivesData.addArcivesNum = result.map(function(obj) {
// return obj.archivesCount
// })
// this.addArcivesData.addArcivesNumFile = result.map(function(obj) {
// return obj.singlesCount
// })
//
for (const type in data.typeGroupBy) {
if (data.typeGroupBy.hasOwnProperty(type)) {
this.typeData.push({ name: type, value: data.typeGroupBy[type] })
}
}
// //
// for (const type in data.typeGroupBy) {
// if (data.typeGroupBy.hasOwnProperty(type)) {
// this.typeData.push({ name: type, value: data.typeGroupBy[type] })
// }
// }
})
}
}
@ -366,10 +400,9 @@ export default {
margin-right: 30px;
padding-bottom: 3px;
border-bottom: 3px solid #fff;
cursor: pointer;
&.home-tab-active{
color: #0348F3;
border-bottom: 3px solid #0348F3;
// border-bottom: 3px solid #0348F3;
}
}
}

236
src/views/visualCheck/checkManage/bookSearch/index.vue

@ -16,7 +16,7 @@
<i class="iconfont icon-ruku" />
批量上架
</el-button> -->
<el-button size="mini" :loading="crud.downloadLoading" :disabled="crud.selections.length === 0" @click="handleRemoveShelf(crud.selections)">
<el-button size="mini" :loading="crud.delAllLoading" :disabled="crud.selections.length === 0" @click="handleRemoveShelf(crud.selections)">
<i class="iconfont icon-chuku" />
一键下架
</el-button>
@ -40,9 +40,15 @@
<el-table-column type="selection" align="center" width="55" />
<el-table-column prop="bookName" label="题名" />
<el-table-column prop="bookAuthor" label="著者" />
<el-table-column prop="barcode" label="条码" />
<el-table-column prop="sortmark" label="索书号" />
<el-table-column prop="regionName" label="所在位置" />
<el-table-column prop="barcode" label="条码" />
<el-table-column prop="floorName" label="所在位置" min-width="120">
<template slot-scope="scope">
<span>
{{ getLocation(scope.row) }}
</span>
</template>
</el-table-column>
<el-table-column label="状态" align="center" prop="bookStatus">
<template slot-scope="scope">
<span v-if="scope.row.bookStatus === '未知'" class="row-state row-warehousing">未知</span>
@ -51,22 +57,27 @@
<span v-if="scope.row.bookStatus === '错序'" class="row-state row-physical state-active">错序</span>
</template>
</el-table-column>
<el-table-column prop="createTime" label="操作">
<template slot-scope="scope">
<el-button v-if="scope.row.bookStatus === '在架'" @click="handlePosition(scope.row)">定位</el-button>
</template>
</el-table-column>
<!-- <el-table-column prop="createTime" label="所属馆藏">
<template slot-scope="scope">
<div>{{ scope.row.createTime | parseTime }}</div>
</template>
</el-table-column> -->
<el-table-column prop="updateTime" label="更新时间">
<!-- <el-table-column prop="updateTime" label="更新时间">
<template slot-scope="scope">
<div>{{ scope.row.updateTime | parseTime }}</div>
</template>
</el-table-column>
</el-table-column> -->
</el-table>
<!--分页组件-->
<pagination v-if="crud.data.length!==0" />
</div>
<!-- form -->
<!-- form 功能隐藏待定 -->
<el-dialog append-to-body :close-on-click-modal="false" :modal-append-to-body="false" :before-close="handleCloseDialog" :visible="addBookShelfVisible" title="批量上架">
<span class="dialog-right-top" />
<span class="dialog-left-bottom" />
@ -150,26 +161,28 @@
<li :class="{'active-tab-nav': tabIndex === 1}" @click="changeDetailTab(1)">盘点信息</li>
</ul>
<ul v-if="tabIndex===0" class="book-detail">
<li><span>题名</span>三国演义</li>
<li><span>著者</span>罗贯中</li>
<li><span>出版社</span>人民出版社</li>
<li><span>索书号</span>I247.57/454:2</li>
<li><span>ISBN</span>95431578551345</li>
<li><span>条码号</span>54898789124454</li>
<li><span>馆藏地</span>机构-楼层-馆藏地名称</li>
<li class="book-img"><img :src="imageUrl" :onerror="defaultImg" alt=""></li>
<li><span>题名</span>{{ detailContent.bookName }}</li>
<li><span>著者</span>{{ detailContent.bookAuthor }}</li>
<li><span>出版社</span>{{ detailContent.publisher }}</li>
<li><span>索书号</span>{{ detailContent.sortmark }}</li>
<li><span>ISBN</span>{{ detailContent.isbn }}</li>
<li><span>条码号</span>{{ detailContent.barcode }}</li>
<!-- <li><span>馆藏地</span>机构-楼层-馆藏地名称</li> -->
<li class="book-img"><img :src="detailContent.bookCover === null ? defaultImg : detailContent.bookCover" :onerror="defaultImg" alt=""></li>
<li class="book-summary"><span>简介</span><p>{{ detailContent.summary ? detailContent.summary :"暂无简介" }}</p></li>
</ul>
<ul v-if="tabIndex===1" class="book-detail book-other">
<li>
<span>状态</span>
<i class="row-state no-state">未知</i>
<!-- <i class="row-state end-state">在架</i>
<i class="row-state cancel-state">错架</i>
<i class="row-state ing-state">错序</i> -->
<i v-if="detailContent.bookStatus === '未知'" class="row-state no-state">未知</i>
<i v-if="detailContent.bookStatus === '在架'" class="row-state end-state">在架</i>
<i v-if="detailContent.bookStatus === '错架'" class="row-state cancel-state">错架</i>
<i v-if="detailContent.bookStatus === '错序'" class="row-state ing-state">错序</i>
</li>
<li><span>当前位置</span>一楼-区域A-001排A面01架1层</li>
<li><span>应在位置</span>一楼-区域A-001排A面01架1层</li>
<li><span>更新时间</span>2024-12-05 15:14</li>
<li><span>当前位置</span>{{ getLocation(detailContent) }}</li>
<!-- <li><span>应在位置</span>{{ getLocation(detailContent) }}</li> -->
<!-- <li><span>更新时间</span>{{ detailContent.updateTime | parseTime }}</li> -->
</ul>
</div>
<div slot="footer" class="dialog-footer">
@ -178,28 +191,70 @@
</div>
</el-dialog>
<el-dialog class="positionDialog" append-to-body :close-on-click-modal="false" :modal-append-to-body="false" :before-close="handleCloseDialog" :visible="positionVisible" title="图书定位">
<span class="dialog-right-top" />
<span class="dialog-left-bottom" />
<div class="setting-dialog">
<ul class="book-detail">
<li><span>所属机构</span>{{ user.fonds.fondsName }}</li>
<li><span>所属楼层</span>{{ positionContent.floorName }}</li>
<li><span>所属区域</span>{{ positionContent.regionName }}</li>
<li><span>所属书架</span>{{ positionContent.gridName }}</li>
<li><span>题名</span>{{ positionContent.bookName }}</li>
</ul>
<div class="position-content">
<div class="position-left">
<h5>平面图</h5>
<div class="venue-preview">
<div v-show="currentMarkData && currentMarkData.signPoint ">
<canvas :id="`canvasPreview${currentMarkData && currentMarkData.id}`" :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 class="position-right">
<h5>书架图</h5>
<div class="shelf-top" :style="rowStyle">
<p v-for="(item,index) in reversedRackNum" :key="index" :style="{width: `calc(${'100%/' + rackNum} - 4px )`}"><span>{{ item + '架' }}</span></p>
</div>
<ul class="data-shelf-row" :style="rowStyle">
<li
v-for="(cell,i) in booShelfGrid"
:key="i"
:class="{ active: i === cellIndex }"
class="data-shelf-cell"
:style="cellStyle"
>
<span class="cell-name">{{ removeAreaPrefix(cell.gridName) }}</span>
</li>
</ul>
</div>
</div>
</div>
</el-dialog>
</div>
</template>
<script>
import { positionCrud } from '../positionMixins/index'
import { FetchLibraryFloorListAll } from '@/api/floor/index'
import { FetchRegionAllByFloor } from '@/api/area/index'
import { FetchShelfAllByRegionId, FetchShelfGridAllByShelfId } from '@/api/shelf/index'
import crudRegion from '@/api/area/index'
import crudBook from '@/api/book/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 { mapGetters } from 'vuex'
import defaultImg from '@/assets/images/system/default-img.jpg'
// import { exportFile } from '@/utils/index'
// import qs from 'qs'
const defaultForm = { id: null, floorId: null, regionId: null, shelfId: null, girdId: null }
export default {
name: 'BookSearch',
components: { crudOperation, rrOperation, pagination },
cruds() {
return CRUD({ title: '图书检索', url: 'api/bookBasice/initBookDetailsSearch', crudMethod: { ...crudRegion }, sort: [], optShow: {
return CRUD({ title: '图书检索', url: 'api/bookBasice/initBookDetailsSearch', crudMethod: { ...crudBook }, sort: [], optShow: {
add: false,
edit: false,
del: false,
@ -208,7 +263,7 @@ export default {
reset: true
}})
},
mixins: [presenter(), header(), form(defaultForm), crud()],
mixins: [presenter(), header(), form(defaultForm), crud(), positionCrud],
data() {
return {
statusOptions: [
@ -224,6 +279,7 @@ export default {
},
addBookShelfVisible: false,
detailVisible: false,
detailContent: {},
floorOptions: [],
regionOptions: [],
shelfOptions: [],
@ -254,26 +310,32 @@ export default {
])
},
created() {
this.getLibraryFloorListAll()
},
methods: {
[CRUD.HOOK.beforeRefresh]() {
this.getLibraryFloorListAll()
},
[CRUD.HOOK.afterRefresh](crud) {
},
//
[CRUD.HOOK.beforeToAdd]() {
}, //
//
[CRUD.HOOK.beforeToEdit](crud, form) {
},
[CRUD.HOOK.beforeValidateCU](crud, form) {
},
//
[CRUD.HOOK.afterValidateCU](crud) {
return false
},
changeDetailTab(index) {
this.tabIndex = index
getLocation(row) {
const parts = []
if (row.floorName) {
parts.push(row.floorName)
}
if (row.regionName) {
parts.push(row.regionName)
}
if (row.gridName) {
parts.push(row.gridName)
}
return parts.length > 0 ? parts.join('-') : '-'
},
//
getLibraryFloorListAll() {
@ -282,6 +344,57 @@ export default {
}).catch(() => {
})
},
clickRowHandler(row) {
this.$refs.table.clearSelection()
this.$refs.table.toggleRowSelection(row)
},
handleDbClick(row) {
console.log('row', row)
this.detailVisible = true
this.tabIndex = 0
crudBook.FetchInitBookDetailsSearchInto({ id: row.id }).then((res) => {
if (res) {
this.detailContent = res
} else {
this.detailContent = null
}
}).catch(err => {
console.log(err)
})
},
changeDetailTab(index) {
this.tabIndex = index
},
handleRemoveShelf(datas) {
console.log(datas)
this.crud.delAllLoading = true
this.$confirm('此操作将下架所选图书' + '<span>你是否还要继续?</span>', '提示', {
confirmButtonText: '继续',
cancelButtonText: '取消',
type: 'warning',
dangerouslyUseHTMLString: true
}).then(() => {
const ids = []
datas.forEach(val => {
ids.push(val.id)
})
console.log(ids)
crudBook.FetchFastDownShelf(ids).then(() => {
this.$message({ message: '一键下架操作成功', 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
})
},
handleBatchListing() {
this.addBookShelfVisible = true
},
changeFloorValue(value) {
console.log(value)
this.crud.form.regionId = null
@ -323,47 +436,6 @@ export default {
},
changeGirdValue(value) {
console.log(value)
},
clickRowHandler(row) {
this.$refs.table.clearSelection()
this.$refs.table.toggleRowSelection(row)
},
handleDbClick(row) {
this.detailVisible = true
},
handleBatchListing() {
this.addBookShelfVisible = true
},
handleRemoveShelf(data) {
console.log(data)
this.crud.downloadLoading = true
this.$confirm('此操作将下架所选图书' + '<span>你是否还要继续?</span>', '提示', {
confirmButtonText: '继续',
cancelButtonText: '取消',
type: 'warning',
dangerouslyUseHTMLString: true
}).then(() => {
const ids = []
data.forEach(val => {
ids.push(val.deptsId)
})
const params = {
'deptsIds': ids
}
console.log(params)
// exportFile(this.baseApi + '/api/depts/download?' + qs.stringify(params, { indices: false }))
// this.crud.downloadLoading = false
}).catch(() => {
this.crud.downloadLoading = false
})
},
handleCloseDialog() {
this.addBookShelfVisible = false
this.detailVisible = false
if (this.$refs.form) {
this.crud.cancelCU()
this.$refs.form.resetFields()
}
}
}
}
@ -432,6 +504,20 @@ export default {
height: 100%;
}
}
.book-summary{
display:flex;
justify-content:flex-start;
line-height: 30px;
p{
flex:1;
overflow: hidden;
text-overflow: ellipsis;
display: -webkit-box;
-webkit-box-orient: vertical;
-webkit-line-clamp: 3;
overflow-y: scroll;
}
}
}
.book-other{
li{

595
src/views/visualCheck/checkManage/bookshelfSearch/index.vue

@ -3,18 +3,22 @@
<div class="head-container">
<div class="head-search">
<!-- 搜索 -->
<el-select v-model="selectFloorVal" clearable size="small" placeholder="楼层" class="filter-item" style="width: 80px" value-key="id" @change="changeBeforeFloor">
<el-select v-model="selectFloorVal" 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="selectRegionVal" clearable size="small" placeholder="区域" class="filter-item" style="width: 140px" value-key="id" @change="changeBeforeRegion">
<el-select v-model="selectRegionVal" size="small" placeholder="区域" class="filter-item" style="width: 140px" 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: 220px;" class="filter-item" @clear="crud.toQuery" @keyup.enter.native="crud.toQuery" />
<rrOperation />
<rrOperation>
<template v-slot:right>
<el-button class="filter-item filter-refresh" size="mini" type="warning" icon="el-icon-refresh-left" @click="resetQuery()">重置</el-button>
</template>
</rrOperation>
</div>
<crudOperation :permission="permission">
<template v-slot:right>
<el-button size="mini" :loading="crud.downloadLoading" :disabled="crud.selections.length === 0" @click="handleRemoveShelf(crud.selections)">
<el-button size="mini" :loading="crud.delAllLoading" :disabled="crud.selections.length === 0" @click="handleRemoveShelf(crud.selections)">
<i class="iconfont icon-chuku" />
一键下架
</el-button>
@ -30,40 +34,38 @@
class="archives-table"
:data="crud.data"
style="width: 100%;"
height="540"
height="calc(100vh - 329px)"
@selection-change="crud.selectionChangeHandler"
@row-click="clickRowHandler"
>
<el-table-column type="selection" align="center" width="55" />
<el-table-column prop="regionName" label="层位名称" />
<el-table-column prop="gridName" label="层位名称" />
<el-table-column prop="floorName" label="所属楼层" />
<el-table-column prop="regionName" label="所属区域" />
<el-table-column prop="booksheflCount" label="盘点开关" align="center">
<!-- slot-scope="scope" -->
<template>
<span class="row-state row-binding state-active">盘点开启</span>
<!-- <span class="row-state row-lending state-active">盘点关闭</span> -->
<el-table-column prop="isCheck" label="盘点开关" align="center">
<template slot-scope="scope">
<span v-if="scope.row.isCheck" class="row-state row-binding state-active">盘点开启</span>
<span v-else class="row-state row-lending state-active">盘点关闭</span>
</template>
</el-table-column>
<el-table-column prop="booksheflCount" label="有序检查" align="center">
<!-- slot-scope="scope" -->
<template>
<span class="row-state row-binding state-active"></span>
<!-- <span class="row-state row-lending state-active"></span> -->
<el-table-column prop="isOrder" label="有序检查" align="center">
<template slot-scope="scope">
<span v-if="scope.row.isOrder" class="row-state row-binding state-active"></span>
<span v-else class="row-state row-lending state-active"></span>
</template>
</el-table-column>
<el-table-column prop="startSortmark" label="索书号范围">
<template slot-scope="scope">
<span>{{ getSortmark(scope.row) }}</span>
</template>
</el-table-column>
<el-table-column prop="booksheflCount" label="索书号范围" />
<el-table-column prop="deptsStatus" label="盘点概况" min-width="160">
<!-- slot-scope="scope" -->
<template>
<template slot-scope="scope">
<div class="tag-info">
<p class="tag-sort">错序<i class="iconfont icon-zhuangtai2" />1</p>
<p class="tag-place">错架<i class="iconfont icon-zhuangtai2" />1</p>
<p class="tag-all">在架<i class="iconfont icon-zhuangtai2" />20</p>
<p class="tag-sort">错序<i class="iconfont icon-zhuangtai2" />{{ scope.row.errorOrderNum }}</p>
<p class="tag-place">错架<i class="iconfont icon-zhuangtai2" />{{ scope.row.errorShelfNum }}</p>
<p class="tag-all">在架<i class="iconfont icon-zhuangtai2" />{{ scope.row.onShelfNum }}</p>
</div>
<!-- <span class="row-state row-binding state-active">在架</span>
<span class="row-state row-lending state-active">错架</span>
<span class="row-state row-physical state-active">错序</span> -->
</template>
</el-table-column>
<el-table-column prop="createTime" label="操作">
@ -76,21 +78,15 @@
<pagination v-if="crud.data.length!==0" />
</div>
<el-dialog class="positionDialog" append-to-body :close-on-click-modal="false" :modal-append-to-body="false" :before-close="handleCloseDialog" :visible="positionVisible" :title="positionTitle+' - 层位定位'">
<el-dialog class="positionDialog" append-to-body :close-on-click-modal="false" :modal-append-to-body="false" :before-close="handleCloseDialog" :visible="positionVisible" title="层位定位">
<span class="dialog-right-top" />
<span class="dialog-left-bottom" />
<div class="setting-dialog">
<ul class="book-detail">
<li><span>所属机构</span>机构A</li>
<li><span>所属楼层</span>五楼</li>
<li><span>所属区域</span>区域A</li>
<li><span>所属书架</span>001排A面</li>
<li>
<i class="row-state no-state">未知</i>
<!-- <i class="row-state end-state">在架</i>
<i class="row-state cancel-state">错架</i>
<i class="row-state ing-state">错序</i> -->
</li>
<li><span>所属机构</span>{{ user.fonds.fondsName }}</li>
<li><span>所属楼层</span>{{ positionContent.floorName }}</li>
<li><span>所属区域</span>{{ positionContent.regionName }}</li>
<li><span>所属书架</span>{{ positionContent.gridName }}</li>
</ul>
<div class="position-content">
<div class="position-left">
@ -128,7 +124,7 @@
</template>
<script>
import { FetchInitShelfGridByShelfId, FetchBookShelfDetails } from '@/api/shelf/index'
import { positionCrud } from '../positionMixins/index'
import { FetchLibraryFloorListAll } from '@/api/floor/index'
import { FetchInitLibraryRegionList } from '@/api/area/index'
import crudShelf from '@/api/shelf/index'
@ -136,25 +132,21 @@ import CRUD, { presenter, header, crud } from '@crud/crud'
import crudOperation from '@crud/CRUD.operation'
import rrOperation from '@crud/RR.operation'
import pagination from '@crud/Pagination'
import { mapGetters } from 'vuex'
import defaultImg from '@/assets/images/system/default-img.jpg'
import { fabric } from 'fabric'
// import { exportFile } from '@/utils/index'
// import qs from 'qs'
export default {
name: 'BookSearch',
components: { crudOperation, rrOperation, pagination },
cruds() {
return CRUD({ title: '架位检索', url: 'api/bookShelf/initBookShelfList', crudMethod: { ...crudShelf }, sort: [], optShow: {
return CRUD({ title: '架位检索', url: 'api/bookShelf/initShelfGridSearch', crudMethod: { ...crudShelf }, sort: [], optShow: {
add: false,
edit: false,
del: false,
download: false,
group: false,
reset: true
reset: false
}})
},
mixins: [presenter(), header(), crud()],
mixins: [presenter(), header(), crud(), positionCrud],
data() {
return {
permission: {
@ -165,205 +157,52 @@ export default {
floorOptions: [],
regionOptions: [],
selectFloorVal: null,
selectRegionVal: null,
positionVisible: false,
positionTitle: '001排A面01架1层',
currentMarkData: null,
defaultImg: defaultImg,
imageUrl: defaultImg,
canvasPreview: {},
width: 900,
height: 600,
drawWidth: 2, //
booShelfGrid: [],
rackNum: 0,
cellIndex: 0
}
},
computed: {
...mapGetters([
'user',
'baseApi'
]),
cellStyle: function() {
// const h = '100%/' + this.layerNum
// const w = '100%/' + this.rackNum
const h = '38px'
const w = '146px'
return { width: `calc(${w})`, height: `calc(${h})` }
},
rowStyle: function() {
const w = 146 * this.rackNum + 'px'
return { width: `calc(${w})` }
},
reversedRackNum() {
if (this.booShelfGrid && this.booShelfGrid.length > 0) {
console.log('ddd')
console.log('this.booShelfGrid[0].gridShelf', this.booShelfGrid[0].gridShelf)
if (this.booShelfGrid[0].gridShelf === '07') {
return Array.from({ length: this.rackNum }, (_, i) => this.rackNum - i).map(x => x.toString())
} else {
return Array.from({ length: this.rackNum }, (_, i) => i + 1).map(x => x.toString())
}
} else {
console.log('fff')
return []
}
selectRegionVal: null
}
},
async created() {
this.getLibraryFloorListAll()
if (localStorage.getItem('dataScreenRegion')) {
const dataScreenRegion = JSON.parse(localStorage.getItem('dataScreenRegion'))
this.floorName = dataScreenRegion.floorName
this.regionName = dataScreenRegion.regionName
this.rowType = dataScreenRegion.rowType
// /
this.tabListData = dataScreenRegion.rowType === 1
? dataScreenRegion.toward === 1
? [{ name: 'A面' }]
: [{ name: 'B面' }]
: [{ name: 'A面' }, { name: 'B面' }]
FetchBookShelfDetails({ 'shelfId': dataScreenRegion.id }).then(res => {
this
this.layerNum = res.shelfFloor
this.rackNum = res.shelfShelf
this.bookShelfDetails = res
this.getInitShelfGridByShelfId(this.bookShelfDetails.toward)
}).catch(() => {
})
}
},
methods: {
[CRUD.HOOK.beforeRefresh]() {
},
[CRUD.HOOK.afterRefresh](crud) {
},
//
[CRUD.HOOK.beforeToAdd]() {
}, //
[CRUD.HOOK.beforeToEdit](crud, form) {
},
[CRUD.HOOK.beforeValidateCU](crud, form) {
},
//
[CRUD.HOOK.afterValidateCU](crud) {
return false
},
removeAreaPrefix(gridNames) {
const index = gridNames.indexOf('面')
if (index !== -1) {
return gridNames.substring(index + 1)
}
return gridNames
},
getInitShelfGridByShelfId(toward) {
this.listLoading = true
// rowType 1 2
// toward 1 A 2 B
// shelfType 1 '1S'
// shelfType 2 'A1B1'
// shelfType 3 'B1A1'
// 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)
console.log(this.booShelfGrid[0].gridShelf)
this.popoverVisible = Array(this.booShelfGrid.length).fill(false)
setTimeout(() => {
this.listLoading = false
}, 1000)
//
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(() => {
})
},
// ,
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)
}
}
getInitLibraryRegionList(val) {
const params = {
'floorId': val
}
return sortedData
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
// } else {
// this.selectRegionVal = null
// this.crud.query.regionId = null
// }
this.crud.toQuery()
}).catch(() => {
})
},
changeBeforeFloor(val) {
if (val) {
@ -379,54 +218,30 @@ export default {
this.crud.toQuery()
}
},
//
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(() => {
})
resetQuery() {
this.crud.query.search = ''
this.selectFloorVal = null
this.selectRegionVal = null
this.crud.query.floorId = null
this.crud.query.regionId = null
this.crud.toQuery()
},
getInitLibraryRegionList(val) {
const params = {
'floorId': val
getSortmark(row) {
const parts = []
if (row.startSortmark) {
parts.push(row.startSortmark)
}
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
} else {
this.selectRegionVal = null
this.crud.query.regionId = null
}
this.crud.toQuery()
}).catch(() => {
})
if (row.endSortmark) {
parts.push(row.endSortmark)
}
return parts.length > 0 ? parts.join('-') : '-'
},
// changeFloorValue(value) {
// console.log(value)
// this.crud.query.regionId = null
// const params = {
// 'floorId': value
// }
// FetchRegionAllByFloor(params).then(res => {
// this.regionOptions = res
// }).catch(() => {
// })
// },
clickRowHandler(row) {
this.$refs.table.clearSelection()
this.$refs.table.toggleRowSelection(row)
},
handleRemoveShelf(data) {
console.log(data)
handleRemoveShelf(datas) {
console.log(datas)
this.crud.downloadLoading = true
this.$confirm('此操作将下架所选层位的所有图书' + '<span>你是否还要继续?</span>', '提示', {
confirmButtonText: '继续',
@ -435,117 +250,24 @@ export default {
dangerouslyUseHTMLString: true
}).then(() => {
const ids = []
data.forEach(val => {
ids.push(val.deptsId)
datas.forEach(val => {
ids.push(val.id)
})
console.log(ids)
crudShelf.FetchFastDownShelf(ids).then((res) => {
console.log(res)
this.$message({ message: '一键下架操作成功', type: 'success', offset: 8 })
this.crud.delAllLoading = false
this.crud.refresh()
}).catch(err => {
this.crud.delAllLoading = false
console.log(err)
})
const params = {
'deptsIds': ids
}
console.log(params)
// exportFile(this.baseApi + '/api/depts/download?' + qs.stringify(params, { indices: false }))
// this.crud.downloadLoading = false
}).catch(() => {
this.crud.downloadLoading = false
})
},
handlePosition(row) {
console.log('position', row)
this.positionVisible = true
},
handleCloseDialog() {
this.addBookShelfVisible = false
this.detailVisible = false
if (this.$refs.form) {
this.crud.cancelCU()
this.$refs.form.resetFields()
}
this.positionVisible = false
},
initCanvasPreview(drawinfo) {
if (!this.currentMarkData) {
console.error('currentMarkData is null or undefined')
return
}
const canvasId = `canvasPreview${this.currentMarkData.id}`
this.canvasPreview = new fabric.Canvas(canvasId, {
skipTargetFind: false,
selectable: false,
selection: false
})
this.$nextTick(() => {
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>
@ -556,132 +278,5 @@ export default {
margin-right: 20px;
}
}
.positionDialog{
::v-deep .el-dialog{
width: 1300px !important;
.el-dialog__body{
padding: 0 !important;
}
}
}
.book-detail{
position: relative;
display: flex;
justify-content: space-between;
padding: 10px 30px !important;
background-color: #F6F8FC;
li{
line-height: 40px;
span{
display: inline-block;
width: 60px;
text-align: right;
margin-right: 20px;
color: #0C0E1E;
}
i{
font-style: normal;
padding: 0 8px;
}
&:last-child{
width: 30%;
text-align: right;
}
}
}
.position-content{
display: flex;
justify-content: space-between;
align-items: flex-start;
padding: 20px 0 !important;
h5{
font-size: 18px;
color: #0C0E1E;
}
.position-left{
width: 600px;
overflow: hidden;
::v-deep .venue-preview{
height: 500px;
}
}
.position-right{
width: 640px;
margin-left: 20px;
}
}
.shelf-top{
display: flex;
justify-content: space-around;
align-items: center;
text-align: center;
margin-top: 30px;
p{
font-size: 12px;
color: #fff;
height: 30px;
line-height: 26px;
background: url('~@/assets/images/shelf04.png') no-repeat center top;
background-size: auto 100%;
}
}
.data-shelf-row{
display: flex;
flex: 1;
flex-wrap: wrap;
text-align: center;
.data-shelf-cell{
position: relative;
font-size: 12px;
color: #0C0E1E;
background: url('~@/assets/images/shelf02.png') repeat-x left top;
background-size: 20% 100%;
border-radius: 3px;
cursor: pointer;
&::before{
content: "";
position: absolute;
left: 0;
top: 0;
width: 6px;
height: 38px;
background: url('~@/assets/images/shelf01.png') no-repeat left top;
background-size: 100% 100%;
}
&::after{
content: "";
position: absolute;
right: -4px;
top: 0;
width: 6px;
height: 38px;
background: url('~@/assets/images/shelf01.png') no-repeat left top;
background-size: 100% 100%;
}
.cell-name{
display: block;
width: 100%;
line-height: 38px;
}
&.active{
color: #fff;
span{
position: relative;
display: block;
&::before{
position: absolute;
top: 0;
left: 6px;
content: '';
width: 98%;
height: 100%;
background-color: rgba(255,0,0,.3);
}
}
}
}
}
</style>

2
src/views/visualCheck/checkManage/dataScreening/girdList.vue

@ -1,7 +1,7 @@
<template>
<div class="app-container">
<div class="venue-header dataScreening-header">
<h4 @click="handleToGrids"><i class="iconfont icon-shuju" />架位总览</h4>
<h4><i class="iconfont icon-shuju" />架位总览</h4>
<div class="bookshelf-area">
<!-- <span class="bookshelf-area">{{ floorName }} - {{ regionName }} - {{ gridRow +'排' }}</span> -->
<router-link :to="{ path: '/check/check/dataScreening', query: {floorTabIndex: floorTabIndex }}">

33
src/views/visualCheck/checkManage/dataScreening/index.vue

@ -63,38 +63,6 @@
</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" :inline="true" :model="form" :rules="rules" size="small" label-width="80px">
<el-form-item label="盘点单号" prop="stockBill">
<el-input v-model="form.stockBill" disabled />
</el-form-item>
<el-form-item label="盘点类型" prop="stockTypeName">
<el-input v-model="form.stockTypeName" disabled />
</el-form-item>
<el-form-item label="目标位置" prop="stockRegion">
<el-input v-model="form.stockRegion" disabled />
</el-form-item>
<el-form-item label="目标数量" prop="stockGridNumName">
<el-input v-model="form.stockGridNumName" disabled />
</el-form-item>
<el-row>
<el-form-item label="备注" prop="stockRemarks">
<el-input v-model="form.stockRemarks" type="textarea" style="width: 572px;" :rows="4" />
</el-form-item>
</el-row>
</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> -->
<!-- @refresh="initData" -->
<eForm ref="eform" />
</div>
</template>
@ -102,7 +70,6 @@
<script>
import { FetchInitLibraryRegionList } from '@/api/area/index'
import crudStockTaskLog from '@/api/stockTaskLog/index'
// import crudFloor from '@/api/floor/index'
import CRUD, { presenter, header, crud } from '@crud/crud'
import crudOperation from '@crud/CRUD.operation'
import { mapGetters } from 'vuex'

2
src/views/visualCheck/checkManage/dataScreening/regionsList.vue

@ -1,7 +1,7 @@
<template>
<div class="app-container">
<div class="venue-header dataScreening-header">
<h4 @click="handleToShelfs"><i class="iconfont icon-shuju" />区域总览</h4>
<h4><i class="iconfont icon-shuju" />区域总览</h4>
<div class="bookshelf-area">
<!-- <span class="bookshelf-area">{{ floorName }} </span> -->
<router-link :to="{ path: '/check/check/dataScreening', query: {floorTabIndex: floorTabIndex }}">

18
src/views/visualCheck/checkManage/dataScreening/shelfList.vue

@ -1,7 +1,7 @@
<template>
<div class="app-container">
<div class="venue-header dataScreening-header">
<h4 @click="handleToGrids"><i class="iconfont icon-shuju" />书架总览</h4>
<h4><i class="iconfont icon-shuju" />书架总览</h4>
<div class="bookshelf-area">
<!-- <span> {{ floorName }} - {{ regionName }}</span> -->
<router-link :to="{ path: '/check/check/dataScreening', query: {floorTabIndex: floorTabIndex }}">
@ -223,7 +223,7 @@ export default {
},
reversedRackNum() {
if (this.booShelfGrid && this.booShelfGrid.length > 0) {
if (this.booShelfGrid[0].gridShelf === '07') {
if (parseInt(this.booShelfGrid[0].gridShelf) === this.rackNum) {
return Array.from({ length: this.rackNum }, (_, i) => this.rackNum - i).map(x => x.toString())
} else {
return Array.from({ length: this.rackNum }, (_, i) => i + 1).map(x => x.toString())
@ -434,11 +434,17 @@ export default {
for (let i = 0; i < this.booShelfGrid.length; i++) {
const columnIndex = i % this.rackNum
// 5
if (columnIndex === this.rackNum - 1) {
lastColumnIndexes.push(i)
//
this.$set(this.popoverStyles, i, { position: 'absolute', left: '-180px', top: '20px' })
console.log('this.booShelfGrid.length', this.booShelfGrid.length)
if (this.rackNum !== 1) {
if (columnIndex === this.rackNum - 1) {
lastColumnIndexes.push(i)
//
this.$set(this.popoverStyles, i, { position: 'absolute', left: '-180px', top: '20px' })
}
} else {
this.$set(this.popoverStyles, i, { position: 'absolute', left: '60px', top: '20px' })
}
// 4
if (columnIndex === this.rackNum - 2) {
secondLastColumnIndexes.push(i)

44
src/views/visualCheck/checkManage/paramSetting/index.vue

@ -11,8 +11,8 @@
<p style="line-height: 32px; margin-left: 20px; font-size: 12px;">设置成功后方可执行视觉盘点任务</p>
</el-row>
<el-row style="display: flex; justify-content: flex-start;">
<el-form-item label="层位占用上限" prop="number">
<el-input v-model="form.number" type="number" placeholder="请输入" style="width: 300px;" />
<el-form-item label="层位占用上限" prop="maxNum">
<el-input v-model="form.maxNum" type="number" placeholder="请输入" style="width: 300px;" />
</el-form-item>
<p style="line-height: 32px; margin-left: 20px; font-size: 12px;">设置成功后方可在倒架建议中给出正确的数据通常情况下上限为 50 </p>
</el-row>
@ -44,12 +44,13 @@
</template>
<script>
import crudStockTask from '@/api/stockTask/index'
import { encrypt } from '@/utils/rsaEncrypt'
import crudParam, { verifyMaintenance } from '@/api/system/param'
import { verifyMaintenance } from '@/api/system/param'
import CRUD, { presenter, header, form, crud } from '@crud/crud'
import { mapGetters } from 'vuex'
const defaultForm = { id: null, ip: '' }
const defaultForm = { ip: '', maxNum: null }
export default {
name: 'ParamSetting',
@ -57,9 +58,13 @@ export default {
cruds() {
return CRUD({
title: '参数设置',
url: 'api/database/databaseList',
crudMethod: { ...crudParam },
url: 'api/stocktask-task/initSetting',
crudMethod: { ...crudStockTask },
sort: [],
query: {
size: null,
page: null
},
optShow: {
add: true,
edit: false,
@ -67,7 +72,8 @@ export default {
download: false,
group: false,
reset: false
}
},
queryOnPresenterCreated: false
})
},
mixins: [presenter(), header(), form(defaultForm), crud()],
@ -87,7 +93,7 @@ export default {
ip: [
{ required: true, message: 'AI处理终端IP不可为空', trigger: 'blur' }
],
number: [
maxNum: [
{ required: true, message: '层位占用上限不可为空', trigger: 'blur' }
]
}
@ -99,6 +105,12 @@ export default {
])
},
created() {
crudStockTask.FetchInitSetting().then(res => {
this.crud.form.ip = res.ip
this.maxNum = res.maxNum
this.crud.form.maxNum = res.maxNum
}).catch(() => {
})
},
methods: {
[CRUD.HOOK.beforeToCU](crud, form, btn) {
@ -109,11 +121,12 @@ export default {
}
},
[CRUD.HOOK.beforeRefresh]() {
},
//
[CRUD.HOOK.afterValidateCU](crud) {
console.log(crud.form)
return true
return false
},
toVerify(btn) {
if (this.form.ip) {
@ -134,16 +147,15 @@ export default {
handleConfirm() {
verifyMaintenance(encrypt(this.verfiyForm.verifyCode)).then((res) => {
if (res) {
//
this.verifyDialogVisible = false
this.verfiyForm.verifyCode = ''
this.showVerifyDialog = false
// this.crud.form.ip
// crudSql.FetchBackupName().then((data) => {
// console.log('data',data)
// }).catch(err => {
// console.log(err)
// })
crudStockTask.FetchEditSetting(this.crud.form).then(res => {
console.log('res', res)
this.$message({ message: '修改成功', type: 'success', offset: 8 })
this.crud.refresh()
}).catch(() => {
})
} else {
this.$message({ message: '验证码错误!', type: 'error', offset: 8 })
}

334
src/views/visualCheck/checkManage/positionMixins/index.js

@ -0,0 +1,334 @@
import { FetchInitShelfGridByShelfId, FetchBookShelfDetails } from '@/api/shelf/index'
import defaultImg from '@/assets/images/system/default-img.jpg'
import { mapGetters } from 'vuex'
import { fabric } from 'fabric'
export const positionCrud = {
mixins: [],
// 组件共用属性
data() {
return {
positionVisible: false,
positionTitle: '',
positionContent: {},
currentMarkData: null,
defaultImg: defaultImg,
imageUrl: defaultImg,
canvasPreview: {},
width: 900,
height: 600,
drawWidth: 2, // 笔触宽度
booShelfGrid: [],
layerNum: 0,
rackNum: 0,
cellIndex: 0,
bookShelfDetails: {},
getGridShelf: '',
getGridFloor: '',
getGridToward: 1
}
},
computed: {
...mapGetters([
'user',
'baseApi'
]),
cellStyle: function() {
const h = '38px'
let w
if (this.rackNum === 1) {
w = '146px'
} else {
w = '100%/' + this.rackNum
}
return { width: `calc(${w})`, height: `calc(${h})` }
},
rowStyle: function() {
let w
if (this.rackNum === 1) {
w = 146 * this.rackNum + 'px'
} else {
w = '100%'
}
return { width: `calc(${w})` }
},
reversedRackNum() {
if (this.booShelfGrid && this.booShelfGrid.length > 0) {
if (parseInt(this.booShelfGrid[0].gridShelf) === this.rackNum) {
return Array.from({ length: this.rackNum }, (_, i) => this.rackNum - i).map(x => x.toString())
} else {
return Array.from({ length: this.rackNum }, (_, i) => i + 1).map(x => x.toString())
}
} else {
return []
}
}
},
// 组件挂载时的共用方法
mounted() {
},
// 组件共用方法
methods: {
removeAreaPrefix(gridNames) {
const index = gridNames.indexOf('面')
if (index !== -1) {
return gridNames.substring(index + 1)
}
return gridNames
},
handlePosition(row) {
if (this.canvasPreview.lowerCanvasEl) {
this.canvasPreview.clear()
this.canvasPreview.dispose()
}
this.booShelfGrid = []
this.currentMarkData = {}
this.positionVisible = true
this.positionTitle = row.gridName
this.positionContent = row
this.updateParts(row.gridName)
FetchBookShelfDetails({ 'shelfId': row.shelfId }).then(res => {
this.layerNum = res.shelfFloor
this.rackNum = res.shelfShelf
this.bookShelfDetails = res
this.currentMarkData = res
if (row.regionMap) {
this.imageUrl = this.baseApi + '/api/fileRelevant/getImg?imgId=' + row.regionMap
this.$nextTick(() => {
const drawinfo = JSON.parse(res.signPoint)
this.initCanvasPreview(drawinfo)
})
} else {
this.imageUrl = this.defaultImg
}
this.getInitShelfGridByShelfId(this.getGridToward)
}).catch(() => {
})
},
updateParts(gridName) {
const parts = gridName.match(/(\d+)区(\d+)排([A-Za-z])面(\d+)架(\d+)层/)
if (parts) {
this.getGridShelf = parts[4]
this.getGridFloor = parts[5]
const toward = parts[3]
if (toward === 'A') {
this.getGridToward = 1
} else if (toward === 'B') {
this.getGridToward = 2
}
console.log(' this.getGridShelf', this.getGridShelf)
console.log(' this.getGridFloor', this.getGridFloor)
console.log(' this.getGridToward', this.getGridToward)
}
},
getInitShelfGridByShelfId(toward) {
this.listLoading = true
// 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)
const index = this.booShelfGrid.findIndex((obj) => {
return obj.gridShelf === this.getGridShelf && obj.gridFloor === this.getGridFloor
})
this.cellIndex = index
setTimeout(() => {
this.listLoading = false
}, 1000)
}).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
},
initCanvasPreview(drawinfo) {
if (!this.currentMarkData) {
console.error('currentMarkData is null or undefined')
return
}
const canvasId = `canvasPreview${this.currentMarkData.id}`
this.canvasPreview = new fabric.Canvas(canvasId, {
skipTargetFind: false,
selectable: false,
selection: false
})
this.$nextTick(() => {
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, 1)',
opacity: 0.5,
selectable: false,
hasBorders: false,
hasControls: false,
originX: 'left',
originY: 'top'
})
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.8, hoverCursor: 'pointer' })
self.canvasPreview.renderAll()
})
polygon.on('mouseout', function() {
this.set({ opacity: 0.5 })
self.canvasPreview.renderAll()
})
// 加载完成后直接对多边形执行zoomToPoint操作
const center = polygon.getCenterPoint()
self.canvasPreview.zoomToPoint({ x: center.x, y: center.y }, 1.4)
}
})
})
self.canvasPreview.renderAll()
},
handleCloseDialog() {
this.positionVisible = false
this.detailVisible = false
// 功能隐藏待定
// this.addBookShelfVisible = false
// if (this.$refs.form) {
// this.crud.cancelCU()
// this.$refs.form.resetFields()
// }
}
}
}

42
src/views/visualCheck/checkManage/statistic/seqShelf/index.vue

@ -10,12 +10,22 @@
@row-click="clickRowHandler"
@selection-change="crud.selectionChangeHandler"
>
<el-table-column prop="gridName" label="层位" min-width="150" />
<el-table-column prop="floorName" label="所属楼层" min-width="150" />
<el-table-column prop="regionName" label="所属区域" min-width="150" />
<el-table-column prop="prop" label="当前错架率" min-width="180">
<el-table-column prop="gridName" label="层位" />
<el-table-column prop="floorName" label="所属楼层" />
<el-table-column prop="regionName" label="所属区域" />
<el-table-column prop="prop" label="在架" align="right">
<template slot-scope="scope">
<div>在架: {{ scope.row.onShelfNum }} / 错架{{ scope.row.onErrorShelfNum }} / {{ scope.row.prop }} </div>
<span v-if="scope.row.onShelfNum">{{ scope.row.onShelfNum }} / </span>
</template>
</el-table-column>
<el-table-column prop="prop" label="错架" align="right">
<template slot-scope="scope">
<div v-if="scope.row.onErrorShelfNum"><span style="color:#ED4A41;">{{ scope.row.onErrorShelfNum }}</span> / </div>
</template>
</el-table-column>
<el-table-column prop="prop" label="当前错架率" align="right">
<template slot-scope="scope">
<span v-if="scope.row.prop">{{ scope.row.prop +'%' }} </span>
</template>
</el-table-column>
<!-- <el-table-column prop="createTime" label="更新时间" min-width="180">
@ -66,4 +76,26 @@ export default {
::v-deep .el-pagination{
margin: 24px 0 10px 0 !important
}
.detail-table-info{
display: flex;
justify-content: flex-start;
li{
width: calc(100% / 3);
margin-right: 15px;
span{
display: inline-block;
width: 40px;
text-align: right;
}
p{
display: inline-block;
text-align: right;
width: calc(100% - 40px);
i{
font-weight: bold;
font-style: normal;
}
}
}
}
</style>

80
src/views/visualCheck/checkManage/upDownLog/index.vue

@ -3,14 +3,15 @@
<div class="head-container">
<div class="head-search">
<!-- 搜索 -->
<el-select v-model="query.type" clearable size="small" placeholder="类型" class="filter-item" style="width: 120px" @change="crud.toQuery">
<el-select v-model="query.udType" clearable size="small" placeholder="类型" class="filter-item" style="width: 120px" @change="crud.toQuery">
<i slot="prefix" class="iconfont icon-zhuangtai" />
<el-option v-for="item in typeOptions" :key="item.key" :label="item.display_name" :value="item.key" />
</el-select>
<el-select v-model="query.other" clearable size="small" placeholder="方式" class="filter-item" style="width: 120px" @change="crud.toQuery">
<el-select v-model="query.udWay" clearable size="small" placeholder="方式" class="filter-item" style="width: 120px" @change="crud.toQuery">
<i slot="prefix" class="iconfont icon-zhuangtai" />
<el-option v-for="item in otherOptions" :key="item.key" :label="item.display_name" :value="item.key" />
</el-select>
<date-range-picker v-model="blurryTime" class="date-item" />
<el-input v-model="query.search" clearable size="small" placeholder="输入关键字搜索" prefix-icon="el-icon-search" style="width: 220px;" class="filter-item" @clear="crud.toQuery" @keyup.enter.native="crud.toQuery" />
<rrOperation />
</div>
@ -35,16 +36,23 @@
height="590"
@selection-change="crud.selectionChangeHandler"
@row-click="clickRowHandler"
@row-dblclick="handleDbClick"
>
<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="booksheflCount" label="条码" />
<el-table-column prop="booksheflCount" label="目标层位" />
<el-table-column prop="booksheflCount" label="盘点单号" />
<el-table-column prop="booksheflCount" label="操作者" />
<el-table-column prop="udType" label="类型" width="60">
<template slot-scope="scope">
<div>{{ scope.row.udType === 1 ? "上架":"下架" }}</div>
</template>
</el-table-column>
<el-table-column prop="udWay" label="方式" width="60">
<template slot-scope="scope">
<div>{{ scope.row.udWay === 1 ? "自动":"手动" }}</div>
</template>
</el-table-column>
<el-table-column prop="bookName" label="题名" />
<el-table-column prop="sortmark" label="索书号" />
<el-table-column prop="barcode" label="条码" />
<el-table-column prop="gridName" label="目标层位" />
<el-table-column prop="bill_no" label="盘点单号" />
<el-table-column prop="createBy" label="操作者" />
<el-table-column prop="createTime" label="操作时间">
<template slot-scope="scope">
<div>{{ scope.row.createTime | parseTime }}</div>
@ -64,16 +72,16 @@ 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 DateRangePicker from '@/components/DateRangePicker'
import { mapGetters } from 'vuex'
// import { exportFile } from '@/utils/index'
// import qs from 'qs'
import { parseTime, saveAs, getBlob } from '@/utils/index'
const defaultForm = { id: null, taskType: null, taskName: null, location: null, number: null, remark: null }
export default {
name: 'UpDownLog',
components: { crudOperation, rrOperation, pagination },
components: { crudOperation, rrOperation, pagination, DateRangePicker },
cruds() {
return CRUD({ title: '上架/下架日志', url: 'api/libraryRegion/initLibraryRegionList', crudMethod: { ...crudRegion }, sort: [], optShow: {
return CRUD({ title: '上架/下架日志', url: 'api/stocktask-task/initUpDownShelfLog', crudMethod: { ...crudRegion }, sort: [], optShow: {
add: false,
edit: false,
del: false,
@ -86,13 +94,14 @@ export default {
data() {
return {
otherOptions: [
{ key: '1', display_name: '自动' },
{ key: '2', display_name: '手动' }
{ key: 1, display_name: '自动' },
{ key: 2, display_name: '手动' }
],
typeOptions: [
{ key: '1', display_name: '上架' },
{ key: '2', display_name: '下架' }
{ key: 1, display_name: '上架' },
{ key: 2, display_name: '下架' }
],
blurryTime: null,
permission: {
add: ['admin', 'checkLog:add'],
edit: ['admin', 'checkLog:edit'],
@ -108,6 +117,13 @@ export default {
},
methods: {
[CRUD.HOOK.beforeRefresh]() {
if (this.blurryTime) {
this.crud.query.startTime = this.blurryTime[0]
this.crud.query.endTime = this.blurryTime[1]
} else {
this.crud.query.startTime = null
this.crud.query.endTime = null
}
},
[CRUD.HOOK.afterRefresh](crud) {
},
@ -135,17 +151,29 @@ export default {
type: 'warning',
dangerouslyUseHTMLString: true
}).then(() => {
const ids = []
data.forEach(val => {
ids.push(val.deptsId)
})
const params = {
'deptsIds': ids
'endTime': this.crud.query.endTime ? this.crud.query.endTime : null,
'startTime': this.crud.query.startTime ? this.crud.query.startTime : null,
'search': this.crud.query.search ? this.crud.query.search : null,
'udType': this.crud.query.udType ? this.crud.query.udType : null,
'udWay': this.crud.query.udWay ? this.crud.query.udWay : null
}
// paramsnull
Object.keys(params).forEach(key => {
if (params[key] === null) {
delete params[key]
}
})
console.log(params)
// exportFile(this.baseApi + '/api/depts/download?' + qs.stringify(params, { indices: false }))
// this.crud.downloadLoading = false
const url = this.baseApi + '/api/stocktask-task/exportUpDownShelfLog' + '?' + new URLSearchParams(params).toString()
getBlob(url, (blob) => {
const fileName = '上下架日志-' + parseTime(new Date()) + '.xlsx'
saveAs(blob, fileName)
})
this.crud.downloadLoading = false
}).catch(() => {
this.crud.downloadLoading = false
})
},
handleCloseDialog() {

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

@ -482,8 +482,8 @@ export default {
name: item.name,
stroke: 'rgba(196,43, 1, 1)',
strokeWidth: self.drawWidth,
fill: 'rgba(196,43, 1, 0.3)',
opacity: 1,
fill: 'rgba(196,43, 1, 1)',
opacity: 0.5,
selectable: false,
hasBorders: false,
hasControls: false,
@ -502,13 +502,13 @@ export default {
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' })
this.set({ opacity: 0.8, hoverCursor: 'pointer' })
self.canvasPreview.renderAll()
})
//
polygon.on('mouseout', function() {
this.set({ opacity: 1 })
this.set({ opacity: 0.5 })
self.canvasPreview.renderAll()
})
}

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

@ -506,6 +506,11 @@ export default {
// 1
if (this.crud.selections.length === 1 && this.crud.selections[0].signPoint) {
this.currentMarkData = val[0]
if (this.canvasPreview.lowerCanvasEl) {
this.canvasPreview.clear()
this.canvasPreview.dispose()
}
try {
const drawinfo = JSON.parse(this.crud.selections[0].signPoint)
this.initCanvasPreview(drawinfo)
@ -632,8 +637,8 @@ export default {
name: item.name,
stroke: 'rgba(196,43, 1, 1)',
strokeWidth: self.drawWidth,
fill: 'rgba(196,43, 1, 0.3)',
opacity: 1,
fill: 'rgba(196,43, 1, 1)',
opacity: 0.5,
selectable: false,
hasBorders: false,
hasControls: false,
@ -652,13 +657,13 @@ export default {
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' })
this.set({ opacity: 0.8, hoverCursor: 'pointer' })
self.canvasPreview.renderAll()
})
//
polygon.on('mouseout', function() {
this.set({ opacity: 1 })
this.set({ opacity: 0.5 })
self.canvasPreview.renderAll()
})
}

Loading…
Cancel
Save