大湾社区城市书房智慧大屏
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.

474 lines
19 KiB

1 month ago
1 month ago
1 month ago
1 month ago
1 month ago
1 month ago
1 month ago
1 month ago
1 month ago
1 month ago
1 month ago
1 month ago
1 month ago
1 month ago
  1. <!-- eslint-disable no-prototype-builtins -->
  2. <template>
  3. <div class="page-wrapper ">
  4. <div class="page-three">
  5. <div class="three-item three01">
  6. <div class="database-title">本年累计借阅数量</div>
  7. <div class="three-lending">
  8. <div class="three-lending-left">
  9. <h5>本年累计借阅</h5>
  10. <ul class="totalItem">
  11. <li
  12. v-for="(item, index) in yearTotal"
  13. :key="index"
  14. :class="[{'yearTotal': item.id === 'yearTotal'}]"
  15. >
  16. <div class="pageLeft-flop-box">
  17. <div>
  18. <span v-for="(ls, i) in item.valueArr" :key="item.id + i" :class="[{'flop-figure': !isNaN(ls)}, {'flop-comma': isNaN(ls)}]">
  19. <i v-if="!isNaN(ls)">0123456789</i>
  20. <!-- <span v-else>{{ ls }}</span> -->
  21. </span>
  22. </div>
  23. </div>
  24. </li>
  25. </ul>
  26. <YearCircle :year-all-num="yearAllNum" />
  27. </div>
  28. <div class="three-lending-right lending-ranking">
  29. <h5>分馆累计借阅排行榜</h5>
  30. <div class="ranking-cont">
  31. <ul class="ranking-title">
  32. <li style="width: 0.625rem;">排名</li>
  33. <li style="width: 1.875rem; text-align: left;">图书馆名称</li>
  34. <li style="flex:1;" />
  35. <li style="width: 1.25rem; padding-right: .125rem; text-align: right;">借阅数量</li>
  36. </ul>
  37. <ul class="ranking-list">
  38. <li v-for="(item,index) in rankingYearWithPercentage" :key="index" :class="{ 'hovered': index === currentHover }">
  39. <div style="width: .625rem; color: #79B8FF;" :class="[{'ranking-num1':index===0},{'ranking-num2':index===1},{'ranking-num3':index===2}]">{{ index>=3 ? index+1 : null }}</div>
  40. <div style="width: 1.75rem; text-align: left;">{{ item.name }}</div>
  41. <div class="ranking-progress" style="flex:1; align-self: center;">
  42. <el-progress :percentage="item.percentage" :stroke-width="8" :show-text="false" color="#009afb" />
  43. </div>
  44. <div style="width: 1.25rem; padding-right: .125rem; text-align: right;">{{ item.JCC_YEAR }}<i style="padding-left:.0625rem;"></i></div>
  45. </li>
  46. </ul>
  47. <!-- <swiper v-if="rankingYearWithPercentage.length > 1 && isKeep" ref="swiperThumbs" class="swiper ranking-list" :options="swiperOptionThumbs">
  48. <swiper-slide v-for="(item,index) in rankingYearWithPercentage" :key="index">
  49. <div class="ranking-item">
  50. <div style="width: .625rem; color: #79B8FF;" :class="[{'ranking-num1':index===0},{'ranking-num2':index===1},{'ranking-num3':index===2}]">{{ index>=3 ? index+1 : null }}</div>
  51. <div style="width: 1.875rem; text-align: left;">{{ item.name }}</div>
  52. <div class="ranking-progress" style="flex:1; align-self: center;">
  53. <el-progress :percentage="item.percentage" :stroke-width="8" :show-text="false" color="#009afb" />
  54. </div>
  55. <div style="width: 1.25rem; padding-right: .125rem; text-align: right;">{{ item.JCC_YEAR }}<i style="padding-left:.0625rem;"></i></div>
  56. </div>
  57. </swiper-slide>
  58. </swiper> -->
  59. </div>
  60. </div>
  61. </div>
  62. </div>
  63. <div class="three-item three02">
  64. <div class="database-title">今日借阅数量</div>
  65. <div class="three-lending">
  66. <div class="three-lending-left">
  67. <h5>今日累计借阅</h5>
  68. <ul class="totalItem">
  69. <li
  70. v-for="(item, index) in todayTotal"
  71. :key="index"
  72. :class="[{'todayTotal': item.id === 'todayTotal'}]"
  73. >
  74. <div class="pageLeft-flop-box">
  75. <div>
  76. <span v-for="(ls, i) in item.valueArr" :key="item.id + i" :class="[{'flop-figure': !isNaN(ls)}, {'flop-comma': isNaN(ls)}]">
  77. <i v-if="!isNaN(ls)">0123456789</i>
  78. <!-- <span v-else>{{ ls }}</span> -->
  79. </span>
  80. </div>
  81. </div>
  82. </li>
  83. </ul>
  84. <TodayCircle :today-all-num="todayAllNum" />
  85. </div>
  86. <div class="three-lending-right lending-ranking">
  87. <h5>分馆今日借阅排行榜 </h5>
  88. <div class="ranking-cont">
  89. <ul class="ranking-title">
  90. <li style="width: 0.625rem;">排名</li>
  91. <li style="width: 1.5rem; text-align: left;">图书馆名称</li>
  92. <li style="flex:1;" />
  93. <li style="width: 1.25rem; padding-right: .125rem; text-align: right;">借阅数量</li>
  94. </ul>
  95. <ul class="ranking-list">
  96. <li v-for="(item,index) in rankingTodayWithPercentage" :key="index" :class="{ 'hovered': index === currentHover }">
  97. <div style="width: 0.625rem; color: #79B8FF;" :class="[{'ranking-num1':index===0},{'ranking-num2':index===1},{'ranking-num3':index===2}]">{{ index>=3 ? index+1 : null }}</div>
  98. <div style="width: 1.75rem; text-align: left;">{{ item.name }}</div>
  99. <div class="ranking-progress" style="flex:1; align-self: center;">
  100. <el-progress :percentage="item.percentage" :stroke-width="8" :show-text="false" color="#009afb" />
  101. </div>
  102. <div style="width: 1.25rem; padding-right: .125rem; text-align: right;">{{ item.JCC_DAY }}<i style="padding-left:.0625rem;"></i></div>
  103. </li>
  104. </ul>
  105. <!-- <swiper v-if="rankingTodayWithPercentage.length > 1 && isKeep" ref="swiperThumbs" class="swiper ranking-list" :options="swiperOptionThumbs">
  106. <swiper-slide v-for="(item,index) in rankingTodayWithPercentage" :key="index">
  107. <div class="ranking-item">
  108. <div style="width: .625rem; color: #79B8FF;" :class="[{'ranking-num1':index===0},{'ranking-num2':index===1},{'ranking-num3':index===2}]">{{ index>=3 ? index+1 : null }}</div>
  109. <div style="width: 1.875rem; text-align: left;">{{ item.name }}</div>
  110. <div class="ranking-progress" style="flex:1; align-self: center;">
  111. <el-progress :percentage="item.percentage" :stroke-width="8" :show-text="false" color="#009afb" />
  112. </div>
  113. <div style="width: 1.25rem; padding-right: .125rem; text-align: right;">{{ item.JCC_DAY }}<i style="padding-left:.0625rem;"></i></div>
  114. </div>
  115. </swiper-slide>
  116. </swiper> -->
  117. </div>
  118. </div>
  119. </div>
  120. </div>
  121. <div class="three-item three03">
  122. <div class="database-title">今日借阅趋势</div>
  123. <div class="chart-wrapper" style="width: 11.25rem; height: calc(100% - 35px);">
  124. <LineChart :chart-day-data="chartDayData" />
  125. </div>
  126. </div>
  127. <div class="three-item three04">
  128. <div class="database-title">近7日借阅统计</div>
  129. <div class="chart-wrapper" style="width: 11.25rem; height: calc(100% - 20px);">
  130. <BarEcharts :chart-weekly-data="chartWeeklyData" />
  131. </div>
  132. </div>
  133. </div>
  134. </div>
  135. </template>
  136. <script>
  137. import { FetchLibcodeDetails, FetchLendingTotal, FetchTodayJH, FetchWeekJH } from '@/api/library'
  138. import LineChart from '@/components/echart/lineChart'
  139. import BarEcharts from '@/components/echart/barEcharts'
  140. import YearCircle from '@/components/echart/yearCircle'
  141. import TodayCircle from '@/components/echart/todayCircle'
  142. // import { swiper, swiperSlide } from 'vue-awesome-swiper'
  143. // import 'swiper/dist/css/swiper.css'
  144. export default {
  145. name: 'PageThree',
  146. components: {
  147. LineChart,
  148. BarEcharts,
  149. YearCircle,
  150. TodayCircle
  151. // swiper,
  152. // swiperSlide
  153. },
  154. data() {
  155. return {
  156. currentHover: -1,
  157. chartDayData: {
  158. timeData: [],
  159. returnData: [],
  160. borrowedData: []
  161. },
  162. chartWeeklyData: {
  163. date: [],
  164. inchartWeeklyData: [],
  165. outchartWeeklyData: []
  166. },
  167. todayTotal: [],
  168. yearTotal: [],
  169. rankingYearData: [],
  170. rankingTodayData: [],
  171. rankingYearWithPercentage: [],
  172. rankingTodayWithPercentage: [],
  173. yearAllNum: {
  174. headerLib: 0,
  175. branchLib: 0
  176. },
  177. todayAllNum: {
  178. headerLib: 0,
  179. branchLib: 0
  180. },
  181. rankInterval: null,
  182. swiperOptionThumbs: {
  183. direction: 'vertical',
  184. loopedSlides: 6,
  185. slidesPerView: 6,
  186. slidesPerGroup: 6,
  187. // loop: true,
  188. // centeredSlides: true,
  189. autoplay: {
  190. delay: 3000,
  191. stopOnLastSlide: false,
  192. disableOnInteraction: true
  193. }
  194. },
  195. isKeep: false
  196. }
  197. },
  198. computed: {
  199. swiper() {
  200. return this.$refs.swiperThumbs.swiper
  201. }
  202. },
  203. beforeDestroy() {
  204. clearInterval(this.rankInterval)
  205. this.rankInterval = null
  206. },
  207. created() {
  208. this.getWeekJH()
  209. },
  210. activated() {
  211. this.getLendingTotal()
  212. this.getTodayJH()
  213. this.isKeep = true
  214. // if (this.rankingYearWithPercentage.length !== 0) {
  215. // this.currentHover = -1
  216. // this.rankInterval = setInterval(() => {
  217. // this.currentHover = (this.currentHover + 1) % this.rankingYearWithPercentage.length
  218. // }, 1000)
  219. // }
  220. },
  221. deactivated() {
  222. clearInterval(this.rankInterval)
  223. this.rankInterval = null
  224. this.isKeep = false
  225. },
  226. mounted() {
  227. // this.getLendingTotal()
  228. // this.getTodayJH()
  229. },
  230. methods: {
  231. paddingNum(num, length) {
  232. for (var len = (num + '').length; len < length; len = num.length) {
  233. num = '0' + num
  234. }
  235. return num
  236. },
  237. // 获取本年/今日借阅情况
  238. getLendingTotal() {
  239. this.todayTotal = []
  240. this.yearTotal = []
  241. FetchLendingTotal().then(res => {
  242. const result = JSON.parse(res.data)
  243. if (result.success & result.resultlist.length !== 0) {
  244. // JCC_YEAR 本年借阅册数
  245. // JCC_DAY 今日借阅册数
  246. const dayNum = result.resultlist.filter(item => item.LIBCODE === 'DWSF').reduce((acc, obj) => acc + obj.JCC_DAY, 0)
  247. const yearNum = result.resultlist.filter(item => item.LIBCODE === 'DWSF').reduce((acc, obj) => acc + obj.JCC_YEAR, 0)
  248. this.todayTotal.push({
  249. id: 'todayTotal',
  250. name: '今日累计借阅',
  251. value: this.$parent.formatter(this.paddingNum(dayNum, 5)),
  252. valueArr: this.$parent.formatter(this.paddingNum(dayNum, 5)).split('')
  253. })
  254. this.yearTotal.push({
  255. id: 'yearTotal',
  256. name: '本年累计借阅',
  257. value: this.$parent.formatter(this.paddingNum(yearNum, 5)),
  258. valueArr: this.$parent.formatter(this.paddingNum(yearNum, 5)).split('')
  259. })
  260. // 总管就是QYTSG的数据,分馆就是其他除去999以为的合计
  261. this.yearAllNum = {
  262. 'headerLib': result.resultlist.filter(item => item.LIBCODE === 'DWSF')[0].JCC_YEAR,
  263. 'branchLib': result.resultlist.filter(item => item.LIBCODE === 'ZJWSF' && item.LIBCODE !== '999').reduce((acc, obj) => acc + obj.JCC_YEAR, 0)
  264. }
  265. this.todayAllNum = {
  266. 'headerLib': result.resultlist.filter(item => item.LIBCODE === 'DWSF')[0].JCC_DAY,
  267. 'branchLib': result.resultlist.filter(item => item.LIBCODE === 'ZJWSF' && item.LIBCODE !== '999').reduce((acc, obj) => acc + obj.JCC_DAY, 0)
  268. }
  269. // 排行榜显示前6的
  270. this.getLibcodeDetails(result.resultlist)
  271. this.$parent.timedRefresh(this.todayTotal, 'todayTotal')
  272. this.$parent.timedRefresh(this.yearTotal, 'yearTotal')
  273. } else {
  274. this.todayTotal = []
  275. this.yearTotal = []
  276. }
  277. }).catch(error => {
  278. console.error('Error', error)
  279. })
  280. },
  281. // 分管显示内容
  282. getLibcodeDetails(data) {
  283. FetchLibcodeDetails().then(res => {
  284. const result = JSON.parse(res.data)
  285. if (result.length !== 0) {
  286. const newDataArray = []
  287. data.forEach(item => {
  288. const foundItem = result.find(library => library.tcId === item.LIBCODE)
  289. if (foundItem) {
  290. const yearValue = item.JCC_YEAR || 0
  291. const dayValue = item.JCC_DAY || 0
  292. const newObj = {
  293. name: foundItem.name,
  294. JCC_YEAR: yearValue,
  295. JCC_DAY: dayValue
  296. }
  297. newDataArray.push(newObj)
  298. }
  299. })
  300. // 2. 根据JCC_YEAR的值进行降序排序
  301. this.rankingYearData = newDataArray.sort((a, b) => b.JCC_YEAR - a.JCC_YEAR)
  302. // this.rankingYearWithPercentage = this.rankingDataComputed(this.rankingYearData, 'JCC_YEAR')
  303. // 不滚动只显示6条
  304. this.rankingYearWithPercentage = this.rankingDataComputed(this.rankingYearData, 'JCC_YEAR').splice(0, 6)
  305. // 3. 根据JCC_DAY的值进行降序排序
  306. this.rankingTodayData = newDataArray.sort((a, b) => b.JCC_DAY - a.JCC_DAY)
  307. // this.rankingYearWithPercentage = this.rankingDataComputed(this.rankingYearData, 'JCC_YEAR')
  308. // 不滚动只显示6条
  309. this.rankingTodayWithPercentage = this.rankingDataComputed(this.rankingTodayData, 'JCC_DAY').splice(0, 6)
  310. // 不滚动只显示6条
  311. this.rankInterval = setInterval(() => {
  312. this.currentHover = (this.currentHover + 1) % this.rankingYearWithPercentage.length
  313. }, 1000)
  314. }
  315. }).catch(error => {
  316. console.error('Error', error)
  317. })
  318. },
  319. rankingDataComputed(rankingData, numType) {
  320. if (!rankingData || rankingData.length === 0) {
  321. console.log('没有数据')
  322. return []
  323. }
  324. // eslint-disable-next-line no-prototype-builtins
  325. // if (typeof rankingData[0] !== 'object' || !rankingData[0].hasOwnProperty(numType)) {
  326. // return []
  327. // }
  328. const firstPlaceNum = rankingData[0][numType] // NAN
  329. if (firstPlaceNum === 0) {
  330. // 处理除数为0的情况
  331. console.log('firstPlaceNum为0,不可用于被除')
  332. return rankingData.map(item => {
  333. return { ...item, percentage: 0 } // 直接将 percentage 设置为 0
  334. })
  335. }
  336. return rankingData.map(item => {
  337. const percentage = (item[numType] / firstPlaceNum) * 100
  338. return { ...item, percentage }
  339. })
  340. },
  341. // 今日借还
  342. getTodayJH() {
  343. FetchTodayJH().then(res => {
  344. this.chartDayData = {
  345. timeData: [],
  346. returnData: [],
  347. borrowedData: []
  348. }
  349. const result = res.data
  350. const time = ['07:00', '08:00', '09:00', '10:00', '11:00', '12:00', '13:00', '14:00', '15:00', '16:00', '17:00', '18:00']
  351. time.forEach((hour, index) => {
  352. // 查找 result 中是否有对应的 logHour
  353. const foundItem = result.find(item => item.logHour === index + 7) // 因为 logHour 是从 7 开始,所以需要加上 7
  354. if (foundItem) {
  355. // 如果找到了对应的 logHour,则将数据加入 chartDayData
  356. this.chartDayData.timeData.push(`${foundItem.logHour}:00`)
  357. this.chartDayData.returnData.push(foundItem.hccDay)
  358. this.chartDayData.borrowedData.push(foundItem.jccDay)
  359. } else {
  360. // 如果没找到对应的 logHour,则将默认值加入 chartDayData
  361. this.chartDayData.timeData.push(`${hour}`)
  362. this.chartDayData.returnData.push(0) // 默认值为 0
  363. this.chartDayData.borrowedData.push(0) // 默认值为 0
  364. }
  365. })
  366. }).catch(error => {
  367. console.error('Error', error)
  368. })
  369. },
  370. getWeekJH() {
  371. FetchWeekJH().then(res => {
  372. this.chartWeeklyData = {
  373. date: [],
  374. inchartWeeklyData: [],
  375. outchartWeeklyData: []
  376. }
  377. const result = res.data
  378. console.log('result', result)
  379. // 获取当天日期
  380. const currentDate = new Date()
  381. const today = currentDate.toISOString().slice(0, 10)
  382. // 根据数据排除当天的数据
  383. const filteredData = result.filter(entry => {
  384. const entryDate = new Date(entry.createTime).toISOString().slice(0, 10)
  385. return entryDate !== today
  386. })
  387. // 获取过去一周的
  388. const pastWeekDates = []
  389. for (let i = 1; i <= 7; i++) {
  390. const date = new Date()
  391. date.setDate(currentDate.getDate() - i)
  392. pastWeekDates.push(date.toISOString().slice(0, 10))
  393. }
  394. console.log('filteredData', filteredData)
  395. const matchData = filteredData.reduce((accData, item) => {
  396. // 根据已有的数据获取相关日期
  397. const entryDate = new Date(item.createTime).toISOString().slice(0, 10)
  398. if (accData[entryDate]) {
  399. accData[entryDate].jccDayTotal += item.jccDayTotal
  400. accData[entryDate].hccDayTotal += item.hccDayTotal
  401. } else {
  402. accData[entryDate] = {
  403. jccDayTotal: item.jccDayTotal,
  404. hccDayTotal: item.hccDayTotal
  405. }
  406. }
  407. return accData
  408. }, {})
  409. console.log('matchData', matchData)
  410. const completeData = pastWeekDates.map(date => ({
  411. date: date.split('-').join('/'),
  412. jccDayTotal: matchData[date] ? matchData[date].jccDayTotal : 0,
  413. hccDayTotal: matchData[date] ? matchData[date].hccDayTotal : 0
  414. }))
  415. // 根据时间排序
  416. completeData.sort((a, b) => new Date(a.date) - new Date(b.date))
  417. console.log('completeData', completeData)
  418. // 日期X轴数据
  419. this.chartWeeklyData.date = completeData.map(item => item.date)
  420. // in 归还
  421. this.chartWeeklyData.inchartWeeklyData = completeData.map(item => item.hccDayTotal)
  422. // // out 借出
  423. this.chartWeeklyData.outchartWeeklyData = completeData.map(item => item.jccDayTotal)
  424. console.log('this.chartWeeklyData', this.chartWeeklyData)
  425. }).catch(error => {
  426. console.error('Error', error)
  427. })
  428. }
  429. }
  430. }
  431. </script>
  432. <style lang="scss">
  433. @import "~@/assets/styles/index.scss";
  434. @import "~@/assets/styles/font-some.css";
  435. // .swiper {
  436. // width: 100%;
  437. // height: 3rem !important;
  438. // .swiper-slide {
  439. // height: .5rem !important;
  440. // }
  441. // .swiper-slide-active,
  442. // .swiper-slide-duplicate-active{
  443. // // background-color: #142B76;
  444. // // border-radius: .05rem;
  445. // // animation: myListScale 1s forwards;
  446. // }
  447. // }
  448. // @keyframes myListScale {
  449. // to {
  450. // -webkit-transform: scaleX(1) scaleY(1);
  451. // transform: scaleX(1) scaleY(1);
  452. // }
  453. // }
  454. </style>