feat(打卡): 完善打卡功能逻辑和接口
- 在ProfilePage.vue中重构打卡按钮点击逻辑,添加无任务时的提示 - 在checkin.js中添加删除、点赞和取消点赞的API接口 - 在IndexCheckInPage.vue中实现点赞和删除打卡动态的功能 - 在HomePage.vue中优化打卡任务显示逻辑,添加无任务时的提示
Showing
4 changed files
with
74 additions
and
18 deletions
| 1 | /* | 1 | /* |
| 2 | * @Date: 2025-06-06 09:26:16 | 2 | * @Date: 2025-06-06 09:26:16 |
| 3 | * @LastEditors: hookehuyr hookehuyr@gmail.com | 3 | * @LastEditors: hookehuyr hookehuyr@gmail.com |
| 4 | - * @LastEditTime: 2025-06-06 17:46:06 | 4 | + * @LastEditTime: 2025-06-06 18:12:47 |
| 5 | * @FilePath: /mlaj/src/api/checkin.js | 5 | * @FilePath: /mlaj/src/api/checkin.js |
| 6 | * @Description: 签到模块相关接口 | 6 | * @Description: 签到模块相关接口 |
| 7 | */ | 7 | */ |
| ... | @@ -15,6 +15,9 @@ const Api = { | ... | @@ -15,6 +15,9 @@ const Api = { |
| 15 | TASK_UPLOAD_LIST: '/srv/?a=checkin&t=upload_list', | 15 | TASK_UPLOAD_LIST: '/srv/?a=checkin&t=upload_list', |
| 16 | TASK_UPLOAD_INFO: '/srv/?a=checkin&t=upload_info', | 16 | TASK_UPLOAD_INFO: '/srv/?a=checkin&t=upload_info', |
| 17 | TASK_UPLOAD_EDIT: '/srv/?a=checkin&t=upload_edit', | 17 | TASK_UPLOAD_EDIT: '/srv/?a=checkin&t=upload_edit', |
| 18 | + TASK_UPLOAD_DEL: '/srv/?a=checkin&t=upload_del', | ||
| 19 | + TASK_UPLOAD_LIKE: '/srv/?a=checkin&t=like', | ||
| 20 | + TASK_UPLOAD_DISLIKE: '/srv/?a=checkin&t=dislike', | ||
| 18 | } | 21 | } |
| 19 | 22 | ||
| 20 | /** | 23 | /** |
| ... | @@ -78,3 +81,24 @@ export const getUploadTaskInfoAPI = (params) => fn(fetch.get(Api.TASK_UPLOAD_IN | ... | @@ -78,3 +81,24 @@ export const getUploadTaskInfoAPI = (params) => fn(fetch.get(Api.TASK_UPLOAD_IN |
| 78 | * @returns | 81 | * @returns |
| 79 | */ | 82 | */ |
| 80 | export const editUploadTaskInfoAPI = (params) => fn(fetch.get(Api.TASK_UPLOAD_EDIT, params)) | 83 | export const editUploadTaskInfoAPI = (params) => fn(fetch.get(Api.TASK_UPLOAD_EDIT, params)) |
| 84 | + | ||
| 85 | +/** | ||
| 86 | + * @description: 删除打卡动态详情 | ||
| 87 | + * @param i 打卡动态ID | ||
| 88 | + * @returns | ||
| 89 | + */ | ||
| 90 | +export const delUploadTaskInfoAPI = (params) => fn(fetch.get(Api.TASK_UPLOAD_DEL, params)) | ||
| 91 | + | ||
| 92 | +/** | ||
| 93 | + * @description: 给打卡点赞 | ||
| 94 | + * @param checkin_id 打卡动态ID | ||
| 95 | + * @returns | ||
| 96 | + */ | ||
| 97 | +export const likeUploadTaskInfoAPI = (params) => fn(fetch.post(Api.TASK_UPLOAD_LIKE, params)) | ||
| 98 | + | ||
| 99 | +/** | ||
| 100 | + * @description: 取消点赞 | ||
| 101 | + * @param checkin_id 打卡动态ID | ||
| 102 | + * @returns | ||
| 103 | + */ | ||
| 104 | +export const dislikeUploadTaskInfoAPI = (params) => fn(fetch.post(Api.TASK_UPLOAD_DISLIKE, params)) | ... | ... |
| 1 | <!-- | 1 | <!-- |
| 2 | * @Date: 2025-03-20 19:55:21 | 2 | * @Date: 2025-03-20 19:55:21 |
| 3 | * @LastEditors: hookehuyr hookehuyr@gmail.com | 3 | * @LastEditors: hookehuyr hookehuyr@gmail.com |
| 4 | - * @LastEditTime: 2025-06-06 17:26:39 | 4 | + * @LastEditTime: 2025-06-06 18:22:14 |
| 5 | * @FilePath: /mlaj/src/views/HomePage.vue | 5 | * @FilePath: /mlaj/src/views/HomePage.vue |
| 6 | * @Description: 美乐爱觉教育首页组件 | 6 | * @Description: 美乐爱觉教育首页组件 |
| 7 | * | 7 | * |
| ... | @@ -74,12 +74,13 @@ | ... | @@ -74,12 +74,13 @@ |
| 74 | </FrostedGlass> | 74 | </FrostedGlass> |
| 75 | 75 | ||
| 76 | <!-- Daily Check-in --> | 76 | <!-- Daily Check-in --> |
| 77 | - <FrostedGlass v-if="checkInTypes.length" class="p-4 rounded-xl"> | 77 | + <FrostedGlass class="p-4 rounded-xl"> |
| 78 | <div class="flex justify-between items-center mb-3"> | 78 | <div class="flex justify-between items-center mb-3"> |
| 79 | <h3 class="font-medium">今日打卡</h3> | 79 | <h3 class="font-medium">今日打卡</h3> |
| 80 | <router-link to="/profile" class="text-green-600 text-sm">打卡记录</router-link> | 80 | <router-link to="/profile" class="text-green-600 text-sm">打卡记录</router-link> |
| 81 | </div> | 81 | </div> |
| 82 | 82 | ||
| 83 | + <template v-if="checkInTypes.length"> | ||
| 83 | <div v-if="checkInSuccess" class="bg-green-50 border border-green-200 rounded-lg p-4 text-center"> | 84 | <div v-if="checkInSuccess" class="bg-green-50 border border-green-200 rounded-lg p-4 text-center"> |
| 84 | <svg xmlns="http://www.w3.org/2000/svg" class="h-10 w-10 text-green-500 mx-auto mb-2" fill="none" viewBox="0 0 24 24" stroke="currentColor"> | 85 | <svg xmlns="http://www.w3.org/2000/svg" class="h-10 w-10 text-green-500 mx-auto mb-2" fill="none" viewBox="0 0 24 24" stroke="currentColor"> |
| 85 | <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 12l2 2 4-4m6 2a9 9 0 11-18 0 9 9 0 0118 0z" /> | 86 | <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 12l2 2 4-4m6 2a9 9 0 11-18 0 9 9 0 0118 0z" /> |
| ... | @@ -132,6 +133,12 @@ | ... | @@ -132,6 +133,12 @@ |
| 132 | </button> | 133 | </button> |
| 133 | </div> | 134 | </div> |
| 134 | </template> | 135 | </template> |
| 136 | + </template> | ||
| 137 | + <template v-else> | ||
| 138 | + <div class="text-center"> | ||
| 139 | + <p class="text-gray-500">暂无打卡任务</p> | ||
| 140 | + </div> | ||
| 141 | + </template> | ||
| 135 | </FrostedGlass> | 142 | </FrostedGlass> |
| 136 | </div> | 143 | </div> |
| 137 | 144 | ... | ... |
| 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-06 17:40:39 | 4 | + * @LastEditTime: 2025-06-06 18:27:24 |
| 5 | * @FilePath: /mlaj/src/views/checkin/IndexCheckInPage.vue | 5 | * @FilePath: /mlaj/src/views/checkin/IndexCheckInPage.vue |
| 6 | * @Description: 文件描述 | 6 | * @Description: 文件描述 |
| 7 | --> | 7 | --> |
| ... | @@ -47,8 +47,7 @@ | ... | @@ -47,8 +47,7 @@ |
| 47 | </div> | 47 | </div> |
| 48 | </div> | 48 | </div> |
| 49 | 49 | ||
| 50 | - <!-- <div v-if="!taskDetail.is_gray" class="text-wrapper"> --> | 50 | + <div v-if="!taskDetail.is_finish" class="text-wrapper"> |
| 51 | - <div v-if="taskDetail.is_gray" class="text-wrapper"> | ||
| 52 | <div class="text-header">打卡类型</div> | 51 | <div class="text-header">打卡类型</div> |
| 53 | <div class="upload-wrapper"> | 52 | <div class="upload-wrapper"> |
| 54 | <div @click="goToCheckinImagePage" class="upload-boxer"> | 53 | <div @click="goToCheckinImagePage" class="upload-boxer"> |
| ... | @@ -164,7 +163,7 @@ import AudioPlayer from "@/components/ui/AudioPlayer.vue"; | ... | @@ -164,7 +163,7 @@ import AudioPlayer from "@/components/ui/AudioPlayer.vue"; |
| 164 | import { useTitle } from '@vueuse/core'; | 163 | import { useTitle } from '@vueuse/core'; |
| 165 | import dayjs from 'dayjs'; | 164 | import dayjs from 'dayjs'; |
| 166 | 165 | ||
| 167 | -import { getTaskDetailAPI, getUploadTaskListAPI } from "@/api/checkin"; | 166 | +import { getTaskDetailAPI, getUploadTaskListAPI, delUploadTaskInfoAPI, likeUploadTaskInfoAPI, dislikeUploadTaskInfoAPI } from "@/api/checkin"; |
| 168 | 167 | ||
| 169 | const route = useRoute() | 168 | const route = useRoute() |
| 170 | const router = useRouter() | 169 | const router = useRouter() |
| ... | @@ -449,7 +448,8 @@ const mockPosts = ref([ | ... | @@ -449,7 +448,8 @@ const mockPosts = ref([ |
| 449 | ]); | 448 | ]); |
| 450 | 449 | ||
| 451 | const themeVars = { | 450 | const themeVars = { |
| 452 | - calendarSelectedDayBackground: '#4caf50' | 451 | + calendarSelectedDayBackground: '#4caf50', |
| 452 | + calendarHeaderShadow: 'rgba(0, 0, 0, 0.1)', | ||
| 453 | } | 453 | } |
| 454 | 454 | ||
| 455 | const progress1 = ref(0); | 455 | const progress1 = ref(0); |
| ... | @@ -531,9 +531,22 @@ const goToCheckinAudioPage = (type) => { | ... | @@ -531,9 +531,22 @@ const goToCheckinAudioPage = (type) => { |
| 531 | }) | 531 | }) |
| 532 | } | 532 | } |
| 533 | 533 | ||
| 534 | -const handLike = (post) => { | 534 | +const handLike = async (post) => { |
| 535 | - post.is_liked = !post.is_liked; | 535 | + if (!post.is_liked) { |
| 536 | - // TODO: 调用接口 | 536 | + const { code, data } = await likeUploadTaskInfoAPI({ checkin_id: post.id, }) |
| 537 | + if (code) { | ||
| 538 | + showSuccessToast('点赞成功') | ||
| 539 | + post.likes++; | ||
| 540 | + post.is_liked = true; | ||
| 541 | + } | ||
| 542 | + } else { | ||
| 543 | + const { code, data } = await dislikeUploadTaskInfoAPI({ checkin_id: post.id, }) | ||
| 544 | + if (code) { | ||
| 545 | + showSuccessToast('取消点赞成功') | ||
| 546 | + post.likes--; | ||
| 547 | + post.is_liked = false; | ||
| 548 | + } | ||
| 549 | + } | ||
| 537 | } | 550 | } |
| 538 | 551 | ||
| 539 | const editCheckin = (post) => { | 552 | const editCheckin = (post) => { |
| ... | @@ -574,12 +587,16 @@ const delCheckin = (post) => { | ... | @@ -574,12 +587,16 @@ const delCheckin = (post) => { |
| 574 | message: '您是否确定要删除该动态?', | 587 | message: '您是否确定要删除该动态?', |
| 575 | confirmButtonColor: '#4caf50', | 588 | confirmButtonColor: '#4caf50', |
| 576 | }) | 589 | }) |
| 577 | - .then(() => { | 590 | + .then(async () => { |
| 578 | - // on confirm | 591 | + // 调用接口 |
| 579 | - // TODO: 调用接口 | 592 | + const { code, data } = await delUploadTaskInfoAPI({ i: post.id }); |
| 593 | + if (code) { | ||
| 580 | // 删除成功后,刷新页面 | 594 | // 删除成功后,刷新页面 |
| 581 | - showSuccessToast('成功文案'); | 595 | + showSuccessToast('删除成功'); |
| 582 | - // showFailToast('失败文案'); | 596 | + router.go(0); |
| 597 | + } else { | ||
| 598 | + showErrorToast('删除失败'); | ||
| 599 | + } | ||
| 583 | }) | 600 | }) |
| 584 | .catch(() => { | 601 | .catch(() => { |
| 585 | // on cancel | 602 | // on cancel | ... | ... |
| ... | @@ -55,8 +55,8 @@ | ... | @@ -55,8 +55,8 @@ |
| 55 | </div> | 55 | </div> |
| 56 | <div class="text-xs text-gray-500 mt-1">最长连续</div> | 56 | <div class="text-xs text-gray-500 mt-1">最长连续</div> |
| 57 | </div> | 57 | </div> |
| 58 | - <div v-if="checkinData.length"> | 58 | + <div> |
| 59 | - <div @click="showCheckInDialog = true" class="cursor-pointer"> | 59 | + <div @click="handleCheckin" class="cursor-pointer"> |
| 60 | <button | 60 | <button |
| 61 | class="bg-gradient-to-r from-green-500 to-green-600 text-white py-2 px-6 rounded-full text-sm shadow-sm" | 61 | class="bg-gradient-to-r from-green-500 to-green-600 text-white py-2 px-6 rounded-full text-sm shadow-sm" |
| 62 | > | 62 | > |
| ... | @@ -274,4 +274,12 @@ const menuItems3 = [ | ... | @@ -274,4 +274,12 @@ const menuItems3 = [ |
| 274 | path: "/profile/settings", | 274 | path: "/profile/settings", |
| 275 | }, | 275 | }, |
| 276 | ]; | 276 | ]; |
| 277 | + | ||
| 278 | +const handleCheckin = () => { | ||
| 279 | + if (checkinData.value.length) { | ||
| 280 | + showCheckInDialog.value = true; | ||
| 281 | + } else { | ||
| 282 | + showToast('暂无打卡任务') | ||
| 283 | + } | ||
| 284 | +} | ||
| 277 | </script> | 285 | </script> | ... | ... |
-
Please register or login to post a comment