hookehuyr

refactor(打卡): 优化文件哈希计算和补打卡功能

- 使用 qiniuFileHash 替代浏览器MD5方案计算文件哈希
- 添加补打卡标识和日期处理逻辑
- 优化日历组件中已打卡和补打卡的样式显示
...@@ -3,7 +3,7 @@ import { useRoute, useRouter } from 'vue-router' ...@@ -3,7 +3,7 @@ import { useRoute, useRouter } from 'vue-router'
3 import { showToast, showLoadingToast } from 'vant' 3 import { showToast, showLoadingToast } from 'vant'
4 import { qiniuTokenAPI, qiniuUploadAPI, saveFileAPI } from '@/api/common' 4 import { qiniuTokenAPI, qiniuUploadAPI, saveFileAPI } from '@/api/common'
5 import { addUploadTaskAPI, getUploadTaskInfoAPI, editUploadTaskInfoAPI } from "@/api/checkin" 5 import { addUploadTaskAPI, getUploadTaskInfoAPI, editUploadTaskInfoAPI } from "@/api/checkin"
6 -import BMF from 'browser-md5-file' 6 +import { qiniuFileHash } from '@/utils/qiniuFileHash';
7 import { useAuth } from '@/contexts/auth' 7 import { useAuth } from '@/contexts/auth'
8 8
9 /** 9 /**
...@@ -45,21 +45,13 @@ export function useCheckin() { ...@@ -45,21 +45,13 @@ export function useCheckin() {
45 }) 45 })
46 46
47 /** 47 /**
48 - * 获取文件MD5值 48 + * 获取文件哈希(与七牛云ETag一致)
49 - * @param {File} file - 文件对象 49 + * @param {File} file 文件对象
50 - * @returns {Promise<string>} MD5值 50 + * @returns {Promise<string>} 哈希字符串
51 + * 注释:使用 qiniuFileHash 进行计算,替代浏览器MD5方案。
51 */ 52 */
52 - const getFileMD5 = (file) => { 53 + const getFileMD5 = async (file) => {
53 - return new Promise((resolve, reject) => { 54 + return await qiniuFileHash(file)
54 - const bmf = new BMF()
55 - bmf.md5(file, (err, md5) => {
56 - if (err) {
57 - reject(err)
58 - return
59 - }
60 - resolve(md5)
61 - })
62 - })
63 } 55 }
64 56
65 /** 57 /**
...@@ -290,7 +282,8 @@ export function useCheckin() { ...@@ -290,7 +282,8 @@ export function useCheckin() {
290 task_id: route.query.id, 282 task_id: route.query.id,
291 note: message.value, 283 note: message.value,
292 file_type: activeType.value, 284 file_type: activeType.value,
293 - meta_id: [] 285 + meta_id: [],
286 + makeup_time: route.query.is_patch ? route.query.date : '',
294 } 287 }
295 288
296 // 如果有文件,添加文件ID 289 // 如果有文件,添加文件ID
......
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-11-10 10:38:27 4 + * @LastEditTime: 2025-11-13 17:22:35
5 * @FilePath: /mlaj/src/views/checkin/IndexCheckInPage.vue 5 * @FilePath: /mlaj/src/views/checkin/IndexCheckInPage.vue
6 * @Description: 文件描述 6 * @Description: 文件描述
7 --> 7 -->
...@@ -72,11 +72,18 @@ ...@@ -72,11 +72,18 @@
72 <div class="post-header"> 72 <div class="post-header">
73 <van-row> 73 <van-row>
74 <van-col span="3"> 74 <van-col span="3">
75 - <van-image round width="2.5rem" height="2.5rem" :src="post.user.avatar || 'https://cdn.ipadbiz.cn/mlaj/images/icon_1.jpeg'" fit="cover" /> 75 + <van-image round width="2.5rem" height="2.5rem" :src="post.user.avatar || 'https://cdn.ipadbiz.cn/mlaj/images/icon_1.jpeg?imageMogr2/thumbnail/200x/strip/quality/70'" fit="cover" />
76 </van-col> 76 </van-col>
77 <van-col span="18"> 77 <van-col span="18">
78 <div class="user-info"> 78 <div class="user-info">
79 - <div class="username">{{ post.user.name }}</div> 79 + <div class="username">
80 + {{ post.user.name }}
81 + <!-- 补打卡标识标签 -->
82 + <span
83 + v-if="post.user.is_makeup"
84 + class="MakeupTag inline-flex items-center ml-2 px-2 py-0.5 rounded-full text-xs font-medium bg-green-50 text-green-600 border border-green-300"
85 + >补打卡</span>
86 + </div>
80 <div class="post-time">{{ post.user.time }}</div> 87 <div class="post-time">{{ post.user.time }}</div>
81 </div> 88 </div>
82 </van-col> 89 </van-col>
...@@ -99,7 +106,7 @@ ...@@ -99,7 +106,7 @@
99 <div v-for="(v, idx) in post.videoList" :key="idx"> 106 <div v-for="(v, idx) in post.videoList" :key="idx">
100 <!-- 视频封面和播放按钮 --> 107 <!-- 视频封面和播放按钮 -->
101 <div v-if="v.video && !v.isPlaying" class="relative w-full rounded-lg overflow-hidden" style="aspect-ratio: 16/9; margin-bottom: 1rem;"> 108 <div v-if="v.video && !v.isPlaying" class="relative w-full rounded-lg overflow-hidden" style="aspect-ratio: 16/9; margin-bottom: 1rem;">
102 - <img :src="v.videoCover || 'https://cdn.ipadbiz.cn/mlaj/images/cover_video_2.png'" 109 + <img :src="v.videoCover || 'https://cdn.ipadbiz.cn/mlaj/images/cover_video_2.png?imageMogr2/thumbnail/200x/strip/quality/70'"
103 :alt="v.content" class="w-full h-full object-cover" /> 110 :alt="v.content" class="w-full h-full object-cover" />
104 <div class="absolute inset-0 flex items-center justify-center cursor-pointer bg-black/20" 111 <div class="absolute inset-0 flex items-center justify-center cursor-pointer bg-black/20"
105 @click="startPlay(v)"> 112 @click="startPlay(v)">
...@@ -444,15 +451,13 @@ const formatter = (day) => { ...@@ -444,15 +451,13 @@ const formatter = (day) => {
444 451
445 // 检查是否已打卡 452 // 检查是否已打卡
446 if (checkin_days.includes(formattedDate)) { 453 if (checkin_days.includes(formattedDate)) {
454 + day.type = 'selected';
455 + day.bottomInfo = '已打卡';
447 // 如果是当前选中的已打卡日期,使用特殊样式 456 // 如果是当前选中的已打卡日期,使用特殊样式
448 if (selectedDate.value === formattedDate) { 457 if (selectedDate.value === formattedDate) {
449 day.className = 'calendar-selected'; 458 day.className = 'calendar-selected';
450 - day.type = 'selected';
451 - day.bottomInfo = '已打卡';
452 } else { 459 } else {
453 day.className = 'calendar-checkin'; 460 day.className = 'calendar-checkin';
454 - day.type = 'selected';
455 - day.bottomInfo = '已打卡';
456 } 461 }
457 } 462 }
458 } 463 }
...@@ -464,14 +469,14 @@ const formatter = (day) => { ...@@ -464,14 +469,14 @@ const formatter = (day) => {
464 // 检查是否已补卡 469 // 检查是否已补卡
465 if (fill_checkin_days.includes(formattedDate)) { 470 if (fill_checkin_days.includes(formattedDate)) {
466 // 如果是当前选中的已补卡日期,使用特殊样式 471 // 如果是当前选中的已补卡日期,使用特殊样式
467 - if (selectedDate.value === formattedDate) {
468 - day.className = 'calendar-selected';
469 day.type = 'selected'; 472 day.type = 'selected';
470 day.bottomInfo = '待补卡'; 473 day.bottomInfo = '待补卡';
474 + if (selectedDate.value === formattedDate) {
475 + day.className = 'calendar-selected';
476 + // 选中的是补卡日期
477 + isPatchCheckin.value = true;
471 } else { 478 } else {
472 day.className = 'calendar-fill-checkin'; 479 day.className = 'calendar-fill-checkin';
473 - day.type = 'selected';
474 - day.bottomInfo = '待补卡';
475 } 480 }
476 } 481 }
477 } 482 }
...@@ -564,7 +569,8 @@ const goToCheckinDetailPage = () => { ...@@ -564,7 +569,8 @@ const goToCheckinDetailPage = () => {
564 path: '/checkin/detail', 569 path: '/checkin/detail',
565 query: { 570 query: {
566 id: route.query.id, 571 id: route.query.id,
567 - date: current_date 572 + date: current_date,
573 + is_patch: isPatchCheckin.value ? '1' : '0',
568 } 574 }
569 }) 575 })
570 } 576 }
...@@ -674,6 +680,8 @@ const myCheckinDates = ref([]); ...@@ -674,6 +680,8 @@ const myCheckinDates = ref([]);
674 const myFillCheckinDates = ref([]); 680 const myFillCheckinDates = ref([]);
675 const checkinDataList = ref([]); 681 const checkinDataList = ref([]);
676 const showProgress = ref(true); 682 const showProgress = ref(true);
683 +// 是否为补卡模式
684 +const isPatchCheckin = ref(false);
677 685
678 // 作品类型选项 686 // 作品类型选项
679 const attachmentTypeOptions = ref([]); 687 const attachmentTypeOptions = ref([]);
...@@ -783,6 +791,7 @@ const formatData = (data) => { ...@@ -783,6 +791,7 @@ const formatData = (data) => {
783 name: item.username, 791 name: item.username,
784 avatar: item.avatar, 792 avatar: item.avatar,
785 time: item.created_time_desc, 793 time: item.created_time_desc,
794 + is_makeup: item.is_makeup,
786 }, 795 },
787 content: item.note, 796 content: item.note,
788 images, 797 images,
......