hookehuyr

feat(家庭排行): 添加已加入家庭数量显示组件并优化布局

在排行榜卡片和家庭排行页面添加已加入家庭数量显示组件,使用NumberRoll实现数字滚动效果
优化页面布局间距,将"参与"文案统一改为"已加入"
1 <!-- 1 <!--
2 * @Date: 2025-01-09 00:00:00 2 * @Date: 2025-01-09 00:00:00
3 * @LastEditors: hookehuyr hookehuyr@gmail.com 3 * @LastEditors: hookehuyr hookehuyr@gmail.com
4 - * @LastEditTime: 2025-10-25 18:39:43 4 + * @LastEditTime: 2025-10-25 18:48:25
5 * @FilePath: /lls_program/src/components/RankingCard.vue 5 * @FilePath: /lls_program/src/components/RankingCard.vue
6 * @Description: 排行榜卡片组件 6 * @Description: 排行榜卡片组件
7 --> 7 -->
...@@ -48,7 +48,7 @@ ...@@ -48,7 +48,7 @@
48 48
49 <view class="relative mb-2 text-white"> 49 <view class="relative mb-2 text-white">
50 <view class="flex items-center justify-center"> 50 <view class="flex items-center justify-center">
51 - <text class="mr-2" style="font-size: 28rpx;">参与 </text> 51 + <text class="mr-2" style="font-size: 28rpx;">已加入</text>
52 <NumberRoll 52 <NumberRoll
53 ref="numberRollRef" 53 ref="numberRollRef"
54 :target-value="currentTotalFamilySum" 54 :target-value="currentTotalFamilySum"
...@@ -301,8 +301,7 @@ const loadLeaderboardData = async (isInitialLoad = false) => { ...@@ -301,8 +301,7 @@ const loadLeaderboardData = async (isInitialLoad = false) => {
301 // 设置当前日期 301 // 设置当前日期
302 currentDate.value = response.data.yesterday 302 currentDate.value = response.data.yesterday
303 // TODO: 设置总家庭数 303 // TODO: 设置总家庭数
304 - const newTotalFamilySum = 2318; 304 + currentTotalFamilySum.value = 2318;
305 - currentTotalFamilySum.value = newTotalFamilySum;
306 } 305 }
307 } catch (error) { 306 } catch (error) {
308 console.error('获取排行榜数据失败:', error) 307 console.error('获取排行榜数据失败:', error)
......
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-10-22 16:21:59 4 + * @LastEditTime: 2025-10-25 18:52:07
5 * @FilePath: /lls_program/src/pages/FamilyRank/index.vue 5 * @FilePath: /lls_program/src/pages/FamilyRank/index.vue
6 * @Description: 文件描述 6 * @Description: 文件描述
7 --> 7 -->
...@@ -44,6 +44,21 @@ ...@@ -44,6 +44,21 @@
44 <view v-if="activeTab === 'support'" class="absolute font-bold text-white bg-orange-500 top-0 rounded-full px-4 py-1" style="right: 70rpx; font-size: 23rpx;" @tap="joinOrganization">助力码</view> 44 <view v-if="activeTab === 'support'" class="absolute font-bold text-white bg-orange-500 top-0 rounded-full px-4 py-1" style="right: 70rpx; font-size: 23rpx;" @tap="joinOrganization">助力码</view>
45 </view> 45 </view>
46 46
47 + <!-- 参与家庭数量显示 -->
48 + <view v-if="!loading" class="family-count-display">
49 + <view class="flex items-center justify-center text-white mb-4">
50 + <text class="mr-2" style="font-size: 28rpx;">已加入</text>
51 + <NumberRoll
52 + ref="numberRollRef"
53 + :target-value="currentTotalFamilySum"
54 + :digit-count="currentTotalFamilySum.length"
55 + :duration="1500"
56 + :digit-delay="150"
57 + />
58 + <text class="ml-2" style="font-size: 28rpx;">个家庭</text>
59 + </view>
60 + </view>
61 +
47 <!-- 助力榜空状态提示 --> 62 <!-- 助力榜空状态提示 -->
48 <view v-if="!loading && activeTab === 'support' && (!supportData || !supportData.families || supportData.families.length === 0)" class="support-empty-state"> 63 <view v-if="!loading && activeTab === 'support' && (!supportData || !supportData.families || supportData.families.length === 0)" class="support-empty-state">
49 <view class="empty-image"> 64 <view class="empty-image">
...@@ -191,6 +206,7 @@ import { ref, computed, onMounted } from 'vue' ...@@ -191,6 +206,7 @@ import { ref, computed, onMounted } from 'vue'
191 import Taro from '@tarojs/taro' 206 import Taro from '@tarojs/taro'
192 import { IconFont } from '@nutui/icons-vue-taro'; 207 import { IconFont } from '@nutui/icons-vue-taro';
193 import BackToTop from '@/components/BackToTop.vue' 208 import BackToTop from '@/components/BackToTop.vue'
209 +import NumberRoll from '@/components/NumberRoll.vue'
194 // 默认头像 210 // 默认头像
195 const defaultAvatar = 'https://cdn.ipadbiz.cn/lls_prog/images/%E5%85%A8%E5%AE%B6%E7%A6%8F3_%E5%89%AF%E6%9C%AC.jpg?imageMogr2/strip/quality/60' 211 const defaultAvatar = 'https://cdn.ipadbiz.cn/lls_prog/images/%E5%85%A8%E5%AE%B6%E7%A6%8F3_%E5%89%AF%E6%9C%AC.jpg?imageMogr2/strip/quality/60'
196 const supportImg = 'https://cdn.ipadbiz.cn/lls_prog/images/support_img_1.png' 212 const supportImg = 'https://cdn.ipadbiz.cn/lls_prog/images/support_img_1.png'
...@@ -209,6 +225,12 @@ const shanghaiRegionOptions = computed(() => { ...@@ -209,6 +225,12 @@ const shanghaiRegionOptions = computed(() => {
209 })) 225 }))
210 }) 226 })
211 227
228 +// NumberRoll组件引用
229 +const numberRollRef = ref(null)
230 +
231 +// 是否已触发数字滚动
232 +const hasTriggeredNumberRoll = ref(false)
233 +
212 // 当前激活的tab 234 // 当前激活的tab
213 const activeTab = ref('') 235 const activeTab = ref('')
214 236
...@@ -242,12 +264,32 @@ const handleRankAskClick = () => { ...@@ -242,12 +264,32 @@ const handleRankAskClick = () => {
242 } 264 }
243 265
244 /** 266 /**
267 + * 触发数字滚动动画
268 + */
269 +const triggerNumberRoll = () => {
270 + if (numberRollRef.value && !hasTriggeredNumberRoll.value) {
271 + numberRollRef.value.start()
272 + hasTriggeredNumberRoll.value = true
273 + }
274 +}
275 +
276 +/**
277 + * 重置数字滚动状态
278 + */
279 +const resetNumberRoll = () => {
280 + hasTriggeredNumberRoll.value = false
281 +}
282 +
283 +/**
245 * 切换tab 284 * 切换tab
246 * @param {string} tab - tab名称 285 * @param {string} tab - tab名称
247 */ 286 */
248 const switchTab = async (tab) => { 287 const switchTab = async (tab) => {
249 if (activeTab.value === tab) return 288 if (activeTab.value === tab) return
250 289
290 + // 重置数字滚动状态
291 + resetNumberRoll()
292 +
251 // 开始切换动画 293 // 开始切换动画
252 isContentSwitching.value = true 294 isContentSwitching.value = true
253 295
...@@ -261,6 +303,11 @@ const switchTab = async (tab) => { ...@@ -261,6 +303,11 @@ const switchTab = async (tab) => {
261 // 内容切换后,结束切换状态,开始淡入动画 303 // 内容切换后,结束切换状态,开始淡入动画
262 setTimeout(() => { 304 setTimeout(() => {
263 isContentSwitching.value = false 305 isContentSwitching.value = false
306 +
307 + // 延迟1秒触发数字滚动动画
308 + setTimeout(() => {
309 + triggerNumberRoll()
310 + }, 1000)
264 }, 50) 311 }, 50)
265 }, 200) 312 }, 200)
266 } 313 }
...@@ -323,6 +370,8 @@ const loadLeaderboardData = async (isInitialLoad = false) => { ...@@ -323,6 +370,8 @@ const loadLeaderboardData = async (isInitialLoad = false) => {
323 leaderboardData.value = response.data 370 leaderboardData.value = response.data
324 } 371 }
325 currentDate.value = response.data.yesterday 372 currentDate.value = response.data.yesterday
373 + // TODO: 设置总家庭数
374 + currentTotalFamilySum.value = 2318;
326 } 375 }
327 } catch (error) { 376 } catch (error) {
328 console.error('获取排行榜数据失败:', error) 377 console.error('获取排行榜数据失败:', error)
...@@ -382,6 +431,9 @@ const getTabDisplayName = (region) => { ...@@ -382,6 +431,9 @@ const getTabDisplayName = (region) => {
382 } 431 }
383 } 432 }
384 433
434 +// 当前总家庭数
435 +const currentTotalFamilySum = ref(0);
436 +
385 /** 437 /**
386 * 计算前三名数据 438 * 计算前三名数据
387 */ 439 */
...@@ -472,6 +524,11 @@ onMounted(async () => { ...@@ -472,6 +524,11 @@ onMounted(async () => {
472 activeTab.value = 'shanghai' 524 activeTab.value = 'shanghai'
473 // 加载排行榜数据 525 // 加载排行榜数据
474 await loadLeaderboardData(true) 526 await loadLeaderboardData(true)
527 +
528 + // 延迟1秒触发数字滚动动画
529 + setTimeout(() => {
530 + triggerNumberRoll()
531 + }, 1000)
475 }) 532 })
476 </script> 533 </script>
477 534
...@@ -561,7 +618,7 @@ onMounted(async () => { ...@@ -561,7 +618,7 @@ onMounted(async () => {
561 color: rgba(255, 255, 255, 0.8); 618 color: rgba(255, 255, 255, 0.8);
562 text-align: center; 619 text-align: center;
563 margin-top: 40rpx; 620 margin-top: 40rpx;
564 - margin-bottom: 40rpx; 621 + margin-bottom: 10rpx;
565 } 622 }
566 } 623 }
567 624
......