feat(scripts): add diagnostic, seed, and test scripts
- 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
This commit is contained in:
181
scripts/diagnose-error-book.ts
Normal file
181
scripts/diagnose-error-book.ts
Normal file
@@ -0,0 +1,181 @@
|
||||
/**
|
||||
* 诊断脚本:检查错题本数据状态
|
||||
* 用法: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)
|
||||
})
|
||||
Reference in New Issue
Block a user