chore(config): update build tooling, CI/CD workflows, and project scripts

- Update ESLint, Prettier, Tailwind, TypeScript, Vitest, Playwright configs

- Update Dockerfile and CI/CD workflows (ci, dr-drill, security)

- Add/Update DB backup, restore, health-check, security-scan scripts

- Update project rules and .gitignore
This commit is contained in:
SpecialX
2026-06-23 17:35:24 +08:00
parent 276577b66c
commit 5195a4bcf1
4 changed files with 398 additions and 21 deletions

View File

@@ -135,7 +135,7 @@ async function seed() {
const questionBanks = await seedQuestions(teacherMap, subjectMap, kpMap);
// --- 12. 试卷(语文、数学各 1 套)+ 学生答题与批改 ---
await seedExamsAndSubmissions(teacherMap, classMap, studentMap, questionBanks);
await seedExamsAndSubmissions(teacherMap, classMap, studentMap, questionBanks, subjectMap, gradeMap);
// --- 13. 作业(引用试卷)+ 学生答题与批改 ---
await seedHomework(teacherMap, classMap, studentMap, questionBanks);
@@ -267,8 +267,8 @@ async function seedSchoolAndGrades() {
const gradeMap: Record<string, string> = {};
const gradeDefs = [
{ key: "G1", name: "一年级", order: 1 },
{ key: "G2", name: "二年级", order: 2 },
{ key: "G1", name: "Grade 1", order: 1 },
{ key: "G2", name: "Grade 2", order: 2 },
];
for (const g of gradeDefs) {
const id = createId();
@@ -303,6 +303,7 @@ async function seedUsers(
password: passwordHash,
image: avatar("admin"),
gender: "男",
onboardedAt: NOW,
});
await db.insert(usersToRoles).values({ userId: adminId, roleId: "role_admin" });
@@ -334,6 +335,7 @@ async function seedUsers(
password: passwordHash,
image: avatar(t.key),
gender: t.gender,
onboardedAt: NOW,
});
await db.insert(usersToRoles).values({ userId: id, roleId: "role_teacher" });
}
@@ -366,9 +368,11 @@ async function seedUsers(
image: avatar(key),
gender: i % 2 === 0 ? "男" : "女",
birthDate: new Date(`201${ck.startsWith("G1") ? 8 : 7}-0${(i % 9) + 1}-15`),
phone: "1380000" + String(studentIdx).padStart(4, "0"),
guardianName: "家长" + name,
guardianPhone: "1380000" + String(studentIdx).padStart(4, "0"),
guardianRelation: i % 2 === 0 ? "父亲" : "母亲",
onboardedAt: NOW,
});
await db.insert(usersToRoles).values({ userId: id, roleId: "role_student" });
}
@@ -389,6 +393,7 @@ async function seedUsers(
password: passwordHash,
image: avatar(pKey),
gender: sInfo.name.includes("明") || sInfo.name.includes("华") || sInfo.name.includes("亮") || sInfo.name.includes("强") || sInfo.name.includes("军") || sInfo.name.includes("涛") ? "男" : "女",
onboardedAt: NOW,
});
await db.insert(usersToRoles).values({ userId: id, roleId: "role_parent" });
}
@@ -422,7 +427,7 @@ async function seedClasses(
schoolName: "阳光小学",
schoolId,
name: c.name,
grade: c.gradeKey === "G1" ? "一年级" : "二年级",
grade: c.gradeKey === "G1" ? "Grade 1" : "Grade 2",
gradeId: gradeMap[c.gradeKey],
homeroom: c.code,
room: c.room,
@@ -510,7 +515,7 @@ async function seedTextbooksAndChapters() {
const textbookDefs = [
{
subjectCode: "CHINESE",
subjectName: "语文",
subjectName: "Chinese",
title: "一年级语文(上册)",
publisher: "人民教育出版社",
chapterTitle: "第一课 秋天",
@@ -518,7 +523,7 @@ async function seedTextbooksAndChapters() {
},
{
subjectCode: "MATH",
subjectName: "数学",
subjectName: "Mathematics",
title: "一年级数学(上册)",
publisher: "人民教育出版社",
chapterTitle: "第一课 1-5 的认识",
@@ -526,7 +531,7 @@ async function seedTextbooksAndChapters() {
},
{
subjectCode: "ENG",
subjectName: "英语",
subjectName: "English",
title: "一年级英语(上册)",
publisher: "外语教学与研究出版社",
chapterTitle: "Unit 1 Hello",
@@ -540,7 +545,7 @@ async function seedTextbooksAndChapters() {
id: tbId,
title: tb.title,
subject: tb.subjectName,
grade: "一年级",
grade: "Grade 1",
publisher: tb.publisher,
});
@@ -549,7 +554,7 @@ async function seedTextbooksAndChapters() {
await db.insert(chapters).values({
id: ch1Id,
textbookId: tbId,
title: `第一章 ${tb.subjectName === "语文" ? "课文" : tb.subjectName === "数学" ? "数一数" : "Greetings"}`,
title: `第一章 ${tb.subjectName === "Chinese" ? "课文" : tb.subjectName === "Mathematics" ? "数一数" : "Greetings"}`,
order: 1,
parentId: null,
content: `# 第一章\n\n${tb.subjectName}第一章导引内容。`,
@@ -853,7 +858,9 @@ async function seedExamsAndSubmissions(
teacherMap: Record<string, { id: string }>,
classMap: Record<string, { id: string }>,
studentMap: Record<string, { id: string; classKey: string }>,
questionBanks: SeedQuestionBank
questionBanks: SeedQuestionBank,
subjectMap: Record<string, string>,
gradeMap: Record<string, string>
) {
console.log("📝 创建试卷与学生答题...");
@@ -884,7 +891,7 @@ async function seedExamsAndSubmissions(
await db.insert(exams).values({
id: chineseExamId,
title: "一年级语文第一单元测验",
description: JSON.stringify({ subject: "语文", grade: "一年级", totalScore: 50, durationMin: 40, questionCount: 5 }),
description: JSON.stringify({ subject: "Chinese", grade: "Grade 1", totalScore: 50, durationMin: 40, questionCount: 5 }),
creatorId: teacherMap.T_C1.id,
subjectId: subjectMap.CHINESE,
gradeId: gradeMap.G1,
@@ -915,7 +922,7 @@ async function seedExamsAndSubmissions(
await db.insert(exams).values({
id: mathExamId,
title: "一年级数学第一单元测验",
description: JSON.stringify({ subject: "数学", grade: "一年级", totalScore: 50, durationMin: 40, questionCount: 5 }),
description: JSON.stringify({ subject: "Mathematics", grade: "Grade 1", totalScore: 50, durationMin: 40, questionCount: 5 }),
creatorId: teacherMap.T_M1.id,
subjectId: subjectMap.MATH,
gradeId: gradeMap.G1,