JoinCheckInPage.vue 7.04 KB
<!--
 * @Date: 2025-11-17 13:42:00
 * @LastEditors: hookehuyr hookehuyr@gmail.com
 * @LastEditTime: 2025-11-17 14:22:00
 * @FilePath: /mlaj/src/views/checkin/JoinCheckInPage.vue
 * @Description: 文件描述
-->
<template>
    <AppLayout :hasTitle="false">
        <div class="join-check-in-page">
            <!-- 头部课程信息 -->
            <div class="joinHeader bg-white rounded-lg shadow px-4 py-3">
                <div class="flex flex-col">
                    <van-image
                        height="8rem"
                        fit="cover"
                        :src="mock_task_info.course_cover_url"
                        class="rounded-lg"
                    />
                    <div class="mt-3 text-center">
                        <div class="courseTitle text-base font-semibold text-gray-800">{{ mock_task_info.course_title }}</div>
                        <div class="teacher flex items-center mt-1 justify-center">
                            <van-image
                                round
                                width="1.4rem"
                                height="1.4rem"
                                fit="cover"
                                :src="mock_task_info.teacher_avatar"
                            />
                            <span class="ml-2 text-sm text-gray-700">{{ mock_task_info.teacher_name }}</span>
                        </div>
                        <div class="schedule text-xs text-gray-500 mt-1">{{ mock_task_info.schedule_desc }}</div>
                    </div>
                </div>
            </div>

            <!-- 作业信息 -->
            <div class="infoCard bg-white rounded-lg shadow mt-4">
                <div class="cardHeader px-4 py-3 border-b border-gray-100">
                    <div class="cardTitle text-sm font-semibold text-gray-800">作业信息</div>
                </div>
                <div class="cardBody px-4 py-3 space-y-2">
                    <div class="infoItem flex justify-between text-sm">
                        <div class="label text-gray-500">作业名称</div>
                        <div class="value text-gray-800">{{ mock_task_info.task_title }}</div>
                    </div>
                    <div class="infoItem flex justify-between text-sm">
                        <div class="label text-gray-500">所属班级</div>
                        <div class="value text-gray-800">{{ mock_task_info.grade_name }} · {{ mock_task_info.class_name }}</div>
                    </div>
                    <div class="infoItem flex justify-between text-sm">
                        <div class="label text-gray-500">目标次数</div>
                        <div class="value text-gray-800">{{ mock_task_info.target_number }} 次</div>
                    </div>
                    <div class="infoItem flex justify-between text-sm">
                        <div class="label text-gray-500">起止时间</div>
                        <div class="value text-gray-800">{{ mock_task_info.period_desc }}</div>
                    </div>
                    <div class="infoItem flex justify-between text-sm">
                        <div class="label text-gray-500">报名截止</div>
                        <div class="value text-gray-800">{{ mock_task_info.join_deadline_desc }}</div>
                    </div>
                </div>
            </div>

            <!-- 作业说明 -->
            <div class="infoCard bg-white rounded-lg shadow mt-4">
                <div class="cardHeader px-4 py-3 border-b border-gray-100">
                    <div class="cardTitle text-sm font-semibold text-gray-800">作业说明</div>
                </div>
                <div class="cardBody px-4 py-3">
                    <div class="text-sm text-gray-700 leading-6 whitespace-pre-line">{{ mock_task_info.task_desc }}</div>
                </div>
            </div>

            <!-- 加入按钮 -->
            <div class="joinAction p-4 bg-gradient-to-t from-white/95 to-white/20">
                <van-button type="primary" round block class="h-11 text-base font-semibold" @click="on_join_click">
                    加入该作业
                </van-button>
            </div>
        </div>
    </AppLayout>
</template>

<script setup>
import { ref, onMounted } from 'vue'
import { useRoute, useRouter } from 'vue-router'
import { useTitle } from "@vueuse/core";
import { showConfirmDialog } from 'vant'
import AppLayout from '@/components/layout/AppLayout.vue'

const $route = useRoute();
const $router = useRouter();
useTitle($route.meta.title);

// Mock数据:课程与作业信息
const mock_task_info = ref({
    course_title: '英语口语提升营',
    course_cover_url: 'https://cdn.ipadbiz.cn/mlaj/images/cover_video_2.png?imageMogr2/thumbnail/200x/strip/quality/70',
    teacher_name: '王老师',
    teacher_avatar: 'https://cdn.ipadbiz.cn/mlaj/images/icon_1.jpeg?imageMogr2/thumbnail/200x/strip/quality/70',
    schedule_desc: '每周二、周四晚 19:00-20:00',
    grade_name: '五年级',
    class_name: '二班',
    task_title: '本周作业:日常口语练习',
    task_desc: '请完成3次日常口语练习打卡,每次不少于60秒,可上传音频或视频。',
    target_number: 3,
    period_desc: '2025-11-01 至 2025-11-30',
    join_deadline_desc: '2025-11-20 23:59',
})

// 目标打卡页作业ID(无真实数据前默认写死)
const target_checkin_id = ref('833668')

/**
 * 载入页面Mock数据
 * @returns {void}
 * 注释:此处预留真实接口接入位置,当前为静态Mock。
 */
const load_mock_data = () => {
    // 预留:后续可根据 $route.query.id 拉取真实数据并映射
}

/**
 * 点击加入作业的处理
 * @returns {Promise<void>}
 * 注释:弹出确认框,确认后跳转到打卡页。
 */
const on_join_click = async () => {
    try {
        await showConfirmDialog({
            title: '确认加入',
            message: '是否确认加入该作业?加入后可前往打卡页进行每日打卡。',
            confirmButtonColor: '#4caf50',
        })
        // 确认后跳转到打卡页
        $router.push({
            path: '/checkin/index',
            query: {
                id: target_checkin_id.value,
            }
        })
    } catch (err) {
        // 用户取消
    }
}

onMounted(() => {
    load_mock_data()
})
</script>

<style lang="less" scoped>
.join-check-in-page {
    min-height: 100vh;
    background: linear-gradient(to bottom right, #f0fdf4, #f0fdfa, #eff6ff);
    padding: 1rem;
    padding-bottom: 6rem;

    .joinHeader {
        .courseTitle {
            line-height: 1.4;
        }
        .teacher {
            .name {
                color: #4caf50;
            }
        }
    }

    .infoCard {
        .cardHeader {
            .cardTitle {
                color: #4caf50;
            }
        }
        .cardBody {
            .infoItem {
                .label {
                    color: #6b7280;
                }
                .value {
                    color: #111827;
                }
            }
        }
    }

    .joinAction {
        box-shadow: 0 -6px 12px rgba(0,0,0,0.06);
    }
}
</style>