hookehuyr

feat(checkin): 实现打卡动态列表分页加载和日期选择优化

重构打卡动态列表为分页加载方式,提升性能
优化日期选择逻辑,自动重置分页参数并重新加载数据
修复日历日期匹配逻辑,支持完整日期格式匹配
1 <!-- 1 <!--
2 * @Date: 2025-05-29 15:34:17 2 * @Date: 2025-05-29 15:34:17
3 * @LastEditors: hookehuyr hookehuyr@gmail.com 3 * @LastEditors: hookehuyr hookehuyr@gmail.com
4 - * @LastEditTime: 2025-06-09 15:50:10 4 + * @LastEditTime: 2025-06-10 10:20:08
5 * @FilePath: /mlaj/src/views/checkin/IndexCheckInPage.vue 5 * @FilePath: /mlaj/src/views/checkin/IndexCheckInPage.vue
6 * @Description: 文件描述 6 * @Description: 文件描述
7 --> 7 -->
...@@ -67,6 +67,14 @@ ...@@ -67,6 +67,14 @@
67 67
68 <div class="text-wrapper"> 68 <div class="text-wrapper">
69 <div class="text-header">打卡动态</div> 69 <div class="text-header">打卡动态</div>
70 + <van-list
71 + v-if="checkinDataList.length"
72 + v-model:loading="loading"
73 + :finished="finished"
74 + finished-text="没有更多了"
75 + @load="onLoad"
76 + class="px-4 py-3 space-y-4"
77 + >
70 <div class="post-card" v-for="post in checkinDataList" :key="post.id"> 78 <div class="post-card" v-for="post in checkinDataList" :key="post.id">
71 <div class="post-header"> 79 <div class="post-header">
72 <van-row> 80 <van-row>
...@@ -143,7 +151,8 @@ ...@@ -143,7 +151,8 @@
143 <span class="like-count">{{ post.likes }}</span> 151 <span class="like-count">{{ post.likes }}</span>
144 </div> 152 </div>
145 </div> 153 </div>
146 - <van-empty v-if="!checkinDataList.length" image="error" description="暂无数据" /> 154 + </van-list>
155 + <van-empty v-else image="error" description="暂无数据" />
147 </div> 156 </div>
148 157
149 <div style="height: 5rem;"></div> 158 <div style="height: 5rem;"></div>
...@@ -353,33 +362,37 @@ const onChange = (index) => { ...@@ -353,33 +362,37 @@ const onChange = (index) => {
353 startPosition.value = index; 362 startPosition.value = index;
354 } 363 }
355 const formatter = (day) => { 364 const formatter = (day) => {
365 + const year = day.date.getFullYear();
356 const month = day.date.getMonth() + 1; 366 const month = day.date.getMonth() + 1;
357 const date = day.date.getDate(); 367 const date = day.date.getDate();
358 368
359 let checkin_days = myCheckinDates.value; 369 let checkin_days = myCheckinDates.value;
360 370
361 - if (month === 6) { 371 + // 检查当前日期是否在签到日期列表中
362 - if (checkin_days.includes(date)) { 372 + if (checkin_days && checkin_days.length > 0) {
373 + // 格式化当前日期为YYYY-MM-DD格式,与checkin_days中的格式匹配
374 + const formattedDate = `${year}-${month.toString().padStart(2, '0')}-${date.toString().padStart(2, '0')}`;
375 +
376 + // 检查是否已签到
377 + if (checkin_days.includes(formattedDate)) {
363 day.className = 'calendar-checkin'; 378 day.className = 'calendar-checkin';
364 day.type = 'selected'; 379 day.type = 'selected';
365 - day.bottomInfo = '已签到' 380 + day.bottomInfo = '已签到';
366 } 381 }
367 } 382 }
383 +
368 // 选中今天的日期 384 // 选中今天的日期
369 if (dayjs(day.date).isSame(new Date(), 'day')) { 385 if (dayjs(day.date).isSame(new Date(), 'day')) {
370 day.className = 'calendar-today'; 386 day.className = 'calendar-today';
371 - day.type ='selected'; 387 + day.type = 'selected';
372 - day.bottomInfo = '今日' 388 + day.bottomInfo = '今日';
373 } 389 }
374 390
375 return day; 391 return day;
376 } 392 }
377 393
378 const onSelectDay = (day) => { 394 const onSelectDay = (day) => {
379 - console.warn('选择了日期', dayjs(day).format('YYYY-MM-DD'));
380 getTaskDetail(dayjs(day).format('YYYY-MM')); 395 getTaskDetail(dayjs(day).format('YYYY-MM'));
381 - // 获取打卡动态列表
382 - initUploadTaskList(dayjs(day).format('YYYY-MM-DD'));
383 // 修改浏览器地址把当前的date加入地址栏, 页面不刷新 396 // 修改浏览器地址把当前的date加入地址栏, 页面不刷新
384 router.push({ 397 router.push({
385 path: route.path, 398 path: route.path,
...@@ -388,6 +401,12 @@ const onSelectDay = (day) => { ...@@ -388,6 +401,12 @@ const onSelectDay = (day) => {
388 date: dayjs(day).format('YYYY-MM-DD') 401 date: dayjs(day).format('YYYY-MM-DD')
389 } 402 }
390 }) 403 })
404 + // 重置分页参数
405 + page.value = 0
406 + checkinDataList.value = []
407 + finished.value = false
408 + // 重新加载数据
409 + onLoad(dayjs(day).format('YYYY-MM-DD'))
391 } 410 }
392 411
393 const onClickSubtitle = (evt) => { 412 const onClickSubtitle = (evt) => {
...@@ -442,7 +461,6 @@ const handLike = async (post) => { ...@@ -442,7 +461,6 @@ const handLike = async (post) => {
442 } 461 }
443 462
444 const editCheckin = (post) => { 463 const editCheckin = (post) => {
445 - console.warn(post);
446 if (post.file_type === 'image') { 464 if (post.file_type === 'image') {
447 router.push({ 465 router.push({
448 path: '/checkin/image', 466 path: '/checkin/image',
...@@ -505,7 +523,6 @@ const showProgress = ref(true); ...@@ -505,7 +523,6 @@ const showProgress = ref(true);
505 const getTaskDetail = async (month) => { 523 const getTaskDetail = async (month) => {
506 const { code, data } = await getTaskDetailAPI({ i: route.query.id, month }); 524 const { code, data } = await getTaskDetailAPI({ i: route.query.id, month });
507 if (code) { 525 if (code) {
508 - console.warn(data);
509 taskDetail.value = data; 526 taskDetail.value = data;
510 progress1.value = (data.checkin_number/data.target_number)*100; // 计算进度条百分比 527 progress1.value = (data.checkin_number/data.target_number)*100; // 计算进度条百分比
511 showProgress.value = !isNaN(progress1.value); // 如果是NaN,就不显示进度条 528 showProgress.value = !isNaN(progress1.value); // 如果是NaN,就不显示进度条
...@@ -513,37 +530,45 @@ const getTaskDetail = async (month) => { ...@@ -513,37 +530,45 @@ const getTaskDetail = async (month) => {
513 // 获取当前用户的打卡日期 530 // 获取当前用户的打卡日期
514 myCheckinDates.value = data.my_checkin_dates; 531 myCheckinDates.value = data.my_checkin_dates;
515 // 把['2025-06-06'] 转化为 [6] 只取日期去掉0 532 // 把['2025-06-06'] 转化为 [6] 只取日期去掉0
516 - myCheckinDates.value = myCheckinDates.value.map(date => { 533 + // myCheckinDates.value = myCheckinDates.value.map(date => {
517 - return dayjs(date).date(); 534 + // return dayjs(date).date();
518 - }) 535 + // })
519 } 536 }
520 } 537 }
521 538
522 -const initUploadTaskList = async (date) => { 539 +const loading = ref(false)
523 - const toast = showLoadingToast({ 540 +const finished = ref(false)
524 - message: '加载中...', 541 +const limit = ref(3)
525 - forbidClick: true, 542 +const page = ref(0)
543 +
544 +const onLoad = async (date) => {
545 + const nextPage = page.value;
546 + const current_date = date || route.query.date || dayjs().format('YYYY-MM-DD');
547 + //
548 + const res = await getUploadTaskListAPI({
549 + limit: limit.value,
550 + page: nextPage,
551 + task_id: route.query.id,
552 + date: current_date
526 }); 553 });
527 - const { code, data } = await getUploadTaskListAPI({ task_id: route.query.id, date, limit: 999 }); 554 + if (res.code) {
528 - if (code) {
529 - console.warn(data?.checkin_list);
530 // 整理数据结构 555 // 整理数据结构
531 - checkinDataList.value = formatData(data) 556 + checkinDataList.value = [...checkinDataList.value, ...formatData(res.data)];
532 - toast.close(); 557 + finished.value = res.data.checkin_list.length < limit.value;
558 + page.value = nextPage + 1;
533 } 559 }
534 -} 560 + loading.value = false;
561 +};
535 562
536 onMounted(async () => { 563 onMounted(async () => {
537 const current_date = route.query.date; 564 const current_date = route.query.date;
538 if (current_date) { 565 if (current_date) {
539 getTaskDetail(dayjs(current_date).format('YYYY-MM')); 566 getTaskDetail(dayjs(current_date).format('YYYY-MM'));
540 - // 获取打卡动态列表
541 - initUploadTaskList(current_date);
542 myRefCalendar.value?.reset(new Date(current_date)); 567 myRefCalendar.value?.reset(new Date(current_date));
568 + onLoad(current_date);
543 } else { 569 } else {
544 getTaskDetail(dayjs().format('YYYY-MM')); 570 getTaskDetail(dayjs().format('YYYY-MM'));
545 - // 获取打卡动态列表 571 + onLoad(dayjs().format('YYYY-MM-DD'));
546 - initUploadTaskList(dayjs().format('YYYY-MM-DD'));
547 } 572 }
548 }) 573 })
549 574
...@@ -606,6 +631,12 @@ const formatData = (data) => { ...@@ -606,6 +631,12 @@ const formatData = (data) => {
606 } 631 }
607 } 632 }
608 633
634 +.calendar-today {
635 + .van-calendar__selected-day {
636 + background: #FAAB0C !important;
637 + }
638 +}
639 +
609 .text-wrapper { 640 .text-wrapper {
610 padding: 1rem; 641 padding: 1rem;
611 color: #4caf50; 642 color: #4caf50;
......