图书馆综合管理系统
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.

672 lines
24 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
  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> {{ floorName }} - {{ regionName }}</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. <div class="double-click-btn"><span>点击左侧位置返回</span></div>
  15. </div>
  16. <p><i class="iconfont icon-gongsi" />{{ user.fonds.fondsName }}</p>
  17. </div>
  18. <div class="venue-content dataScreening-content">
  19. <crudOperation :permission="permission">
  20. <template v-slot:middle>
  21. <el-select v-model="layerVal" size="small" placeholder="楼层" class="filter-item" style="width: 100px; margin-right: 10px;" value-key="id" @change="changeShelfGetGrid">
  22. <el-option v-for="item in layerOptions" :key="item.id" :label="item.name" :value="item" />
  23. </el-select>
  24. <el-button v-permission="permission.add" class="check-btn" size="mini" @click="toAdd(4)">
  25. <i class="iconfont icon-shengchengpandiandan" />
  26. 书架盘点
  27. </el-button>
  28. </template>
  29. <template v-slot:right>
  30. <el-button :loading="crud.downloadLoading" size="mini" @click="doExport(3)">
  31. <i class="iconfont icon-daochu" />
  32. 导出
  33. </el-button>
  34. </template>
  35. </crudOperation>
  36. <div class="venue-left">
  37. <div class="container-right tab-content">
  38. <span class="right-top-line" />
  39. <span class="left-bottom-line" />
  40. <ul class="tab-nav">
  41. <li v-for="(item,index) in tabListData" :key="index" :class="{ 'active-tab-nav': tabIndex == index }" @click="changeActiveTab(index)">{{ item.name }}<i /></li>
  42. <!-- 最右侧装饰img -->
  43. <span class="tab-right-img" />
  44. </ul>
  45. <div class="tag-info">
  46. <p class="tag-sort">错序<i class="iconfont icon-zhuangtai2" /></p>
  47. <p class="tag-place">错架<i class="iconfont icon-zhuangtai2" /></p>
  48. <p class="tag-all">在架<i class="iconfont icon-zhuangtai2" /></p>
  49. </div>
  50. <!-- </div> -->
  51. <div class="shelf-top" :style="rowStyle">
  52. <p v-for="(item,index) in reversedRackNum" :key="index" :style="{width: `calc(142px)`}"><span>{{ item + '架' }}</span></p>
  53. </div>
  54. <ul v-loading="listLoading" class="data-shelf-row" :style="rowStyle">
  55. <!-- :class="{ active: i === cellIndex }" -->
  56. <!-- { active: columnIndex === i % rackNum} -->
  57. <li
  58. v-for="(cell,i) in booShelfGrid"
  59. :key="i"
  60. :class="['data-shelf-cell',{'active': isActiveColumn(i)}]"
  61. :style="cellStyle"
  62. @dblclick="handleCellCurrent(cell,i)"
  63. @mouseenter="showPopover(i)"
  64. @mouseleave="hidePopover"
  65. >
  66. <div class="mask" />
  67. <div class="tag-info">
  68. <p class="tag-sort"><i class="iconfont icon-zhuangtai2" />{{ cell.errorOrderNum }}</p>
  69. <p class="tag-place"><i class="iconfont icon-zhuangtai2" />{{ cell.errorShelfNum }}</p>
  70. <p class="tag-all"><i class="iconfont icon-zhuangtai2" />{{ cell.onShelfNum }}</p>
  71. </div>
  72. <el-popover
  73. v-if="popoverIndex === i"
  74. ref="popover"
  75. :visible="popoverVisible[i]"
  76. width="400"
  77. :style="popoverStyles[i]"
  78. trigger="manual"
  79. >
  80. <div slot="reference" class="popover-content-set">
  81. <div class="tooltip-top">
  82. <h4>本架概况</h4>
  83. <i class="update-time">2024-11-28 09:46</i>
  84. </div>
  85. <ul>
  86. <li><p>架位</p><em class="percentage"><i style="color: #fff;">{{ removeAreaPrefix(cell.gridName) }}</i></em></li>
  87. <li><p>在架</p><em><i>{{ itemStockData.onShelfNum }}</i></em></li>
  88. <li><p>错架</p><em><i>{{ itemStockData.errorShelfNum }}</i></em> <em class="percentage">{{ itemStockData.errorShelfProbo }}</em></li>
  89. <li><p>错序</p><em><i>{{ itemStockData.errorOrderNum }}</i></em><em class="percentage">{{ itemStockData.errorOrderProbo }}</em></li>
  90. </ul>
  91. </div>
  92. </el-popover>
  93. </li>
  94. </ul>
  95. </div>
  96. </div>
  97. <div class="venue-right">
  98. <div class="lib-right-item lib-info">
  99. <h4>书架概况</h4>
  100. <ul class="data-right-list">
  101. <li><p>书架</p><span><i>{{ bookShelfDetails.shelfName }}</i></span></li>
  102. <li><p>规格</p><span><i>{{ bookShelfDetails.rowType===1?'单面':'双面' }} {{ bookShelfDetails.shelfFloor }} x {{ bookShelfDetails.shelfShelf }}</i></span></li>
  103. </ul>
  104. </div>
  105. <div class="lib-right-item">
  106. <h4>书架盘点概况</h4>
  107. <div class="refresh-date">{{ bookShelfDetails.update_time | parseTime }}</div>
  108. <ul class="data-right-list">
  109. <li><p>在架</p><span><i>{{ baseStockData.onShelfNum }}</i></span></li>
  110. <li><p>错架</p><span><i>{{ baseStockData.errorShelfNum }}</i></span> <span class="percentage">{{ baseStockData.errorShelfProbo }}</span></li>
  111. <li><p>错序</p><span><i>{{ baseStockData.errorOrderNum }}</i></span><span class="percentage">{{ baseStockData.errorOrderProbo }}</span></li>
  112. </ul>
  113. </div>
  114. </div>
  115. </div>
  116. <eForm ref="eform" />
  117. <exportForm ref="exportform" export-type="shelf" />
  118. </div>
  119. </template>
  120. <script>
  121. import { dataScreeningCrud } from '@/views/visualCheck/mixins/index'
  122. import { FetchInitBookShelfList, FetchInitShelfGridByShelfId, FetchBookShelfDetails } from '@/api/shelf/index'
  123. import { FetchInitStockInfo } from '@/api/stockTask/index'
  124. import crudRegion from '@/api/area/index'
  125. import CRUD, { presenter, header, crud } from '@crud/crud'
  126. import crudOperation from '@crud/CRUD.operation'
  127. import { mapGetters } from 'vuex'
  128. import eForm from './module/form'
  129. import exportForm from './module/export'
  130. export default {
  131. name: 'DataScreening',
  132. components: { crudOperation, eForm, exportForm },
  133. cruds() {
  134. return CRUD({ title: '架位总览', url: 'api/libraryRegion/initLibraryRegionList', crudMethod: { ...crudRegion }, sort: [], optShow: {
  135. add: false,
  136. edit: false,
  137. del: false,
  138. download: false,
  139. group: false,
  140. reset: false
  141. },
  142. queryOnPresenterCreated: false
  143. })
  144. },
  145. mixins: [presenter(), header(), crud(), dataScreeningCrud],
  146. data() {
  147. const _this = this
  148. return {
  149. listLoading: false,
  150. tabIndex: 0,
  151. floorTabIndex: 0,
  152. regionTabIndex: 0,
  153. floorName: null,
  154. floorId: null,
  155. regionName: null,
  156. regionId: null,
  157. rowType: null,
  158. bookShelfDetails: {},
  159. booShelfGrid: [],
  160. cellInfo: {
  161. gridName: null,
  162. startSortmark: null,
  163. endSortmark: null,
  164. cameraId: null
  165. },
  166. callNumVisible: false,
  167. layerNum: 0,
  168. rackNum: 0,
  169. swiperActiveIndex: 0,
  170. cellIndex: null,
  171. columnIndex: null,
  172. swiperOptionContent: {
  173. slidesPerView: 'auto',
  174. on: {
  175. slideChangeTransitionStart: function() {
  176. _this.cellIndex = null
  177. _this.swiperActiveIndex = this.activeIndex
  178. _this.swiperTitle.slideTo(this.activeIndex, 500, false)
  179. }
  180. }
  181. },
  182. swiperOptionTitle: {
  183. slidesPerView: 'auto',
  184. freeMode: true
  185. },
  186. layerVal: null,
  187. layerOptions: [],
  188. tabListData: [],
  189. permission: {
  190. add: ['admin', 'floor:add'],
  191. edit: ['admin', 'floor:edit'],
  192. del: ['admin', 'floor:del']
  193. },
  194. popoverIndex: null,
  195. popoverVisible: [],
  196. popoverStyles: [],
  197. activeColumns: {},
  198. itemStockData: {}
  199. }
  200. },
  201. computed: {
  202. ...mapGetters([
  203. 'user',
  204. 'baseApi'
  205. ]),
  206. swiperContent() {
  207. return this.$refs.swiperContent.$el.swiper
  208. },
  209. swiperTitle() {
  210. return this.$refs.swiperTitle.$el.swiper
  211. },
  212. // cellStyle: function() {
  213. // // const h = '100%/' + this.layerNum
  214. // // const w = '100%/' + this.rackNum
  215. // const h = '76px'
  216. // const w = '100%/' + this.rackNum
  217. // return { width: `calc(${w} )`, height: `calc(${h})` }
  218. // },
  219. cellStyle: function() {
  220. const h = '76px'
  221. // const w = '100%/' + this.rackNum
  222. const w = '146px'
  223. return { width: `calc(${w} )`, height: `calc(${h})` }
  224. },
  225. rowStyle: function() {
  226. const w = 146 * this.rackNum + 'px'
  227. return { width: `calc(${w})` }
  228. },
  229. reversedRackNum() {
  230. if (this.booShelfGrid && this.booShelfGrid.length > 0) {
  231. if (parseInt(this.booShelfGrid[0].gridShelf) === this.rackNum) {
  232. return Array.from({ length: this.rackNum }, (_, i) => this.rackNum - i).map(x => x.toString())
  233. } else {
  234. return Array.from({ length: this.rackNum }, (_, i) => i + 1).map(x => x.toString())
  235. }
  236. } else {
  237. return []
  238. }
  239. }
  240. },
  241. async created() {
  242. if (localStorage.getItem('dataScreenFloorTableIndex')) {
  243. this.floorTabIndex = localStorage.getItem('dataScreenFloorTableIndex')
  244. }
  245. if (localStorage.getItem('dataScreenRegionTableIndex')) {
  246. this.regionTabIndex = localStorage.getItem('dataScreenRegionTableIndex')
  247. }
  248. if (localStorage.getItem('dataScreenRegion')) {
  249. const dataScreenRegion = JSON.parse(localStorage.getItem('dataScreenRegion'))
  250. this.floorName = dataScreenRegion.floorName
  251. this.floorId = dataScreenRegion.floorId
  252. this.regionName = dataScreenRegion.regionName
  253. this.regionId = dataScreenRegion.regionId
  254. this.rowType = dataScreenRegion.rowType
  255. this.initData(dataScreenRegion)
  256. this.getInitBookShelfList(dataScreenRegion)
  257. this.getInitStockInfo(dataScreenRegion)
  258. }
  259. },
  260. methods: {
  261. [CRUD.HOOK.beforeRefresh]() {
  262. },
  263. [CRUD.HOOK.afterRefresh](crud) {
  264. },
  265. // 提交前的验证
  266. [CRUD.HOOK.afterValidateCU](crud) {
  267. return true
  268. },
  269. initData(data) {
  270. // 单面/双面
  271. this.tabListData = data.rowType === 1
  272. ? data.toward === 1
  273. ? [{ name: 'A面' }]
  274. : [{ name: 'B面' }]
  275. : [{ name: 'A面' }, { name: 'B面' }]
  276. this.tabIndex = this.$route.query.tabIndex ? this.$route.query.tabIndex : 0
  277. FetchBookShelfDetails({ 'shelfId': data.id }).then(res => {
  278. this.layerNum = res.shelfFloor
  279. this.rackNum = res.shelfShelf
  280. this.bookShelfDetails = res
  281. if (this.$route.query.tabIndex) {
  282. this.getInitShelfGridByShelfId(this.bookShelfDetails.id, this.$route.query.tabIndex + 1)
  283. } else {
  284. this.getInitShelfGridByShelfId(this.bookShelfDetails.id, this.bookShelfDetails.toward)
  285. }
  286. }).catch(() => {
  287. })
  288. },
  289. getInitStockInfo(data) {
  290. const params = {
  291. // 'floorId': this.floorId,
  292. // 'regionId': this.regionId,
  293. 'shelfId': data.id
  294. }
  295. this.handleInitStockInfo(params)
  296. },
  297. getInitBookShelfList(data) {
  298. const params = { 'floorId': data.floorId, 'regionId': data.regionId }
  299. FetchInitBookShelfList(params).then(res => {
  300. this.layerOptions = res.content.map(item => {
  301. return {
  302. name: item.shelfName,
  303. id: item.shelfId,
  304. toward: item.toward,
  305. rowType: item.rowType
  306. }
  307. })
  308. this.layerVal = data
  309. }).catch(() => {
  310. })
  311. },
  312. changeShelfGetGrid(val) {
  313. this.initData(val)
  314. this.getInitStockInfo(val)
  315. },
  316. toAdd(type) {
  317. this.$refs.eform.formVisible = true
  318. this.$refs.eform.form.shelfId = this.bookShelfDetails.id
  319. this.$refs.eform.form.stockRegion = this.floorName + this.regionName + this.bookShelfDetails.shelfName
  320. this.$refs.eform.setData(type)
  321. },
  322. doExport(type) {
  323. this.$refs.exportform.formExportVisible = true
  324. this.$refs.exportform.type = 3
  325. this.$refs.exportform.params = {
  326. 'floorId': this.floorId,
  327. 'regionId': this.regionId,
  328. 'shelfId': this.bookShelfDetails.id
  329. }
  330. },
  331. removeAreaPrefix(gridNames) {
  332. return gridNames.replace(/\d*区|\d*层/g, '')
  333. },
  334. getInitShelfGridByShelfId(shelfId, toward) {
  335. this.listLoading = true
  336. // rowType 1 单 2 双
  337. // toward 1 A面 2 B面
  338. // shelfType 1 '始终最左边为第1架(S型排架)'
  339. // shelfType 2 'A面最左为第1架(B面最左为最后1架)'
  340. // shelfType 3 'B面最左为第1架(A面最左为最后1架)'
  341. // floorType 1 '最顶层为第一层(从上至下)'
  342. // floorType 2 '最底层为第一层(从下至上)'
  343. FetchInitShelfGridByShelfId({ 'shelfId': shelfId, 'toward': toward }).then(res => {
  344. const sortFunction = toward === 1 ? {
  345. 1: { 1: 'sortBookshelvesLeftTop', 2: 'sortBookshelvesLeftBottom' },
  346. 2: { 1: 'sortBookshelvesLeftTop', 2: 'sortBookshelvesLeftBottom' },
  347. 3: { 1: 'sortBookshelvesRightTop', 2: 'sortBookshelvesRightBottom' }
  348. } : {
  349. 1: { 1: 'sortBookshelvesLeftTop', 2: 'sortBookshelvesLeftBottom' },
  350. 2: { 1: 'sortBookshelvesRightTop', 2: 'sortBookshelvesRightBottom' },
  351. 3: { 1: 'sortBookshelvesLeftTop', 2: 'sortBookshelvesLeftBottom' }
  352. }
  353. const shelfType = this.bookShelfDetails.shelfType
  354. const floorType = this.bookShelfDetails.floorType
  355. const sortMethod = sortFunction[shelfType][floorType]
  356. this.booShelfGrid = this[sortMethod](res)
  357. this.popoverVisible = Array(this.booShelfGrid.length).fill(false)
  358. setTimeout(() => {
  359. this.listLoading = false
  360. }, 1000)
  361. }).catch(() => {
  362. })
  363. },
  364. // 最左为第一架, 最顶层为第一层 从上往下
  365. sortBookshelvesLeftTop(data) {
  366. const sortedData = []
  367. const maxFloor = Math.max(...data.map(item => parseInt(item.gridFloor)))
  368. const maxShelf = Math.max(...data.map(item => parseInt(item.gridShelf.slice(-1))))
  369. for (let i = 1; i <= maxFloor; i++) {
  370. for (let j = 1; j <= maxShelf; j++) {
  371. const currentShelf = data.find(item => parseInt(item.gridFloor) === i && parseInt(item.gridShelf.slice(-1)) === j)
  372. if (currentShelf) {
  373. sortedData.push(currentShelf)
  374. }
  375. }
  376. }
  377. return sortedData
  378. },
  379. // 最右为第一架,最左为最后一架, 最顶层为第一层 从上往下
  380. sortBookshelvesRightTop(data) {
  381. const sortedData = []
  382. // 获取最大的楼层数
  383. const maxFloor = Math.max(...data.map(item => parseInt(item.gridFloor)))
  384. const maxShelf = Math.max(...data.map(item => parseInt(item.gridShelf.match(/\d+$/)[0])))
  385. for (let i = 1; i <= maxFloor; i++) {
  386. // 从最大的书架层数开始,向下排序
  387. for (let j = maxShelf; j >= 1; j--) {
  388. const currentShelf = data.find(item => parseInt(item.gridFloor) === i && parseInt(item.gridShelf.match(/\d+$/)[0]) === j)
  389. if (currentShelf) {
  390. sortedData.push(currentShelf)
  391. }
  392. }
  393. }
  394. return sortedData
  395. },
  396. // 最左为第一架, 最底层为第一层 从下往上
  397. sortBookshelvesLeftBottom(data) {
  398. const sortedData = []
  399. // 获取最大的楼层数
  400. const maxFloor = Math.max(...data.map(item => parseInt(item.gridFloor)))
  401. // 获取最大的书架层数
  402. const maxShelf = Math.max(...data.map(item => parseInt(item.gridShelf.slice(-1))))
  403. for (let i = maxFloor; i >= 1; i--) {
  404. for (let j = 1; j <= maxShelf; j++) {
  405. const currentShelf = data.find(item => parseInt(item.gridFloor) === i && parseInt(item.gridShelf.slice(-1)) === j)
  406. if (currentShelf) {
  407. sortedData.push(currentShelf)
  408. }
  409. }
  410. }
  411. return sortedData
  412. },
  413. // 最左为最后一架, 最底层为第一层 从下往上
  414. sortBookshelvesRightBottom(data) {
  415. const sortedData = []
  416. // 获取最大的楼层数
  417. const maxFloor = Math.max(...data.map(item => parseInt(item.gridFloor)))
  418. const maxShelfPerFloor = data.map(item => parseInt(item.gridShelf.match(/\d+$/)[0]))
  419. .reduce((acc, curr, index, arr) => {
  420. const floor = parseInt(data[index].gridFloor)
  421. if (!acc[floor]) acc[floor] = 1
  422. if (acc[floor] < curr) acc[floor] = curr
  423. return acc
  424. }, {})
  425. // 从最大的楼层开始向下遍历
  426. for (let i = maxFloor; i >= 1; i--) {
  427. // 从最大的书架编号开始向左遍历
  428. for (let j = maxShelfPerFloor[i] || 1; j >= 1; j--) {
  429. const currentShelf = data.find(item => parseInt(item.gridFloor) === i && parseInt(item.gridShelf.match(/\d+$/)[0]) === j)
  430. if (currentShelf) {
  431. sortedData.push(currentShelf)
  432. }
  433. }
  434. }
  435. return sortedData
  436. },
  437. changeActiveTab(index) {
  438. this.tabIndex = index
  439. this.cellIndex = null
  440. this.getInitShelfGridByShelfId(this.layerVal.id, index + 1)
  441. },
  442. handleCellCurrent(item, index) {
  443. this.cellIndex = index
  444. this.cellInfo = {
  445. id: item.id,
  446. gridName: item.gridName,
  447. gridRow: item.gridRow,
  448. gridShelf: item.gridShelf,
  449. shelfId: item.shelfId,
  450. floorName: this.floorName,
  451. regionName: this.regionName,
  452. rowType: this.layerVal.rowType,
  453. toward: item.toward
  454. }
  455. this.currentShelfAllGrid = this.booShelfGrid.filter(gird => gird.gridShelf === item.gridShelf)
  456. this.handleToGrids(this.cellInfo, this.currentShelfAllGrid)
  457. },
  458. handleToGrids(data, currentShelfAllGrid) {
  459. this.$router.push({ path: '/dataScreening/gird' })
  460. if (localStorage.getItem('dataScreenRegion')) {
  461. const dataScreenRegion = JSON.parse(localStorage.getItem('dataScreenRegion'))
  462. dataScreenRegion.rowType = this.layerVal.rowType
  463. dataScreenRegion.toward = this.layerVal.toward
  464. dataScreenRegion.name = this.layerVal.name
  465. dataScreenRegion.id = this.layerVal.id
  466. localStorage.setItem('dataScreenRegion', JSON.stringify(dataScreenRegion))
  467. }
  468. localStorage.setItem('dataScreenShelf', JSON.stringify(data))
  469. localStorage.setItem('dataScreenShelfAllGrid', JSON.stringify(currentShelfAllGrid))
  470. localStorage.setItem('dataScreenShelfTableIndex', this.tabIndex)
  471. },
  472. showPopover(index) {
  473. this.popoverIndex = index
  474. if (!this.popoverVisible[index]) {
  475. this.$set(this.popoverVisible, index, true)
  476. }
  477. const lastColumnIndexes = []
  478. const secondLastColumnIndexes = []
  479. for (let i = 0; i < this.booShelfGrid.length; i++) {
  480. const columnIndex = i % this.rackNum
  481. // 如果是最后一列(第5列)
  482. if (this.rackNum !== 1) {
  483. if (columnIndex === this.rackNum - 1) {
  484. lastColumnIndexes.push(i)
  485. // 更新最后一列的样式
  486. this.$set(this.popoverStyles, i, { position: 'absolute', left: '-180px', top: '20px' })
  487. }
  488. } else {
  489. this.$set(this.popoverStyles, i, { position: 'absolute', left: '60px', top: '20px' })
  490. }
  491. // 如果是倒数第二列(第4列)
  492. if (columnIndex === this.rackNum - 2) {
  493. secondLastColumnIndexes.push(i)
  494. // 更新倒数第二列的样式
  495. // this.$set(this.popoverStyles, i, { position: 'absolute', left: '-20px', top: '20px' })
  496. }
  497. }
  498. const columnIndex = index % this.rackNum
  499. this.activeColumns[columnIndex] = true
  500. const params = {
  501. 'floorId': this.floorId,
  502. 'regionId': this.regionId,
  503. 'shelfId': this.bookShelfDetails.id,
  504. 'gridShelf': this.booShelfGrid[columnIndex].gridShelf
  505. }
  506. FetchInitStockInfo(params).then(res => {
  507. this.itemStockData = res
  508. }).catch(() => {
  509. })
  510. },
  511. isActiveColumn(index) {
  512. const columnIndex = index % this.rackNum
  513. return this.activeColumns[columnIndex] === true
  514. },
  515. hidePopover() {
  516. this.activeColumns = {}
  517. this.popoverIndex = null
  518. this.popoverVisible.forEach((isVisible, index) => {
  519. if (isVisible) {
  520. this.$set(this.popoverVisible, index, false)
  521. }
  522. })
  523. }
  524. }
  525. }
  526. </script>
  527. <style lang="scss" scoped>
  528. .container-right{
  529. min-height: calc(100vh - 232px) !important;
  530. }
  531. .data-right-list {
  532. padding-top: 10px;
  533. li{
  534. display: flex;
  535. justify-content: flex-start;
  536. align-items: center;
  537. line-height: 36px;
  538. p{
  539. width: 80px;
  540. font-weight: bold;
  541. text-align: right;
  542. }
  543. span{
  544. width: 140px;
  545. display: block;
  546. text-align: right;
  547. i{
  548. font-style: normal;
  549. font-weight: bold;
  550. padding: 0 10px;
  551. color: #0348f3;
  552. }
  553. &.percentage{
  554. width: auto;
  555. }
  556. }
  557. }
  558. }
  559. .tag-info{
  560. position: absolute;
  561. right: 20px;
  562. top: 8px;
  563. p{
  564. margin-left: 20px;
  565. }
  566. }
  567. .shelf-top{
  568. display: flex;
  569. justify-content: space-around;
  570. align-items: center;
  571. text-align: center;
  572. margin-top: 20px;
  573. p{
  574. font-size: 14px;
  575. color: #fff;
  576. height: 36px;
  577. line-height: 30px;
  578. background: url('~@/assets/images/shelf04.png') no-repeat center top;
  579. background-size: auto 100%;
  580. }
  581. }
  582. .data-shelf-row{
  583. display: flex;
  584. flex: 1;
  585. flex-wrap: wrap;
  586. text-align: center;
  587. // margin-top: -2px;
  588. // padding-top: 40px;
  589. .data-shelf-cell{
  590. position: relative;
  591. font-size: 14px;
  592. color: #0C0E1E;
  593. background: url('~@/assets/images/shelf02.png') repeat-x left top;
  594. background-size: 20% 100%;
  595. border-radius: 3px;
  596. cursor: pointer;
  597. .tag-info{
  598. right: 12px;
  599. top: 44px;
  600. p{
  601. margin-left: 10px;
  602. }
  603. }
  604. &::before{
  605. content: "";
  606. position: absolute;
  607. left: 0;
  608. top: 0;
  609. width: 6px;
  610. height: 76px;
  611. background: url('~@/assets/images/shelf01.png') no-repeat left top;
  612. background-size: 100% 100%;
  613. }
  614. &::after{
  615. content: "";
  616. position: absolute;
  617. right: -4px;
  618. top: 0;
  619. width: 6px;
  620. height: 76px;
  621. background: url('~@/assets/images/shelf01.png') no-repeat left top;
  622. background-size: 100% 100%;
  623. }
  624. .cell-name{
  625. display: block;
  626. width: 100%;
  627. line-height: 76px;
  628. }
  629. &.active{
  630. .mask{
  631. position: absolute;
  632. top: 0;
  633. left: 6px;
  634. width: 98%;
  635. height: 100%;
  636. background-color: rgba(255,0,0,.3);
  637. }
  638. }
  639. }
  640. }
  641. ::v-deep .data-shelf-row span.el-popover__reference-wrapper{
  642. position: absolute !important;
  643. left: 60% !important;
  644. top: 48px !important;
  645. width: 250px;
  646. // height: 210px;
  647. background:rgba(0,0,0,1);
  648. color: #fff;
  649. border-radius: 6px;
  650. z-index: 99999999;
  651. }
  652. </style>