IntelliClass_FE/pages/course/[id]/classes.vue
2025-04-19 01:52:37 +08:00

185 lines
4.8 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<script lang="ts" setup>
import { toTypedSchema } from '@vee-validate/zod'
import { useForm } from 'vee-validate'
import { toast } from 'vue-sonner'
import { z } from 'zod'
import {
createClass,
getClassListByCourse,
getCourseDetail,
} from '~/api/course'
definePageMeta({
requiresAuth: true,
})
const {
params: { id: courseId },
} = useRoute()
// const loginState = useLoginState();
const course = await getCourseDetail(courseId as string)
const { data: classes, refresh: refreshClasses } = useAsyncData(() =>
getClassListByCourse(parseInt(courseId as string)),
)
const createClassDialogOpen = ref(false)
const createClassSchema = toTypedSchema(
z.object({
className: z
.string()
.min(2, '班级名称至少2个字符')
.max(32, '最大长度32个字符'),
notes: z.string().max(200, '班级介绍最大长度200个字符'),
courseId: z.number().min(1, '课程ID不能为空'),
}),
)
const createClassForm = useForm({
validationSchema: createClassSchema,
initialValues: {
className: '',
notes: '',
courseId: Number(courseId),
},
})
const onCreateClassSubmit = createClassForm.handleSubmit((values) => {
toast.promise(createClass(values), {
loading: '正在创建班级...',
success: () => {
createClassForm.resetForm()
createClassDialogOpen.value = false
return '创建班级成功'
},
error: () => {
return '创建班级失败'
},
finally: () => {
refreshClasses()
},
})
})
// const onDeleteClass = (classId: number) => {
// toast.promise(deleteCourseClass(classId), {
// loading: "正在删除班级...",
// success: () => {
// refreshClasses();
// return "删除班级成功";
// },
// error: () => {
// return "删除班级失败";
// },
// });
// };
</script>
<template>
<div class="flex flex-col gap-4 px-4 py-2">
<div class="flex justify-between items-start">
<h1 class="text-xl font-medium">
课程班级管理
<span class="block text-sm text-muted-foreground">
课程负责人{{ course.data.teacherName || '未知' }}
</span>
</h1>
<div class="flex items-center gap-4">
<Dialog v-model:open="createClassDialogOpen">
<DialogTrigger as-child>
<Button
variant="secondary"
size="sm"
class="flex items-center gap-1"
>
<Icon
name="tabler:plus"
size="16px"
/>
<span>创建班级</span>
</Button>
</DialogTrigger>
<DialogContent class="sm:max-w-[425px]">
<DialogHeader>
<DialogTitle>创建班级</DialogTitle>
</DialogHeader>
<form
id="create-class-form"
autocomplete="off"
class="space-y-2"
@submit="onCreateClassSubmit"
>
<FormField
v-slot="{ componentField }"
name="className"
>
<FormItem v-auto-animate>
<FormLabel>班级名称</FormLabel>
<FormControl>
<Input
type="text"
placeholder="请输入班级名称"
v-bind="componentField"
/>
</FormControl>
<FormMessage />
</FormItem>
</FormField>
<FormField
v-slot="{ componentField }"
name="notes"
>
<FormItem v-auto-animate>
<FormLabel>班级介绍</FormLabel>
<FormControl>
<Textarea
placeholder="请输入班级介绍"
v-bind="componentField"
/>
</FormControl>
<FormMessage />
</FormItem>
</FormField>
<input
type="hidden"
name="courseId"
/>
</form>
<DialogFooter>
<Button
type="submit"
form="create-class-form"
>
创建
</Button>
</DialogFooter>
</DialogContent>
</Dialog>
</div>
</div>
<div
v-if="classes?.data && classes.data.length > 0"
class="grid gap-6 grid-cols-1 sm:grid-cols-2 2xl:grid-cols-4"
>
<CourseClassCard
v-for="classItem in classes.data"
:key="classItem.classId"
:class-item="classItem"
/>
</div>
<EmptyScreen
v-else
title="暂无班级"
description="课程下没有班级请创建新的班级"
icon="fluent-color:people-list-24"
/>
</div>
</template>
<style scoped></style>