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

479 lines
16 KiB

7 months ago
6 months ago
7 months ago
6 months ago
6 months ago
7 months ago
6 months ago
6 months ago
7 months ago
6 months ago
7 months ago
6 months ago
7 months ago
6 months ago
7 months ago
5 months ago
7 months ago
5 months ago
7 months ago
7 months ago
6 months ago
7 months ago
7 months ago
7 months ago
7 months ago
7 months ago
7 months ago
7 months ago
7 months ago
6 months ago
7 months ago
5 months ago
6 months ago
6 months ago
7 months ago
5 months ago
7 months ago
6 months ago
5 months ago
7 months ago
6 months ago
7 months ago
6 months ago
7 months ago
5 months ago
7 months ago
5 months ago
7 months ago
6 months ago
6 months ago
6 months ago
5 months ago
6 months ago
7 months ago
5 months ago
7 months ago
6 months ago
5 months ago
6 months ago
5 months ago
6 months ago
7 months ago
6 months ago
7 months ago
6 months ago
7 months ago
6 months ago
7 months ago
5 months ago
7 months ago
6 months ago
7 months ago
5 months ago
7 months ago
  1. <template>
  2. <div class="dashboard-container">
  3. <div class="dashboard-editor-container">
  4. <panel-group :top-object-num="topObjectNum" />
  5. <el-row :gutter="20" style="margin-bottom:20px;height: calc(50vh - 174px);">
  6. <el-col :xs="24" :sm="24" :lg="12">
  7. <div class="container-wrap">
  8. <span class="right-top-line" />
  9. <span class="left-bottom-line" />
  10. <h3 class="home-item-title">
  11. 盘点日志
  12. <router-link :to="{ path: '/check/check/checkLog'}">
  13. <div style="position: absolute; right: 20px; top: 20px; color: #999;" class="el-icon-more" />
  14. </router-link>
  15. </h3>
  16. <div class="home-flowable" style="height: calc(100% - 54px); overflow-x: hidden;">
  17. <div class="home-tab">
  18. <span :class="{'home-tab-active': flowableTabIndex == 0}">未完成({{ stockLogIncompleteData.length !==0? stockLogIncompleteData.length: 0 }})</span>
  19. <span :class="{'home-tab-active': flowableTabIndex == 1}">已结束({{ stockLogCompletedData.length !==0? stockLogCompletedData.length: 0 }})</span>
  20. <!-- <span :class="{'home-tab-active': flowableTabIndex == 2}">已完成({{ flowableData.length !==0? flowableData.length: 0 }})</span>
  21. <span :class="{'home-tab-active': flowableTabIndex == 3}" @click="toMoreProcess">更多任务</span> -->
  22. </div>
  23. <div class="home-flowable-list" style="height: calc(100% - 45px); overflow-y: auto; overflow-x: hidden;">
  24. <el-table v-if="stockLogIncompleteData.length !== 0" height="calc(100%)" :data="stockLogIncompleteData" class="archives-table" stripe style="width: 100%">
  25. <el-table-column prop="stockBill" label="盘点单号" />
  26. <el-table-column prop="stockRegion" label="目标位置" min-width="180" />
  27. <el-table-column prop="stockGridNum" label="目标数量" align="right">
  28. <template slot-scope="scope">
  29. <div>{{ scope.row.stockGridNum + ' / '+ (scope.row.totalGridNum?scope.row.totalGridNum:'0') +' 层位' }}</div>
  30. </template>
  31. </el-table-column>
  32. <el-table-column prop="state" label="盘点状态" align="center">
  33. <template slot-scope="scope">
  34. <span v-if="scope.row.state === 0" class="row-state row-lending state-active">已终止</span>
  35. <span v-if="scope.row.state === 1" class="row-state row-warehousing state-active">排队中</span>
  36. <span v-if="scope.row.state === 2" class="row-state row-binding state-active">盘点中</span>
  37. <span v-if="scope.row.state === 3" class="row-state row-physical state-active">已完成</span>
  38. </template>
  39. </el-table-column>
  40. <!-- <el-table-column prop="createTime" label="申请时间" width="180"> -->
  41. <!-- <template slot-scope="scope"> -->
  42. <!-- <div>{{ scope.row.createTime | parseTime }}</div> -->
  43. <!-- </template> -->
  44. <!-- </el-table-column> -->
  45. </el-table>
  46. <div v-else class="empty-main" style="height: 100%;">
  47. <svg-icon icon-class="empty" class-name="empty-img" />
  48. <p>暂无数据</p>
  49. </div>
  50. </div>
  51. </div>
  52. </div>
  53. </el-col>
  54. <el-col :xs="24" :sm="24" :lg="12">
  55. <div class="container-wrap">
  56. <span class="right-top-line" />
  57. <span class="left-bottom-line" />
  58. <h3 class="home-item-title">
  59. 服务器监控
  60. <div style="position: absolute; right: 20px; top: 20px; color: #999; cursor: pointer;" class="el-icon-refresh" @click="refreshSystemData" />
  61. </h3>
  62. <!-- <div class="chart-wrapper"> -->
  63. <!-- <serverProgress :system-data="systemData" /> -->
  64. <!-- </div> -->
  65. <swiper
  66. ref="swiperServer"
  67. class="swiper-server"
  68. :options="swiperOptionServer"
  69. :auto-update="true"
  70. :auto-destroy="true"
  71. :delete-instance-on-destroy="true"
  72. :cleanup-styles-on-destroy="true"
  73. >
  74. <swiper-slide class="swiper-slide-server">
  75. <serverProgress :system-data="systemData" />
  76. </swiper-slide>
  77. <swiper-slide class="swiper-slide-server cpu-echarts">
  78. <serverGpuUse :utilization="utilization" />
  79. <div class="cpu-right">
  80. <serverGpu :temperature="temperature" />
  81. <serverGpuOther :memory-total="memoryTotal" :memory-free="memoryFree" />
  82. </div>
  83. <div style="position: absolute; bottom: 136px; right: 70px; font-weight: bold;">{{ GPUName }}</div>
  84. </swiper-slide>
  85. <swiper-slide class="swiper-slide-server">
  86. <serveTerminal ref="serveTerminalRefs" />
  87. </swiper-slide>
  88. <div slot="pagination" class="swiper-pagination" />
  89. </swiper>
  90. </div>
  91. </el-col>
  92. </el-row>
  93. <el-row :gutter="20" style="height:calc(50vh - 174px);">
  94. <el-col :xs="24" :sm="24" :lg="8">
  95. <!-- 档案借阅 -->
  96. <div class="container-wrap">
  97. <span class="right-top-line" />
  98. <span class="left-bottom-line" />
  99. <h3 class="home-item-title">
  100. 盘点概况
  101. </h3>
  102. <div v-if="taskStockLogData.length !== 0" class="chart-wrapper">
  103. <taskStockLogEcharts :task-stock-log-data="taskStockLogData" />
  104. </div>
  105. <div v-else class="empty-main">
  106. <svg-icon icon-class="empty" class-name="empty-img" />
  107. <p>暂无数据</p>
  108. </div>
  109. </div>
  110. </el-col>
  111. <el-col :xs="24" :sm="24" :lg="8">
  112. <!-- 档案门类 -->
  113. <div class="container-wrap">
  114. <span class="right-top-line" />
  115. <span class="left-bottom-line" />
  116. <h3 class="home-item-title">
  117. 盘点统计
  118. </h3>
  119. <div class="chart-wrapper" style="padding: 0 10px; margin-top: -10px;">
  120. <checkSwiper ref="checkSwiperRefs" />
  121. </div>
  122. <!-- <div v-else class="empty-main">
  123. <svg-icon icon-class="empty" class-name="empty-img" />
  124. <p>暂无数据</p>
  125. </div> -->
  126. </div>
  127. </el-col>
  128. <el-col :xs="24" :sm="24" :lg="8">
  129. <!-- 档案类型 -->
  130. <div class="container-wrap">
  131. <span class="right-top-line" />
  132. <span class="left-bottom-line" />
  133. <h3 class="home-item-title">
  134. 流通统计
  135. </h3>
  136. <!-- <div class="refresh-date">2024-11-28 09:46</div> -->
  137. <div class="chart-wrapper" style="padding: 0 10px; margin-top: -10px;">
  138. <bookSwiper ref="bookSwiperRefs" />
  139. </div>
  140. </div>
  141. </el-col>
  142. </el-row>
  143. </div>
  144. </div>
  145. </template>
  146. <script>
  147. import PanelGroup from './dashboard/PanelGroup'
  148. import taskStockLogEcharts from '@/views/components/echarts/taskStockLog.vue'
  149. // import lendAcross from '@/views/components/echarts/lendAcross.vue'
  150. // import catePie from '@/views/components/echarts/catePie.vue'
  151. // import typePie from '@/views/components/echarts/typePie.vue'
  152. import bookSwiper from '@/views/components/bookSwiper.vue'
  153. import checkSwiper from '@/views/components/checkSwiper.vue'
  154. import serverProgress from '@/views/components/echarts/serverProgress.vue'
  155. import serverGpu from '@/views/components/echarts/serverGpu.vue'
  156. import serverGpuUse from '@/views/components/echarts/serverGpuUse.vue'
  157. import serverGpuOther from '@/views/components/echarts/serverGpuOther.vue'
  158. import serveTerminal from '@/views/components/serveTerminal.vue'
  159. import { FetchInitHomeInfo, FetchInitStockInfo } from '@/api/stockTask/index'
  160. import { FetchInitStockLogList } from '@/api/stockTaskLog/index'
  161. import { FetchSystemInfo } from '@/api/home/cpu/index'
  162. import { mapGetters } from 'vuex'
  163. import { swiper, swiperSlide } from 'vue-awesome-swiper'
  164. import 'swiper/dist/css/swiper.css'
  165. export default {
  166. name: 'Dashboard',
  167. components: {
  168. PanelGroup,
  169. // lendAcross,
  170. taskStockLogEcharts,
  171. // catePie,
  172. bookSwiper,
  173. checkSwiper,
  174. // typePie,
  175. serverProgress,
  176. serverGpu,
  177. serverGpuUse,
  178. serverGpuOther,
  179. serveTerminal,
  180. swiper,
  181. swiperSlide
  182. },
  183. data() {
  184. return {
  185. topObjectNum: {
  186. regionCount: 0,
  187. shelfCount: 0,
  188. gridCount: 0,
  189. deviceCount: 0,
  190. noStockGridCount: 0,
  191. deviceErrorCount: 0
  192. },
  193. taskStockLogData: [],
  194. echartsTimer: null,
  195. refreshtime: 10000,
  196. systemTimer: null,
  197. systemData: {
  198. cpuPercentage: 0,
  199. memPercentage: 0,
  200. sysFilesPercentage: 0
  201. },
  202. stockLogCompletedData: [],
  203. stockLogIncompleteData: [],
  204. archivesTotalNum: 0,
  205. flowableData: [],
  206. flowableTabIndex: 0,
  207. lendData: {
  208. archivesTotalNum: null,
  209. otherData: []
  210. },
  211. cateData: [],
  212. typeData: [],
  213. addArcivesData: {
  214. addArcivesMaxCount: null,
  215. addArcivesMonth: [],
  216. addArcivesNum: [],
  217. addArcivesNumFile: []
  218. },
  219. swiperActiveIndex: 0,
  220. swiperOptionServer: {
  221. autoplay: {
  222. delay: 8000,
  223. disableOnInteraction: false
  224. },
  225. slidesPerView: 'auto',
  226. pagination: {
  227. el: '.swiper-pagination',
  228. clickable: true
  229. }
  230. },
  231. memoryFree: 0,
  232. memoryTotal: 0,
  233. GPUName: '',
  234. temperature: 0,
  235. utilization: 0
  236. }
  237. },
  238. computed: {
  239. ...mapGetters([
  240. 'user'
  241. ]),
  242. swiperServer() {
  243. return this.$refs.swiperServer.$el.swiper
  244. }
  245. },
  246. created() {
  247. this.handleMainData()
  248. this.getSystemInfo()
  249. this.getStockLog()
  250. this.handleInitStockInfo()
  251. this.$nextTick(() => {
  252. this.$refs.bookSwiperRefs.swiperParams = {}
  253. this.$refs.bookSwiperRefs.swiperShelfParams = {}
  254. if (this.$refs.bookSwiperRefs.swiperActiveIndex === 0) {
  255. this.$refs.bookSwiperRefs.getInitHotBookList()
  256. } else {
  257. this.$refs.bookSwiperRefs.getInitHotShelfList()
  258. }
  259. this.$refs.serveTerminalRefs.initData()
  260. })
  261. },
  262. mounted() {
  263. // const _this = this
  264. // // 每隔一分钟刷新档案借阅和档案类型的数据
  265. // this.echartsTimer = setInterval(() => {
  266. // _this.lendData = {
  267. // archivesTotalNum: null,
  268. // otherData: []
  269. // }
  270. // _this.cateData = []
  271. // _this.typeData = []
  272. // _this.addArcivesData = {
  273. // addArcivesMaxCount: null,
  274. // addArcivesMonth: [],
  275. // addArcivesNum: [],
  276. // addArcivesNumFile: []
  277. // }
  278. // _this.handleMainData()
  279. // }, this.refreshtime)
  280. // 服务器监控定时更新
  281. // this.systemTimer = setInterval(() => {
  282. // _this.systemData = {
  283. // cpuPercentage: 0,
  284. // memPercentage: 0,
  285. // sysFilesPercentage: 0
  286. // }
  287. // this.getSystemInfo()
  288. // }, 3000)
  289. },
  290. methods: {
  291. getSystemInfo() {
  292. FetchSystemInfo().then(res => {
  293. // cpu 占有率 (总的cpuTotal-空闲的cpuFree)/总的cpuTotal
  294. this.systemData.cpuPercentage = Math.round((res.cpuTotal - res.cpuFree) / res.cpuTotal * 100)
  295. // 内存占比 使用的memUsed/总的memTotal
  296. this.systemData.memPercentage = Math.round(res.memUsed / res.memTotal * 100)
  297. this.memoryFree = res.memoryFree
  298. this.memoryTotal = res.memoryTotal
  299. this.GPUName = res.GPUName
  300. this.temperature = res.temperature
  301. this.utilization = res.utilization
  302. // 磁盘占比 多个磁盘 使用总和sysFiles[i].used的和/总的总和sysFiles[i].total的和
  303. let sysFilesTotalUsed = 0
  304. let sysFilesTotal = 0
  305. res.sysFiles.forEach(item => {
  306. sysFilesTotalUsed += parseFloat(item.used)
  307. sysFilesTotal += parseFloat(item.total)
  308. })
  309. this.systemData.sysFilesPercentage = Math.round((sysFilesTotalUsed / sysFilesTotal) * 100)
  310. })
  311. },
  312. refreshSystemData() {
  313. this.systemData = {
  314. cpuPercentage: 0,
  315. memPercentage: 0,
  316. sysFilesPercentage: 0
  317. }
  318. this.memoryFree = 0
  319. this.memoryTotal = 0
  320. this.GPUName = ''
  321. this.temperature = 0
  322. this.utilization = 0
  323. this.getSystemInfo()
  324. this.$refs.serveTerminalRefs.initData()
  325. },
  326. getStockLog() {
  327. FetchInitStockLogList().then(res => {
  328. this.stockLogCompletedData = res.content.filter(item => [0, 3].includes(item.state))
  329. this.stockLogIncompleteData = res.content.filter(item => [1, 2].includes(item.state))
  330. })
  331. },
  332. handleMainData() {
  333. FetchInitHomeInfo().then(data => {
  334. this.topObjectNum = {
  335. regionCount: data.regionCount,
  336. shelfCount: data.shelfCount,
  337. gridCount: data.gridCount,
  338. deviceCount: data.deviceCount,
  339. noStockGridCount: data.noStockGridCount,
  340. deviceErrorCount: data.deviceErrorCount
  341. }
  342. })
  343. },
  344. handleInitStockInfo(params) {
  345. FetchInitStockInfo(params).then(res => {
  346. this.taskStockLogData = [
  347. { value: res.onShelfNum - res.errorShelfNum - res.errorOrderNum, name: '正常在架' },
  348. { value: res.errorShelfNum, name: '错架' },
  349. { value: res.errorOrderNum, name: '错序' }
  350. ]
  351. }).catch(() => {
  352. })
  353. }
  354. }
  355. }
  356. </script>
  357. <style rel="stylesheet/scss" lang="scss" scoped>
  358. .dashboard-editor-container {
  359. padding: 20px;
  360. position: relative;
  361. .chart-wrapper {
  362. height: calc(100% - 120px);
  363. }
  364. }
  365. @media (max-width: 1024px) {
  366. .chart-wrapper {
  367. padding: 8px;
  368. }
  369. }
  370. .el-col {
  371. height: 100%;
  372. }
  373. .container-left,
  374. .container-right,
  375. .container-wrap,
  376. .el-card,
  377. .header-container-wrap {
  378. min-height: 100%;
  379. }
  380. .container-wrap {
  381. min-height: auto;
  382. height: 100%;
  383. }
  384. .home-item-title{
  385. position: relative;
  386. padding: 18px 0 18px 15px;
  387. font-size: 16px;
  388. color: #0C0E1E;
  389. &::before{
  390. position: absolute;
  391. left: 0;
  392. top: 50%;
  393. content: "";
  394. width: 3px;
  395. height: 16px;
  396. background-color: #0348F3;
  397. transform: translateY(-50%);
  398. }
  399. }
  400. .home-flowable{
  401. padding: 0 20px;
  402. }
  403. .home-tab{
  404. display: flex;
  405. justify-content: flex-start;
  406. span{
  407. display: block;
  408. margin-right: 30px;
  409. padding-bottom: 3px;
  410. border-bottom: 3px solid #fff;
  411. &.home-tab-active{
  412. color: #0348F3;
  413. // border-bottom: 3px solid #0348F3;
  414. }
  415. }
  416. }
  417. ::v-deep .home-flowable-list .el-table__body-wrapper::-webkit-scrollbar {
  418. width: 5px !important;
  419. height: 5px !important;
  420. background-color: #DDE8FB !important;
  421. }
  422. ::v-deep .home-flowable-list .el-table__body-wrapper::-webkit-scrollbar-thumb {
  423. border-radius: 3px;
  424. background-color: #4578F6 !important;
  425. }
  426. ::v-deep .home-flowable-list .el-table__body-wrapper::-webkit-scrollbar-thumb:hover {
  427. background-color: #4578F6 !important;
  428. }
  429. ::v-deep .home-flowable-list .el-table__body-wrapper::-webkit-scrollbar-corner {
  430. background-color: #DDE8FB !important;
  431. }
  432. .refresh-date{
  433. position: absolute;
  434. right: 14px;
  435. top: 10px;
  436. font-size: 12px;
  437. line-height: 30px;
  438. }
  439. .swiper-server{
  440. position: relative;
  441. height: 300px;
  442. ::v-deep .swiper-wrapper{
  443. height: 344px;
  444. }
  445. .swiper-pagination{
  446. bottom: 80px;
  447. }
  448. }
  449. .cpu-echarts{
  450. position: relative;
  451. display: flex;
  452. justify-content: flex-start;
  453. align-items: center;
  454. // background-color: #000;
  455. .cpu-right{
  456. flex: 1;
  457. height: 100%;
  458. display: flex;
  459. justify-content: flex-start;
  460. // flex-direction: column;
  461. // flex-wrap: wrap;
  462. }
  463. }
  464. </style>