- Add add-ai-provider-visibility and add-missing-columns migration scripts - Add clear-error-book, seed-error-book, diagnose-error-book scripts - Add diagnose-tables and create-missing-tables scripts - Add test-failing-modules and test-teacher-pages test scripts
182 lines
6.6 KiB
TypeScript
182 lines
6.6 KiB
TypeScript
/**
|
||
* 诊断脚本:检查错题本数据状态
|
||
* 用法:npx tsx scripts/diagnose-error-book.ts
|
||
*/
|
||
import "dotenv/config"
|
||
import { db } from "../src/shared/db"
|
||
import {
|
||
errorBookItems,
|
||
errorBookReviews,
|
||
examSubmissions,
|
||
homeworkSubmissions,
|
||
users,
|
||
usersToRoles,
|
||
roles,
|
||
classes,
|
||
classEnrollments,
|
||
classSubjectTeachers,
|
||
grades,
|
||
exams,
|
||
homeworkAssignments,
|
||
} from "../src/shared/db/schema"
|
||
import { eq, inArray, count } from "drizzle-orm"
|
||
|
||
async function diagnose() {
|
||
console.log("🔍 错题本数据诊断开始...\n")
|
||
|
||
// 1. 检查表是否存在且有数据
|
||
const [itemsCount] = await db.select({ value: count() }).from(errorBookItems)
|
||
const [reviewsCount] = await db.select({ value: count() }).from(errorBookReviews)
|
||
console.log(`📊 错题本表数据:`)
|
||
console.log(` error_book_items: ${itemsCount.value} 行`)
|
||
console.log(` error_book_reviews: ${reviewsCount.value} 行`)
|
||
|
||
if (Number(itemsCount.value) === 0) {
|
||
console.log("\n❌ error_book_items 表为空!需要运行 seed-error-book.ts")
|
||
return
|
||
}
|
||
|
||
// 2. 检查错题的 subjectId 分布
|
||
const subjectDist = await db
|
||
.select({
|
||
subjectId: errorBookItems.subjectId,
|
||
count: count(),
|
||
})
|
||
.from(errorBookItems)
|
||
.groupBy(errorBookItems.subjectId)
|
||
console.log(`\n📊 错题 subjectId 分布:`)
|
||
for (const row of subjectDist) {
|
||
console.log(` subjectId=${row.subjectId ?? "NULL"}: ${row.count} 条`)
|
||
}
|
||
|
||
// 3. 检查错题的 sourceType 分布
|
||
const sourceDist = await db
|
||
.select({
|
||
sourceType: errorBookItems.sourceType,
|
||
count: count(),
|
||
})
|
||
.from(errorBookItems)
|
||
.groupBy(errorBookItems.sourceType)
|
||
console.log(`\n📊 错题 sourceType 分布:`)
|
||
for (const row of sourceDist) {
|
||
console.log(` ${row.sourceType}: ${row.count} 条`)
|
||
}
|
||
|
||
// 4. 检查有错题的学生
|
||
const studentsWithErrors = await db
|
||
.select({
|
||
studentId: errorBookItems.studentId,
|
||
itemCount: count(),
|
||
})
|
||
.from(errorBookItems)
|
||
.groupBy(errorBookItems.studentId)
|
||
console.log(`\n📊 有错题的学生 (${studentsWithErrors.length} 名):`)
|
||
for (const row of studentsWithErrors) {
|
||
console.log(` ${row.studentId}: ${row.itemCount} 条`)
|
||
}
|
||
|
||
// 5. 检查教师角色用户
|
||
const teacherRole = await db.select({ id: roles.id }).from(roles).where(eq(roles.name, "teacher")).limit(1)
|
||
if (teacherRole.length > 0) {
|
||
const teachers = await db
|
||
.select({ userId: usersToRoles.userId })
|
||
.from(usersToRoles)
|
||
.where(eq(usersToRoles.roleId, teacherRole[0].id))
|
||
console.log(`\n📊 教师用户 (${teachers.length} 名):`)
|
||
for (const t of teachers) {
|
||
const user = await db.select({ name: users.name }).from(users).where(eq(users.id, t.userId)).limit(1)
|
||
// 查询该教师能访问的班级
|
||
const homeroomClasses = await db.select({ id: classes.id, name: classes.name }).from(classes).where(eq(classes.teacherId, t.userId))
|
||
const subjectClasses = await db
|
||
.select({ classId: classSubjectTeachers.classId })
|
||
.from(classSubjectTeachers)
|
||
.where(eq(classSubjectTeachers.teacherId, t.userId))
|
||
const allClassIds = [...new Set([...homeroomClasses.map((c) => c.id), ...subjectClasses.map((c) => c.classId)])]
|
||
|
||
// 查询这些班级的学生
|
||
let studentCount = 0
|
||
let errorCount = 0
|
||
if (allClassIds.length > 0) {
|
||
const students = await db
|
||
.select({ studentId: classEnrollments.studentId })
|
||
.from(classEnrollments)
|
||
.where(inArray(classEnrollments.classId, allClassIds))
|
||
const studentIds = [...new Set(students.map((s) => s.studentId))]
|
||
studentCount = studentIds.length
|
||
|
||
if (studentIds.length > 0) {
|
||
const errorItems = await db
|
||
.select({ value: count() })
|
||
.from(errorBookItems)
|
||
.where(inArray(errorBookItems.studentId, studentIds))
|
||
errorCount = Number(errorItems[0]?.value ?? 0)
|
||
}
|
||
}
|
||
|
||
console.log(` ${user[0]?.name ?? t.userId} (${t.userId}): 班级=${allClassIds.length}, 学生=${studentCount}, 错题=${errorCount}`)
|
||
}
|
||
}
|
||
|
||
// 6. 检查年级组长
|
||
const gradeHeadRole = await db.select({ id: roles.id }).from(roles).where(eq(roles.name, "grade_head")).limit(1)
|
||
if (gradeHeadRole.length > 0) {
|
||
const gradeHeads = await db
|
||
.select({ userId: usersToRoles.userId })
|
||
.from(usersToRoles)
|
||
.where(eq(usersToRoles.roleId, gradeHeadRole[0].id))
|
||
console.log(`\n📊 年级组长 (${gradeHeads.length} 名):`)
|
||
for (const gh of gradeHeads) {
|
||
const user = await db.select({ name: users.name }).from(users).where(eq(users.id, gh.userId)).limit(1)
|
||
const managedGrades = await db.select({ id: grades.id, name: grades.name }).from(grades).where(eq(grades.gradeHeadId, gh.userId))
|
||
console.log(` ${user[0]?.name ?? gh.userId} (${gh.userId}): 管理年级=${managedGrades.length}`)
|
||
for (const g of managedGrades) {
|
||
const gradeClasses = await db.select({ id: classes.id }).from(classes).where(eq(classes.gradeId, g.id))
|
||
console.log(` 年级 ${g.name}: ${gradeClasses.length} 个班级`)
|
||
}
|
||
}
|
||
}
|
||
|
||
// 7. 检查已批改的提交数量
|
||
const gradedExams = await db.select({ value: count() }).from(examSubmissions).where(eq(examSubmissions.status, "graded"))
|
||
const gradedHw = await db.select({ value: count() }).from(homeworkSubmissions).where(eq(homeworkSubmissions.status, "graded"))
|
||
console.log(`\n📊 已批改提交:`)
|
||
console.log(` 考试提交: ${gradedExams[0]?.value ?? 0}`)
|
||
console.log(` 作业提交: ${gradedHw[0]?.value ?? 0}`)
|
||
|
||
// 8. 检查 exams 表的 subjectId 是否有值
|
||
const examSubjectStats = await db
|
||
.select({
|
||
subjectId: exams.subjectId,
|
||
count: count(),
|
||
})
|
||
.from(exams)
|
||
.groupBy(exams.subjectId)
|
||
console.log(`\n📊 exams 表 subjectId 分布:`)
|
||
for (const row of examSubjectStats) {
|
||
console.log(` subjectId=${row.subjectId ?? "NULL"}: ${row.count} 个考试`)
|
||
}
|
||
|
||
// 9. 检查 homeworkAssignments 是否有 subjectId 字段(应该没有)
|
||
console.log(`\n📊 homeworkAssignments 表结构检查:`)
|
||
try {
|
||
const hwRows = await db.select().from(homeworkAssignments).limit(1)
|
||
if (hwRows.length > 0) {
|
||
const keys = Object.keys(hwRows[0])
|
||
console.log(` 字段列表: ${keys.join(", ")}`)
|
||
console.log(` 是否有 subjectId 字段: ${keys.includes("subjectId") ? "是" : "否"}`)
|
||
} else {
|
||
console.log(` 表为空`)
|
||
}
|
||
} catch (e) {
|
||
console.log(` 查询失败: ${(e as Error).message}`)
|
||
}
|
||
|
||
console.log("\n✅ 诊断完成")
|
||
process.exit(0)
|
||
}
|
||
|
||
diagnose().catch((e) => {
|
||
console.error("❌ 诊断失败:", e)
|
||
process.exit(1)
|
||
})
|