index.vue 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101
  1. <template>
  2. <view class="scoreboard-page">
  3. <view class="page-header">
  4. <text class="page-title">实时积分榜</text>
  5. <text class="page-desc" v-if="className">{{ className }}</text>
  6. </view>
  7. <view v-if="board.length === 0" class="empty-state">
  8. <text class="empty-text">暂无积分数据</text>
  9. </view>
  10. <view class="rank-list">
  11. <view class="rank-item" v-for="(item, idx) in board" :key="idx" :class="rankClass(idx)">
  12. <view class="rank-num">
  13. <text v-if="idx < 3" class="rank-medal">{{ ['🥇','🥈','🥉'][idx] }}</text>
  14. <text v-else class="rank-index">{{ idx + 1 }}</text>
  15. </view>
  16. <view class="rank-info">
  17. <text class="rank-name">{{ item.groupName }}</text>
  18. <text class="rank-slogan" v-if="item.slogan">{{ item.slogan }}</text>
  19. <text class="rank-members">{{ item.memberCount }}人</text>
  20. </view>
  21. <view class="rank-score">
  22. <text class="score-num">{{ item.total }}</text>
  23. <text class="score-label">分</text>
  24. </view>
  25. </view>
  26. </view>
  27. </view>
  28. </template>
  29. <script>
  30. import { getScoreboard, getClassInfo } from '@/utils/api.js'
  31. import { guardPage } from '@/utils/guard.js'
  32. export default {
  33. data() {
  34. return {
  35. board: [],
  36. className: ''
  37. }
  38. },
  39. onShow() {
  40. if (!guardPage()) return
  41. this.loadData()
  42. },
  43. methods: {
  44. loadData() {
  45. var self = this
  46. var classId = self.$store.state.classId
  47. var doLoad = function(cid) {
  48. return getScoreboard(cid).then(function(resp) {
  49. self.board = resp.data || []
  50. })
  51. }
  52. if (classId) {
  53. doLoad(classId)
  54. getClassInfo().then(function(resp) {
  55. if (resp.data) self.className = resp.data.name
  56. }).catch(function() {})
  57. } else {
  58. getClassInfo().then(function(resp) {
  59. if (resp.data) {
  60. self.className = resp.data.name
  61. self.$store.commit('setClassId', resp.data.id)
  62. return doLoad(resp.data.id)
  63. }
  64. }).catch(function() {})
  65. }
  66. },
  67. rankClass(idx) {
  68. if (idx === 0) return 'rank-gold'
  69. if (idx === 1) return 'rank-silver'
  70. if (idx === 2) return 'rank-bronze'
  71. return ''
  72. }
  73. }
  74. }
  75. </script>
  76. <style scoped>
  77. .scoreboard-page { min-height: 100vh; background: #F5F5F5; padding: 24rpx 32rpx; }
  78. .page-header { margin-bottom: 32rpx; }
  79. .page-title { display: block; font-size: 40rpx; font-weight: 700; color: #1E293B; margin-bottom: 8rpx; }
  80. .page-desc { display: block; font-size: 26rpx; color: #64748B; }
  81. .empty-state { text-align: center; padding: 80rpx 0; }
  82. .empty-text { font-size: 28rpx; color: #94A3B8; }
  83. .rank-list { display: flex; flex-direction: column; gap: 16rpx; }
  84. .rank-item { display: flex; align-items: center; background: #FFF; border-radius: 16rpx; padding: 24rpx; }
  85. .rank-gold { background: linear-gradient(135deg, #FFF7ED, #FFFBEB); border: 2rpx solid #FDE68A; }
  86. .rank-silver { background: linear-gradient(135deg, #F8FAFC, #F1F5F9); border: 2rpx solid #E2E8F0; }
  87. .rank-bronze { background: linear-gradient(135deg, #FFF7ED, #FEF3E2); border: 2rpx solid #FED7AA; }
  88. .rank-num { width: 80rpx; text-align: center; margin-right: 16rpx; }
  89. .rank-medal { font-size: 40rpx; }
  90. .rank-index { font-size: 32rpx; font-weight: 700; color: #94A3B8; }
  91. .rank-info { flex: 1; }
  92. .rank-name { display: block; font-size: 30rpx; font-weight: 600; color: #1E293B; }
  93. .rank-slogan { display: block; font-size: 24rpx; color: #F97316; margin-top: 4rpx; }
  94. .rank-members { display: block; font-size: 22rpx; color: #94A3B8; margin-top: 4rpx; }
  95. .rank-score { text-align: right; }
  96. .score-num { font-size: 40rpx; font-weight: 700; color: #F97316; }
  97. .score-label { font-size: 22rpx; color: #64748B; margin-left: 4rpx; }
  98. </style>