江夏区图书馆自助查询机
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.

577 lines
19 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
  1. <template>
  2. <div class="content-main">
  3. <Search refs="searchRefs" search-type="noList" />
  4. <div class="box-style" style="margin: 30px 44px;">
  5. <div class="dataScreening-header">
  6. <h4 class="filter-header">架位总览</h4>
  7. <div class="bookshelf-area">
  8. <!-- <span class="bookshelf-area">{{ floorName }} - {{ regionName }} - {{ gridRow +'排' }}</span> -->
  9. <!-- <router-link :to="{ path: '/', query: {floorTabIndex: floorTabIndex }}">
  10. {{ floorName }}
  11. </router-link>
  12. <span>/</span>
  13. <router-link :to="{ path: '/regions', query: {regionTabIndex: regionTabIndex }}">
  14. {{ regionName }}
  15. </router-link>
  16. <span>/</span>
  17. <router-link :to="{ path: '/shelf', query: {tabIndex: tabIndex }}">
  18. {{ gridRow +'排' }}
  19. </router-link>
  20. <div class="double-click-btn"><span>点击左侧位置返回</span></div> -->
  21. <router-link :to="{ path: '/shelf', query: {tabIndex: tabIndex }}">
  22. <i class="iconfont icon-huifu" />返回
  23. </router-link>
  24. </div>
  25. </div>
  26. <div class="tab-content">
  27. <ul class="tab-nav">
  28. <li v-for="(item,index) in tabListData" :key="index" class="active-tab-nav">{{ item.name }}<i /></li>
  29. </ul>
  30. <div v-loading="shelfAllGridDataLoading" class="gird-data-book">
  31. <div v-for="(item,index) in shelfAllGridData" :key="index" class="gird-layer">
  32. <span class="gird-left-line" />
  33. <span class="gird-right-line" />
  34. <div class="layer-left">
  35. <div class="layer-left-book">
  36. <!-- <div
  37. v-for="(book,i) in item.books"
  38. :key="i"
  39. :class="['book-item', { 'red-active' : book.bookStatus === '错架'} ,{ 'blue-active' : book.bookStatus === '错序'}]"
  40. @touchstart="handleTouchStart(index, i, $event)"
  41. @touchmove="handleTouchMove(index, i, $event)"
  42. @touchend="handleTouchEnd(index, i, $event)"
  43. >
  44. <span class="book-name">{{ book.bookName }}</span>
  45. </div> -->
  46. <!-- @touchstart="handleTouchStart(index, i, book, $event)" -->
  47. <div :class="['swiper'+index,'rack-box-list']">
  48. <div class="swiper-wrapper">
  49. <div v-for="book in item.books" :key="book.id" :class="['list-item swiper-slide', { 'red-active' : book.bookStatus === '错架'} ,{ 'blue-active' : book.bookStatus === '错序'}]" @click="getBookDetaisByBookRecNo(book)">
  50. <span class="book-name">{{ book.bookName }}</span>
  51. </div>
  52. </div>
  53. </div>
  54. </div>
  55. </div>
  56. <div class="layer-right-handle">
  57. <div class="layer-info-header">
  58. <h4>{{ item.gridName }}</h4>
  59. <!-- <span>2024-11-28 09:46</span> -->
  60. </div>
  61. <div class="layer-right-content">
  62. <div class="layer-tag-info">
  63. <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>
  64. <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>
  65. <div class="tag-item tag-all">在架<i class="iconfont icon-zhuangtai2" /><p>{{ baseStockData.length !==0 && baseStockData[index].onShelfNum }}</p></div>
  66. </div>
  67. </div>
  68. </div>
  69. </div>
  70. <!-- popover -->
  71. <div
  72. v-if="popoverIndex !== null"
  73. class="popover-external-set"
  74. :style="popoverStyle"
  75. >
  76. <div class="popover-content-set">
  77. <div class="tooltip-top">
  78. <h4>{{ shelfAllGridData[popoverIndex.layer].books[popoverIndex.book].bookName }}</h4>
  79. <span v-if="shelfAllGridData[popoverIndex.layer].books[popoverIndex.book].bookStatus === '错序'" class="tag-item tag-place">错序</span>
  80. <span v-if="shelfAllGridData[popoverIndex.layer].books[popoverIndex.book].bookStatus === '错架'" class="tag-item tag-sort">错架</span>
  81. </div>
  82. <ul>
  83. <li><p>索书号</p><em>{{ shelfAllGridData[popoverIndex.layer].books[popoverIndex.book].sortmark }}</em></li>
  84. <li><p>ISBN</p><em>{{ shelfAllGridData[popoverIndex.layer].books[popoverIndex.book].isbn }}</em></li>
  85. <li><p>著者</p><em>{{ shelfAllGridData[popoverIndex.layer].books[popoverIndex.book].bookAuthor }}</em></li>
  86. <li><p>出版社</p><em>{{ shelfAllGridData[popoverIndex.layer].books[popoverIndex.book].bookPublish }}</em></li>
  87. </ul>
  88. </div>
  89. </div>
  90. </div>
  91. <!-- <ul class="change-layer">
  92. <li v-for="(item,index) in rackOptions" :key="index" :class="{ 'active': layerVal === index+1 }" @click="changeShelfGetGrid(parseInt(item.name))">{{ item.name }}</li>
  93. </ul> -->
  94. <swiper
  95. ref="swiperTitleLayer"
  96. class="swiper-title layerShelf-swiper"
  97. :options="swiperOptionTitlelayer"
  98. :auto-update="true"
  99. :auto-destroy="true"
  100. >
  101. <swiper-slide
  102. v-for="(item,index) in rackOptions"
  103. :key="index"
  104. ref="swiperSlideItem"
  105. class="swiper-slide-title"
  106. >
  107. <div
  108. class="tab-name"
  109. :class="{ active: layerVal === index+1 }"
  110. @click="changeShelfGetGrid(parseInt(item.name))"
  111. >
  112. {{ item.name }}
  113. </div>
  114. </swiper-slide>
  115. </swiper>
  116. </div>
  117. </div>
  118. <BookDetails ref="bookDetailsRef" />
  119. </div>
  120. </template>
  121. <script>
  122. import { FetchShelfGridByShelfIdAndGridShelf, FetchBillByShelfIdAndGridShelf, FetchBookShelfDetails, FetchInitStockInfo, FetchInitBookDetailsByGrids, FetchBookDetaisByBookRecNo } from '@/api/inquiryMachine'
  123. import { positionCrud } from './mixins/index.js'
  124. import Search from './module/search'
  125. import BookDetails from './module/bookDetails'
  126. import { Swiper, swiper, swiperSlide } from 'vue-awesome-swiper'
  127. import 'swiper/swiper-bundle.css'
  128. export default {
  129. name: 'Index',
  130. components: {
  131. Search,
  132. BookDetails,
  133. swiper,
  134. swiperSlide
  135. },
  136. mixins: [positionCrud],
  137. data() {
  138. return {
  139. activeIndex: 0,
  140. detailVisible: false,
  141. detailTable: [],
  142. detailCurrent: {},
  143. tabdialogIndex: 0,
  144. listLoading: false,
  145. tabIndex: 0,
  146. floorTabIndex: 0,
  147. regionTabIndex: 0,
  148. floorName: null,
  149. floorId: null,
  150. regionName: null,
  151. regionId: null,
  152. gridRow: null,
  153. gridShelf: null,
  154. bookShelfDetails: null,
  155. booShelfGrid: null,
  156. shelfAllGridData: [],
  157. layerNum: 0,
  158. rackNum: 0,
  159. bookNum: 46,
  160. layerVal: null,
  161. rackOptions: [],
  162. tabListData: [],
  163. popoverIndex: null,
  164. popoverVisible: [],
  165. popoverStyles: [],
  166. popoverPosition: { x: 0, y: 0 }, // Popover的位置
  167. baseStockData: [],
  168. shelfAllGridDataLoading: false,
  169. billNoImg: null,
  170. bigImg: '',
  171. gridName: '',
  172. getGridToward: 1,
  173. swiperOptionTitlelayer: {
  174. slidesPerView: 'auto',
  175. freeMode: true
  176. }
  177. }
  178. },
  179. computed: {
  180. swiperTitleLayer() {
  181. return this.$refs.swiperTitleLayer.$el.swiper
  182. },
  183. cellStyle: function() {
  184. const h = '76px'
  185. const w = '100%/' + this.rackNum
  186. return { width: `calc(${w} )`, height: `calc(${h})` }
  187. },
  188. popoverStyle() {
  189. return {
  190. top: `${this.popoverPosition.y - 300}px`, // 鼠标的Y坐标偏移10px
  191. left: `${this.popoverPosition.x - 240}px`, // 鼠标的X坐标偏移10px
  192. position: 'absolute'
  193. }
  194. }
  195. },
  196. created() {
  197. if (localStorage.getItem('dataScreenFloorTableIndex')) {
  198. this.floorTabIndex = localStorage.getItem('dataScreenFloorTableIndex')
  199. }
  200. if (localStorage.getItem('dataScreenRegionTableIndex')) {
  201. this.regionTabIndex = localStorage.getItem('dataScreenRegionTableIndex')
  202. }
  203. if (localStorage.getItem('dataScreenShelf')) {
  204. const dataScreenShelf = JSON.parse(localStorage.getItem('dataScreenShelf'))
  205. this.floorName = dataScreenShelf.floorName
  206. this.regionName = dataScreenShelf.regionName
  207. this.gridName = dataScreenShelf.gridName
  208. this.gridRow = dataScreenShelf.gridRow
  209. this.gridShelf = dataScreenShelf.gridShelf
  210. if (localStorage.getItem('dataScreenShelfAllGrid')) {
  211. this.shelfAllGridData = JSON.parse(localStorage.getItem('dataScreenShelfAllGrid'))
  212. }
  213. // 单面/双面
  214. this.tabListData = [{ name: dataScreenShelf.regionName + ' - ' + this.removeAreaPrefix(dataScreenShelf.gridName) }]
  215. this.tabIndex = dataScreenShelf.toward - 1
  216. FetchBookShelfDetails({ 'shelfId': dataScreenShelf.shelfId }).then(res => {
  217. this.layerNum = res.shelfFloor
  218. this.rackNum = res.shelfShelf
  219. this.floorId = res.floorId
  220. this.regionId = res.regionId
  221. this.bookShelfDetails = res
  222. this.rackOptions = []
  223. for (let i = 1; i <= this.rackNum; i++) {
  224. this.rackOptions.push({ id: i, name: `0${i}` })
  225. }
  226. this.layerVal = parseInt(this.gridShelf) || ''
  227. this.getInitStockInfo(this.shelfAllGridData)
  228. this.getInitBookDetailsByGrids(this.shelfAllGridData)
  229. this.initSwiper()
  230. }).catch(() => {
  231. })
  232. }
  233. },
  234. mounted() {
  235. },
  236. methods: {
  237. initSwiper() {
  238. this.$nextTick(() => {
  239. this.shelfAllGridData.forEach((el, index) => {
  240. new Swiper('.swiper' + index, {
  241. slidesPerView: 'auto',
  242. slidesPerGroup: 15,
  243. observer: true
  244. })
  245. })
  246. })
  247. },
  248. removeAreaPrefix(gridNames) {
  249. const index = gridNames.indexOf('面')
  250. if (index !== -1) {
  251. return gridNames.substring(0, index + 1)
  252. }
  253. return gridNames
  254. },
  255. getBillByShelfIdAndGridShelf(data) {
  256. const params = {
  257. 'gridShelf': data[0].gridShelf,
  258. 'ShelfId': data[0].shelfId,
  259. 'size': 5
  260. }
  261. FetchBillByShelfIdAndGridShelf(params).then(res => {
  262. if (res !== null) {
  263. this.checkDateLine = res.sort((a, b) => {
  264. return new Date(b.endTime) - new Date(a.endTime)
  265. })
  266. this.billNoImg = this.checkDateLine[0].stockBill
  267. this.checkDateLine[0].icon = 'el-icon-more'
  268. this.checkDateLine[0].color = '#0bbd87'
  269. } else {
  270. this.checkDateLine = []
  271. }
  272. }).catch(() => {
  273. })
  274. },
  275. async getInitStockInfo(data) {
  276. const promises = data.map(item => {
  277. const params = {
  278. 'fondsCode': this.libcode,
  279. 'floorId': this.floorId,
  280. 'regionId': this.regionId,
  281. 'shelfId': item.shelfId,
  282. 'gridId': item.id
  283. }
  284. return FetchInitStockInfo(params)
  285. })
  286. const results = await Promise.all(promises)
  287. if (!Array.isArray(this.baseStockData)) {
  288. this.baseStockData = []
  289. }
  290. this.baseStockData = this.baseStockData.concat(results)
  291. },
  292. getInitBookDetailsByGrids(data) {
  293. const ids = data.map(item => item.id)
  294. const params = {
  295. 'grids': ids.join(',')
  296. }
  297. FetchInitBookDetailsByGrids(params).then(res => {
  298. this.shelfAllGridData.forEach((item) => {
  299. const gridId = item.id
  300. if (Object.prototype.hasOwnProperty.call(res, gridId)) {
  301. // item.books = res[gridId]
  302. this.$set(item, 'books', res[gridId])
  303. }
  304. })
  305. }).catch(() => {
  306. })
  307. },
  308. handleDetail(item) {
  309. console.log('item', item)
  310. this.detailVisible = true
  311. this.detailTable = item.books
  312. this.detailCurrent = item
  313. if (this.detailCurrent.onShelfNum) {
  314. this.bigImg = `${this.baseApi}/api/fileRelevant/getImg?imgType=1&imgId=/${this.libcode}/${this.billNoImg}/${this.detailCurrent.gridCode}/img_result/result_LSD_compressed.jpg`
  315. } else {
  316. this.bigImg = ''
  317. }
  318. },
  319. // handleTouchStart(item) {
  320. // // this.isTouching = true
  321. // // this.showPopover(layerIndex, bookIndex, event)
  322. // // this.$refs.bookDetailsRef.detailShow = true
  323. // },
  324. getBookDetaisByBookRecNo(item) {
  325. FetchBookDetaisByBookRecNo({
  326. 'bookRecNo': item.bookRecNo
  327. }).then(res => {
  328. this.$refs.bookDetailsRef.getBookRankingDetail(res)
  329. }).catch(() => {
  330. this.$message.error('接口错误')
  331. })
  332. },
  333. handleTouchMove(layerIndex, bookIndex, event) {
  334. if (this.isTouching) {
  335. this.showPopover(layerIndex, bookIndex, event)
  336. }
  337. },
  338. handleTouchEnd(layerIndex, bookIndex, event) {
  339. this.isTouching = false
  340. this.hidePopover()
  341. },
  342. showPopover(layerIndex, bookIndex, event) {
  343. this.popoverIndex = { layer: layerIndex, book: bookIndex }
  344. const bookElement = event.target // 获取书籍项元素
  345. const rect = bookElement.getBoundingClientRect() // 获取边界
  346. if (layerIndex === 0) {
  347. this.popoverPosition = {
  348. x: window.scrollX + rect.left + rect.width / 2 - 40,
  349. y: window.scrollY + rect.top + rect.height
  350. }
  351. } else {
  352. this.popoverPosition = {
  353. x: window.scrollX + rect.left + rect.width / 2 - 40,
  354. y: window.scrollY + rect.top + rect.height - 170
  355. }
  356. }
  357. },
  358. hidePopover() {
  359. this.popoverIndex = null
  360. },
  361. updateParts(gridName) {
  362. const parts = gridName.match(/(\d+)区(\d+)排([A-Za-z])面(\d+)架(\d+)层/)
  363. if (parts) {
  364. this.getGridShelf = parts[4]
  365. this.getGridFloor = parts[5]
  366. const toward = parts[3]
  367. if (toward === 'A') {
  368. this.getGridToward = 1
  369. } else if (toward === 'B') {
  370. this.getGridToward = 2
  371. }
  372. }
  373. },
  374. changeShelfGetGrid(val) {
  375. this.updateParts(this.gridName)
  376. this.shelfAllGridDataLoading = true
  377. this.layerVal = val
  378. const params = {
  379. 'gridShelf': '0' + val,
  380. 'shelfId': this.bookShelfDetails.id,
  381. 'toward': this.getGridToward,
  382. 'floorType': this.bookShelfDetails.floorType
  383. }
  384. FetchShelfGridByShelfIdAndGridShelf(params).then(res => {
  385. this.shelfAllGridData = []
  386. this.shelfAllGridData = res
  387. this.getInitStockInfo(this.shelfAllGridData)
  388. this.getInitBookDetailsByGrids(this.shelfAllGridData)
  389. this.shelfAllGridDataLoading = false
  390. }).catch(() => {
  391. })
  392. }
  393. }
  394. }
  395. </script>
  396. <style lang="scss" scoped>
  397. @import "~@/assets/styles/index.scss";
  398. .gird-data-book{
  399. position: relative;
  400. // padding: 0 10px;
  401. // height: 650px;
  402. // margin-top: 4px;
  403. // overflow: hidden;
  404. // overflow-y: scroll;
  405. }
  406. .gird-layer{
  407. position: relative;
  408. display: flex;
  409. justify-content: space-between;
  410. .gird-left-line{
  411. position: absolute;
  412. left: 0;
  413. top: 0;
  414. display: block;
  415. width: 6px;
  416. height: 130px;
  417. background: url('~@/assets/images/shelf01.png') no-repeat left top;
  418. background-size: 100% 100%;
  419. z-index: 999;
  420. }
  421. .gird-right-line{
  422. position: absolute;
  423. right: calc(310px);
  424. top: 0;
  425. display: block;
  426. width: 6px;
  427. height: 130px;
  428. background: url('~@/assets/images/shelf01.png') no-repeat left top;
  429. background-size: 100% 100%;
  430. z-index: 999;
  431. }
  432. .layer-left{
  433. width: calc(100% - 300px);
  434. height: 130px;
  435. margin-right: 5px;
  436. padding: 0 0 0 12px;
  437. background: url('~@/assets/images/shelf02.png') repeat left top;
  438. background-size: 10% 100%;
  439. overflow: hidden;
  440. overflow-x: scroll;
  441. }
  442. .layer-left-book{
  443. // width: calc(100vw - 655px);
  444. height: 130px;
  445. white-space: nowrap;
  446. .rack-box-list{
  447. height: 200px;
  448. width: 100%;
  449. overflow: hidden;
  450. white-space: nowrap;
  451. }
  452. .list-item{
  453. display: inline-block;
  454. border: none;
  455. width: 42px;
  456. height: 120px;
  457. background: url('~@/assets/images/shelf03.png') no-repeat left top;
  458. background-size: 100% 100%;
  459. position: relative;
  460. margin-left: -14px;
  461. margin-top: 10px;
  462. .book-name{
  463. position: absolute;
  464. left: 12px;
  465. top: 16px;
  466. display: block;
  467. height: 90px;
  468. font-size: 16px;
  469. writing-mode:vertical-rl;
  470. overflow: hidden;
  471. white-space: nowrap;
  472. text-overflow: ellipsis;
  473. }
  474. &.red-active{
  475. background: url('~@/assets/images/shelf05.png') no-repeat left top;
  476. background-size: 100% 100%;
  477. }
  478. &.blue-active{
  479. background: url('~@/assets/images/shelf06.png') no-repeat left top;
  480. background-size: 100% 100%;
  481. }
  482. }
  483. }
  484. }
  485. .layer-right-handle{
  486. width: 300px;
  487. padding: 0 10px;
  488. background-color: #E8F2FF;
  489. margin: 3px 5px;
  490. border-radius: 6px;
  491. }
  492. .layer-info-header{
  493. display: flex;
  494. justify-content: space-between;
  495. align-items: center;
  496. line-height: 36px;
  497. h4{
  498. font-size: 20px;
  499. color: #0c0e1e;
  500. }
  501. span{
  502. font-size: 12px;
  503. }
  504. }
  505. .layer-right-content{
  506. display: flex;
  507. justify-content: space-between;
  508. }
  509. .layer-tag-info{
  510. div.tag-item {
  511. display: flex;
  512. justify-content: flex-start;
  513. line-height: 26px;
  514. font-size: 18px;
  515. }
  516. }
  517. .layer-handle{
  518. display: flex;
  519. flex-direction: column;
  520. .el-button,
  521. .el-button--info.is-plain {
  522. margin-left: 0 !important;
  523. margin-bottom: 10px;
  524. padding: 7px 10px !important;
  525. font-weight: bold !important;
  526. border-color: #0348f3 !important;
  527. color: #0348f3 !important;
  528. }
  529. .check-btn{
  530. color: #fff !important;
  531. background-color: #0348f3 !important;
  532. }
  533. }
  534. .layerShelf-swiper{
  535. margin-top: 20px;
  536. ::v-deep .swiper-wrapper{
  537. font-size: 20px;
  538. border-bottom: none !important;
  539. .swiper-slide-title {
  540. width: auto !important;
  541. margin-right: 20px;
  542. cursor: pointer;
  543. .tab-name {
  544. padding: 5px 10px;
  545. &.active {
  546. background-color: #0348F3;
  547. color: #fff;
  548. border-radius: 6px;
  549. border: 2px solid #0348F3;
  550. }
  551. }
  552. }
  553. }
  554. }
  555. </style>