图书馆综合管理系统
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

999 lines
34 KiB

6 months ago
6 months ago
6 months ago
6 months ago
6 months ago
6 months ago
6 months ago
6 months ago
6 months ago
6 months ago
6 months ago
6 months ago
6 months ago
6 months ago
6 months ago
6 months ago
6 months ago
6 months ago
6 months ago
6 months ago
6 months ago
6 months ago
6 months ago
6 months ago
6 months ago
6 months ago
6 months ago
6 months ago
6 months ago
6 months ago
6 months ago
6 months ago
6 months ago
6 months ago
6 months ago
6 months ago
6 months ago
6 months ago
6 months ago
6 months ago
6 months ago
6 months ago
6 months ago
6 months ago
6 months ago
6 months ago
6 months ago
6 months ago
6 months ago
6 months ago
6 months ago
6 months ago
6 months ago
6 months ago
6 months ago
6 months ago
6 months ago
6 months ago
6 months ago
6 months ago
6 months ago
6 months ago
6 months ago
6 months ago
6 months ago
6 months ago
6 months ago
6 months ago
6 months ago
6 months ago
6 months ago
6 months ago
6 months ago
6 months ago
6 months ago
6 months ago
6 months ago
6 months ago
6 months ago
6 months ago
6 months ago
6 months ago
6 months ago
6 months ago
6 months ago
5 months ago
6 months ago
6 months ago
6 months ago
6 months ago
6 months ago
6 months ago
5 months ago
6 months ago
6 months ago
6 months ago
5 months ago
6 months ago
6 months ago
6 months ago
6 months ago
6 months ago
6 months ago
6 months ago
6 months ago
6 months ago
6 months ago
6 months ago
6 months ago
6 months ago
6 months ago
6 months ago
6 months ago
6 months ago
6 months ago
6 months ago
6 months ago
6 months ago
6 months ago
6 months ago
6 months ago
6 months ago
6 months ago
6 months ago
6 months ago
6 months ago
6 months ago
6 months ago
6 months ago
6 months ago
5 months ago
6 months ago
5 months ago
6 months ago
5 months ago
6 months ago
5 months ago
6 months ago
6 months ago
6 months ago
6 months ago
6 months ago
6 months ago
6 months ago
6 months ago
6 months ago
6 months ago
6 months ago
6 months ago
6 months ago
6 months ago
6 months ago
6 months ago
6 months ago
6 months ago
6 months ago
6 months ago
6 months ago
6 months ago
6 months ago
6 months ago
6 months ago
6 months ago
6 months ago
6 months ago
6 months ago
6 months ago
6 months ago
  1. <template>
  2. <div class="app-container">
  3. <div class="venue-header dataScreening-header">
  4. <h4><i class="iconfont icon-shuju" />架位总览</h4>
  5. <div class="bookshelf-area">
  6. <!-- <span class="bookshelf-area">{{ floorName }} - {{ regionName }} - {{ gridRow +'排' }}</span> -->
  7. <router-link :to="{ path: '/check/check/dataScreening', query: {floorTabIndex: floorTabIndex }}">
  8. {{ floorName }}
  9. </router-link>
  10. <span>/</span>
  11. <router-link :to="{ path: '/dataScreening/regions', query: {regionTabIndex: regionTabIndex }}">
  12. {{ regionName }}
  13. </router-link>
  14. <span>/</span>
  15. <router-link :to="{ path: '/dataScreening/shelf', query: {tabIndex: tabIndex }}">
  16. {{ gridRow +'排' }}
  17. </router-link>
  18. <div class="double-click-btn"><span>点击左侧位置返回</span></div>
  19. </div>
  20. <p><i class="iconfont icon-gongsi" />{{ user.fonds.fondsName }}</p>
  21. </div>
  22. <div class="venue-content">
  23. <div class="tab-content">
  24. <span class="right-top-line" />
  25. <span class="left-bottom-line" />
  26. <div class="gird-data-header">
  27. <ul class="tab-nav">
  28. <li v-for="(item,index) in tabListData" :key="index" class="active-tab-nav">{{ item.name }}<i /></li>
  29. <!-- 最右侧装饰img -->
  30. <span class="tab-right-img" />
  31. </ul>
  32. <!-- <div class="tag-info">
  33. <p class="tag-sort">错序<i class="iconfont icon-zhuangtai2" />1</p>
  34. <p class="tag-place">错架<i class="iconfont icon-zhuangtai2" />1</p>
  35. <p class="tag-all">在架<i class="iconfont icon-zhuangtai2" />20</p>
  36. </div> -->
  37. <div v-if="checkDateLine.length !== 0" class="time-update-cont">
  38. <span class="time-left-txt">最后更新时间</span>
  39. <!-- <el-button class="time-btn-txt">{{ checkDateLine[2].endTime }}</el-button> -->
  40. <el-button>{{ checkDateLine[timeIndex].stockType === 0 ? '现在' : checkDateLine[timeIndex].endTime }}</el-button>
  41. <div class="time-update-line">
  42. <ul class="el-timeline">
  43. <li v-for="(activity, index) in checkDateLine" :key="index" class="el-timeline-item" @click="handleHistory(activity,index)">
  44. <div class="el-timeline-item__tail" />
  45. <div class="el-timeline-item__node el-timeline-item__node--normal" :style="index === timeIndex ? 'background-color: rgb(11, 189, 135);' : ''">
  46. <i v-if="index === timeIndex" class="el-timeline-item__icon el-icon-more" />
  47. </div>
  48. <div class="el-timeline-item__wrapper">
  49. <div class="el-timeline-item__content">
  50. {{ computedStockType(activity.stockType) }}
  51. </div>
  52. <div class="el-timeline-item__timestamp is-bottom">
  53. {{ activity.endTime }}
  54. </div>
  55. </div>
  56. </li>
  57. </ul>
  58. </div>
  59. </div>
  60. <crudOperation :permission="permission">
  61. <template v-slot:middle>
  62. <el-select v-model="layerVal" size="small" placeholder="架位" class="filter-item" style="width: 100px; margin-right: 10px;" @change="changeShelfGetGrid">
  63. <el-option v-for="item in rackOptions" :key="item.id" :label="item.name" :value="item.id" />
  64. </el-select>
  65. <el-button v-permission="permission.add" class="check-btn" size="mini" @click="toAdd(5)">
  66. <i class="iconfont icon-shengchengpandiandan" />
  67. 架位盘点
  68. </el-button>
  69. </template>
  70. <template v-slot:right>
  71. <!-- @click="doExport(crud.selections)" -->
  72. <el-button :loading="crud.downloadLoading" size="mini" @click="doExport(3)">
  73. <i class="iconfont icon-daochu" />
  74. 导出
  75. </el-button>
  76. </template>
  77. </crudOperation>
  78. </div>
  79. <div v-loading="shelfAllGridDataLoading" class="gird-data-book">
  80. <div v-for="(item,index) in shelfAllGridData" :key="index" class="gird-layer">
  81. <span class="gird-left-line" />
  82. <span class="gird-right-line" />
  83. <div class="layer-left">
  84. <div class="layer-left-book">
  85. <div
  86. v-for="(book,i) in item.books"
  87. :key="i"
  88. :class="['book-item', { 'red-active' : book.bookStatus === '错架'} ,{ 'blue-active' : book.bookStatus === '错序'}]"
  89. @mouseenter="showPopover(index, i, $event)"
  90. @mouseleave="hidePopover"
  91. >
  92. <span class="book-name">{{ book.bookName }}</span>
  93. </div>
  94. </div>
  95. </div>
  96. <div class="layer-right-handle">
  97. <div class="layer-info-header">
  98. <h4>{{ item.gridName }}</h4>
  99. <!-- <span>2024-11-28 09:46</span> -->
  100. </div>
  101. <div class="layer-right-content">
  102. <div class="layer-tag-info">
  103. <div class="tag-item tag-sort">错序<i class="iconfont icon-zhuangtai2" /><p>{{ baseStockData.length !==0 && baseStockData[index].errorOrderNum }}</p><span>{{ baseStockData.length !==0 && baseStockData[index].errorOrderProbo }}</span></div>
  104. <div class="tag-item tag-place">错架<i class="iconfont icon-zhuangtai2" /><p>{{ baseStockData.length !==0 &&baseStockData[index].errorShelfNum }}</p><span>{{ baseStockData.length !==0 && baseStockData[index].errorShelfProbo }}</span></div>
  105. <div class="tag-item tag-all">在架<i class="iconfont icon-zhuangtai2" /><p>{{ baseStockData.length !==0 && baseStockData[index].onShelfNum }}</p></div>
  106. </div>
  107. <div class="layer-handle">
  108. <el-button size="mini" @click="handleDetail(item)">
  109. <i class="iconfont icon-xiaowenjian" />
  110. 详情
  111. </el-button>
  112. <el-button size="mini" class="check-btn" @click="toAdd(6,item)">
  113. <i class="iconfont icon-shengchengpandiandan" />
  114. 盘点
  115. </el-button>
  116. </div>
  117. </div>
  118. </div>
  119. </div>
  120. <!-- popover -->
  121. <div
  122. v-if="popoverIndex !== null"
  123. class="popover-external-set"
  124. :style="popoverStyle"
  125. >
  126. <div class="popover-content-set">
  127. <div class="tooltip-top">
  128. <h4>{{ shelfAllGridData[popoverIndex.layer].books[popoverIndex.book].bookName }}</h4>
  129. <span v-if="shelfAllGridData[popoverIndex.layer].books[popoverIndex.book].bookStatus === '错序'" class="tag-item tag-place">错序</span>
  130. <span v-if="shelfAllGridData[popoverIndex.layer].books[popoverIndex.book].bookStatus === '错架'" class="tag-item tag-sort">错架</span>
  131. </div>
  132. <ul>
  133. <li><p>索书号</p><em>{{ shelfAllGridData[popoverIndex.layer].books[popoverIndex.book].sortmark }}</em></li>
  134. <li><p>ISBN</p><em>{{ shelfAllGridData[popoverIndex.layer].books[popoverIndex.book].isbn }}</em></li>
  135. <li><p>著者</p><em>{{ shelfAllGridData[popoverIndex.layer].books[popoverIndex.book].bookAuthor }}</em></li>
  136. <li><p>出版社</p><em>{{ shelfAllGridData[popoverIndex.layer].books[popoverIndex.book].bookPublish }}</em></li>
  137. </ul>
  138. </div>
  139. </div>
  140. </div>
  141. </div>
  142. </div>
  143. <!-- 详情 -->
  144. <el-dialog class="dialog-grid-detail" append-to-body :close-on-click-modal="false" :visible.sync="detailVisible" :title="detailCurrent.gridName +'- 详情'" @close="handleCloseDialog">
  145. <span class="dialog-right-top" />
  146. <span class="dialog-left-bottom" />
  147. <div class="setting-dialog">
  148. <div class="detail-tab tab-content">
  149. <!-- <el-button v-if="detailCurrent && detailCurrent.onShelfNum" class="check-view-img" size="mini" @click="handleViewImg">
  150. <i class="iconfont icon-sulan" />
  151. 盘点照片
  152. </el-button> -->
  153. <div v-if="detailCurrent && detailCurrent.onShelfNum" style="height: 260px; background-color: #ccc; overflow: hidden; position: relative;" @click="handleViewImg">
  154. <img style="display:block; width: 100%;" :src="bigImg" alt="">
  155. <span style="position: absolute; top: 0; right: 0; padding: 4px 6px; color: #fff; background-color: rgba(3,72,243,.8); border-radius: 4px;">单击可查看所有图片</span>
  156. </div>
  157. <ul class="tab-nav">
  158. <li :class="{'active-tab-nav': tabdialogIndex === 0}" @click="changeDialogTab(0)">图书列表</li>
  159. </ul>
  160. <el-table
  161. ref="table"
  162. class="archives-table"
  163. :data="detailTable"
  164. style="width: 100%;"
  165. height="calc(100vh - 560px)"
  166. >
  167. <el-table-column type="index" label="序号" width="55" align="center" />
  168. <el-table-column prop="bookName" label="题名" min-width="110" show-overflow-tooltip />
  169. <el-table-column prop="isbn" label="ISBN" />
  170. <el-table-column prop="sortmark" label="索书号" />
  171. <el-table-column prop="barcode" label="条码" />
  172. <el-table-column prop="floorName" label="所在位置" min-width="160">
  173. <template slot-scope="scope">
  174. <span>
  175. {{ getLocation(scope.row) }}
  176. </span>
  177. </template>
  178. </el-table-column>
  179. <el-table-column prop="bookStatus" label="盘点结果" align="center">
  180. <template slot-scope="scope">
  181. <span v-if="scope.row.bookStatus === '未知'" class="row-state row-warehousing">未知</span>
  182. <span v-if="scope.row.bookStatus === '在架'" class="row-state row-binding state-active">在架</span>
  183. <span v-if="scope.row.bookStatus === '错架'" class="row-state row-lending state-active">错架</span>
  184. <span v-if="scope.row.bookStatus === '错序'" class="row-state row-physical state-active">错序</span>
  185. </template>
  186. </el-table-column>
  187. <!-- <el-table-column prop="updateTime" label="盘点时间">
  188. <template slot-scope="scope">
  189. <div>{{ scope.row.updateTime | parseTime }}</div>
  190. </template>
  191. </el-table-column> -->
  192. </el-table>
  193. </div>
  194. </div>
  195. </el-dialog>
  196. <el-dialog class="gird-img-detail" append-to-body :close-on-click-modal="false" :visible.sync="detailImgVisible">
  197. <span class="dialog-right-top" />
  198. <span class="dialog-left-bottom" />
  199. <div class="gird-img-button">
  200. <el-button size="mini" :loading="downImgLoading" :disabled="downImgLoading" @click="handleDownloadImg">
  201. <i class="iconfont icon-xiazai" />
  202. 下载
  203. </el-button>
  204. <el-button size="mini" @click="handleCloseImgDialog">
  205. <i class="iconfont icon-guanbixiao" />
  206. 关闭
  207. </el-button>
  208. </div>
  209. <div class="setting-dialog">
  210. <el-carousel ref="carousel" indicator-position="outside" :autoplay="false" @setActiveItem="setActiveItem">
  211. <el-carousel-item v-for="item in bookImgData" :key="item">
  212. <img :src="item" alt="">
  213. </el-carousel-item>
  214. </el-carousel>
  215. </div>
  216. </el-dialog>
  217. <eForm ref="eform" />
  218. <exportForm ref="exportform" export-type="grid" />
  219. </div>
  220. </template>
  221. <script>
  222. import { FetchInitStockInfo, FetchInitBookDetailsByGrids, FetchBillByShelfIdAndGridShelf, FetchIsGoodcutByBillNoAndGridId, FetchShowByBillIdAndShelfIdAndGridShelf } from '@/api/stockTask/index'
  223. import { dataScreeningCrud } from '@/views/visualCheck/mixins/index'
  224. import { FetchBookShelfDetails, FetchShelfGridByShelfIdAndGridShelf } from '@/api/shelf/index'
  225. import crudRegion from '@/api/area/index'
  226. import CRUD, { presenter, header, crud } from '@crud/crud'
  227. import crudOperation from '@crud/CRUD.operation'
  228. import { mapGetters } from 'vuex'
  229. import eForm from './module/form'
  230. import exportForm from './module/export'
  231. import { parseTime, saveAs, getBlob } from '@/utils/index'
  232. export default {
  233. name: 'DataScreening',
  234. components: { crudOperation, eForm, exportForm },
  235. cruds() {
  236. return CRUD({ title: '架位盘点', url: 'api/libraryRegion/initLibraryRegionList', crudMethod: { ...crudRegion }, sort: [], optShow: {
  237. add: false,
  238. edit: false,
  239. del: false,
  240. download: false,
  241. group: false,
  242. reset: false
  243. },
  244. queryOnPresenterCreated: false
  245. })
  246. },
  247. mixins: [presenter(), header(), crud(), dataScreeningCrud],
  248. data() {
  249. return {
  250. activeIndex: 0,
  251. downImgLoading: false,
  252. detailVisible: false,
  253. detailImgVisible: false,
  254. detailTable: [],
  255. detailCurrent: {},
  256. tabdialogIndex: 0,
  257. listLoading: false,
  258. tabIndex: 0,
  259. floorTabIndex: 0,
  260. regionTabIndex: 0,
  261. floorName: null,
  262. floorId: null,
  263. regionName: null,
  264. regionId: null,
  265. gridRow: null,
  266. gridShelf: null,
  267. bookShelfDetails: null,
  268. booShelfGrid: null,
  269. shelfAllGridData: [],
  270. layerNum: 0,
  271. rackNum: 0,
  272. bookNum: 46,
  273. layerVal: null,
  274. rackOptions: [],
  275. tabListData: [],
  276. permission: {
  277. add: ['admin', 'floor:add'],
  278. edit: ['admin', 'floor:edit'],
  279. del: ['admin', 'floor:del']
  280. },
  281. popoverIndex: null,
  282. popoverVisible: [],
  283. popoverStyles: [],
  284. currentBookName: '', // 当前书籍的名称
  285. popoverPosition: { x: 0, y: 0 }, // Popover的位置
  286. checkDateLine: [],
  287. baseStockData: [],
  288. shelfAllGridDataLoading: false,
  289. billNoImg: null,
  290. bookImgData: [],
  291. bigImg: '',
  292. timeIndex: 0,
  293. gridName: '',
  294. getGridToward: 1
  295. }
  296. },
  297. computed: {
  298. ...mapGetters([
  299. 'user',
  300. 'baseApi'
  301. ]),
  302. swiperContent() {
  303. return this.$refs.swiperContent.$el.swiper
  304. },
  305. swiperTitle() {
  306. return this.$refs.swiperTitle.$el.swiper
  307. },
  308. cellStyle: function() {
  309. const h = '76px'
  310. const w = '100%/' + this.rackNum
  311. return { width: `calc(${w} )`, height: `calc(${h})` }
  312. },
  313. popoverStyle() {
  314. return {
  315. top: `${this.popoverPosition.y - 300}px`, // 鼠标的Y坐标偏移10px
  316. left: `${this.popoverPosition.x - 240}px`, // 鼠标的X坐标偏移10px
  317. position: 'absolute'
  318. }
  319. }
  320. },
  321. async created() {
  322. this.initData()
  323. },
  324. methods: {
  325. [CRUD.HOOK.beforeRefresh]() {
  326. },
  327. [CRUD.HOOK.afterRefresh](crud) {
  328. },
  329. // 提交前的验证
  330. [CRUD.HOOK.afterValidateCU](crud) {
  331. return true
  332. },
  333. computedStockType(stockType) {
  334. switch (stockType) {
  335. case 1:
  336. return '全量盘点'
  337. case 2:
  338. return '区域盘点'
  339. case 3:
  340. return '计划盘点'
  341. case 4:
  342. return '书架盘点'
  343. case 5:
  344. return '架位盘点'
  345. case 6:
  346. return '层位盘点'
  347. default:
  348. return '现在'
  349. }
  350. },
  351. initData() {
  352. if (localStorage.getItem('dataScreenFloorTableIndex')) {
  353. this.floorTabIndex = localStorage.getItem('dataScreenFloorTableIndex')
  354. }
  355. if (localStorage.getItem('dataScreenRegionTableIndex')) {
  356. this.regionTabIndex = localStorage.getItem('dataScreenRegionTableIndex')
  357. }
  358. if (localStorage.getItem('dataScreenShelf')) {
  359. const dataScreenShelf = JSON.parse(localStorage.getItem('dataScreenShelf'))
  360. this.floorName = dataScreenShelf.floorName
  361. this.regionName = dataScreenShelf.regionName
  362. this.gridName = dataScreenShelf.gridName
  363. this.gridRow = dataScreenShelf.gridRow
  364. this.gridShelf = dataScreenShelf.gridShelf
  365. if (localStorage.getItem('dataScreenShelfAllGrid')) {
  366. this.shelfAllGridData = JSON.parse(localStorage.getItem('dataScreenShelfAllGrid'))
  367. }
  368. // 单面/双面
  369. this.tabListData = [{ name: dataScreenShelf.regionName + ' - ' + this.removeAreaPrefix(dataScreenShelf.gridName) }]
  370. // dataScreenShelf.rowType === 1
  371. // ? dataScreenShelf.toward === 1
  372. // ? [{ name: 'A面' }]
  373. // : [{ name: 'B面' }]
  374. // : [{ name: 'A面' }, { name: 'B面' }]
  375. this.tabIndex = dataScreenShelf.toward - 1
  376. FetchBookShelfDetails({ 'shelfId': dataScreenShelf.shelfId }).then(res => {
  377. this.layerNum = res.shelfFloor
  378. this.rackNum = res.shelfShelf
  379. this.floorId = res.floorId
  380. this.regionId = res.regionId
  381. this.bookShelfDetails = res
  382. this.rackOptions = []
  383. for (let i = 1; i <= this.rackNum; i++) {
  384. this.rackOptions.push({ id: i, name: `0${i}` })
  385. }
  386. this.layerVal = parseInt(this.gridShelf) || ''
  387. this.getInitStockInfo(this.shelfAllGridData)
  388. this.getInitBookDetailsByGrids(this.shelfAllGridData)
  389. this.getBillByShelfIdAndGridShelf(this.shelfAllGridData)
  390. }).catch(() => {
  391. })
  392. }
  393. },
  394. removeAreaPrefix(gridNames) {
  395. const index = gridNames.indexOf('面')
  396. if (index !== -1) {
  397. return gridNames.substring(0, index + 1)
  398. }
  399. return gridNames
  400. },
  401. getLocation(row) {
  402. const parts = []
  403. if (row.floorName) {
  404. parts.push(row.floorName)
  405. }
  406. if (row.regionName) {
  407. parts.push(row.regionName)
  408. }
  409. if (row.gridName) {
  410. parts.push(row.gridName)
  411. }
  412. return parts.length > 0 ? parts.join('-') : '-'
  413. },
  414. getBillByShelfIdAndGridShelf(data) {
  415. const params = {
  416. 'gridShelf': data[0].gridShelf,
  417. 'ShelfId': data[0].shelfId,
  418. 'size': 5
  419. }
  420. FetchBillByShelfIdAndGridShelf(params).then(res => {
  421. if (res !== null) {
  422. this.checkDateLine = res.sort((a, b) => {
  423. return new Date(b.endTime) - new Date(a.endTime)
  424. })
  425. this.checkDateLine.unshift({
  426. stockType: 0,
  427. icon: 'el-icon-more',
  428. color: '#0bbd87'
  429. })
  430. this.billNoImg = this.checkDateLine[this.timeIndex].stockType === 0 ? this.checkDateLine[1].stockBill : this.checkDateLine[this.timeIndex].stockBill
  431. } else {
  432. this.checkDateLine = []
  433. }
  434. }).catch(() => {
  435. })
  436. },
  437. async getInitStockInfo(data) {
  438. const promises = data.map(item => {
  439. const params = {
  440. 'floorId': this.floorId,
  441. 'regionId': this.regionId,
  442. 'shelfId': item.shelfId,
  443. 'gridId': item.id
  444. }
  445. return FetchInitStockInfo(params)
  446. })
  447. const results = await Promise.all(promises)
  448. if (!Array.isArray(this.baseStockData)) {
  449. this.baseStockData = []
  450. }
  451. this.baseStockData = this.baseStockData.concat(results)
  452. },
  453. getInitBookDetailsByGrids(data) {
  454. const ids = data.map(item => item.id)
  455. const params = {
  456. 'grids': ids.join(',')
  457. }
  458. FetchInitBookDetailsByGrids(params).then(res => {
  459. this.shelfAllGridData.forEach((item) => {
  460. const gridId = item.id
  461. if (res.hasOwnProperty(gridId)) {
  462. this.$set(item, 'books', res[gridId])
  463. }
  464. })
  465. }).catch(() => {
  466. })
  467. },
  468. toAdd(type, item) {
  469. if (type === 5) {
  470. this.$refs.eform.formVisible = true
  471. this.$refs.eform.form.shelfId = this.bookShelfDetails.id
  472. this.$refs.eform.form.gridShelf = this.gridShelf
  473. this.$refs.eform.form.stockRegion = this.floorName + this.regionName + this.bookShelfDetails.shelfName + this.gridShelf + '架'
  474. } else {
  475. if (item.isCheck) {
  476. this.$refs.eform.formVisible = true
  477. this.$refs.eform.form.shelfId = null
  478. this.$refs.eform.form.gridShelf = null
  479. this.$refs.eform.form.gridId = item.id
  480. this.$refs.eform.form.stockRegion = item.gridName
  481. } else {
  482. this.$message({ message: '当前层位不可盘点', type: 'error', offset: 8 })
  483. }
  484. }
  485. this.$refs.eform.setData(type)
  486. },
  487. doExport(type) {
  488. this.$refs.exportform.formExportVisible = true
  489. this.$refs.exportform.type = 3
  490. this.$refs.exportform.params = {
  491. // 'floorId': this.floorId,
  492. // 'regionId': this.regionId,
  493. 'shelfId': this.bookShelfDetails.id
  494. }
  495. },
  496. handleCellCurrent(item, index) {
  497. this.cellIndex = index
  498. this.cellInfo = {
  499. id: item.id,
  500. gridName: item.gridName,
  501. startSortmark: item.startSortmark,
  502. endSortmark: item.endSortmark,
  503. cameraId: item.cameraId,
  504. check: item.isCheck,
  505. order: item.isOrder
  506. }
  507. this.handleToGrids(this.cellInfo)
  508. },
  509. handleDetail(item) {
  510. this.detailVisible = true
  511. this.detailTable = item.books
  512. this.detailCurrent = item
  513. if (this.detailCurrent.onShelfNum) {
  514. this.bigImg = `${this.baseApi}/api/fileRelevant/getImg?imgType=1&imgId=/${this.libcode}/${this.billNoImg}/${this.detailCurrent.gridCode}/img_result/result_LSD_compressed.jpg`
  515. } else {
  516. this.bigImg = ''
  517. }
  518. },
  519. setActiveItem(index) {
  520. this.$refs.carousel.setActiveItem(index)
  521. },
  522. handleViewImg() {
  523. // /PD20250102001/040011011/img_result/result_cut_1.jpg
  524. // /PD20250102001/040011011/img_result/result_cut_2.jpg
  525. // /PD20250102001/040011011/img_result/result_cut_3.jpg
  526. // http://192.168.99.67:12010/api/fileRelevant/getImg?imgType=1&imgId=/ceshi111/1_1_book_spine-0.png
  527. // http://192.168.99.67:12010/api/fileRelevant/getImg?imgType=1&imgId=/1501/PD20250108013/010011015/img_result/result_LSD.jpg
  528. // http://192.168.99.67:12010/api/fileRelevant/getImg?imgType=1&imgId=/1501/PD20250108013/010011015/img_result/result_cut_1_compressed.jpg
  529. this.bookImgData = []
  530. this.detailImgVisible = true
  531. const params = {
  532. 'billNo': this.billNoImg,
  533. 'gridId': this.detailCurrent.id
  534. }
  535. FetchIsGoodcutByBillNoAndGridId(params)
  536. .then(res => {
  537. const baseUrl = `${this.baseApi}/api/fileRelevant/getImg?imgType=1&imgId=/${this.libcode}/${this.billNoImg}/${this.detailCurrent.gridCode}/img_result/`
  538. const commonImgs = [
  539. `${baseUrl}result_LSD_compressed.jpg`,
  540. `${baseUrl}result_cut_1_compressed.jpg`,
  541. `${baseUrl}result_cut_2_compressed.jpg`
  542. ]
  543. this.$refs.carousel.setActiveItem(0)
  544. if (res) {
  545. this.bookImgData = commonImgs
  546. } else {
  547. this.bookImgData = [...commonImgs, `${baseUrl}result_cut_3_compressed.jpg`]
  548. }
  549. })
  550. .catch(error => {
  551. console.error(error)
  552. })
  553. },
  554. handleDownloadImg() {
  555. this.downImgLoading = true
  556. const idsArray = []
  557. for (const url of this.bookImgData) {
  558. const startIndex = url.indexOf('imgId=') + 'imgId='.length
  559. const endIndex = url.length
  560. idsArray.push(url.slice(startIndex, endIndex))
  561. }
  562. // 下载桶图片
  563. const params = {
  564. 'imgIds': idsArray
  565. }
  566. const url = this.baseApi + '/api/fileRelevant/uploadImgs' + '?' + new URLSearchParams(params).toString()
  567. getBlob(url, (blob) => {
  568. const fileName = this.billNoImg + '-' + parseTime(new Date()) + '.zip'
  569. saveAs(blob, fileName)
  570. this.downImgLoading = false
  571. })
  572. },
  573. handleCloseDialog() {
  574. this.detailVisible = false
  575. },
  576. handleCloseImgDialog() {
  577. this.detailImgVisible = false
  578. this.activeIndex = 0
  579. },
  580. handleToGrids(data) {
  581. this.$router.push({ path: '/dataScreening/gird' })
  582. localStorage.setItem('dataScreenShelf', JSON.stringify(data))
  583. },
  584. showPopover(layerIndex, bookIndex, event) {
  585. this.popoverIndex = { layer: layerIndex, book: bookIndex }
  586. const bookElement = event.target // 获取书籍项元素
  587. const rect = bookElement.getBoundingClientRect() // 获取边界
  588. if (layerIndex === 0) {
  589. this.popoverPosition = {
  590. x: window.scrollX + rect.left + rect.width / 2 - 40,
  591. y: window.scrollY + rect.top + rect.height
  592. }
  593. } else {
  594. this.popoverPosition = {
  595. x: window.scrollX + rect.left + rect.width / 2 - 40,
  596. y: window.scrollY + rect.top + rect.height - 170
  597. }
  598. }
  599. },
  600. hidePopover() {
  601. this.popoverIndex = null
  602. // 隐藏所有的popover
  603. // this.popoverVisible.forEach((isVisible, index) => {
  604. // if (isVisible) {
  605. // this.$set(this.popoverVisible, index, false)
  606. // }
  607. // })
  608. },
  609. changeDialogTab(index) {
  610. this.tabdialogIndex = index
  611. },
  612. updateParts(gridName) {
  613. const parts = gridName.match(/(\d+)区(\d+)排([A-Za-z])面(\d+)架(\d+)层/)
  614. if (parts) {
  615. this.getGridShelf = parts[4]
  616. this.getGridFloor = parts[5]
  617. const toward = parts[3]
  618. if (toward === 'A') {
  619. this.getGridToward = 1
  620. } else if (toward === 'B') {
  621. this.getGridToward = 2
  622. }
  623. }
  624. },
  625. changeShelfGetGrid(val) {
  626. this.updateParts(this.gridName)
  627. this.shelfAllGridDataLoading = true
  628. const params = {
  629. 'gridShelf': '0' + val,
  630. 'shelfId': this.bookShelfDetails.id,
  631. 'toward': this.getGridToward,
  632. 'floorType': this.bookShelfDetails.floorType
  633. }
  634. FetchShelfGridByShelfIdAndGridShelf(params).then(res => {
  635. this.shelfAllGridData = []
  636. this.shelfAllGridData = res
  637. this.getInitStockInfo(this.shelfAllGridData)
  638. this.getInitBookDetailsByGrids(this.shelfAllGridData)
  639. this.shelfAllGridDataLoading = false
  640. }).catch(() => {
  641. })
  642. },
  643. handleHistory(item, index) {
  644. this.shelfAllGridDataLoading = true
  645. this.timeIndex = index
  646. this.billNoImg = this.checkDateLine[this.timeIndex].stockType === 0 ? this.checkDateLine[1].stockBill : this.checkDateLine[this.timeIndex].stockBill
  647. if (item.stockType === 0) {
  648. this.initData()
  649. setTimeout(() => {
  650. this.shelfAllGridDataLoading = false
  651. }, 500)
  652. } else {
  653. const params = {
  654. 'gridShelf': '0' + this.layerVal,
  655. 'ShelfId': this.bookShelfDetails.id,
  656. 'toward': this.bookShelfDetails.toward,
  657. 'billId': item.stockBill
  658. }
  659. FetchShowByBillIdAndShelfIdAndGridShelf(params).then(res => {
  660. this.shelfAllGridData.forEach((item) => {
  661. console.log(item.id)
  662. const gridId = item.id
  663. if (res.hasOwnProperty(gridId)) {
  664. this.$set(item, 'books', res.gridShelfList[gridId])
  665. }
  666. })
  667. const sortedKeys = Object.keys(res.gridShelfList).sort()
  668. const sortedShelfDetails = []
  669. sortedKeys.forEach(key => {
  670. res.shelfDetails.forEach(shelfDetail => {
  671. if (shelfDetail.gridId === key) {
  672. sortedShelfDetails.push(shelfDetail)
  673. }
  674. })
  675. })
  676. this.baseStockData = sortedShelfDetails
  677. setTimeout(() => {
  678. this.shelfAllGridDataLoading = false
  679. }, 500)
  680. }).catch(() => {
  681. })
  682. }
  683. }
  684. }
  685. }
  686. </script>
  687. <style lang="scss" scoped>
  688. .venue-content{
  689. position: relative;
  690. padding: 20px;
  691. background-color: #fff;
  692. }
  693. .tab-content{
  694. width: 100%;
  695. min-height: calc(100vh - 232px) !important;
  696. .tab-nav{
  697. flex: 1;
  698. }
  699. }
  700. .gird-data-header{
  701. display: flex;
  702. justify-content: space-between;
  703. }
  704. .tag-info{
  705. display: flex;
  706. justify-content: flex-start;
  707. align-items: center;
  708. padding: 0 20px;
  709. p{
  710. margin-left: 20px;
  711. font-size: 14px;
  712. font-weight: bold;
  713. }
  714. }
  715. .time-update-cont{
  716. position: relative;
  717. display: flex;
  718. justify-content: flex-start;
  719. align-items: center;
  720. padding: 0 20px;
  721. span.time-left-txt{
  722. font-size: 14px;
  723. }
  724. .el-button{
  725. width: 134px;
  726. padding:5px;
  727. border: none;
  728. text-align: left;
  729. }
  730. .time-update-line{
  731. display: none;
  732. position: absolute;
  733. top: 33px;
  734. right: 20px;
  735. z-index: 9999;
  736. width: 250px;
  737. max-height: 645px;
  738. padding: 20px 30px;
  739. background-color: #fff;
  740. border: 1px solid #e8f2ff;
  741. border-radius: 10px;
  742. -webkit-box-shadow: 0 2px 12px 0 rgba(0, 0, 0, .5);
  743. box-shadow: 0 2px 12px 0 rgba(0, 0, 0, .5);
  744. overflow: hidden;
  745. overflow-y: scroll;
  746. }
  747. }
  748. .time-update-cont:hover .time-update-line {
  749. display: block;
  750. }
  751. .gird-data-book{
  752. position: relative;
  753. height: 650px;
  754. margin-top: 4px;
  755. overflow: hidden;
  756. overflow-y: scroll;
  757. }
  758. .gird-layer{
  759. position: relative;
  760. display: flex;
  761. justify-content: space-between;
  762. .gird-left-line{
  763. position: absolute;
  764. left: 0;
  765. top: 0;
  766. display: block;
  767. width: 6px;
  768. height: 130px;
  769. background: url('~@/assets/images/shelf01.png') no-repeat left top;
  770. background-size: 100% 100%;
  771. z-index: 999;
  772. }
  773. .gird-right-line{
  774. position: absolute;
  775. right: calc(298px);
  776. top: 0;
  777. display: block;
  778. width: 6px;
  779. height: 130px;
  780. background: url('~@/assets/images/shelf01.png') no-repeat left top;
  781. background-size: 100% 100%;
  782. z-index: 999;
  783. }
  784. .layer-left{
  785. width: calc(100% - 240px);
  786. height: 130px;
  787. margin-right: 5px;
  788. padding: 0 16px 0 20px;
  789. background: url('~@/assets/images/shelf02.png') repeat left top;
  790. background-size: 10% 100%;
  791. overflow: hidden;
  792. overflow-x: scroll;
  793. }
  794. .layer-left-book{
  795. // width: calc(100vw - 655px);
  796. height: 130px;
  797. white-space: nowrap;
  798. .book-item{
  799. position: relative;
  800. display: inline-block;
  801. width: 42px;
  802. height: 120px;
  803. margin-top: 18px;
  804. background: url('~@/assets/images/shelf03.png') no-repeat left top;
  805. background-size: 100% 100%;
  806. margin-left: -15px;
  807. cursor: pointer;
  808. span.book-name{
  809. position: absolute;
  810. left: 15px;
  811. top: 16px;
  812. display: block;
  813. height: 90px;
  814. font-size: 12px;
  815. writing-mode:vertical-rl;
  816. overflow: hidden;
  817. white-space: nowrap;
  818. text-overflow: ellipsis;
  819. }
  820. &.red-active{
  821. background: url('~@/assets/images/shelf05.png') no-repeat left top;
  822. background-size: 100% 100%;
  823. }
  824. &.blue-active{
  825. background: url('~@/assets/images/shelf06.png') no-repeat left top;
  826. background-size: 100% 100%;
  827. }
  828. }
  829. }
  830. }
  831. .layer-right-handle{
  832. width: 300px;
  833. padding: 0 10px;
  834. background-color: #E8F2FF;
  835. margin: 3px 5px;
  836. border-radius: 6px;
  837. }
  838. .layer-info-header{
  839. display: flex;
  840. justify-content: space-between;
  841. align-items: center;
  842. line-height: 30px;
  843. h4{
  844. color: #0c0e1e;
  845. }
  846. span{
  847. font-size: 12px;
  848. }
  849. }
  850. .layer-right-content{
  851. display: flex;
  852. justify-content: space-between;
  853. }
  854. .layer-tag-info{
  855. div.tag-item {
  856. display: flex;
  857. justify-content: flex-start;
  858. line-height: 26px;
  859. font-size: 14px;
  860. }
  861. }
  862. .layer-handle{
  863. display: flex;
  864. flex-direction: column;
  865. .el-button{
  866. margin-left: 0 !important;
  867. margin-bottom: 10px
  868. }
  869. }
  870. .dialog-grid-detail{
  871. ::v-deep .el-dialog{
  872. width: 1200px !important;
  873. .el-dialog__body{
  874. padding: 0 !important;
  875. }
  876. .tab-nav{
  877. margin: 14px 0 10px 0 !important;
  878. }
  879. }
  880. .detail-tab{
  881. position: relative;
  882. }
  883. .check-view-img{
  884. position: absolute;
  885. right: 0;
  886. top: -10px;
  887. }
  888. }
  889. .gird-img-detail{
  890. ::v-deep .el-dialog{
  891. width: 1200px !important;
  892. padding: 0 !important;
  893. background: none;
  894. box-shadow: none;
  895. .el-dialog__header{
  896. display: none;
  897. }
  898. .el-dialog__body{
  899. padding: 0 !important;
  900. }
  901. }
  902. ::v-deep .el-carousel__container{
  903. height: 600px !important;
  904. .el-carousel__item{
  905. display: flex;
  906. align-items: center;
  907. }
  908. .el-carousel__item img{
  909. display: block;
  910. max-width: 100%;
  911. max-height: 100%;
  912. margin: 0 auto;
  913. }
  914. .el-carousel__arrow{
  915. background-color: rgba(3,72,243,1);
  916. i.el-icon-arrow-left,
  917. i.el-icon-arrow-right{
  918. color: #fff;
  919. }
  920. .el-icon-arrow-right:before{
  921. color: #fff;
  922. }
  923. }
  924. }
  925. ::v-deep .el-carousel__button{
  926. height: 6px !important;
  927. }
  928. ::v-deep .el-carousel__indicators--outside button{
  929. background-color: rgba(3,72,243,1);
  930. }
  931. .gird-img-button{
  932. position: fixed;
  933. right: -200px;
  934. top: -60px;
  935. display: flex;
  936. justify-content: flex-start;
  937. align-items: center;
  938. z-index: 9999999;
  939. .el-button{
  940. background-color: #e8f2ff;
  941. }
  942. }
  943. }
  944. .venue-content {
  945. .tab-content .tab-nav {
  946. li{
  947. cursor: default;
  948. }
  949. }
  950. }
  951. .popover-external-set{
  952. ul li p{
  953. width: 50px;
  954. font-weight: bold;
  955. text-align: right;
  956. }
  957. ul li span,
  958. ul li em{
  959. width: 140px;
  960. display: block;
  961. text-align: right;
  962. font-style: normal;
  963. }
  964. }
  965. </style>