|
|
|
|
@@ -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(),
|
|
|
|
|
|