完整性更新
Some checks failed
CI / build-and-test (push) Failing after 3m50s
CI / deploy (push) Has been skipped

现在已经实现了大部分基础功能
This commit is contained in:
SpecialX
2026-01-08 11:14:03 +08:00
parent 0da2eac0b4
commit 57807def37
155 changed files with 26421 additions and 1036 deletions

View File

@@ -0,0 +1,9 @@
"use client"
import * as React from "react"
import { SessionProvider } from "next-auth/react"
export function AuthSessionProvider({ children }: { children: React.ReactNode }) {
return <SessionProvider>{children}</SessionProvider>
}

View File

@@ -1,3 +1,5 @@
"use client"
import * as React from "react"
import * as ScrollAreaPrimitive from "@radix-ui/react-scroll-area"

View File

@@ -16,6 +16,7 @@ const SelectTrigger = React.forwardRef<
>(({ className, children, ...props }, ref) => (
<SelectPrimitive.Trigger
ref={ref}
suppressHydrationWarning
className={cn(
"flex h-9 w-full items-center justify-between whitespace-nowrap rounded-md border border-input bg-transparent px-3 py-2 text-sm shadow-sm ring-offset-background placeholder:text-muted-foreground focus:outline-none focus:ring-1 focus:ring-ring disabled:cursor-not-allowed disabled:opacity-50 [&>span]:line-clamp-1",
className

View File

@@ -10,6 +10,11 @@ import {
questionsToKnowledgePoints,
textbooks,
chapters,
schools,
grades,
classes,
classEnrollments,
classSchedule,
exams,
examQuestions,
examSubmissions,
@@ -27,6 +32,8 @@ export const usersRelations = relations(users, ({ many }) => ({
accounts: many(accounts),
sessions: many(sessions),
usersToRoles: many(usersToRoles),
teachingClasses: many(classes),
classEnrollments: many(classEnrollments),
createdExams: many(exams),
createdHomeworkAssignments: many(homeworkAssignments),
submissions: many(examSubmissions),
@@ -98,6 +105,11 @@ export const knowledgePointsRelations = relations(knowledgePoints, ({ one, many
children: many(knowledgePoints, {
relationName: "kp_hierarchy",
}),
chapter: one(chapters, {
fields: [knowledgePoints.chapterId],
references: [chapters.id],
}),
questionsToKnowledgePoints: many(questionsToKnowledgePoints),
}));
@@ -132,6 +144,64 @@ export const chaptersRelations = relations(chapters, ({ one, many }) => ({
children: many(chapters, {
relationName: "chapter_hierarchy",
}),
knowledgePoints: many(knowledgePoints),
}));
export const schoolsRelations = relations(schools, ({ many }) => ({
grades: many(grades),
classes: many(classes),
}))
export const gradesRelations = relations(grades, ({ one, many }) => ({
school: one(schools, {
fields: [grades.schoolId],
references: [schools.id],
}),
gradeHead: one(users, {
fields: [grades.gradeHeadId],
references: [users.id],
}),
teachingHead: one(users, {
fields: [grades.teachingHeadId],
references: [users.id],
}),
classes: many(classes),
}))
export const classesRelations = relations(classes, ({ one, many }) => ({
teacher: one(users, {
fields: [classes.teacherId],
references: [users.id],
}),
school: one(schools, {
fields: [classes.schoolId],
references: [schools.id],
}),
gradeEntity: one(grades, {
fields: [classes.gradeId],
references: [grades.id],
}),
enrollments: many(classEnrollments),
scheduleItems: many(classSchedule),
}));
export const classEnrollmentsRelations = relations(classEnrollments, ({ one }) => ({
class: one(classes, {
fields: [classEnrollments.classId],
references: [classes.id],
}),
student: one(users, {
fields: [classEnrollments.studentId],
references: [users.id],
}),
}));
export const classScheduleRelations = relations(classSchedule, ({ one }) => ({
class: one(classes, {
fields: [classSchedule.classId],
references: [classes.id],
}),
}));
export const examsRelations = relations(exams, ({ one, many }) => ({

View File

@@ -111,6 +111,8 @@ export const knowledgePoints = mysqlTable("knowledge_points", {
// Tree Structure: Parent KP
parentId: varchar("parent_id", { length: 128 }), // Self-reference defined in relations
chapterId: varchar("chapter_id", { length: 128 }),
// Metadata for ordering or level
level: int("level").default(0),
@@ -120,6 +122,7 @@ export const knowledgePoints = mysqlTable("knowledge_points", {
updatedAt: timestamp("updated_at").defaultNow().onUpdateNow().notNull(),
}, (table) => ({
parentIdIdx: index("parent_id_idx").on(table.parentId),
chapterIdIdx: index("kp_chapter_id_idx").on(table.chapterId),
}));
// --- 3. Question Bank (Core) ---
@@ -190,6 +193,8 @@ export const chapters = mysqlTable("chapters", {
// Chapters can also be nested
parentId: varchar("parent_id", { length: 128 }),
content: text("content"),
createdAt: timestamp("created_at").defaultNow().notNull(),
updatedAt: timestamp("updated_at").defaultNow().onUpdateNow().notNull(),
@@ -198,6 +203,179 @@ export const chapters = mysqlTable("chapters", {
parentIdIdx: index("parent_id_idx").on(table.parentId),
}));
// --- 5. School Management ---
export const departments = mysqlTable("departments", {
id: id("id").primaryKey(),
name: varchar("name", { length: 255 }).notNull().unique(),
description: text("description"),
createdAt: timestamp("created_at").defaultNow().notNull(),
updatedAt: timestamp("updated_at").defaultNow().onUpdateNow().notNull(),
}, (table) => ({
nameIdx: index("departments_name_idx").on(table.name),
}))
export const classrooms = mysqlTable("classrooms", {
id: id("id").primaryKey(),
name: varchar("name", { length: 255 }).notNull().unique(),
building: varchar("building", { length: 100 }),
floor: int("floor"),
capacity: int("capacity"),
createdAt: timestamp("created_at").defaultNow().notNull(),
updatedAt: timestamp("updated_at").defaultNow().onUpdateNow().notNull(),
}, (table) => ({
nameIdx: index("classrooms_name_idx").on(table.name),
}))
export const academicYears = mysqlTable("academic_years", {
id: id("id").primaryKey(),
name: varchar("name", { length: 100 }).notNull().unique(),
startDate: timestamp("start_date", { mode: "date" }).notNull(),
endDate: timestamp("end_date", { mode: "date" }).notNull(),
isActive: boolean("is_active").default(false).notNull(),
createdAt: timestamp("created_at").defaultNow().notNull(),
updatedAt: timestamp("updated_at").defaultNow().onUpdateNow().notNull(),
}, (table) => ({
nameIdx: index("academic_years_name_idx").on(table.name),
activeIdx: index("academic_years_active_idx").on(table.isActive),
}))
export const schools = mysqlTable("schools", {
id: id("id").primaryKey(),
name: varchar("name", { length: 255 }).notNull().unique(),
code: varchar("code", { length: 50 }).unique(),
createdAt: timestamp("created_at").defaultNow().notNull(),
updatedAt: timestamp("updated_at").defaultNow().onUpdateNow().notNull(),
}, (table) => ({
nameIdx: index("schools_name_idx").on(table.name),
codeIdx: index("schools_code_idx").on(table.code),
}))
export const grades = mysqlTable("grades", {
id: id("id").primaryKey(),
schoolId: varchar("school_id", { length: 128 }).notNull(),
name: varchar("name", { length: 100 }).notNull(),
order: int("order").default(0).notNull(),
gradeHeadId: varchar("grade_head_id", { length: 128 }),
teachingHeadId: varchar("teaching_head_id", { length: 128 }),
createdAt: timestamp("created_at").defaultNow().notNull(),
updatedAt: timestamp("updated_at").defaultNow().onUpdateNow().notNull(),
}, (table) => ({
schoolIdx: index("grades_school_idx").on(table.schoolId),
schoolNameUnique: index("grades_school_name_uniq").on(table.schoolId, table.name),
gradeHeadIdx: index("grades_grade_head_idx").on(table.gradeHeadId),
teachingHeadIdx: index("grades_teaching_head_idx").on(table.teachingHeadId),
schoolFk: foreignKey({
columns: [table.schoolId],
foreignColumns: [schools.id],
name: "g_s_fk",
}).onDelete("cascade"),
gradeHeadFk: foreignKey({
columns: [table.gradeHeadId],
foreignColumns: [users.id],
name: "g_gh_fk",
}).onDelete("set null"),
teachingHeadFk: foreignKey({
columns: [table.teachingHeadId],
foreignColumns: [users.id],
name: "g_th_fk",
}).onDelete("set null"),
}))
// --- 6. Classes / Enrollment / Schedule ---
export const classEnrollmentStatusEnum = mysqlEnum("class_enrollment_status", ["active", "inactive"]);
export const classes = mysqlTable("classes", {
id: id("id").primaryKey(),
schoolName: varchar("school_name", { length: 255 }),
schoolId: varchar("school_id", { length: 128 }),
name: varchar("name", { length: 255 }).notNull(),
grade: varchar("grade", { length: 50 }).notNull(),
gradeId: varchar("grade_id", { length: 128 }),
homeroom: varchar("homeroom", { length: 50 }),
room: varchar("room", { length: 50 }),
invitationCode: varchar("invitation_code", { length: 6 }).unique(),
teacherId: varchar("teacher_id", { length: 128 }).notNull().references(() => users.id, { onDelete: "cascade" }),
createdAt: timestamp("created_at").defaultNow().notNull(),
updatedAt: timestamp("updated_at").defaultNow().onUpdateNow().notNull(),
}, (table) => ({
teacherIdx: index("classes_teacher_idx").on(table.teacherId),
gradeIdx: index("classes_grade_idx").on(table.grade),
schoolIdx: index("classes_school_idx").on(table.schoolId),
gradeIdIdx: index("classes_grade_id_idx").on(table.gradeId),
schoolFk: foreignKey({
columns: [table.schoolId],
foreignColumns: [schools.id],
name: "c_s_fk",
}).onDelete("set null"),
gradeFk: foreignKey({
columns: [table.gradeId],
foreignColumns: [grades.id],
name: "c_g_fk",
}).onDelete("set null"),
}));
export const classSubjectEnum = mysqlEnum("subject", ["语文", "数学", "英语", "美术", "体育", "科学", "社会", "音乐"]);
export const classSubjectTeachers = mysqlTable("class_subject_teachers", {
classId: varchar("class_id", { length: 128 }).notNull(),
subject: classSubjectEnum.notNull(),
teacherId: varchar("teacher_id", { length: 128 }).references(() => users.id, { onDelete: "set null" }),
createdAt: timestamp("created_at").defaultNow().notNull(),
updatedAt: timestamp("updated_at").defaultNow().onUpdateNow().notNull(),
}, (table) => ({
pk: primaryKey({ columns: [table.classId, table.subject] }),
classIdx: index("class_subject_teachers_class_idx").on(table.classId),
teacherIdx: index("class_subject_teachers_teacher_idx").on(table.teacherId),
classFk: foreignKey({
columns: [table.classId],
foreignColumns: [classes.id],
name: "cst_c_fk",
}).onDelete("cascade"),
}));
export const classEnrollments = mysqlTable("class_enrollments", {
classId: varchar("class_id", { length: 128 }).notNull(),
studentId: varchar("student_id", { length: 128 }).notNull(),
status: classEnrollmentStatusEnum.default("active").notNull(),
createdAt: timestamp("created_at").defaultNow().notNull(),
}, (table) => ({
pk: primaryKey({ columns: [table.classId, table.studentId] }),
classIdx: index("class_enrollments_class_idx").on(table.classId),
studentIdx: index("class_enrollments_student_idx").on(table.studentId),
classFk: foreignKey({
columns: [table.classId],
foreignColumns: [classes.id],
name: "ce_c_fk",
}).onDelete("cascade"),
studentFk: foreignKey({
columns: [table.studentId],
foreignColumns: [users.id],
name: "ce_s_fk",
}).onDelete("cascade"),
}));
export const classSchedule = mysqlTable("class_schedule", {
id: id("id").primaryKey(),
classId: varchar("class_id", { length: 128 }).notNull(),
weekday: int("weekday").notNull(),
startTime: varchar("start_time", { length: 5 }).notNull(),
endTime: varchar("end_time", { length: 5 }).notNull(),
course: varchar("course", { length: 255 }).notNull(),
location: varchar("location", { length: 100 }),
createdAt: timestamp("created_at").defaultNow().notNull(),
updatedAt: timestamp("updated_at").defaultNow().onUpdateNow().notNull(),
}, (table) => ({
classIdx: index("class_schedule_class_idx").on(table.classId),
classDayIdx: index("class_schedule_class_day_idx").on(table.classId, table.weekday),
classFk: foreignKey({
columns: [table.classId],
foreignColumns: [classes.id],
name: "cs_c_fk",
}).onDelete("cascade"),
}));
export const exams = mysqlTable("exams", {
id: id("id").primaryKey(),
title: varchar("title", { length: 255 }).notNull(),