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

1051 lines
38 KiB

5 months ago
5 months ago
5 months ago
5 months ago
5 months ago
5 months ago
5 months ago
5 months ago
5 months ago
5 months ago
1 month ago
5 months ago
1 month ago
5 months ago
1 month ago
5 months ago
1 month ago
5 months ago
5 months ago
5 months ago
5 months ago
5 months ago
5 months ago
5 months ago
5 months ago
1 month ago
5 months ago
1 month ago
5 months ago
5 months ago
5 months ago
5 months ago
5 months ago
1 month ago
5 months ago
5 months ago
5 months ago
5 months ago
5 months ago
5 months ago
5 months ago
1 month ago
5 months ago
5 months ago
1 month ago
5 months ago
  1. <template>
  2. <div style="padding: 0 .4rem;">
  3. <div class="pageOne-database" style="height: 6.25rem !important; ">
  4. <!-- 到馆统计 -->
  5. <div class="database-left">
  6. <h3 class="database-title">到馆统计</h3>
  7. <ul class="inLib-num">
  8. <!-- , {'lastYearTotal': item.id === 'lastYearTotal'} -->
  9. <li
  10. v-for="item in leftData"
  11. :key="item.timestamp"
  12. :class="[{'totayTotal': item.id === 'totayTotal'}]"
  13. >
  14. <div class="pageLeft-flop-box">
  15. <div>
  16. <span v-for="(ls, i) in item.valueArr" :key="item.id + i" :class="[{'flop-figure': !isNaN(ls)}, {'flop-comma': isNaN(ls)}]">
  17. <i v-if="!isNaN(ls)">0123456789</i>
  18. <span v-else>{{ ls }}</span>
  19. </span>
  20. <em></em>
  21. </div>
  22. </div>
  23. <div class="flop-item-name">{{ item.name }}</div>
  24. </li>
  25. </ul>
  26. <ul class="pageOne-left-progress">
  27. <li v-for="(item,index) in progressData" :key="index" :class="[{'blue-progress':item.type===1 || item.type === 2},{'orange-progress':item.type===3 || item.type === 4}]">
  28. <p>{{ item.name }}</p>
  29. <span class="progress-num">{{ item.value }}<i></i></span>
  30. <el-progress :percentage="computedPercentage(item)" :stroke-width="8" :show-text="false" />
  31. </li>
  32. </ul>
  33. </div>
  34. <div class="database-middle">
  35. <div class="middle-img">
  36. <div class="middle-img-book" />
  37. <div class="wq" />
  38. <!-- <div class="line-box">
  39. <div class="box">
  40. <div class="ball" />
  41. </div>
  42. </div> -->
  43. <div class="middle-img-bottom">
  44. <!-- width: 360px; height: 200px; margin: 50px 0 0 30px; -->
  45. <div style="position: relative; margin: 50px 0 0 20px;">
  46. <svg width="360" height="200">
  47. <path d="M0 80 S 170 160, 400 70" />
  48. </svg>
  49. <div class="rect qxRect" />
  50. </div>
  51. </div>
  52. <div class="middle-img-dot" />
  53. </div>
  54. <div v-for="(item,index) in middleData" :key="index" :class="['middle2-item', {'totalBook': item.id === 'totalBook'}, {'fansNum': item.id === 'fansNum'}, {'lendingNum': item.id === 'lendingNum'}, {'cardNum': item.id === 'cardNum'}]">
  55. <p>{{ item.name }}</p>
  56. <div class="middle-num">
  57. <div class="small-module">
  58. <div class="chartNum">
  59. <div class="box-items">
  60. <li v-for="(e,i) in item.valueArr" :key="i" :class="!isNaN(e) ? 'number-item':'number-item num-dot'">
  61. <span v-if="!isNaN(e)" class="items-int"><i ref="numberItem" class="item">0123456789</i></span>
  62. <span v-else>{{ e }}</span>
  63. <!-- <span><i ref="numberItem" class="item">0123456789</i></span> -->
  64. </li>
  65. </div>
  66. </div>
  67. </div>
  68. <span v-if="item.id === 'totalBook'" class="middle-unit"></span>
  69. <span v-if="item.id === 'fansNum'" class="middle-unit"></span>
  70. <span v-if="item.id === 'cardNum'" class="middle-unit"></span>
  71. <span v-if="item.id === 'lendingNum'" class="middle-unit"></span>
  72. </div>
  73. </div>
  74. </div>
  75. <!-- 热门搜索 -->
  76. <div class="database-right">
  77. <h3 class="database-title">热门搜索</h3>
  78. <div class="tagcloud-main">
  79. <div v-if="tagList.length !== 0" id="tagscloud" ref="tagcloudall" class="tagscloud">
  80. <!-- <a v-for="(item,index) in hotTagData" :key="index" :class="'tagc' + ((index % 4) + 1)">
  81. {{ item }}
  82. </a> -->
  83. <a v-for="(item,index) in tagList" :key="index" :class="'tagc' + ((index % 4) + 1)">{{ item }}</a>
  84. </div>
  85. </div>
  86. </div>
  87. </div>
  88. <!-- 底部 图书推荐 -->
  89. <div class="pageOne-book" style="margin-top: .13rem !important;">
  90. <!-- <h3 class="database-title">图书推荐</h3> -->
  91. <div class="pageOne-book-content" style="padding: .2rem 0 !important;">
  92. <div class="scrollBox">
  93. <vue-seamless-scroll
  94. ref="listData"
  95. :data="listData1"
  96. :class-option="defaultOption"
  97. class="seamless01"
  98. >
  99. <ul>
  100. <li v-for="(item, index) in listData1" :key="index">
  101. <div class="bord">
  102. <div class="book-img">
  103. <img :src="item.nbImgPath" :onerror="defaultImg">
  104. </div>
  105. </div>
  106. </li>
  107. </ul>
  108. </vue-seamless-scroll>
  109. <vue-seamless-scroll
  110. ref="listData2"
  111. :data="listData2"
  112. :class-option="default2Option"
  113. class="seamless02"
  114. >
  115. <ul>
  116. <li v-for="(item, index) in listData2" :key="index">
  117. <div class="bord">
  118. <div class="book-img">
  119. <img :src="item.nbImgPath" :onerror="defaultImg">
  120. </div>
  121. </div>
  122. </li>
  123. </ul>
  124. </vue-seamless-scroll>
  125. </div>
  126. <div style=" writing-mode: vertical-rl; padding: 0 .38rem 0 .5rem; font-size: .5rem; letter-spacing: 8px;">热门图书推荐</div>
  127. <!-- <div class="wechat-code">
  128. <div class="wechat-img">
  129. <img :src="wecharQrCodeSrc">
  130. </div>
  131. <span>微信扫一扫关注</span>
  132. </div> -->
  133. </div>
  134. </div>
  135. </div>
  136. </template>
  137. <script>
  138. // FetchFansCount
  139. // FetchLibBookTotal 暂时隐藏,因为馆藏量暂时写死
  140. import { FetchInitSetting, FetchInitIntoNum, FetchUsertotal, FetchHotSearch, FetchLendingTotal, FetchNewBook, FetchMarcByISBN } from '@/api/library'
  141. export default {
  142. name: 'PageOne',
  143. data() {
  144. return {
  145. intervalLeft: null,
  146. isDataLoaded: false,
  147. pageOneVisitBase: '0', // 本年到馆基础数
  148. wecharQrCodeSrc: null,
  149. newList: [],
  150. listData1: [],
  151. listData2: [],
  152. defaultImg: 'this.src="' + require('@/assets/images/book_03.png') + '"',
  153. leftData: [],
  154. progressData: [],
  155. hotTagData: [],
  156. middleData: [],
  157. tagList: [],
  158. // 热门搜索的
  159. radius: 160,
  160. dtr: Math.PI / 180,
  161. d: 200,
  162. mcList: [],
  163. active: false,
  164. lasta: 1,
  165. lastb: 1,
  166. distr: true,
  167. tspeed: 4,
  168. size: 200,
  169. mouseX: 0,
  170. mouseY: 20,
  171. howElliptical: 1,
  172. oList: null,
  173. oA: null,
  174. sa: 0,
  175. ca: 0,
  176. sb: 0,
  177. cb: 0,
  178. sc: 0,
  179. cc: 0
  180. }
  181. },
  182. computed: {
  183. defaultOption() {
  184. return {
  185. step: 0.5, // 数值越大速度滚动越快
  186. limitMoveNum: 4, // 开始无缝滚动的数据量 this.dataList.length
  187. hoverStop: true, // 是否开启鼠标悬停stop
  188. direction: 2, // 0向下 1向上 2向左 3向右
  189. openWatch: true, // 开启数据实时监控刷新dom
  190. singleHeight: 0, // 单步运动停止的高度(默认值0是无缝不停止的滚动) direction => 0/1
  191. singleWidth: 0, // 单步运动停止的宽度(默认值0是无缝不停止的滚动) direction => 2/3
  192. waitTime: 1000 // 单步运动停止的时间(默认值1000ms)
  193. }
  194. },
  195. default2Option() {
  196. return {
  197. step: 0.5, // 数值越大速度滚动越快
  198. limitMoveNum: 4, // 开始无缝滚动的数据量 this.dataList.length
  199. hoverStop: true, // 是否开启鼠标悬停stop
  200. direction: 3, // 0向下 1向上 2向左 3向右
  201. openWatch: true, // 开启数据实时监控刷新dom
  202. singleHeight: 0, // 单步运动停止的高度(默认值0是无缝不停止的滚动) direction => 0/1
  203. singleWidth: 0, // 单步运动停止的宽度(默认值0是无缝不停止的滚动) direction => 2/3
  204. waitTime: 1000 // 单步运动停止的时间(默认值1000ms)
  205. }
  206. },
  207. computedPercentage() {
  208. return (item) => {
  209. if (item.type === 1) {
  210. return item.value > this.getType3Value() ? 100 : 70
  211. } else if (item.type === 2) {
  212. return item.value > this.getType4Value() ? 100 : 70
  213. } else if (item.type === 3) {
  214. return item.value > this.getType1Value() ? 100 : 70
  215. } else if (item.type === 4) {
  216. return item.value > this.getType2Value() ? 100 : 70
  217. }
  218. }
  219. }
  220. },
  221. async created() {
  222. if (localStorage.getItem('yesterdayCountCache')) {
  223. localStorage.removeItem('yesterdayCountCache')
  224. }
  225. if (localStorage.getItem('lastMonthCountCache')) {
  226. localStorage.removeItem('lastMonthCountCache')
  227. }
  228. // this.getInitData()
  229. // this.getMiddleAllData()
  230. this.getHotSearch()
  231. this.getNewBook()
  232. },
  233. beforeDestroy() {
  234. clearInterval(this.intervalLeft)
  235. this.intervalLeft = null
  236. },
  237. activated() {
  238. this.pageOneVisitBase = 0
  239. this.getInitData()
  240. this.getMiddleAllData()
  241. },
  242. deactivated() {
  243. clearInterval(this.intervalLeft)
  244. this.intervalLeft = null
  245. },
  246. mounted() {
  247. // this.getTest()
  248. if (localStorage.getItem('wecharQrCodeSrc')) {
  249. this.wecharQrCodeSrc = localStorage.getItem('wecharQrCodeSrc')
  250. }
  251. },
  252. methods: {
  253. // getTest() {
  254. // const resData = {
  255. // 'errCode': 0,
  256. // 'errMsg': 'ok',
  257. // 'data': '{"success":true,"resultlist":[{"JCC_YEAR":0,"HRC_MONTH":0,"HCC_MONTH":0,"HCC":11,"JCC":0,"JRC_DAY":0,"JRC_YEAR":0,"HRC_YEAR":1,"BZL_MONTH":0,"JRC_MONTH":0,"HCC_DAY":0,"BZL":2,"HRC":1,"JCC_DAY":0,"JRC":0,"BZL_YEAR":1,"HCC_YEAR":11,"BZL_DAY":0,"HRC_DAY":0,"JCC_MONTH":0,"LIBCODE":"999"},{"JCC_YEAR":21822,"HRC_MONTH":296,"HCC_MONTH":770,"HCC":98972,"JCC":123736,"JRC_DAY":2,"JRC_YEAR":2837,"HRC_YEAR":2167,"BZL_MONTH":158,"JRC_MONTH":409,"HCC_DAY":0,"BZL":9814,"HRC":30813,"JCC_DAY":3,"JRC":39642,"BZL_YEAR":929,"HCC_YEAR":20298,"BZL_DAY":0,"HRC_DAY":0,"JCC_MONTH":1085,"LIBCODE":"GD"},{"JCC_YEAR":195,"HRC_MONTH":25,"HCC_MONTH":46,"HCC":106,"JCC":195,"JRC_DAY":1,"JRC_YEAR":102,"HRC_YEAR":62,"BZL_MONTH":0,"JRC_MONTH":38,"HCC_DAY":77,"BZL":2,"HRC":62,"JCC_DAY":9,"JRC":102,"BZL_YEAR":2,"HCC_YEAR":106,"BZL_DAY":0,"HRC_DAY":1,"JCC_MONTH":81,"LIBCODE":"DWSF"},{"JCC_YEAR":92,"HRC_MONTH":12,"HCC_MONTH":18,"HCC":65,"JCC":92,"JRC_DAY":0,"JRC_YEAR":46,"HRC_YEAR":36,"BZL_MONTH":0,"JRC_MONTH":19,"HCC_DAY":0,"BZL":0,"HRC":36,"JCC_DAY":0,"JRC":46,"BZL_YEAR":0,"HCC_YEAR":65,"BZL_DAY":0,"HRC_DAY":0,"JCC_MONTH":37,"LIBCODE":"ZJWSF"}]}'
  258. // }
  259. // const result = JSON.parse(resData.data)
  260. // console.log('【解析后的完整结果】', result)
  261. // if (result.success & result.resultlist.length !== 0) {
  262. // const filterData = result.resultlist.filter(item => item.LIBCODE === 'DWSF')
  263. // console.log('【过滤出 DWSF 的数据】', filterData)
  264. // // 4. 累加 JCC_DAY 并打印累加过程 借
  265. // const total = filterData.reduce((acc, obj) => {
  266. // console.log(`【累加过程】当前累计值:${acc} + 当前项 JCC_DAY:${obj.JCC_DAY} = ${acc + obj.JCC_DAY}`)
  267. // return acc + obj.JCC_DAY
  268. // }, 0)
  269. // // 还
  270. // const totalH = filterData.reduce((acc, obj) => {
  271. // console.log(`【累加过程】当前累计值:${acc} + 当前项 JCC_DAY:${obj.HCC_DAY} = ${acc + obj.HCC_DAY}`)
  272. // return acc + obj.HCC_DAY
  273. // }, 0)
  274. // // 5. 打印最终结果
  275. // console.log('借', total)
  276. // console.log('还', totalH)
  277. // return total
  278. // } else {
  279. // console.log('【执行结果】数据获取失败或无结果,返回 0')
  280. // return 0
  281. // }
  282. // },
  283. getInitData() {
  284. // visitBase 本年到馆基础数
  285. // wecharQrCode 二维码 用/downloadFile/+wecharQrCode
  286. // iNotice 公告
  287. const linkSrc = process.env.NODE_ENV === 'production' ? window.g.ApiUrl : process.env.VUE_APP_BASE_API
  288. console.log('linkSrc', linkSrc)
  289. FetchInitSetting().then(res => {
  290. const result = JSON.parse(res.data)
  291. this.pageOneVisitBase = result.visitBase
  292. this.wecharQrCodeSrc = linkSrc + '/downloadFile' + result.wecharQrCode
  293. // this.initLeftPreview(result)
  294. this.initIntoNum()
  295. })
  296. },
  297. initIntoNum() {
  298. // 初始化数据,使用更语义化的变量名
  299. this.progressData = []
  300. this.leftData = []
  301. FetchInitIntoNum()
  302. .then(res => {
  303. const result = res?.data || {}
  304. const progressDataConfig = [
  305. // { name: '今日出馆', key: 'dayOutNUm', type: 3 },
  306. { name: '本月到馆', key: 'monthPeopleNum', type: 3 },
  307. { name: '本年到馆', key: 'historyPeopleNum', type: 1 }
  308. ]
  309. this.progressData = progressDataConfig.map(item => ({
  310. name: item.name,
  311. value: result[item.key] || 0,
  312. type: item.type
  313. }))
  314. // 处理今日到馆数据,抽离变量提高可读性
  315. const dayPeopleNum = result.dayPeopleNum || 0
  316. const formattedNum = this.$parent.formatter(dayPeopleNum)
  317. const newData = [{
  318. id: 'totayTotal',
  319. name: '今日到馆',
  320. value: formattedNum,
  321. valueArr: formattedNum.split(''),
  322. timestamp: Date.now()
  323. }]
  324. // 更新数据
  325. this.$set(this, 'leftData', newData)
  326. this.$parent.timedRefresh(this.leftData, 'left')
  327. })
  328. .catch(error => {
  329. console.error('获取入馆数据失败:', error)
  330. })
  331. },
  332. initLeftPreview(result) {
  333. this.progressData = []
  334. this.leftData = []
  335. // visitBase 本年累计人次
  336. // visitBaseCheck 是否直接显示 0false 1true
  337. // lastYearVisitBase 去年累计人次
  338. // todayVisitBase 今日人次
  339. // todayVisitBaseCheck 是否显示
  340. // yesterdayVisitBase 昨天人次
  341. // yesterdayVisitBaseCheck 是否显示
  342. // thisMonthVisitBase 本月人次
  343. // thisMonthVisitBaseCheck 是否显示
  344. // lastMonthVisitBase 上个月人次
  345. // lastMonthVisitBaseCheck 是否显示
  346. const baseTotal = this.pageOneVisitBase // 本年到馆人数
  347. console.log('假设本年到馆人数', baseTotal)
  348. // 本年到馆/12个月 = 月基数
  349. const monthBase = Math.floor(baseTotal / 12) // 月基数
  350. console.log('月基数', monthBase)
  351. // 月随机数(-100到200之间)
  352. const randomMonth = Math.floor(Math.random() * (200 - (-100) + 1)) + (-100)
  353. const now = new Date()
  354. const year = now.getFullYear() // 当前年份
  355. const month = now.getMonth() + 1 // 当前月份
  356. const daysInMonth = new Date(year, month, 0).getDate() // 当月天数
  357. console.log('当月天数', daysInMonth)
  358. // 月基数/当月天数(28、29、30、31)= 日基数
  359. const dayBase = Math.floor(monthBase / daysInMonth) // 日基数
  360. console.log('日基数', dayBase)
  361. // 本年累计=月基数*月份+月随机数(-100到200之间)
  362. let nowYearCount
  363. if (result.visitBaseCheck === '1') {
  364. nowYearCount = result.visitBase
  365. } else {
  366. nowYearCount = Math.floor(monthBase * month + randomMonth) // 本年累计
  367. }
  368. console.log('本年累计', nowYearCount)
  369. // 昨日到馆=日基数+日随机数(-20到50之间)
  370. let yesterdayCount = 0
  371. if (result.yesterdayVisitBaseCheck === '1') {
  372. yesterdayCount = result.yesterdayVisitBase
  373. } else {
  374. const randomDay = Math.floor(Math.random() * (50 - (-20) + 1)) + (-20) // 日随机数(-20到50之间)
  375. // yesterdayCount = localStorage.getItem('yesterdayCountCache') ? localStorage.getItem('yesterdayCountCache') : dayBase + randomDay // 昨日到馆
  376. yesterdayCount = dayBase + randomDay // 昨日到馆
  377. }
  378. console.log('昨日到馆', yesterdayCount)
  379. // 上月到馆=月基数+月随机数(-100到200之间)
  380. let lastMonthCount = 0
  381. if (result.lastMonthVisitBaseCheck === '1') {
  382. lastMonthCount = result.lastMonthVisitBase
  383. } else {
  384. // lastMonthCount = localStorage.getItem('lastMonthCountCache') ? localStorage.getItem('lastMonthCountCache') : monthBase + randomMonth
  385. lastMonthCount = monthBase + randomMonth
  386. }
  387. console.log('上月到馆', lastMonthCount)
  388. // 日基数/10小时=小时基数
  389. const hourBase = Math.floor(dayBase / 10) // 小时基数
  390. console.log('小时基数', hourBase)
  391. // 图书馆营业时间(8:00-18:00共10小时)
  392. // 8:00-9:00 算第1个小时、9:00-10:00算第2个小时、以此类推
  393. const openTime = 8 // 开门时间
  394. const closeTime = 18 // 结束时间
  395. const currentHour = now.getHours() // 当前时间点
  396. // 今日到馆=小时基数 * 第N小时+小时随机数(-5到10之间)
  397. let todayCount = 0
  398. if (result.todayVisitBaseCheck === '1') {
  399. todayCount = result.todayVisitBase
  400. } else {
  401. if (currentHour < openTime || currentHour >= closeTime) {
  402. console.log('当前时间不在图书馆营业时间内')
  403. todayCount = 0
  404. } else {
  405. const N = currentHour - openTime
  406. // console.log('第N个小时', N)
  407. const randomHour = Math.floor(Math.random() * (10 - (-5) + 1)) + (-5) // 小时随机数(-5到10之间)
  408. todayCount = Math.floor(hourBase * N + randomHour) // 今日到馆
  409. }
  410. }
  411. console.log('今日到馆', todayCount)
  412. // 本月到馆=月基数 * (当前月的日期dd/当前月的天数)+ 月随机数(-100到200之间)
  413. let nowMonthCount = 0
  414. if (result.thisMonthVisitBaseCheck === '1') {
  415. nowMonthCount = result.thisMonthVisitBase
  416. } else {
  417. if (now.getDate() === 1) {
  418. nowMonthCount = todayCount
  419. } else {
  420. nowMonthCount = Math.floor(monthBase * (now.getDate() / daysInMonth) + randomMonth) // 本月到馆
  421. }
  422. }
  423. console.log('本月到馆', nowMonthCount)
  424. this.progressData.push(
  425. // {
  426. // name: '今日到馆',
  427. // value: result.todayVisitBase,
  428. // type: 1
  429. // },
  430. {
  431. name: '本年到馆',
  432. value: result.visitBase,
  433. type: 1
  434. },
  435. {
  436. name: '本月到馆',
  437. value: result.thisMonthVisitBase,
  438. type: 2
  439. },
  440. // {
  441. // name: '昨日到馆',
  442. // value: result.yesterdayVisitBase,
  443. // type: 3
  444. // },
  445. {
  446. name: '去年到馆',
  447. value: result.lastYearVisitBase,
  448. type: 3
  449. },
  450. {
  451. name: '上月到馆',
  452. value: result.lastMonthVisitBase,
  453. type: 4
  454. }
  455. )
  456. // this.leftData.push(
  457. // {
  458. // // name: '今日到馆',
  459. // // value: result.todayVisitBase,
  460. // // type: 1
  461. // id: 'totayTotal',
  462. // name: '今日到馆',
  463. // value: this.$parent.formatter(result.todayVisitBase),
  464. // valueArr: this.$parent.formatter(result.todayVisitBase)
  465. // }
  466. // // {
  467. // // id: 'allTotal',
  468. // // name: '本年累计到馆',
  469. // // value: this.$parent.formatter(result.visitBase),
  470. // // valueArr: this.$parent.formatter(result.visitBase).split('')
  471. // // },
  472. // // {
  473. // // id: 'lastYearTotal',
  474. // // name: '去年累计到馆',
  475. // // value: this.$parent.formatter(result.lastYearVisitBase),
  476. // // valueArr: this.$parent.formatter(result.lastYearVisitBase).split('')
  477. // // }
  478. // )
  479. // 更新数据
  480. const newData = [{
  481. id: 'totayTotal',
  482. name: '今日到馆',
  483. value: this.$parent.formatter(result.todayVisitBase),
  484. valueArr: this.$parent.formatter(result.todayVisitBase).split(''),
  485. timestamp: Date.now()
  486. }]
  487. this.$set(this, 'leftData', newData)
  488. this.$parent.timedRefresh(this.leftData, 'left')
  489. // 昨日到馆、上月到馆存一个缓存!当前第一次计算好之后就不变了!
  490. // localStorage.setItem('yesterdayCountCache', yesterdayCount)
  491. // localStorage.setItem('lastMonthCountCache', lastMonthCount)
  492. },
  493. // 热门搜索
  494. getHotSearch() {
  495. const params = {
  496. 'size': 40
  497. }
  498. FetchHotSearch(params).then(res => {
  499. // this.hotTagData = res.data.replace(/^\[|\]$/g, '').split(', ')
  500. this.hotTagData = ['儒林外史', '七色花', '灰尘的旅行', '余华', '伍美珍', '石刻', '龙族', '骆驼祥子', '克雷洛夫寓言', '东野圭吾', '郁雨君', '汤姆索亚历险记', '中国古代寓言故事', '哪吒闹海', '三毛流浪记', '神笔马良', '中国古代寓言', '伊索寓言', '爱的教育', '看看我们的地球', '查理', '小鲤鱼跳龙门', '尼尔斯骑鹅旅行记', '窄门', '童年', '白洋淀纪事', '愿望的实现', '宝葫芦的秘密', '张居正', '许三观卖血记', '山海经', '查理九世', '论语', '红鞋子', '孤独的小螃蟹', '兄弟', '阳光姐姐', '李四光', '乡土中国', '读读童谣和儿歌']
  501. this.$nextTick(() => {
  502. this.tagList = this.hotTagData
  503. this.onReady()
  504. })
  505. })
  506. },
  507. getMiddleAllData() {
  508. this.middleData = []
  509. Promise.all([
  510. this.getLibBookTotal(),
  511. this.getUserTotal(),
  512. this.getLendingData()
  513. ]).then(([libBookTotal, userCardNum, lendingData]) => {
  514. const { fansNum, lendingTotal } = lendingData
  515. this.middleData.push(
  516. {
  517. id: 'totalBook',
  518. name: '藏书总量',
  519. value: libBookTotal,
  520. valueArr: this.$parent.formatter(libBookTotal).toString().split('')
  521. },
  522. {
  523. id: 'cardNum',
  524. name: '累计办证',
  525. value: userCardNum,
  526. valueArr: this.$parent.formatter(userCardNum).toString().split('')
  527. },
  528. {
  529. id: 'fansNum',
  530. name: '今日归还',
  531. value: fansNum,
  532. valueArr: this.$parent.formatter(fansNum).toString().split('')
  533. },
  534. {
  535. id: 'lendingNum',
  536. name: '今日借出',
  537. value: lendingTotal,
  538. valueArr: this.$parent.formatter(lendingTotal).toString().split('')
  539. }
  540. )
  541. this.$parent.timedRefresh(this.middleData, 'middle')
  542. }).catch(error => {
  543. console.error('获取中间数据失败:', error)
  544. })
  545. },
  546. // 馆藏量
  547. getLibBookTotal() {
  548. // const params = {
  549. // 'libcode': this.libcode,
  550. // 'starttime': '2000-01-01',
  551. // 'endtime': '2034-01-01'
  552. // }
  553. // return FetchLibBookTotal(params).then(res => {
  554. // const result = JSON.parse(res.data)
  555. // if (result.success & result.resultlist.length !== 0) {
  556. // return result.resultlist.reduce((acc, obj) => acc + obj.GCL, 0)
  557. // } else {
  558. // return 9145
  559. // }
  560. // }).catch(error => {
  561. // console.error('Error', error)
  562. // return 0
  563. // })
  564. return Promise.resolve(9145)
  565. },
  566. // 累计办证
  567. getTotalForLibcode(libcode) {
  568. const params = {
  569. 'libcode': libcode,
  570. // 'startdate': this.getFormattedDate(new Date(), -1),
  571. // 'enddate': this.getFormattedDate(new Date()),
  572. 'startdate': '2010-01-01',
  573. 'enddate': this.getFormattedDate(new Date()),
  574. 'isrdtype': 0
  575. }
  576. return FetchUsertotal(params).then(res => {
  577. const result = JSON.parse(res.data)
  578. if (result.success && result.pagedata.length > 0) {
  579. return result.pagedata[0].count
  580. } else {
  581. throw new Error('Failed')
  582. }
  583. }).catch(error => {
  584. console.error('Error', error)
  585. return 0
  586. })
  587. },
  588. getUserTotal() {
  589. const libraries = ['GD']
  590. const getTotalPromises = libraries.map(libcode => this.getTotalForLibcode(libcode))
  591. return Promise.all(getTotalPromises)
  592. .then(counts => counts.reduce((sum, count) => sum + parseInt(count, 10), 0))
  593. .catch(error => {
  594. console.error('Error', error)
  595. return 0
  596. })
  597. },
  598. getLendingData() {
  599. return FetchLendingTotal().then(res => {
  600. const result = JSON.parse(res.data)
  601. const dwsfData = result.success && result.resultlist.length
  602. ? result.resultlist.filter(item => item.LIBCODE === 'DWSF')
  603. : []
  604. // 归还
  605. const fansNum = dwsfData.reduce((acc, obj) => acc + obj.HCC_DAY, 0)
  606. // 借出
  607. const lendingTotal = dwsfData.reduce((acc, obj) => acc + obj.JCC_DAY, 0)
  608. return { fansNum, lendingTotal }
  609. }).catch(error => {
  610. console.error('获取借阅数据失败:', error)
  611. return { fansNum: 0, lendingTotal: 0 }
  612. })
  613. },
  614. // 粉丝数量
  615. // getFansNum() {
  616. // return FetchFansCount().then(res => {
  617. // return res.data ? parseInt(res.data) : 0
  618. // }).catch(error => {
  619. // console.error('Error', error)
  620. // return 0
  621. // })
  622. // },
  623. // 今日归还
  624. // getFansNum() {
  625. // return FetchLendingTotal().then(res => {
  626. // const result = JSON.parse(res.data)
  627. // if (result.success && result.resultlist.length !== 0) {
  628. // return result.resultlist.filter(item => item.LIBCODE === 'DWSF').reduce((acc, obj) => acc + obj.HCC_DAY, 0)
  629. // } else {
  630. // return 0
  631. // }
  632. // }).catch(error => {
  633. // console.error('Error', error)
  634. // return 0
  635. // })
  636. // },
  637. // 今日借出
  638. // getLendingTotal() {
  639. // return FetchLendingTotal().then(res => {
  640. // const result = JSON.parse(res.data)
  641. // if (result.success && result.resultlist.length !== 0) {
  642. // return result.resultlist.filter(item => item.LIBCODE === 'DWSF').reduce((acc, obj) => acc + obj.JCC_DAY, 0)
  643. // } else {
  644. // return 0
  645. // }
  646. // }).catch(error => {
  647. // console.error('Error', error)
  648. // return 0
  649. // })
  650. // },
  651. // bottom - 图书推荐
  652. getNewBook() {
  653. const params = {
  654. 'size': 40
  655. }
  656. FetchNewBook(params).then(res => {
  657. // 图片地址格式 http://192.168.99.67:8080/downloadFile/qytsg/ae281b90-b100-4541-9379-3e104854652c.png
  658. const linkSrc = process.env.NODE_ENV === 'production' ? window.g.ApiUrl : process.env.VUE_APP_BASE_API
  659. this.newList = res.data.map(item => {
  660. if (item.nbImgPath) {
  661. item.nbImgPath = linkSrc + '/downloadFile' + item.nbImgPath
  662. return Promise.resolve(item)
  663. } else {
  664. const params = {
  665. 'sIsbn': item.isbn
  666. }
  667. return FetchMarcByISBN(params).then(response => {
  668. const result = JSON.parse(response.data)[0]
  669. if (result.srcurl) {
  670. item.nbImgPath = result.srcurl
  671. return item
  672. } else if (result.img) {
  673. item.nbImgPath = 'data:image/png;base64,' + result.img
  674. return item
  675. } else {
  676. return null // 或者根据需求返回其他值或处理
  677. }
  678. })
  679. }
  680. })
  681. Promise.all(this.newList).then(results => {
  682. // 过滤掉返回的空项(根据实际需求)
  683. this.newList = results.filter(item => item !== null)
  684. // 一分为二得两行
  685. const halfLength = Math.ceil(this.newList.length / 2)
  686. this.listData1 = this.newList.slice(0, halfLength)
  687. this.listData2 = this.newList.slice(halfLength)
  688. })
  689. })
  690. },
  691. getType1Value() {
  692. const type1Item = this.progressData.find(item => item.type === 1)
  693. return type1Item ? type1Item.value : 0
  694. },
  695. getType2Value() {
  696. const type2Item = this.progressData.find(item => item.type === 2)
  697. return type2Item ? type2Item.value : 0
  698. },
  699. getType3Value() {
  700. const type3Item = this.progressData.find(item => item.type === 3)
  701. return type3Item ? type3Item.value : 0
  702. },
  703. getType4Value() {
  704. const type4Item = this.progressData.find(item => item.type === 4)
  705. return type4Item ? type4Item.value : 0
  706. },
  707. // 以下生成云标签部分
  708. // 三角函数角度计算
  709. sineCosine(a, b, c) {
  710. this.sa = Math.sin(a * this.dtr)
  711. this.ca = Math.cos(a * this.dtr)
  712. this.sb = Math.sin(b * this.dtr)
  713. this.cb = Math.cos(b * this.dtr)
  714. this.sc = Math.sin(c * this.dtr)
  715. this.cc = Math.cos(c * this.dtr)
  716. },
  717. // 设置初始定位
  718. positionAll() {
  719. this.$nextTick(() => { // 注意: 所有的在onReady方法中执行的方法都需要$nextTick确保所有的标签都已经渲染
  720. var phi = 0
  721. var theta = 0
  722. var max = this.mcList.length
  723. var aTmp = []
  724. var oFragment = document.createDocumentFragment()
  725. // 随机排序
  726. for (let i = 0; i < this.tagList.length; i++) {
  727. aTmp.push(this.oA[i])
  728. }
  729. aTmp.sort(() => {
  730. return Math.random() < 0.5 ? 1 : -1
  731. })
  732. for (let i = 0; i < aTmp.length; i++) {
  733. oFragment.appendChild(aTmp[i])
  734. }
  735. this.oList.appendChild(oFragment)
  736. for (let i = 1; i < max + 1; i++) {
  737. if (this.distr) {
  738. phi = Math.acos(-1 + (2 * i - 1) / max)
  739. theta = Math.sqrt(max * Math.PI) * phi
  740. } else {
  741. phi = Math.random() * (Math.PI)
  742. theta = Math.random() * (2 * Math.PI)
  743. }
  744. this.radius = this.oList.offsetWidth / 2 - 40
  745. // 坐标变换
  746. this.mcList[i - 1].cx = this.radius * Math.cos(theta) * Math.sin(phi)
  747. this.mcList[i - 1].cy = this.radius * Math.sin(theta) * Math.sin(phi)
  748. this.mcList[i - 1].cz = this.radius * Math.cos(phi)
  749. this.oA[i - 1].style.left = this.mcList[i - 1].cx + this.oList.offsetWidth / 2 - this.mcList[i - 1].offsetWidth / 2 + 'px'
  750. this.oA[i - 1].style.top = this.mcList[i - 1].cy + this.oList.offsetHeight / 2 - this.mcList[i - 1].offsetHeight / 2 + 'px'
  751. }
  752. })
  753. },
  754. // 坐标更新 让标签动起来
  755. update() {
  756. this.$nextTick(() => { // 注意: 所有的在onReady方法中执行的方法都需要$nextTick确保所有的标签都已经渲染
  757. var a
  758. var b
  759. // if (this.active) {
  760. a = (Math.min(Math.max(-this.mouseY, -this.size), this.size) / this.radius) * this.tspeed
  761. b = (-Math.min(Math.max(-this.mouseX, -this.size), this.size) / this.radius) * this.tspeed
  762. // } else {
  763. // a = this.lasta * 0.98
  764. // b = this.lastb * 0.98
  765. // }
  766. this.lasta = a
  767. this.lastb = b
  768. if (Math.abs(a) <= 0.01 && Math.abs(b) <= 0.01) {
  769. return
  770. }
  771. var c = 0
  772. this.sineCosine(a, b, c)
  773. for (var j = 0; j < this.mcList.length; j++) {
  774. if (this.mcList[j].on) {
  775. continue
  776. }
  777. var rx1 = this.mcList[j].cx
  778. var ry1 = this.mcList[j].cy * this.ca + this.mcList[j].cz * (-this.sa)
  779. var rz1 = this.mcList[j].cy * this.sa + this.mcList[j].cz * this.ca
  780. var rx2 = rx1 * this.cb + rz1 * this.sb
  781. var ry2 = ry1
  782. var rz2 = rx1 * (-this.sb) + rz1 * this.cb
  783. var rx3 = rx2 * this.cc + ry2 * (-this.sc)
  784. var ry3 = rx2 * this.sc + ry2 * this.cc
  785. var rz3 = rz2
  786. this.mcList[j].cx = rx3
  787. this.mcList[j].cy = ry3
  788. this.mcList[j].cz = rz3
  789. var per = this.d / (this.d + rz3)
  790. this.mcList[j].x = (this.howElliptical * rx3 * per) - (this.howElliptical * 2)
  791. this.mcList[j].y = ry3 * per
  792. this.mcList[j].scale = per
  793. var alpha = per
  794. alpha = (alpha - 0.6) * (10 / 6)
  795. this.mcList[j].alpha = alpha * alpha * alpha - 0.2
  796. // this.mcList[j].alpha = (this.mcList[j].alpha - 0.6) * (10 / 6)
  797. this.mcList[j].zIndex = Math.ceil(100 - Math.floor(this.mcList[j].cz))
  798. }
  799. this.doPosition()
  800. this.depthSort()
  801. })
  802. },
  803. //
  804. doPosition() {
  805. this.$nextTick(() => { // 注意: 所有的在onReady方法中执行的方法都需要$nextTick确保所有的标签都已经渲染
  806. var l = this.oList.offsetWidth / 2
  807. var t = this.oList.offsetHeight / 2
  808. for (var i = 0; i < this.mcList.length; i++) {
  809. this.oA[i].style.left = this.mcList[i].cx + l - this.mcList[i].offsetWidth / 2 + 'px'
  810. this.oA[i].style.top = this.mcList[i].cy + t - this.mcList[i].offsetHeight / 2 + 'px'
  811. // this.oA[i].style.fontSize = Math.ceil(12 * this.mcList[i].scale / 2) + 8 + 'px'
  812. this.oA[i].style.filter = 'alpha(opacity=' + 100 * this.mcList[i].alpha + ')'
  813. this.oA[i].style.opacity = this.mcList[i].alpha
  814. }
  815. })
  816. },
  817. depthSort() {
  818. this.$nextTick(() => { // 注意: 所有的在onReady方法中执行的方法都需要$nextTick确保所有的标签都已经渲染
  819. var aTmp = []
  820. for (let i = 0; i < this.oA.length; i++) {
  821. aTmp.push(this.oA[i])
  822. }
  823. aTmp.sort(function(vItem1, vItem2) {
  824. if (vItem1.cz > vItem2.cz) {
  825. return -1
  826. } else if (vItem1.cz < vItem2.cz) {
  827. return 1
  828. } else {
  829. return 0
  830. }
  831. })
  832. for (let i = 0; i < aTmp.length; i++) {
  833. aTmp[i].style.zIndex = i
  834. }
  835. })
  836. },
  837. onReady() {
  838. this.$nextTick(() => {
  839. this.oList = this.$refs.tagcloudall
  840. this.oA = this.oList.getElementsByTagName('a')
  841. var oTag = null
  842. for (var i = 0; i < this.oA.length; i++) {
  843. oTag = {}
  844. oTag.offsetWidth = this.oA[i].offsetWidth
  845. oTag.offsetHeight = this.oA[i].offsetHeight
  846. this.mcList.push(oTag)
  847. }
  848. this.sineCosine(0, 0, 0)
  849. this.positionAll()
  850. this.oList.onmouseover = () => {
  851. this.active = true
  852. }
  853. this.oList.onmouseout = () => {
  854. this.active = false
  855. }
  856. // this.oList.onmousemove = (event) => {
  857. // var oEvent = window.event || event
  858. // this.mouseX = oEvent.clientX - (this.oList.offsetLeft + this.oList.offsetWidth / 2)
  859. // this.mouseY = oEvent.clientY - (this.oList.offsetTop + this.oList.offsetHeight / 2)
  860. // this.mouseX /= 5
  861. // this.mouseY /= 5
  862. // }
  863. setInterval(() => {
  864. this.update()
  865. }, 40) // 定时器执行 不能写setInterval(this.update(), 30)
  866. })
  867. }
  868. }
  869. }
  870. </script>
  871. <style lang="scss">
  872. @import "~@/assets/styles/index.scss";
  873. @import "~@/assets/styles/font-some.css";
  874. #tagscloud{
  875. width:5rem;
  876. height:4.75rem;
  877. position:relative;
  878. margin:0 auto;
  879. }
  880. #tagscloud a{
  881. position:absolute;
  882. top:0px;
  883. left:0px;
  884. line-height:24px;
  885. text-align:center;
  886. font-size:18px;
  887. padding:3px 5px;
  888. display:inline-block;
  889. text-wrap: nowrap;
  890. }
  891. #tagscloud a.tagc1{
  892. // border: 1px solid #30ADA6;
  893. // background-color: #106B66;
  894. // color: #51EAE2;
  895. color: #F4C263;
  896. }
  897. #tagscloud a.tagc2{
  898. font-size: 22px;
  899. // border: 1px solid #3A64BE;
  900. // background: rgba(16,45,107,0.7);
  901. color: #7EA7FF;
  902. }
  903. #tagscloud a.tagc3{
  904. font-size: 18px;
  905. // border: 1px solid #9439B6;
  906. // background: rgba(74,18,95,0.8);
  907. // color: #CD63F4;
  908. color: #7EA7FF;
  909. }
  910. #tagscloud a.tagc4{
  911. font-size: 26px;
  912. // border: 1px solid #C2943C;
  913. // background: rgba(107,76,16,0.7);
  914. color: #F4C263;
  915. }
  916. .tagcloud {
  917. width: 10rem;
  918. height: 5rem;
  919. overflow: hidden;
  920. p{
  921. padding: .0625rem;
  922. border-bottom: 2px dashed rgba(24, 77, 97, 0.5);
  923. span{
  924. display: block;
  925. padding: .075rem 8px;
  926. white-space: nowrap;
  927. }
  928. &.color1{
  929. border-top: 2px dashed #1F6374;
  930. border-left: 3px dashed #184D61;
  931. border-right: 3px dashed #184D61;
  932. span{
  933. border: 1px solid #30ADA6;
  934. background-color: #106B66;
  935. color: #51EAE2;
  936. }
  937. }
  938. &.color2{
  939. border-top: 2px dashed #203F7F;
  940. border-left: 3px dashed #102857;
  941. border-right: 3px dashed #102857;
  942. span{
  943. border: 1px solid #3A64BE;
  944. background: rgba(16,45,107,0.7);
  945. color: #7EA7FF;
  946. }
  947. }
  948. &.color3{
  949. border-top: 2px dashed #613689;
  950. border-left: 3px dashed #4C2E75;
  951. border-right: 3px dashed #4C2E75;
  952. span{
  953. border: 1px solid #9439B6;
  954. background: rgba(74,18,95,0.8);
  955. color: #CD63F4;
  956. }
  957. }
  958. &.color4{
  959. border-top: 2px dashed #6A5735;
  960. border-left: 3px dashed #655435;
  961. border-right: 3px dashed #655435;
  962. span{
  963. border: 1px solid #C2943C;
  964. background: rgba(107,76,16,0.7);
  965. color: #F4C263;
  966. }
  967. }
  968. }
  969. }
  970. .scrollBox{
  971. flex: 1;
  972. height: calc(100%);
  973. box-sizing: border-box;
  974. margin-left: 0.45rem;
  975. overflow: hidden;
  976. .seamless01{
  977. margin-bottom: .35rem;
  978. }
  979. ul{
  980. display: flex;
  981. height: 2rem;
  982. // overflow: hidden;
  983. li{
  984. width: 1.375rem;
  985. height: 2rem;
  986. margin-right: .7375rem;
  987. cursor: pointer;
  988. .bord{
  989. display: flex;
  990. flex-wrap: wrap;
  991. justify-content: space-around;
  992. align-items: center;
  993. .book-img{
  994. width: 1.375rem;
  995. height: 2rem;
  996. // background: url('~@/assets/images/book_03.png') no-repeat center center;
  997. // background-size: contain;
  998. display: flex;
  999. align-items: center;
  1000. overflow: hidden;
  1001. img{
  1002. display: block;
  1003. width: 100%;
  1004. }
  1005. }
  1006. }
  1007. }
  1008. }
  1009. }
  1010. </style>