feat(排行榜): 添加活动排行榜图标并优化切换动画和样式
为活动排行榜按钮添加图标并优化家庭排行榜页面的交互体验 - 在活动排行榜按钮前添加分类图标 - 实现平滑的标签切换动画和指示器 - 优化排名卡片和交互元素的悬停效果 - 调整排行榜布局和视觉细节
Showing
2 changed files
with
84 additions
and
12 deletions
| ... | @@ -83,6 +83,7 @@ | ... | @@ -83,6 +83,7 @@ |
| 83 | <view class="px-5 mb-4 mt-4"> | 83 | <view class="px-5 mb-4 mt-4"> |
| 84 | <view @tap="openFamilyRank" class="w-full bg-blue-500 text-white py-3 rounded-lg flex flex-col items-center justify-center"> | 84 | <view @tap="openFamilyRank" class="w-full bg-blue-500 text-white py-3 rounded-lg flex flex-col items-center justify-center"> |
| 85 | <view class="flex items-center justify-center"> | 85 | <view class="flex items-center justify-center"> |
| 86 | + <Category size="16" class="mr-2" /> | ||
| 86 | 活动排行榜 | 87 | 活动排行榜 |
| 87 | </view> | 88 | </view> |
| 88 | </view> | 89 | </view> |
| ... | @@ -172,7 +173,7 @@ | ... | @@ -172,7 +173,7 @@ |
| 172 | <script setup> | 173 | <script setup> |
| 173 | import { ref, computed, onMounted } from 'vue'; | 174 | import { ref, computed, onMounted } from 'vue'; |
| 174 | import Taro, { useDidShow } from '@tarojs/taro'; | 175 | import Taro, { useDidShow } from '@tarojs/taro'; |
| 175 | -import { Setting, Photograph, Right, Close } from '@nutui/icons-vue-taro'; | 176 | +import { Setting, Photograph, Right, Close, Category } from '@nutui/icons-vue-taro'; |
| 176 | import BottomNav from '../../components/BottomNav.vue'; | 177 | import BottomNav from '../../components/BottomNav.vue'; |
| 177 | import PointsCollector from '@/components/PointsCollector.vue' | 178 | import PointsCollector from '@/components/PointsCollector.vue' |
| 178 | import WeRunAuth from '@/components/WeRunAuth.vue' | 179 | import WeRunAuth from '@/components/WeRunAuth.vue' | ... | ... |
| 1 | <!-- | 1 | <!-- |
| 2 | * @Date: 2025-09-01 13:07:52 | 2 | * @Date: 2025-09-01 13:07:52 |
| 3 | * @LastEditors: hookehuyr hookehuyr@gmail.com | 3 | * @LastEditors: hookehuyr hookehuyr@gmail.com |
| 4 | - * @LastEditTime: 2025-09-01 14:46:59 | 4 | + * @LastEditTime: 2025-09-01 16:05:41 |
| 5 | * @FilePath: /lls_program/src/pages/FamilyRank/index.vue | 5 | * @FilePath: /lls_program/src/pages/FamilyRank/index.vue |
| 6 | * @Description: 文件描述 | 6 | * @Description: 文件描述 |
| 7 | --> | 7 | --> |
| ... | @@ -10,6 +10,11 @@ | ... | @@ -10,6 +10,11 @@ |
| 10 | <!-- 顶部导航 --> | 10 | <!-- 顶部导航 --> |
| 11 | <view class="header"> | 11 | <view class="header"> |
| 12 | <view class="nav-tabs"> | 12 | <view class="nav-tabs"> |
| 13 | + <!-- 滑动指示器 --> | ||
| 14 | + <view | ||
| 15 | + class="tab-indicator" | ||
| 16 | + :class="{ 'indicator-shanghai': activeTab === 'shanghai' }" | ||
| 17 | + ></view> | ||
| 13 | <view | 18 | <view |
| 14 | class="tab-item" | 19 | class="tab-item" |
| 15 | :class="{ active: activeTab === 'huangpu' }" | 20 | :class="{ active: activeTab === 'huangpu' }" |
| ... | @@ -28,7 +33,7 @@ | ... | @@ -28,7 +33,7 @@ |
| 28 | </view> | 33 | </view> |
| 29 | 34 | ||
| 30 | <!-- 排行榜内容 --> | 35 | <!-- 排行榜内容 --> |
| 31 | - <view class="rank-content"> | 36 | + <view class="rank-content" :class="{ 'content-switching': isContentSwitching }"> |
| 32 | <!-- 前三名展示 --> | 37 | <!-- 前三名展示 --> |
| 33 | <view class="top-three"> | 38 | <view class="top-three"> |
| 34 | <!-- 第二名 --> | 39 | <!-- 第二名 --> |
| ... | @@ -126,12 +131,28 @@ import { ref, computed } from 'vue' | ... | @@ -126,12 +131,28 @@ import { ref, computed } from 'vue' |
| 126 | // 当前激活的tab | 131 | // 当前激活的tab |
| 127 | const activeTab = ref('huangpu') | 132 | const activeTab = ref('huangpu') |
| 128 | 133 | ||
| 134 | +// 内容切换状态 | ||
| 135 | +const isContentSwitching = ref(false) | ||
| 136 | + | ||
| 129 | /** | 137 | /** |
| 130 | * 切换tab | 138 | * 切换tab |
| 131 | * @param {string} tab - tab名称 | 139 | * @param {string} tab - tab名称 |
| 132 | */ | 140 | */ |
| 133 | const switchTab = (tab) => { | 141 | const switchTab = (tab) => { |
| 134 | - activeTab.value = tab | 142 | + if (activeTab.value === tab) return |
| 143 | + | ||
| 144 | + // 开始切换动画 | ||
| 145 | + isContentSwitching.value = true | ||
| 146 | + | ||
| 147 | + // 延迟切换内容,让淡出动画先执行 | ||
| 148 | + setTimeout(() => { | ||
| 149 | + activeTab.value = tab | ||
| 150 | + | ||
| 151 | + // 内容切换后,结束切换状态,开始淡入动画 | ||
| 152 | + setTimeout(() => { | ||
| 153 | + isContentSwitching.value = false | ||
| 154 | + }, 50) | ||
| 155 | + }, 200) | ||
| 135 | } | 156 | } |
| 136 | 157 | ||
| 137 | /** | 158 | /** |
| ... | @@ -250,6 +271,25 @@ const myRank = ref({ | ... | @@ -250,6 +271,25 @@ const myRank = ref({ |
| 250 | border-radius: 60rpx; | 271 | border-radius: 60rpx; |
| 251 | padding: 8rpx; | 272 | padding: 8rpx; |
| 252 | margin: 0 80rpx; | 273 | margin: 0 80rpx; |
| 274 | + position: relative; | ||
| 275 | + overflow: hidden; | ||
| 276 | + | ||
| 277 | + .tab-indicator { | ||
| 278 | + position: absolute; | ||
| 279 | + top: 8rpx; | ||
| 280 | + left: 8rpx; | ||
| 281 | + width: calc(50% - 8rpx); | ||
| 282 | + height: calc(100% - 16rpx); | ||
| 283 | + background: rgba(255, 255, 255, 1); | ||
| 284 | + border-radius: 52rpx; | ||
| 285 | + transition: all 0.4s cubic-bezier(0.4, 0, 0.2, 1); | ||
| 286 | + box-shadow: 0 4rpx 12rpx rgba(0, 0, 0, 0.1); | ||
| 287 | + z-index: 1; | ||
| 288 | + | ||
| 289 | + &.indicator-shanghai { | ||
| 290 | + transform: translateX(100%); | ||
| 291 | + } | ||
| 292 | + } | ||
| 253 | 293 | ||
| 254 | .tab-item { | 294 | .tab-item { |
| 255 | flex: 1; | 295 | flex: 1; |
| ... | @@ -260,12 +300,18 @@ const myRank = ref({ | ... | @@ -260,12 +300,18 @@ const myRank = ref({ |
| 260 | font-size: 28rpx; | 300 | font-size: 28rpx; |
| 261 | font-weight: 500; | 301 | font-weight: 500; |
| 262 | transition: all 0.3s ease; | 302 | transition: all 0.3s ease; |
| 303 | + position: relative; | ||
| 304 | + z-index: 2; | ||
| 305 | + cursor: pointer; | ||
| 263 | 306 | ||
| 264 | &.active { | 307 | &.active { |
| 265 | - background: rgba(255, 255, 255, 1); | ||
| 266 | color: #4A90E2; | 308 | color: #4A90E2; |
| 267 | font-weight: 600; | 309 | font-weight: 600; |
| 268 | - box-shadow: 0 4rpx 12rpx rgba(0, 0, 0, 0.1); | 310 | + transform: scale(1.02); |
| 311 | + } | ||
| 312 | + | ||
| 313 | + &:hover { | ||
| 314 | + color: rgba(255, 255, 255, 1); | ||
| 269 | } | 315 | } |
| 270 | } | 316 | } |
| 271 | } | 317 | } |
| ... | @@ -273,6 +319,14 @@ const myRank = ref({ | ... | @@ -273,6 +319,14 @@ const myRank = ref({ |
| 273 | 319 | ||
| 274 | .rank-content { | 320 | .rank-content { |
| 275 | padding: 0 40rpx; | 321 | padding: 0 40rpx; |
| 322 | + transition: all 0.3s ease; | ||
| 323 | + transform: translateY(0); | ||
| 324 | + opacity: 1; | ||
| 325 | + | ||
| 326 | + &.content-switching { | ||
| 327 | + opacity: 0.3; | ||
| 328 | + transform: translateY(-20rpx); | ||
| 329 | + } | ||
| 276 | } | 330 | } |
| 277 | 331 | ||
| 278 | .top-three { | 332 | .top-three { |
| ... | @@ -281,7 +335,7 @@ const myRank = ref({ | ... | @@ -281,7 +335,7 @@ const myRank = ref({ |
| 281 | justify-content: center; | 335 | justify-content: center; |
| 282 | align-items: flex-end; | 336 | align-items: flex-end; |
| 283 | margin: 180rpx 0 0 0; | 337 | margin: 180rpx 0 0 0; |
| 284 | - height: 400rpx; | 338 | + height: 360rpx; |
| 285 | gap: -40rpx; | 339 | gap: -40rpx; |
| 286 | 340 | ||
| 287 | .rank-item { | 341 | .rank-item { |
| ... | @@ -289,17 +343,22 @@ const myRank = ref({ | ... | @@ -289,17 +343,22 @@ const myRank = ref({ |
| 289 | flex-direction: column; | 343 | flex-direction: column; |
| 290 | align-items: center; | 344 | align-items: center; |
| 291 | position: relative; | 345 | position: relative; |
| 346 | + transition: all 0.4s cubic-bezier(0.4, 0, 0.2, 1); | ||
| 347 | + | ||
| 348 | + &:hover { | ||
| 349 | + transform: translateY(-10rpx); | ||
| 350 | + } | ||
| 292 | 351 | ||
| 293 | .crown { | 352 | .crown { |
| 294 | font-size: 40rpx; | 353 | font-size: 40rpx; |
| 295 | margin-bottom: 10rpx; | 354 | margin-bottom: 10rpx; |
| 296 | 355 | ||
| 297 | &.crown-gold { | 356 | &.crown-gold { |
| 298 | - filter: hue-rotate(45deg) brightness(1.2); | 357 | + filter: grayscale(0.3) brightness(1.1); |
| 299 | } | 358 | } |
| 300 | 359 | ||
| 301 | &.crown-silver { | 360 | &.crown-silver { |
| 302 | - filter: grayscale(0.3) brightness(1.1); | 361 | + filter: hue-rotate(45deg) brightness(1.2); |
| 303 | } | 362 | } |
| 304 | 363 | ||
| 305 | &.crown-bronze { | 364 | &.crown-bronze { |
| ... | @@ -377,7 +436,7 @@ const myRank = ref({ | ... | @@ -377,7 +436,7 @@ const myRank = ref({ |
| 377 | 436 | ||
| 378 | .rank-number { | 437 | .rank-number { |
| 379 | width: 220rpx; | 438 | width: 220rpx; |
| 380 | - height: 200rpx; | 439 | + height: 180rpx; |
| 381 | background: linear-gradient(135deg, #C0C0C0 0%, #A0A0A0 100%); | 440 | background: linear-gradient(135deg, #C0C0C0 0%, #A0A0A0 100%); |
| 382 | } | 441 | } |
| 383 | } | 442 | } |
| ... | @@ -395,7 +454,7 @@ const myRank = ref({ | ... | @@ -395,7 +454,7 @@ const myRank = ref({ |
| 395 | 454 | ||
| 396 | .rank-number { | 455 | .rank-number { |
| 397 | width: 220rpx; | 456 | width: 220rpx; |
| 398 | - height: 260rpx; | 457 | + height: 220rpx; |
| 399 | background: linear-gradient(135deg, #FFD700 0%, #FFA500 100%); | 458 | background: linear-gradient(135deg, #FFD700 0%, #FFA500 100%); |
| 400 | } | 459 | } |
| 401 | } | 460 | } |
| ... | @@ -412,7 +471,7 @@ const myRank = ref({ | ... | @@ -412,7 +471,7 @@ const myRank = ref({ |
| 412 | 471 | ||
| 413 | .rank-number { | 472 | .rank-number { |
| 414 | width: 220rpx; | 473 | width: 220rpx; |
| 415 | - height: 180rpx; | 474 | + height: 160rpx; |
| 416 | background: linear-gradient(135deg, #CD7F32 0%, #B8860B 100%); | 475 | background: linear-gradient(135deg, #CD7F32 0%, #B8860B 100%); |
| 417 | } | 476 | } |
| 418 | } | 477 | } |
| ... | @@ -433,6 +492,12 @@ const myRank = ref({ | ... | @@ -433,6 +492,12 @@ const myRank = ref({ |
| 433 | justify-content: space-between; | 492 | justify-content: space-between; |
| 434 | padding: 24rpx 32rpx; | 493 | padding: 24rpx 32rpx; |
| 435 | border-bottom: 1rpx solid rgba(0, 0, 0, 0.05); | 494 | border-bottom: 1rpx solid rgba(0, 0, 0, 0.05); |
| 495 | + transition: all 0.3s ease; | ||
| 496 | + | ||
| 497 | + &:hover { | ||
| 498 | + background: rgba(74, 144, 226, 0.05); | ||
| 499 | + transform: translateX(8rpx); | ||
| 500 | + } | ||
| 436 | 501 | ||
| 437 | &:last-child { | 502 | &:last-child { |
| 438 | border-bottom: none; | 503 | border-bottom: none; |
| ... | @@ -505,6 +570,12 @@ const myRank = ref({ | ... | @@ -505,6 +570,12 @@ const myRank = ref({ |
| 505 | backdrop-filter: blur(10px); | 570 | backdrop-filter: blur(10px); |
| 506 | box-shadow: 0 8rpx 32rpx rgba(0, 0, 0, 0.1); | 571 | box-shadow: 0 8rpx 32rpx rgba(0, 0, 0, 0.1); |
| 507 | z-index: 99; | 572 | z-index: 99; |
| 573 | + transition: all 0.3s ease; | ||
| 574 | + | ||
| 575 | + &:hover { | ||
| 576 | + transform: translateY(-4rpx); | ||
| 577 | + box-shadow: 0 12rpx 40rpx rgba(0, 0, 0, 0.15); | ||
| 578 | + } | ||
| 508 | 579 | ||
| 509 | .my-rank-content { | 580 | .my-rank-content { |
| 510 | display: flex; | 581 | display: flex; | ... | ... |
-
Please register or login to post a comment