图书馆小程序
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.

300 lines
7.8 KiB

2 months ago
2 months ago
1 month ago
2 months ago
1 month ago
2 months ago
1 month ago
2 months ago
1 month ago
1 month ago
1 month ago
1 month ago
2 months ago
1 month ago
2 months ago
1 month ago
2 months ago
2 months ago
2 months ago
1 month ago
1 month ago
2 months ago
1 month ago
2 months ago
1 month ago
2 months ago
1 month ago
2 months ago
1 month ago
2 months ago
1 month ago
2 months 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 month ago
1 month ago
1 month ago
1 month ago
1 month ago
2 months ago
2 months ago
2 months ago
1 month ago
2 months ago
2 months ago
1 month ago
2 months ago
1 month ago
1 month ago
1 month ago
1 month ago
2 months ago
2 months ago
  1. <template>
  2. <view>
  3. <view class="ranking-header">
  4. <image
  5. class="ranking-heander-bg"
  6. src="@/static/images/ranking-bg.png"
  7. mode="aspectFill"
  8. />
  9. <view class="ranking-header-txt">
  10. <view class="ranking-title">
  11. <uni-icons custom-prefix="iconfont" type="icon-paihangbang2" size="20"></uni-icons>
  12. <text class="title-text">读者借阅排行</text>
  13. </view>
  14. <text class="ranking-header-tip">由本图书馆近30天读者借阅次数生成排行榜单</text>
  15. </view>
  16. </view>
  17. <view class="ranking-list">
  18. <!-- 加载中状态 -->
  19. <view class="loading" v-if="loading">
  20. <uni-icons type="loading" size="40" color="#01a4fe" spin></uni-icons>
  21. <text>加载中...</text>
  22. </view>
  23. <!-- 空状态 -->
  24. <view class="empty" v-else-if="rankingData.length === 0">
  25. <uni-icons style="margin-left: 20px;" custom-prefix="iconfont" type="icon-kongshuju" size="80" color="#ccc"></uni-icons>
  26. <text style="margin-top: 20px;">暂无读者排行数据</text>
  27. </view>
  28. <view
  29. class="ranking-item"
  30. :class="[
  31. index === 0 ? 'first-item' : '',
  32. index === 1 ? 'two-item' : '',
  33. index === 2 ? 'three-item' : ''
  34. ]"
  35. v-for="(item, index) in rankingData"
  36. :key="index"
  37. v-else
  38. >
  39. <!-- 第一名 -->
  40. <uni-icons class="ranking-icon" v-if="index === 0" custom-prefix="iconfont" type="icon-TOP2" size="26" color="#E6CB97"></uni-icons>
  41. <!-- 第二名 -->
  42. <uni-icons class="ranking-icon" v-if="index === 1" custom-prefix="iconfont" type="icon-TOP" size="26" color="#a2b2c3"></uni-icons>
  43. <!-- 第三名 -->
  44. <uni-icons class="ranking-icon" v-if="index === 2" custom-prefix="iconfont" type="icon-TOP1" size="26" color="#D0BA9D"></uni-icons>
  45. <!-- 4~10 显示数字 -->
  46. <view v-if="index >= 3" class="ranking-common-icon">
  47. <uni-icons custom-prefix="iconfont" type="icon-tag" size="28" color="#8899ab"></uni-icons>
  48. <text class="common-num">{{ index + 1 }}</text>
  49. </view>
  50. <!-- 书籍封面 -->
  51. <view class="ranking-item-img">
  52. <image
  53. class="book-cover"
  54. :src="item.cover || defaultCover"
  55. mode="scaleToFill"
  56. @error="onImgError"
  57. />
  58. </view>
  59. <!-- 书籍信息 -->
  60. <view class="ranking-book-info">
  61. <text class="book-info-title">{{ item.TITLE || '暂无书名' }}</text>
  62. <text class="book-info-name">{{ item.AUTHOR || '佚名' }}</text>
  63. <text class="book-info-desc line-clamp-3">
  64. 借阅次数{{ item.TOTALNUM || 0 }}
  65. </text>
  66. </view>
  67. </view>
  68. </view>
  69. </view>
  70. </template>
  71. <script>
  72. import { FetchInitScreenSetting } from '@/api/user';
  73. import { FetchBookRanking } from '@/api/book';
  74. import config from '@/utils/config';
  75. import { loadBookCoversBase64 } from '@/utils/bookCover';
  76. export default {
  77. data() {
  78. return {
  79. rankingData: [],
  80. defaultCover: '/static/images/default-book.png',
  81. loading: true,
  82. };
  83. },
  84. onLoad() {
  85. this.getScreenSetting();
  86. },
  87. methods: {
  88. async getScreenSetting() {
  89. try {
  90. const res = await FetchInitScreenSetting({ libcode: config.LIB_CODE });
  91. this.getReadRanking(res.data);
  92. } catch (err) {
  93. console.error('获取屏幕配置失败:', err);
  94. }
  95. },
  96. getFormattedDate(date) {
  97. const year = date.getFullYear();
  98. const month = date.getMonth() + 1;
  99. const day = date.getDate();
  100. return `${year}-${month < 10 ? '0' + month : month}-${day < 10 ? '0' + day : day}`;
  101. },
  102. getReadRanking(result) {
  103. const currentDate = new Date()
  104. currentDate.setDate(currentDate.getDate() - 30)
  105. const year = currentDate.getFullYear()
  106. const month = currentDate.getMonth() + 1
  107. const day = currentDate.getDate()
  108. const formattedDate = `${year}-${month < 10 ? '0' + month : month}-${day < 10 ? '0' + day : day}`
  109. const params = {
  110. 'libcode': 'GD',
  111. 'starttime': formattedDate,
  112. 'endtime': this.getFormattedDate(new Date()),
  113. 'rownum': 10,
  114. 'thirdAppid': result.open_lib_appId?.context || '',
  115. 'thirdSecret': result.open_lib_secret?.context || '',
  116. 'thirdUrl': result.open_lib_http?.context || ''
  117. }
  118. FetchBookRanking(params).then(res => {
  119. // console.log('排行接口返回数据', res)
  120. const innerStr = res.data;
  121. const resultJson = JSON.parse(innerStr);
  122. // console.log(resultJson)
  123. if (resultJson.success && resultJson.resultlist.length > 0) {
  124. // 按借阅次数降序
  125. this.rankingData = resultJson.resultlist.sort((a, b) => b.TOTALNUM - a.TOTALNUM);
  126. // 加载封面
  127. this.loadCoversForList();
  128. } else {
  129. this.rankingData = [];
  130. }
  131. this.loading = false;
  132. }).catch(error => {
  133. console.error('排行接口错误', error)
  134. this.rankingData = [];
  135. this.loading = false;
  136. })
  137. },
  138. // 加载封面
  139. async loadCoversForList() {
  140. await loadBookCoversBase64(this.rankingData, (index, coverUrl) => {
  141. if (this.rankingData[index]) {
  142. this.$set(this.rankingData[index], 'cover', coverUrl);
  143. }
  144. });
  145. }
  146. }
  147. }
  148. </script>
  149. <style lang="scss" scoped>
  150. .ranking-header{
  151. position: relative;
  152. width: 100%;
  153. height: 150px;
  154. .ranking-heander-bg{
  155. width: 100%;
  156. height: 100%;
  157. }
  158. .ranking-header-txt{
  159. position: absolute;
  160. top: 0;
  161. left: 0;
  162. height: 150px;
  163. padding: 20px;
  164. display: flex;
  165. flex-direction: column;
  166. justify-content: flex-start;
  167. .ranking-title{
  168. display: flex;
  169. justify-content: flex-start;
  170. align-items: center;
  171. font-size: 26px;
  172. font-weight: bold;
  173. color: #1a1a1a;
  174. ::v-deep .uni-icons{
  175. color: #01a4fe !important;
  176. }
  177. .title-text{
  178. text-shadow: 0 2px 4px rgba(0, 0, 0, 0.15),
  179. 0 1px 2px rgba(0, 0, 0, 0.1);
  180. letter-spacing: 1px;
  181. margin-left: 8px;
  182. }
  183. }
  184. .ranking-header-tip,
  185. .ranking-num{
  186. color: #333;
  187. font-size: 14px;
  188. padding-top: 15px;
  189. }
  190. }
  191. }
  192. .ranking-list{
  193. position: relative;
  194. background-color: #fff;
  195. border-radius: 26px 26px 0 0;
  196. margin-top: -30px;
  197. z-index: 999;
  198. padding: 20px 0;
  199. min-height: 60vh;
  200. }
  201. /* 加载中状态 */
  202. .loading {
  203. display: flex;
  204. flex-direction: column;
  205. justify-content: center;
  206. align-items: center;
  207. height: 50vh;
  208. text-align: center;
  209. color: #999;
  210. font-size: 14px;
  211. }
  212. /* 空状态 */
  213. .empty {
  214. height: 50vh;
  215. }
  216. .ranking-item{
  217. position: relative;
  218. display: flex;
  219. justify-content: space-between;
  220. margin: 30px 20px 0 20px;
  221. padding: 10px;
  222. background-color: #f7f8fc;
  223. border-radius: 6px;
  224. .ranking-item-img{
  225. margin-right: 10px;
  226. .book-cover{
  227. width: 100px;
  228. height: 150px;
  229. border-radius: 10px;
  230. padding: 0 10px;
  231. background-color: #fff;
  232. }
  233. }
  234. .ranking-book-info{
  235. flex: 1;
  236. display: flex;
  237. flex-direction: column;
  238. font-size: 14px;
  239. color: #666;
  240. .book-info-title{
  241. font-size: 16px;
  242. font-weight: bold;
  243. color: #000;
  244. padding-top: 10px;
  245. }
  246. .book-info-name,
  247. .book-info-desc{
  248. padding-top: 10px;
  249. line-height: 24px;
  250. }
  251. }
  252. &.first-item{
  253. background-color: #fBF0BB;
  254. }
  255. &.two-item{
  256. background-color: #e9eff6;
  257. }
  258. &.three-item{
  259. background-color: #fBF0BB;
  260. }
  261. .ranking-icon{
  262. position: absolute;
  263. right: 10px;
  264. top: -10px;
  265. }
  266. .ranking-common-icon{
  267. position: absolute;
  268. right: 10px;
  269. top: -4px;
  270. .common-num{
  271. position: absolute;
  272. left: 0;
  273. top: 0;
  274. width: 28px;
  275. height: 28px;
  276. text-align: center;
  277. color: #fff;
  278. }
  279. }
  280. }
  281. </style>