CourseGroupCascader.vue 4.25 KB
<!--
 * @Author: hookehuyr hookehuyr@gmail.com
 * @Date: 2025-11-07 11:00:00
 * @LastEditors: hookehuyr hookehuyr@gmail.com
 * @LastEditTime: 2025-11-07 17:46:23
 * @FilePath: /mlaj/src/components/ui/CourseGroupCascader.vue
 * @Description: 教师页面筛选组件(年级/班级/课程),内部管理v-model与options并对外emit change事件
-->
<template>
    <!-- 课程 / 年级 / 班级 级联筛选 -->
    <van-dropdown-menu active-color="#10b981" swipe-threshold="2">
        <van-dropdown-item v-model="select_course_value" :options="course_option" @change="on_course_change" />
        <van-dropdown-item v-model="select_major_group_value" :options="major_group_option"
            @change="on_major_group_change" />
        <van-dropdown-item v-model="select_minor_group_value" :options="minor_group_option"
            @change="on_minor_group_change" />
    </van-dropdown-menu>
</template>

<script setup>
import { ref, onMounted } from 'vue'
import { getTeacherGradeClassListAPI } from "@/api/teacher";

// 组件对外事件
const emit = defineEmits(['change'])

// 本组件内部管理的选择值(课程 / 年级 / 班级)
const select_course_value = ref(null)
const select_major_group_value = ref(null)
const select_minor_group_value = ref(null)

// 本组件内部管理的选项数据(课程 / 年级 / 班级)
const course_option = ref([])
const major_group_option = ref([])
const minor_group_option = ref([])

// 获取筛选选项列表
const getFilterList = async (group_id = null, team_id = null) => {
    const { code, data } = await getTeacherGradeClassListAPI({ group_id, team_id });
    if (code) {
        // 处理数据
        course_option.value = data.group_list?.map(item => {
            return {
                text: item.title,
                value: item.id,
            }
        });
        course_option.value.unshift({
            text: '全部课程',
            value: null,
        });
        major_group_option.value = data.team_list?.map(item => {
            return {
                text: item.team_name,
                value: item.id,
            }
        });
        major_group_option.value.unshift({
            text: '全部年级',
            value: null,
        });
        minor_group_option.value = data.subteam_list?.map(item => {
            return {
                text: item.subteam_name,
                value: item.id,
            }
        });
        minor_group_option.value.unshift({
            text: '全部班级',
            value: null,
        });
    }
}

/**
 * 课程变化处理
 * @param {number|null} val 选中的课程ID
 * @returns {void}
 */
const on_course_change = async (val) => {
    select_course_value.value = val
    // 切换课程时重置分组选择
    select_major_group_value.value = null
    select_minor_group_value.value = null
    // 重建年级选项
    getFilterList(val)
    // 对外发出change事件,标识来源与值
    emit('change', { type: 'course', value: val })
}

/**
 * 年级变化处理
 * @param {number|null} val 选中的年级ID
 * @returns {void}
 */
const on_major_group_change = async (val) => {
    select_major_group_value.value = val
    // 切换年级时重置班级选择并重建班级选项
    select_minor_group_value.value = null
    getFilterList(select_course_value.value, val)
    // 对外发出change事件,标识来源与值
    emit('change', { type: 'major_group', value: val })
}

/**
 * 班级变化处理
 * @param {number|null} val 选中的班级ID
 * @returns {void}
 */
const on_minor_group_change = (val) => {
    select_minor_group_value.value = val
    // 对外发出change事件,标识来源与值
    emit('change', { type: 'minor_group', value: val })
}

/**
 * 组件挂载时初始化筛选选项
 * @returns {void}
 */
onMounted(async () => {
    getFilterList()
})
</script>

<style lang="less">
// 保持与页面一致的下拉菜单样式(如需可局部覆盖)
.van-dropdown-menu {
    background-color: white;
    border-radius: 0.75rem;
    box-shadow: 0 1px 3px 0 rgba(0, 0, 0, 0.1);
}

.van-dropdown-item {
    .van-cell__title {
        white-space: nowrap;
        overflow: hidden;
        text-overflow: ellipsis;
        max-width: 100%;
        flex: 0 0 80%;
    }

    .van-cell__value {
        flex: 0 0 20%;
    }
}
</style>