完整性更新

现在已经实现了大部分基础功能
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,183 @@
import "server-only"
import { cache } from "react"
import { asc, eq, inArray, or } from "drizzle-orm"
import { db } from "@/shared/db"
import { academicYears, departments, grades, schools, users } from "@/shared/db/schema"
import type { AcademicYearListItem, DepartmentListItem, GradeListItem, SchoolListItem, StaffOption } from "./types"
const toIso = (d: Date) => d.toISOString()
export const getDepartments = cache(async (): Promise<DepartmentListItem[]> => {
try {
const rows = await db.select().from(departments).orderBy(asc(departments.name))
return rows.map((r) => ({
id: r.id,
name: r.name,
description: r.description ?? null,
createdAt: toIso(r.createdAt),
updatedAt: toIso(r.updatedAt),
}))
} catch {
return []
}
})
export const getAcademicYears = cache(async (): Promise<AcademicYearListItem[]> => {
try {
const rows = await db.select().from(academicYears).orderBy(asc(academicYears.startDate))
return rows.map((r) => ({
id: r.id,
name: r.name,
startDate: toIso(r.startDate),
endDate: toIso(r.endDate),
isActive: Boolean(r.isActive),
createdAt: toIso(r.createdAt),
updatedAt: toIso(r.updatedAt),
}))
} catch {
return []
}
})
export const getSchools = cache(async (): Promise<SchoolListItem[]> => {
try {
const rows = await db.select().from(schools).orderBy(asc(schools.name))
return rows.map((r) => ({
id: r.id,
name: r.name,
code: r.code ?? null,
createdAt: toIso(r.createdAt),
updatedAt: toIso(r.updatedAt),
}))
} catch {
return []
}
})
export const getGrades = cache(async (): Promise<GradeListItem[]> => {
try {
const rows = await db
.select({
id: grades.id,
name: grades.name,
order: grades.order,
schoolId: schools.id,
schoolName: schools.name,
gradeHeadId: grades.gradeHeadId,
teachingHeadId: grades.teachingHeadId,
createdAt: grades.createdAt,
updatedAt: grades.updatedAt,
})
.from(grades)
.innerJoin(schools, eq(schools.id, grades.schoolId))
.orderBy(asc(schools.name), asc(grades.order), asc(grades.name))
const headIds = Array.from(
new Set(
rows
.flatMap((r) => [r.gradeHeadId, r.teachingHeadId])
.filter((v): v is string => typeof v === "string" && v.length > 0)
)
)
const heads = headIds.length
? await db
.select({ id: users.id, name: users.name, email: users.email })
.from(users)
.where(inArray(users.id, headIds))
: []
const headById = new Map<string, StaffOption>()
for (const u of heads) {
headById.set(u.id, { id: u.id, name: u.name ?? "Unnamed", email: u.email })
}
return rows.map((r) => ({
id: r.id,
school: { id: r.schoolId, name: r.schoolName },
name: r.name,
order: Number(r.order ?? 0),
gradeHead: r.gradeHeadId ? headById.get(r.gradeHeadId) ?? null : null,
teachingHead: r.teachingHeadId ? headById.get(r.teachingHeadId) ?? null : null,
createdAt: toIso(r.createdAt),
updatedAt: toIso(r.updatedAt),
}))
} catch {
return []
}
})
export const getStaffOptions = cache(async (): Promise<StaffOption[]> => {
try {
const rows = await db
.select({ id: users.id, name: users.name, email: users.email })
.from(users)
.where(inArray(users.role, ["teacher", "admin"]))
.orderBy(asc(users.name), asc(users.email))
return rows.map((r) => ({
id: r.id,
name: r.name ?? "Unnamed",
email: r.email,
}))
} catch {
return []
}
})
export const getGradesForStaff = cache(async (staffId: string): Promise<GradeListItem[]> => {
const id = staffId.trim()
if (!id) return []
try {
const rows = await db
.select({
id: grades.id,
name: grades.name,
order: grades.order,
schoolId: schools.id,
schoolName: schools.name,
gradeHeadId: grades.gradeHeadId,
teachingHeadId: grades.teachingHeadId,
createdAt: grades.createdAt,
updatedAt: grades.updatedAt,
})
.from(grades)
.innerJoin(schools, eq(schools.id, grades.schoolId))
.where(or(eq(grades.gradeHeadId, id), eq(grades.teachingHeadId, id)))
.orderBy(asc(schools.name), asc(grades.order), asc(grades.name))
const headIds = Array.from(
new Set(
rows
.flatMap((r) => [r.gradeHeadId, r.teachingHeadId])
.filter((v): v is string => typeof v === "string" && v.length > 0)
)
)
const heads = headIds.length
? await db
.select({ id: users.id, name: users.name, email: users.email })
.from(users)
.where(inArray(users.id, headIds))
: []
const headById = new Map<string, StaffOption>()
for (const u of heads) headById.set(u.id, { id: u.id, name: u.name ?? "Unnamed", email: u.email })
return rows.map((r) => ({
id: r.id,
school: { id: r.schoolId, name: r.schoolName },
name: r.name,
order: Number(r.order ?? 0),
gradeHead: r.gradeHeadId ? headById.get(r.gradeHeadId) ?? null : null,
teachingHead: r.teachingHeadId ? headById.get(r.teachingHeadId) ?? null : null,
createdAt: toIso(r.createdAt),
updatedAt: toIso(r.updatedAt),
}))
} catch {
return []
}
})