TaskFilter.vue 5.83 KB
<template>
  <div class="task-filter bg-white">
    <div class="flex gap-2">
      <!-- 大作业选择 -->
      <div class="flex-1 min-w-0" @click="showTaskPicker = true">
        <div class="flex items-center justify-between bg-gray-50 rounded px-3 py-2 border border-gray-100">
          <span class="text-sm text-gray-700 truncate mr-1">{{ selectedTaskName || '全部作业' }}</span>
          <van-icon name="arrow-down" color="#9ca3af" size="12" />
        </div>
      </div>

      <!-- 小作业选择 -->
      <div class="flex-1 min-w-0" @click="handleSubtaskClick">
        <div class="flex items-center justify-between bg-gray-50 rounded px-3 py-2 border border-gray-100"
            :class="{ 'opacity-50': !selectedTaskId }">
          <span class="text-sm text-gray-700 truncate mr-1">{{ selectedSubtaskName || '全部小作业' }}</span>
          <van-icon name="arrow-down" color="#9ca3af" size="12" />
        </div>
      </div>
    </div>

    <!-- 大作业弹窗 -->
    <van-popup v-model:show="showTaskPicker" position="bottom" round>
      <van-picker
        :columns="taskColumns"
        @confirm="onConfirmTask"
        @cancel="showTaskPicker = false"
        show-toolbar
        title="选择作业"
      />
    </van-popup>

    <!-- 小作业弹窗 -->
    <van-popup v-model:show="showSubtaskPicker" position="bottom" round>
      <van-picker
        :columns="subtaskColumns"
        @confirm="onConfirmSubtask"
        @cancel="showSubtaskPicker = false"
        show-toolbar
        title="选择小作业"
      />
    </van-popup>
  </div>
</template>

<script setup>
import { ref, computed, watch, onMounted } from 'vue'
import { getTeacherTaskListAPI, getTeacherTaskDetailAPI } from '@/api/teacher'
import { showToast } from 'vant'

const props = defineProps({
  /** 班级群组ID */
  groupId: {
    type: [String, Number],
    default: ''
  }
})

const emit = defineEmits([
  /**
   * 筛选条件变更事件
   * @property {Object} payload
   * @property {string|number} payload.task_id - 作业ID
   * @property {string|number} payload.subtask_id - 子作业ID
   */
  'change',
  /**
   * 弹窗显示状态变更事件
   * @property {boolean} visible - 是否显示
   */
  'popup-visible-change'
])

// 状态
const showTaskPicker = ref(false)
const showSubtaskPicker = ref(false)

// 监听弹窗显示状态
watch([showTaskPicker, showSubtaskPicker], ([showTask, showSubtask]) => {
  emit('popup-visible-change', showTask || showSubtask)
})
const taskList = ref([])
const subtaskList = ref([])
const selectedTaskId = ref('')
const selectedSubtaskId = ref('')

// 计算属性 - 选项列表
const taskColumns = computed(() => {
  const list = taskList.value.map(item => ({ text: item.title, value: item.id }))
  return [{ text: '全部作业', value: '' }, ...list]
})

const subtaskColumns = computed(() => {
  const list = subtaskList.value.map(item => ({ text: item.title, value: item.id }))
  return [{ text: '全部小作业', value: '' }, ...list]
})

// 计算属性 - 显示名称
const selectedTaskName = computed(() => {
  if (!selectedTaskId.value) return '全部作业'
  const found = taskList.value.find(item => item.id === selectedTaskId.value)
  return found ? found.title : ''
})

const selectedSubtaskName = computed(() => {
  if (!selectedSubtaskId.value) return '全部小作业'
  const found = subtaskList.value.find(item => item.id === selectedSubtaskId.value)
  return found ? found.title : ''
})

/**
 * @description 获取大作业列表
 * 1. 检查 groupId 是否存在
 * 2. 调用 getTeacherTaskListAPI 获取列表
 * 3. 更新 taskList 数据
 * @returns {Promise<void>}
 */
const fetchTaskList = async () => {
  if (!props.groupId) {
    taskList.value = []
    return
  }

  try {
    const res = await getTeacherTaskListAPI({
      group_id: props.groupId,
      limit: 1000,
      page: 0
    })

    if (res.code === 1) {
      taskList.value = res.data || []
    }
  } catch (error) {
    console.error('获取作业列表失败:', error)
  }
}

// 监听 groupId 变化
watch(() => props.groupId, (newVal) => {
  fetchTaskList()
}, { immediate: true })

/**
 * @description 获取作业详情
 * @param {number|string} taskId 作业ID
 * @returns {Promise<void>}
 */
const fetchTaskDetail = async (taskId) => {
  if (!taskId) {
    subtaskList.value = []
    return
  }

  try {
    const res = await getTeacherTaskDetailAPI({ id: taskId })
    if (res.code === 1) {
      subtaskList.value = res.data.subtask_list || []
    }
  } catch (error) {
    console.error('获取作业详情失败:', error)
  }
}

/**
 * @description 确认选择作业
 * @param {Object} params
 * @param {Array} params.selectedOptions - 选中的选项数组
 */
const onConfirmTask = async ({ selectedOptions }) => {
  const option = selectedOptions[0]
  if (selectedTaskId.value !== option.value) {
    selectedTaskId.value = option.value
    // 重置小作业
    selectedSubtaskId.value = ''
    subtaskList.value = []

    if (option.value) {
      await fetchTaskDetail(option.value)
    }

    emitChange()
  }
  showTaskPicker.value = false
}

/**
 * @description 确认选择子作业
 * @param {Object} params
 * @param {Array} params.selectedOptions - 选中的选项数组
 */
const onConfirmSubtask = ({ selectedOptions }) => {
  const option = selectedOptions[0]
  selectedSubtaskId.value = option.value
  emitChange()
  showSubtaskPicker.value = false
}

/**
 * @description 处理子作业点击
 * 如果未选择作业,提示用户
 */
const handleSubtaskClick = () => {
  if (!selectedTaskId.value) {
    showToast('请先选择作业')
    return
  }
  showSubtaskPicker.value = true
}

/**
 * @description 触发 change 事件
 */
const emitChange = () => {
  emit('change', {
    task_id: selectedTaskId.value,
    subtask_id: selectedSubtaskId.value
  })
}
</script>

<style lang="less" scoped>
.task-filter {
  // 可以在这里添加额外的样式
}
</style>