IntelliClass_FE/pages/course/[id]/classes.vue
Timothy Yin 3a8b78ea7b
feat: update course resource types and interfaces, add resource uploader component
- Expanded CourseResourceType to include "resource" and "temp".
- Renamed ICourseResource to IResource and updated its properties for consistency.
- Introduced ICreateResource type for resource creation.
- Modified ICourseSection and ICourseChapter interfaces to use the new IResource type and updated property names for camelCase.
- Implemented uploadFile function in file API for handling file uploads.
- Created ResourceUploader component for uploading resources with validation and feedback.
- Developed Card component for displaying course class details and managing student enrollment.
- Added AlertDialog components for consistent alert dialog UI.
- Enhanced table components for better data presentation and management.
- Implemented preview page for displaying various resource types based on file extension.
2025-04-08 00:04:29 +08:00

168 lines
4.6 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>