Files
Edu/services/content/src/lesson-plans/lesson-plans.repository.ts
SpecialX 78e406b317 feat(content): v2 扩展 Elective/LessonPlan/CoursePlan 三业务域
新增 3 个业务域(10 RPC):
- ElectiveService: 选修课列表/学生选课记录/选课/退课(含容量与重复校验)
- LessonPlanService: 教师备课列表/学生备课列表(仅 published)/详情
- CoursePlanService: 学生课程计划列表/详情
- KnowledgeGraphService.GetKnowledgePath: 与 GetLearningPath 同实现

新增 4 张 MySQL 表(elective_courses/selections/lesson_plans/course_plans),含完整索引。

新增 11 个权限点,覆盖 admin/teacher/student/parent 四角色。

proto 由 4 Service/22 RPC 扩展至 7 Service/32 RPC,v1 全部 RPC 保持向后兼容。

修复 logger.ts pino 导入: default import 在 NodeNext ESM 下不可调用,
改用 named import(与 iam/msg/core-edu 对齐)。

Docker 本地测试全部通过(HTTP + gRPC 双协议),健康检查、
Elective/LessonPlan/CoursePlan CRUD、4 个新 gRPC Service 全部验证通过。

nextstep-v2.md 已创建,记录上下游依赖与 6 项联调待办。
2026-07-14 17:54:37 +08:00

70 lines
2.0 KiB
TypeScript

import { eq, and } from "drizzle-orm";
import { getDb } from "../config/database.js";
import {
lessonPlans,
type LessonPlan,
type NewLessonPlan,
} from "./lesson-plans.schema.js";
export class LessonPlansRepository {
async findById(id: string): Promise<LessonPlan | undefined> {
const [result] = await getDb()
.select()
.from(lessonPlans)
.where(eq(lessonPlans.id, id))
.limit(1);
return result;
}
async findByTeacher(query: {
teacherId: string;
classId?: string;
subjectId?: string;
}): Promise<LessonPlan[]> {
const db = getDb();
const conditions = [eq(lessonPlans.teacherId, query.teacherId)];
if (query.classId) {
conditions.push(eq(lessonPlans.classId, query.classId));
}
if (query.subjectId) {
conditions.push(eq(lessonPlans.subjectId, query.subjectId));
}
return db
.select()
.from(lessonPlans)
.where(and(...conditions));
}
async findByStudent(query: {
studentId: string;
classId?: string;
}): Promise<LessonPlan[]> {
// 学生视角:按班级查询教师发布的备课计划
// studentId 不直接关联备课计划(备课计划是教师创建的),
// 通过 classId 过滤学生所在班级的备课计划
const db = getDb();
const conditions = [eq(lessonPlans.status, "published")];
if (query.classId) {
conditions.push(eq(lessonPlans.classId, query.classId));
}
return db
.select()
.from(lessonPlans)
.where(and(...conditions));
}
async create(data: NewLessonPlan): Promise<void> {
await getDb().insert(lessonPlans).values(data);
}
async update(id: string, data: Partial<NewLessonPlan>): Promise<void> {
await getDb().update(lessonPlans).set(data).where(eq(lessonPlans.id, id));
}
async delete(id: string): Promise<void> {
await getDb().delete(lessonPlans).where(eq(lessonPlans.id, id));
}
}
export const lessonPlansRepository = new LessonPlansRepository();