185 lines
4.8 KiB
Vue
185 lines
4.8 KiB
Vue
<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>
|