BadgeGrid.vue 1.4 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556
  1. <template>
  2. <view class="badge-grid" v-if="badges.length > 0">
  3. <view class="badge-grid-inner">
  4. <view class="badge-cell" v-for="badge in badges" :key="badge.id"
  5. :class="{ 'badge-cell--locked': !badge.unlocked }">
  6. <view class="badge-icon-wrap" :class="{ 'badge-icon-wrap--locked': !badge.unlocked }">
  7. <text class="badge-icon">{{ badge.unlocked ? badge.icon : '🔒' }}</text>
  8. </view>
  9. <text class="badge-name">{{ badge.name }}</text>
  10. </view>
  11. </view>
  12. </view>
  13. </template>
  14. <script>
  15. export default {
  16. props: {
  17. badges: { type: Array, default: function() { return [] } }
  18. }
  19. }
  20. </script>
  21. <style scoped>
  22. .badge-grid {
  23. background: #fff;
  24. border-radius: 20rpx;
  25. padding: 24rpx;
  26. box-shadow: 0 2rpx 12rpx rgba(0,0,0,0.06);
  27. }
  28. .badge-grid-inner {
  29. display: flex;
  30. flex-wrap: wrap;
  31. gap: 16rpx;
  32. }
  33. .badge-cell {
  34. width: calc(33.33% - 11rpx);
  35. display: flex;
  36. flex-direction: column;
  37. align-items: center;
  38. padding: 12rpx 0;
  39. }
  40. .badge-cell--locked { opacity: 0.5; }
  41. .badge-icon-wrap {
  42. width: 80rpx;
  43. height: 80rpx;
  44. border-radius: 50%;
  45. background: linear-gradient(135deg, #FFD700, #FFA500);
  46. display: flex;
  47. align-items: center;
  48. justify-content: center;
  49. margin-bottom: 8rpx;
  50. }
  51. .badge-icon-wrap--locked { background: #E2E8F0; }
  52. .badge-icon { font-size: 36rpx; }
  53. .badge-name { font-size: 22rpx; color: #333; text-align: center; }
  54. </style>