feat(签到): 实现从后端获取签到类型列表功能
- 新增checkin.js API模块用于获取签到任务列表 - 修改CheckInDialog和HomePage组件,移除硬编码的签到类型 - 根据后端返回的task_type动态显示不同图标 - 添加onMounted钩子异步获取签到列表数据
Showing
3 changed files
with
62 additions
and
29 deletions
src/api/checkin.js
0 → 100644
| 1 | +/* | ||
| 2 | + * @Date: 2025-06-06 09:26:16 | ||
| 3 | + * @LastEditors: hookehuyr hookehuyr@gmail.com | ||
| 4 | + * @LastEditTime: 2025-06-06 09:31:00 | ||
| 5 | + * @FilePath: /mlaj/src/api/checkin.js | ||
| 6 | + * @Description: 签到模块相关接口 | ||
| 7 | + */ | ||
| 8 | +import { fn, fetch } from './fn' | ||
| 9 | + | ||
| 10 | +const Api = { | ||
| 11 | + GET_TASK_LIST: '/srv/?a=task&t=my_list' | ||
| 12 | +} | ||
| 13 | + | ||
| 14 | +/** | ||
| 15 | + * @description: 获取签到类型列表 | ||
| 16 | + * @param: keyword 搜索课程名称 | ||
| 17 | + * @return: data: [{ id 作业id, title 作业名称, begin_date 开始时间, end_date 结束时间, task_type 任务类型 [checkin=签到 | file=上传附件], is_gray 作业是否应该置灰 }] | ||
| 18 | + */ | ||
| 19 | + | ||
| 20 | +export const getTaskListAPI = (params) => fn(fetch.get(Api.GET_TASK_LIST, params)) |
| ... | @@ -38,10 +38,8 @@ | ... | @@ -38,10 +38,8 @@ |
| 38 | ? 'bg-green-500 text-white' | 38 | ? 'bg-green-500 text-white' |
| 39 | : 'bg-gray-100 text-gray-500' | 39 | : 'bg-gray-100 text-gray-500' |
| 40 | ]"> | 40 | ]"> |
| 41 | - <van-icon v-if="checkInType.id === 'reflection'" name="coupon-o" size="1.5rem"/> | 41 | + <van-icon v-if="checkInType.task_type === 'checkin'" name="edit" size="1.5rem" /> |
| 42 | - <van-icon v-if="checkInType.id === 'reading'" name="edit" size="1.5rem" /> | 42 | + <van-icon v-if="checkInType.task_type === 'file'" name="tosend" size="1.5rem" /> |
| 43 | - <van-icon v-if="checkInType.id === 'exercise'" name="tosend" size="1.5rem" /> | ||
| 44 | - <van-icon v-if="checkInType.id === 'mix'" name="send-gift-o" size="1.5rem" /> | ||
| 45 | </div> | 43 | </div> |
| 46 | <span class="text-xs">{{ checkInType.name }}</span> | 44 | <span class="text-xs">{{ checkInType.name }}</span> |
| 47 | </button> | 45 | </button> |
| ... | @@ -74,14 +72,10 @@ | ... | @@ -74,14 +72,10 @@ |
| 74 | import { ref } from 'vue' | 72 | import { ref } from 'vue' |
| 75 | import { showToast } from 'vant' | 73 | import { showToast } from 'vant' |
| 76 | import { useRoute, useRouter } from 'vue-router' | 74 | import { useRoute, useRouter } from 'vue-router' |
| 75 | +import { getTaskListAPI } from "@/api/checkin"; | ||
| 77 | 76 | ||
| 78 | -// TODO: 从后端获取 | 77 | +// 签到列表 |
| 79 | -const checkInTypes = [ | 78 | +const checkInTypes = ref([]); |
| 80 | - { id: 'reading', name: '课程打卡', icon: 'book', path: '/checkin/reading' }, | ||
| 81 | - { id: 'exercise', name: '签到打卡', icon: 'running', path: '/checkin/exercise' }, | ||
| 82 | - { id: 'reflection', name: '学习打卡', icon: 'pencil-alt', path: '/checkin/writing' }, | ||
| 83 | - { id: 'mix', name: '图文打卡', icon: 'pencil-alt', path: '/checkin/index' } | ||
| 84 | -]; | ||
| 85 | 79 | ||
| 86 | const route = useRoute() | 80 | const route = useRoute() |
| 87 | const router = useRouter() | 81 | const router = useRouter() |
| ... | @@ -102,7 +96,7 @@ const isCheckingIn = ref(false) | ... | @@ -102,7 +96,7 @@ const isCheckingIn = ref(false) |
| 102 | const checkInSuccess = ref(false) | 96 | const checkInSuccess = ref(false) |
| 103 | 97 | ||
| 104 | const handleCheckInSelect = (type) => { | 98 | const handleCheckInSelect = (type) => { |
| 105 | - if (type.id === 'mix') { | 99 | + if (type.task_type === 'file') { |
| 106 | router.push({ | 100 | router.push({ |
| 107 | path: '/checkin/index', | 101 | path: '/checkin/index', |
| 108 | }) | 102 | }) |
| ... | @@ -147,4 +141,18 @@ const handleClose = () => { | ... | @@ -147,4 +141,18 @@ const handleClose = () => { |
| 147 | checkInSuccess.value = false | 141 | checkInSuccess.value = false |
| 148 | emit('update:show', false) | 142 | emit('update:show', false) |
| 149 | } | 143 | } |
| 144 | + | ||
| 145 | +onMounted(async () => { | ||
| 146 | + // 获取签到列表 | ||
| 147 | + const task = await getTaskListAPI() | ||
| 148 | + if (task.code) { | ||
| 149 | + task.data.forEach(item => { | ||
| 150 | + checkInTypes.value.push({ | ||
| 151 | + id: item.id, | ||
| 152 | + name: item.title, | ||
| 153 | + task_type: item.task_type, | ||
| 154 | + }) | ||
| 155 | + }) | ||
| 156 | + } | ||
| 157 | +}) | ||
| 150 | </script> | 158 | </script> | ... | ... |
| 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-04 09:38:40 | 4 | + * @LastEditTime: 2025-06-06 11:10:02 |
| 5 | * @FilePath: /mlaj/src/views/HomePage.vue | 5 | * @FilePath: /mlaj/src/views/HomePage.vue |
| 6 | * @Description: 美乐爱觉教育首页组件 | 6 | * @Description: 美乐爱觉教育首页组件 |
| 7 | * | 7 | * |
| ... | @@ -106,10 +106,8 @@ | ... | @@ -106,10 +106,8 @@ |
| 106 | ? 'bg-green-500 text-white' | 106 | ? 'bg-green-500 text-white' |
| 107 | : 'bg-gray-100 text-gray-500' | 107 | : 'bg-gray-100 text-gray-500' |
| 108 | ]"> | 108 | ]"> |
| 109 | - <van-icon v-if="checkInType.id === 'reflection'" name="coupon-o" size="1.5rem"/> | 109 | + <van-icon v-if="checkInType.task_type === 'checkin'" name="edit" size="1.5rem" /> |
| 110 | - <van-icon v-if="checkInType.id === 'reading'" name="edit" size="1.5rem" /> | 110 | + <van-icon v-if="checkInType.task_type === 'file'" name="tosend" size="1.5rem" /> |
| 111 | - <van-icon v-if="checkInType.id === 'exercise'" name="tosend" size="1.5rem" /> | ||
| 112 | - <van-icon v-if="checkInType.id === 'mix'" name="send-gift-o" size="1.5rem" /> | ||
| 113 | </div> | 111 | </div> |
| 114 | <span class="text-xs">{{ checkInType.name }}</span> | 112 | <span class="text-xs">{{ checkInType.name }}</span> |
| 115 | </button> | 113 | </button> |
| ... | @@ -525,6 +523,7 @@ import { showToast } from 'vant' | ... | @@ -525,6 +523,7 @@ import { showToast } from 'vant' |
| 525 | 523 | ||
| 526 | // 导入接口 | 524 | // 导入接口 |
| 527 | import { getCourseListAPI } from "@/api/course"; | 525 | import { getCourseListAPI } from "@/api/course"; |
| 526 | +import { getTaskListAPI } from "@/api/checkin"; | ||
| 528 | 527 | ||
| 529 | // 视频播放状态管理 | 528 | // 视频播放状态管理 |
| 530 | const activeVideoIndex = ref(null); // 当前播放的视频索引 | 529 | const activeVideoIndex = ref(null); // 当前播放的视频索引 |
| ... | @@ -565,14 +564,8 @@ const getRecommendations = (random = false) => { | ... | @@ -565,14 +564,8 @@ const getRecommendations = (random = false) => { |
| 565 | return userRecommendations.value.slice(0, 4) | 564 | return userRecommendations.value.slice(0, 4) |
| 566 | } | 565 | } |
| 567 | 566 | ||
| 568 | -// TODO: 从后端获取 | 567 | +// 签到列表 |
| 569 | -const checkInTypes = [ | 568 | +const checkInTypes = ref([]); |
| 570 | - { id: 'reading', name: '课程打卡', icon: 'book', path: '/checkin/reading' }, | ||
| 571 | - { id: 'exercise', name: '签到打卡', icon: 'running', path: '/checkin/exercise' }, | ||
| 572 | - // { id: 'study', name: '团队打卡', icon: 'graduation-cap', path: '/checkin/study' }, | ||
| 573 | - { id: 'reflection', name: '学习打卡', icon: 'pencil-alt', path: '/checkin/writing' }, | ||
| 574 | - { id: 'mix', name: '图文打卡', icon: 'pencil-alt', path: '/checkin/index' } | ||
| 575 | -]; | ||
| 576 | 569 | ||
| 577 | // 自动轮播 | 570 | // 自动轮播 |
| 578 | let carouselInterval | 571 | let carouselInterval |
| ... | @@ -599,6 +592,20 @@ onMounted(async () => { | ... | @@ -599,6 +592,20 @@ onMounted(async () => { |
| 599 | if (res2.code) { | 592 | if (res2.code) { |
| 600 | hotCourses.value = res2.data | 593 | hotCourses.value = res2.data |
| 601 | } | 594 | } |
| 595 | + | ||
| 596 | + // 获取签到列表 | ||
| 597 | + if(currentUser.value) { | ||
| 598 | + const task = await getTaskListAPI() | ||
| 599 | + if (task.code) { | ||
| 600 | + task.data.forEach(item => { | ||
| 601 | + checkInTypes.value.push({ | ||
| 602 | + id: item.id, | ||
| 603 | + name: item.title, | ||
| 604 | + task_type: item.task_type, | ||
| 605 | + }) | ||
| 606 | + }) | ||
| 607 | + } | ||
| 608 | + } | ||
| 602 | }) | 609 | }) |
| 603 | 610 | ||
| 604 | onUnmounted(() => { | 611 | onUnmounted(() => { |
| ... | @@ -636,7 +643,7 @@ const rightContent = h(RightContent) | ... | @@ -636,7 +643,7 @@ const rightContent = h(RightContent) |
| 636 | // 工具函数:处理图片加载错误,设置默认头像 | 643 | // 工具函数:处理图片加载错误,设置默认头像 |
| 637 | const handleImageError = (e) => { | 644 | const handleImageError = (e) => { |
| 638 | e.target.onerror = null // 防止循环触发错误 | 645 | e.target.onerror = null // 防止循环触发错误 |
| 639 | - e.target.src = 'https://cdn.ipadbiz.cn/mlaj/images/user-avatar-2.jpg' // 设置默认头像 | 646 | + e.target.src = '' // 设置默认头像 |
| 640 | } | 647 | } |
| 641 | 648 | ||
| 642 | // 工具函数:格式化今天的日期为中文格式 | 649 | // 工具函数:格式化今天的日期为中文格式 |
| ... | @@ -660,7 +667,7 @@ const scrollToSlide = (index) => { | ... | @@ -660,7 +667,7 @@ const scrollToSlide = (index) => { |
| 660 | 667 | ||
| 661 | // 打卡功能:处理打卡类型选择 | 668 | // 打卡功能:处理打卡类型选择 |
| 662 | const handleCheckInSelect = (checkInType) => { | 669 | const handleCheckInSelect = (checkInType) => { |
| 663 | - if (checkInType.id === 'mix') { | 670 | + if (checkInType.task_type === 'file') { |
| 664 | $router.push({ | 671 | $router.push({ |
| 665 | path: '/checkin/index', | 672 | path: '/checkin/index', |
| 666 | }) | 673 | }) |
| ... | @@ -697,8 +704,6 @@ const handleCheckInSubmit = () => { | ... | @@ -697,8 +704,6 @@ const handleCheckInSubmit = () => { |
| 697 | }, 1500) | 704 | }, 1500) |
| 698 | } | 705 | } |
| 699 | 706 | ||
| 700 | - | ||
| 701 | - | ||
| 702 | const contentRef = ref(null) // 内容区域的ref引用 | 707 | const contentRef = ref(null) // 内容区域的ref引用 |
| 703 | 708 | ||
| 704 | // 监听activeTab变化,重置内容区域位置 | 709 | // 监听activeTab变化,重置内容区域位置 | ... | ... |
-
Please register or login to post a comment