22 changed files with 1933 additions and 449 deletions
			
			
		- 
					37src/api/stockTask/index.js
- 
					14src/assets/iconfonts/light/iconfont.css
- 
					2src/assets/iconfonts/light/iconfont.js
- 
					14src/assets/iconfonts/light/iconfont.json
- 
					BINsrc/assets/iconfonts/light/iconfont.ttf
- 
					BINsrc/assets/iconfonts/light/iconfont.woff
- 
					BINsrc/assets/iconfonts/light/iconfont.woff2
- 
					BINsrc/assets/images/shelf01.png
- 
					BINsrc/assets/images/shelf02.png
- 
					BINsrc/assets/images/shelf03.png
- 
					BINsrc/assets/images/shelf04.png
- 
					36src/assets/styles/manage.scss
- 
					8src/utils/index.js
- 
					10src/views/visualCheck/checkManage/bookshelfSearch/index.vue
- 
					244src/views/visualCheck/checkManage/checkPlan/index.vue
- 
					852src/views/visualCheck/checkManage/dataScreening/girdList.vue
- 
					1src/views/visualCheck/checkManage/dataScreening/index.vue
- 
					3src/views/visualCheck/checkManage/dataScreening/regionsList.vue
- 
					686src/views/visualCheck/checkManage/dataScreening/shelfList copy.vue
- 
					316src/views/visualCheck/checkManage/dataScreening/shelfList.vue
- 
					149src/views/visualCheck/checkManage/upDownLog/index.vue
- 
					10src/views/visualCheck/venueDevice/bookshelfPosition/index.vue
| @ -0,0 +1,37 @@ | |||
| import request from '@/utils/request' | |||
| // import qs from 'qs'
 | |||
| 
 | |||
| export function add(data) { | |||
|   return request({ | |||
|     url: 'api/stocktask-task/editStockTask', | |||
|     method: 'post', | |||
|     data | |||
|   }) | |||
| } | |||
| 
 | |||
| export function edit(data) { | |||
|   return request({ | |||
|     url: 'api/stocktask-task/editStockTask', | |||
|     method: 'post', | |||
|     data | |||
|   }) | |||
| } | |||
| 
 | |||
| export function del(ids) { | |||
|   return request({ | |||
|     url: '', | |||
|     method: 'post', | |||
|     data: ids | |||
|   }) | |||
| } | |||
| 
 | |||
| // 修改盘点任务状态
 | |||
| export function FetchUpdateStockTaskStatus(data) { | |||
|   return request({ | |||
|     url: 'api/stocktask-task/updateStockTaskStatus', | |||
|     method: 'post', | |||
|     data | |||
|   }) | |||
| } | |||
| 
 | |||
| export default { add, edit, del, FetchUpdateStockTaskStatus } | |||
						
							
						
						
							2
	
						
						src/assets/iconfonts/light/iconfont.js
						
							File diff suppressed because it is too large
							
							
								
									View File
								
							
						
					
				File diff suppressed because it is too large
							
							
								
									View File
								
							
						| After Width: 32 | Height: 441 | Size: 1.4 KiB | 
| After Width: 368 | Height: 441 | Size: 62 KiB | 
| After Width: 48 | Height: 192 | Size: 2.1 KiB | 
| After Width: 256 | Height: 256 | Size: 3.0 KiB | 
| @ -0,0 +1,686 @@ | |||
| <template> | |||
|   <div class="app-container"> | |||
|     <div class="venue-header"> | |||
|       <h4 @click="handleToGrids"><i class="iconfont icon-shuju" />书架总览</h4> | |||
|       <span class="bookshelf-area">{{ floorName }} - {{ regionName }}</span> | |||
|       <p><i class="iconfont icon-gongsi" />{{ user.fonds.fondsName }}</p> | |||
|     </div> | |||
|     <div class="venue-content"> | |||
|       <crudOperation :permission="permission"> | |||
|         <template v-slot:middle> | |||
|           <el-select v-model="layerVal" clearable size="small" placeholder="楼层" class="filter-item" style="width: 100px; margin-right: 20px;"> | |||
|             <el-option v-for="item in layerOptions" :key="item.id" :label="item.name" :value="item.id" /> | |||
|           </el-select> | |||
|           <el-button v-permission="permission.add" size="mini" @click="crud.toAdd"> | |||
|             <i class="iconfont icon-shengchengpandiandan" /> | |||
|             书架盘点 | |||
|           </el-button> | |||
|         </template> | |||
|         <template v-slot:right> | |||
|           <el-button :loading="crud.downloadLoading" size="mini" @click="doExport(crud.selections)"> | |||
|             <i class="iconfont icon-daochu" /> | |||
|             导出 | |||
|           </el-button> | |||
|         </template> | |||
|       </crudOperation> | |||
|       <div class="venue-left"> | |||
|         <div class="container-right tab-content"> | |||
|           <span class="right-top-line" /> | |||
|           <span class="left-bottom-line" /> | |||
| 
 | |||
|           <!-- <div style="display: flex;justify-content: flex-start; align-items: center;"> --> | |||
|           <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> | |||
|           <div class="tag-info"> | |||
|             <p>错序:1</p> | |||
|             <p>错架:1</p> | |||
|             <p>在架:20</p> | |||
|           </div> | |||
|           <!-- </div> --> | |||
|           <swiper | |||
|             ref="swiperContent" | |||
|             class="swiper-content" | |||
|             :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"> | |||
|                 <li | |||
|                   v-for="(cell,i) in booShelfGrid" | |||
|                   :key="i" | |||
|                   class="cabinet-cell" | |||
|                   :style="cellStyle" | |||
|                   :class="{ active: i === cellIndex }" | |||
|                   @click="handleCellCurrent(cell,i)" | |||
|                   @mouseenter="showPopover(i)" | |||
|                   @mouseleave="hidePopover" | |||
|                 > | |||
|                   <span class="cell-name">{{ removeAreaPrefix(cell.gridName) }}</span> | |||
|                   <!-- v-if="popoverIndex === i" --> | |||
|                   <el-popover | |||
|                     v-if="popoverIndex === i" | |||
|                     ref="popover" | |||
|                     :visible="popoverVisible[i]" | |||
|                     width="400" | |||
|                     :style="popoverStyles[i]" | |||
|                     trigger="manual" | |||
|                   > | |||
|                     <div slot="reference" class="popover-content"> | |||
|                       <div class="tooltip-top"> | |||
|                         <h4>层位概况</h4> | |||
|                         <i class="update-time">2024-11-28 09:46</i> | |||
|                       </div> | |||
|                       <ul> | |||
|                         <li><p>层位</p><em class="percentage"><i style="color: #fff;">{{ removeAreaPrefix(cell.gridName) }}</i></em></li> | |||
|                         <li><p>在架</p><em><i>15000</i>册</em></li> | |||
|                         <li><p>错架</p><em><i>300</i>层</em> <em class="percentage">(2.00%)</em></li> | |||
|                         <li><p>错序</p><em><i>0</i>层</em><em class="percentage">(0.00%)</em></li> | |||
|                       </ul> | |||
|                     </div> | |||
|                   </el-popover> | |||
|                 </li> | |||
|               </ul> | |||
|             </swiper-slide> | |||
|           </swiper> | |||
|         </div> | |||
|       </div> | |||
|       <div class="venue-right"> | |||
|         <div class="lib-right-item lib-info"> | |||
|           <h4>本架概况</h4> | |||
|           <ul class="data-right-list"> | |||
|             <li><p>书架</p><span><i>001排</i></span></li> | |||
|             <li><p>规则</p><span><i>双面 6 x 5</i></span></li> | |||
|           </ul> | |||
|         </div> | |||
|         <div class="lib-right-item"> | |||
|           <h4>本架盘点概况</h4> | |||
|           <div class="refresh-date">2024-11-28 09:46</div> | |||
|           <ul class="data-right-list"> | |||
|             <li><p>在架</p><span><i>15000</i>册</span></li> | |||
|             <li><p>错架</p><span><i>300</i>层</span> <span class="percentage">(2.00%)</span></li> | |||
|             <li><p>错序</p><span><i>0</i>层</span><span class="percentage">(0.00%)</span></li> | |||
|           </ul> | |||
|         </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="taskName"> | |||
|             <el-input v-model="form.taskName" /> | |||
|           </el-form-item> | |||
|           <el-form-item label="盘点类型" prop="taskType"> | |||
|             <el-input v-model="form.taskType" /> | |||
|           </el-form-item> | |||
|           <el-form-item label="目标位置" prop="location"> | |||
|             <el-input v-model="form.location" /> | |||
|           </el-form-item> | |||
|           <el-form-item label="目标数量" prop="number"> | |||
|             <el-input v-model="form.number" /> | |||
|           </el-form-item> | |||
|           <el-row> | |||
|             <el-form-item label="备注" prop="remark"> | |||
|               <el-input v-model="form.remark" 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> | |||
|   </div> | |||
| </template> | |||
| 
 | |||
| <script> | |||
| import { FetchInitShelfGridByShelfId, FetchBookShelfDetails } from '@/api/shelf/index' | |||
| import crudRegion from '@/api/area/index' | |||
| import CRUD, { presenter, header, form, crud } from '@crud/crud' | |||
| import crudOperation from '@crud/CRUD.operation' | |||
| import { mapGetters } from 'vuex' | |||
| import { swiper, swiperSlide } from 'vue-awesome-swiper' | |||
| import 'swiper/dist/css/swiper.css' | |||
| 
 | |||
| const defaultForm = { id: null, taskType: null, taskName: null, location: null, number: null, remark: null } | |||
| export default { | |||
|   name: 'DataScreening', | |||
|   components: { swiper, swiperSlide, crudOperation }, | |||
|   cruds() { | |||
|     return CRUD({ title: '架位总览', url: 'api/libraryRegion/initLibraryRegionList', crudMethod: { ...crudRegion }, sort: [], optShow: { | |||
|       add: false, | |||
|       edit: false, | |||
|       del: false, | |||
|       download: false, | |||
|       group: false, | |||
|       reset: false | |||
|     }, | |||
|     queryOnPresenterCreated: false | |||
|     }) | |||
|   }, | |||
|   mixins: [presenter(), header(), form(defaultForm), crud()], | |||
|   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, | |||
|       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 | |||
|       }, | |||
|       layerVal: '001排', | |||
|       layerOptions: [{ id: 1, name: '001排' }], | |||
|       tabListData: [], | |||
|       permission: { | |||
|         add: ['admin', 'floor:add'], | |||
|         edit: ['admin', 'floor:edit'], | |||
|         del: ['admin', 'floor:del'] | |||
|       }, | |||
|       rules: { | |||
|         taskName: [ | |||
|           { required: true, message: '请输入盘点单号', trigger: 'blur' } | |||
|         ], | |||
|         taskType: [ | |||
|           { required: true, message: '请输入盘点类型', trigger: 'blur' } | |||
|         ], | |||
|         location: [ | |||
|           { required: true, message: '请输入目标位置', trigger: 'blur' } | |||
|         ], | |||
|         number: [ | |||
|           { required: true, message: '请输入目标数量', trigger: 'blur' } | |||
|         ] | |||
|       }, | |||
|       popoverIndex: 1, | |||
|       popoverVisible: [], | |||
|       popoverStyles: [] | |||
|     } | |||
|   }, | |||
|   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 = '70px' | |||
|       const w = '100%/' + this.rackNum | |||
|       return { width: `calc(${w} - 4px )`, height: `calc(${h} - 2px)` } | |||
|     } | |||
|   }, | |||
|   async created() { | |||
|     if (localStorage.getItem('dataScreenRegion')) { | |||
|       const dataScreenRegion = JSON.parse(localStorage.getItem('dataScreenRegion')) | |||
|       this.floorName = dataScreenRegion.floorName | |||
|       this.regionName = dataScreenRegion.regionName | |||
|       // 单面/双面 | |||
|       this.tabListData = dataScreenRegion.rowType === 1 | |||
|         ? dataScreenRegion.toward === 1 | |||
|           ? [{ name: 'A面' }] | |||
|           : [{ name: 'B面' }] | |||
|         : [{ name: 'A面' }, { name: 'B面' }] | |||
| 
 | |||
|       FetchBookShelfDetails({ 'shelfId': dataScreenRegion.id }).then(res => { | |||
|         this.layerNum = res.shelfFloor | |||
|         this.rackNum = res.shelfShelf | |||
|         this.bookShelfDetails = res | |||
|         this.getInitShelfGridByShelfId(this.bookShelfDetails.toward) | |||
|       }).catch(() => { | |||
|       }) | |||
|     } | |||
|   }, | |||
|   methods: { | |||
|     handleToGrids() { | |||
|       this.$router.push({ path: '/dataScreening/gird', query: { }}) | |||
|     }, | |||
|     [CRUD.HOOK.beforeRefresh]() { | |||
|     }, | |||
|     [CRUD.HOOK.afterRefresh](crud) { | |||
|     }, | |||
|     // 提交前的验证 | |||
|     [CRUD.HOOK.afterValidateCU](crud) { | |||
|       return true | |||
|     }, | |||
|     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) | |||
| 
 | |||
|         this.popoverVisible = Array(this.booShelfGrid.length).fill(false) | |||
|         // this.popoverStyles = new Array(this.booShelfGrid.length).fill({ position: 'absolute', left: '20%', top: '48px' }) | |||
|       }).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) { | |||
|       console.log('index', 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 | |||
|       } | |||
|     }, | |||
|     showPopover(index) { | |||
|       this.popoverIndex = index | |||
|       // 显示对应的 popover | |||
|       if (!this.popoverVisible[index]) { | |||
|         this.$set(this.popoverVisible, index, true) | |||
|       } | |||
| 
 | |||
|       const lastColumnIndexes = [] | |||
|       const secondLastColumnIndexes = [] | |||
| 
 | |||
|       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: '-140px', top: '48px' }) | |||
|         } | |||
|         // 如果是倒数第二列(第4列) | |||
|         if (columnIndex === this.rackNum - 2) { | |||
|           secondLastColumnIndexes.push(i) | |||
|           // 更新倒数第二列的样式 | |||
|           this.$set(this.popoverStyles, i, { position: 'absolute', left: '-20px', top: '48px' }) | |||
|         } | |||
|       } | |||
|     }, | |||
|     hidePopover() { | |||
|       this.popoverIndex = null | |||
|       // 隐藏所有的popover | |||
|       this.popoverVisible.forEach((isVisible, index) => { | |||
|         if (isVisible) { | |||
|           this.$set(this.popoverVisible, index, false) | |||
|         } | |||
|       }) | |||
|     } | |||
|   } | |||
| } | |||
| </script> | |||
| 
 | |||
| <style lang="scss" scoped> | |||
| .container-right{ | |||
|   min-height: calc(100vh - 232px) !important; | |||
| } | |||
| .venue-content{ | |||
|   position: relative; | |||
| } | |||
| 
 | |||
| .crud-opts{ | |||
|   position: absolute; | |||
|   right: 20px; | |||
|   top: 10px; | |||
| } | |||
| .venue-left{ | |||
|   flex: 1; | |||
|   margin-right: 0 !important; | |||
|   .venue-preview{ | |||
|     height: 633px !important; | |||
|   } | |||
| } | |||
| .venue-right{ | |||
|   display: flex; | |||
|   flex-direction: column; | |||
|   width: 400px; | |||
|   padding: 50px 10px 20px 10px !important; | |||
|   .lib-right-item{ | |||
|     position: relative; | |||
|     padding-bottom: 10px; | |||
|     margin-bottom: 10px; | |||
|     border: 1px solid #E8F2FF; | |||
|     border-radius: 4px; | |||
|     h4{ | |||
|       padding: 6px 10px; | |||
|       background-color: #E8F2FF; | |||
|       color: #000; | |||
|       line-height: 30px; | |||
|       border-bottom: 1px solid #edeff3; | |||
|     } | |||
|     .refresh-date{ | |||
|       position: absolute; | |||
|       right: 14px; | |||
|       top: 10px; | |||
|       font-size: 12px; | |||
|       line-height: 30px; | |||
|     } | |||
|   } | |||
| } | |||
| 
 | |||
| .data-right-list { | |||
|   padding-top: 10px; | |||
|   li{ | |||
|     display: flex; | |||
|     justify-content: flex-start; | |||
|     align-items: center; | |||
|     line-height: 36px; | |||
| 
 | |||
|     p{ | |||
|       width: 80px; | |||
|       font-weight: bold; | |||
|       text-align: right; | |||
|     } | |||
|     span{ | |||
|       width: 140px; | |||
|       display: block; | |||
|       text-align: right; | |||
|       i{ | |||
|         font-style: normal; | |||
|         font-weight: bold; | |||
|         padding: 0 10px; | |||
|         color: #0348f3; | |||
|       } | |||
|       &.percentage{ | |||
|         width: auto; | |||
|       } | |||
|     } | |||
|   } | |||
| } | |||
| .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: 610px; | |||
| } | |||
| .tag-info{ | |||
|   position: absolute; | |||
|   right: 20px; | |||
|   top: 34px; | |||
|   display: flex; | |||
|   justify-content: flex-start; | |||
|   padding-left: 100px; | |||
|   p{ | |||
|     margin-left: 20px; | |||
|     margin-top: -4px; | |||
|     font-size: 14px; | |||
|   } | |||
| } | |||
| .cabinet-row .cabinet-cell{ | |||
|   background: url('~@/assets/images/shelf02.png') repeat-x left top; | |||
|   background-size: 100% 100%; | |||
|   border: none; | |||
|   overflow: inherit; | |||
|   cursor: pointer; | |||
|   &::before{ | |||
|     content: ""; | |||
|     position: absolute; | |||
|     left: 0; | |||
|     top: 0; | |||
|     width: 6px; | |||
|     height: 68px; | |||
|     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: 68px; | |||
|     background: url('~@/assets/images/shelf01.png') no-repeat left top; | |||
|     background-size: 100% 100%; | |||
|   } | |||
|   span.cell-name{ | |||
|     position: initial !important; | |||
|     transform: none; | |||
|     line-height: 68px; | |||
|   } | |||
| } | |||
| ::v-deep .cabinet-row .cabinet-cell span.el-popover__reference-wrapper{ | |||
|   position: absolute !important; | |||
|   left: 50% !important; | |||
|   top: 20px !important; | |||
|   transform: none; | |||
|   width: 300px; | |||
|   height: 210px; | |||
|   background:rgba(0,0,0,.8); | |||
|   color: #fff; | |||
|   border-radius: 6px; | |||
|   z-index: 99999999; | |||
| 
 | |||
|   .popover-content{ | |||
|     .tooltip-top{ | |||
|       display: flex; | |||
|       justify-content: space-between; | |||
|       align-items: center; | |||
|       height: 40px; | |||
|       line-height: 40px; | |||
|       padding: 0 10px; | |||
|       border-bottom: 1px solid #fff; | |||
|     } | |||
|     .tooltip-top i{ | |||
|       font-style: normal; | |||
|       font-size: 12px; | |||
|     } | |||
|     ul{ | |||
|       padding: 10px; | |||
|     } | |||
|     ul li{ | |||
|       display: flex; | |||
|       justify-content: flex-start; | |||
|       align-items: center; | |||
|       line-height: 36px; | |||
|       font-style: normal; | |||
|     } | |||
| 
 | |||
|     ul li p{ | |||
|       width: 80px; | |||
|       font-weight: bold; | |||
|       text-align: right; | |||
|     } | |||
|     ul li em{ | |||
|       width: 100px; | |||
|       display: block; | |||
|       text-align: right; | |||
|       font-style: normal; | |||
|     } | |||
|     ul li i{ | |||
|       font-style: normal; | |||
|       font-weight: bold; | |||
|       padding: 0 10px; | |||
|       color: #0348f3; | |||
|     } | |||
|     ul li em.percentage{ | |||
|       width: auto; | |||
|     } | |||
|   } | |||
| } | |||
| </style> | |||
| @ -1,16 +1,159 @@ | |||
| <template> | |||
|   <div class="app-container"> | |||
|     上架/下架日志 | |||
|   <div class="app-container  row-container"> | |||
|     <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"> | |||
|           <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"> | |||
|           <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> | |||
|         <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> | |||
|       <crudOperation :permission="permission"> | |||
|         <template v-slot:right> | |||
|           <el-button :loading="crud.downloadLoading" size="mini" @click="doExport(crud.selections)"> | |||
|             <i class="iconfont icon-daochu" /> | |||
|             导出 | |||
|           </el-button> | |||
|         </template> | |||
|       </crudOperation> | |||
|     </div> | |||
|     <div class="container-wrap"> | |||
|       <span class="right-top-line" /> | |||
|       <span class="left-bottom-line" /> | |||
|       <el-table | |||
|         ref="table" | |||
|         v-loading="crud.loading" | |||
|         class="archives-table" | |||
|         :data="crud.data" | |||
|         style="width: 100%;" | |||
|         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="createTime" label="操作时间"> | |||
|           <template slot-scope="scope"> | |||
|             <div>{{ scope.row.createTime | parseTime }}</div> | |||
|           </template> | |||
|         </el-table-column> | |||
|       </el-table> | |||
|       <!--分页组件--> | |||
|       <pagination v-if="crud.data.length!==0" /> | |||
|     </div> | |||
| 
 | |||
|   </div> | |||
| </template> | |||
| 
 | |||
| <script> | |||
| import crudRegion from '@/api/area/index' | |||
| import CRUD, { presenter, header, form, crud } from '@crud/crud' | |||
| import crudOperation from '@crud/CRUD.operation' | |||
| import rrOperation from '@crud/RR.operation' | |||
| import pagination from '@crud/Pagination' | |||
| import { mapGetters } from 'vuex' | |||
| // import { exportFile } from '@/utils/index' | |||
| // import qs from 'qs' | |||
| 
 | |||
| const defaultForm = { id: null, taskType: null, taskName: null, location: null, number: null, remark: null } | |||
| export default { | |||
|   name: 'UpDownLog', | |||
|   components: { crudOperation, rrOperation, pagination }, | |||
|   cruds() { | |||
|     return CRUD({ title: '上架/下架日志', url: 'api/libraryRegion/initLibraryRegionList', crudMethod: { ...crudRegion }, sort: [], optShow: { | |||
|       add: false, | |||
|       edit: false, | |||
|       del: false, | |||
|       download: false, | |||
|       group: false, | |||
|       reset: false | |||
|     }}) | |||
|   }, | |||
|   mixins: [presenter(), header(), form(defaultForm), crud()], | |||
|   data() { | |||
|     return { | |||
|       otherOptions: [ | |||
|         { key: '1', display_name: '自动' }, | |||
|         { key: '2', display_name: '手动' } | |||
|       ], | |||
|       typeOptions: [ | |||
|         { key: '1', display_name: '上架' }, | |||
|         { key: '2', display_name: '下架' } | |||
|       ], | |||
|       permission: { | |||
|         add: ['admin', 'checkLog:add'], | |||
|         edit: ['admin', 'checkLog:edit'], | |||
|         del: ['admin', 'checkLog:del'] | |||
|       } | |||
|     } | |||
|   }, | |||
|   computed: { | |||
|     ...mapGetters([ | |||
|       'user', | |||
|       'baseApi' | |||
|     ]) | |||
|   }, | |||
|   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 | |||
|     }, | |||
|     clickRowHandler(row) { | |||
|       this.$refs.table.clearSelection() | |||
|       this.$refs.table.toggleRowSelection(row) | |||
|     }, | |||
|     doExport(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(() => { | |||
|       }) | |||
|     }, | |||
|     handleCloseDialog() { | |||
| 
 | |||
|     } | |||
|   } | |||
| } | |||
| </script> | |||
| <style scoped> | |||
| 
 | |||
| <style lang="scss" scoped> | |||
| </style> | |||
						Write
						Preview
					
					
					Loading…
					
					Cancel
						Save
					
		Reference in new issue