hookehuyr

feat(签到): 实现从后端获取签到类型列表功能

- 新增checkin.js API模块用于获取签到任务列表
- 修改CheckInDialog和HomePage组件,移除硬编码的签到类型
- 根据后端返回的task_type动态显示不同图标
- 添加onMounted钩子异步获取签到列表数据
/*
* @Date: 2025-06-06 09:26:16
* @LastEditors: hookehuyr hookehuyr@gmail.com
* @LastEditTime: 2025-06-06 09:31:00
* @FilePath: /mlaj/src/api/checkin.js
* @Description: 签到模块相关接口
*/
import { fn, fetch } from './fn'
const Api = {
GET_TASK_LIST: '/srv/?a=task&t=my_list'
}
/**
* @description: 获取签到类型列表
* @param: keyword 搜索课程名称
* @return: data: [{ id 作业id, title 作业名称, begin_date 开始时间, end_date 结束时间, task_type 任务类型 [checkin=签到 | file=上传附件], is_gray 作业是否应该置灰 }]
*/
export const getTaskListAPI = (params) => fn(fetch.get(Api.GET_TASK_LIST, params))
......@@ -38,10 +38,8 @@
? 'bg-green-500 text-white'
: 'bg-gray-100 text-gray-500'
]">
<van-icon v-if="checkInType.id === 'reflection'" name="coupon-o" size="1.5rem"/>
<van-icon v-if="checkInType.id === 'reading'" name="edit" size="1.5rem" />
<van-icon v-if="checkInType.id === 'exercise'" name="tosend" size="1.5rem" />
<van-icon v-if="checkInType.id === 'mix'" name="send-gift-o" size="1.5rem" />
<van-icon v-if="checkInType.task_type === 'checkin'" name="edit" size="1.5rem" />
<van-icon v-if="checkInType.task_type === 'file'" name="tosend" size="1.5rem" />
</div>
<span class="text-xs">{{ checkInType.name }}</span>
</button>
......@@ -74,14 +72,10 @@
import { ref } from 'vue'
import { showToast } from 'vant'
import { useRoute, useRouter } from 'vue-router'
import { getTaskListAPI } from "@/api/checkin";
// TODO: 从后端获取
const checkInTypes = [
{ id: 'reading', name: '课程打卡', icon: 'book', path: '/checkin/reading' },
{ id: 'exercise', name: '签到打卡', icon: 'running', path: '/checkin/exercise' },
{ id: 'reflection', name: '学习打卡', icon: 'pencil-alt', path: '/checkin/writing' },
{ id: 'mix', name: '图文打卡', icon: 'pencil-alt', path: '/checkin/index' }
];
// 签到列表
const checkInTypes = ref([]);
const route = useRoute()
const router = useRouter()
......@@ -102,7 +96,7 @@ const isCheckingIn = ref(false)
const checkInSuccess = ref(false)
const handleCheckInSelect = (type) => {
if (type.id === 'mix') {
if (type.task_type === 'file') {
router.push({
path: '/checkin/index',
})
......@@ -147,4 +141,18 @@ const handleClose = () => {
checkInSuccess.value = false
emit('update:show', false)
}
onMounted(async () => {
// 获取签到列表
const task = await getTaskListAPI()
if (task.code) {
task.data.forEach(item => {
checkInTypes.value.push({
id: item.id,
name: item.title,
task_type: item.task_type,
})
})
}
})
</script>
......
<!--
* @Date: 2025-03-20 19:55:21
* @LastEditors: hookehuyr hookehuyr@gmail.com
* @LastEditTime: 2025-06-04 09:38:40
* @LastEditTime: 2025-06-06 11:10:02
* @FilePath: /mlaj/src/views/HomePage.vue
* @Description: 美乐爱觉教育首页组件
*
......@@ -106,10 +106,8 @@
? 'bg-green-500 text-white'
: 'bg-gray-100 text-gray-500'
]">
<van-icon v-if="checkInType.id === 'reflection'" name="coupon-o" size="1.5rem"/>
<van-icon v-if="checkInType.id === 'reading'" name="edit" size="1.5rem" />
<van-icon v-if="checkInType.id === 'exercise'" name="tosend" size="1.5rem" />
<van-icon v-if="checkInType.id === 'mix'" name="send-gift-o" size="1.5rem" />
<van-icon v-if="checkInType.task_type === 'checkin'" name="edit" size="1.5rem" />
<van-icon v-if="checkInType.task_type === 'file'" name="tosend" size="1.5rem" />
</div>
<span class="text-xs">{{ checkInType.name }}</span>
</button>
......@@ -525,6 +523,7 @@ import { showToast } from 'vant'
// 导入接口
import { getCourseListAPI } from "@/api/course";
import { getTaskListAPI } from "@/api/checkin";
// 视频播放状态管理
const activeVideoIndex = ref(null); // 当前播放的视频索引
......@@ -565,14 +564,8 @@ const getRecommendations = (random = false) => {
return userRecommendations.value.slice(0, 4)
}
// TODO: 从后端获取
const checkInTypes = [
{ id: 'reading', name: '课程打卡', icon: 'book', path: '/checkin/reading' },
{ id: 'exercise', name: '签到打卡', icon: 'running', path: '/checkin/exercise' },
// { id: 'study', name: '团队打卡', icon: 'graduation-cap', path: '/checkin/study' },
{ id: 'reflection', name: '学习打卡', icon: 'pencil-alt', path: '/checkin/writing' },
{ id: 'mix', name: '图文打卡', icon: 'pencil-alt', path: '/checkin/index' }
];
// 签到列表
const checkInTypes = ref([]);
// 自动轮播
let carouselInterval
......@@ -599,6 +592,20 @@ onMounted(async () => {
if (res2.code) {
hotCourses.value = res2.data
}
// 获取签到列表
if(currentUser.value) {
const task = await getTaskListAPI()
if (task.code) {
task.data.forEach(item => {
checkInTypes.value.push({
id: item.id,
name: item.title,
task_type: item.task_type,
})
})
}
}
})
onUnmounted(() => {
......@@ -636,7 +643,7 @@ const rightContent = h(RightContent)
// 工具函数:处理图片加载错误,设置默认头像
const handleImageError = (e) => {
e.target.onerror = null // 防止循环触发错误
e.target.src = 'https://cdn.ipadbiz.cn/mlaj/images/user-avatar-2.jpg' // 设置默认头像
e.target.src = '' // 设置默认头像
}
// 工具函数:格式化今天的日期为中文格式
......@@ -660,7 +667,7 @@ const scrollToSlide = (index) => {
// 打卡功能:处理打卡类型选择
const handleCheckInSelect = (checkInType) => {
if (checkInType.id === 'mix') {
if (checkInType.task_type === 'file') {
$router.push({
path: '/checkin/index',
})
......@@ -697,8 +704,6 @@ const handleCheckInSubmit = () => {
}, 1500)
}
const contentRef = ref(null) // 内容区域的ref引用
// 监听activeTab变化,重置内容区域位置
......