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

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