// This is your Prisma schema file, // learn more about it in the docs: https://pris.ly/d/prisma-schema generator client { provider = "prisma-client-js" } datasource db { provider = "postgresql" url = env("DATABASE_URL") } model User { id String @id @default(uuid()) phone String? @unique appleId String? @unique @map("apple_id") nickname String? avatar String? agreementAccepted Boolean @default(false) @map("agreement_accepted") isPro Boolean @default(false) @map("is_pro") // 是否为付费会员 proExpireDate DateTime? @map("pro_expire_date") // 会员过期时间(可选,预留给订阅制) createdAt DateTime @default(now()) @map("created_at") updatedAt DateTime @updatedAt @map("updated_at") settings UserSettings? learningProgress UserLearningProgress[] achievements UserAchievement[] courses UserCourse[] @@map("users") } model UserSettings { userId String @id @map("user_id") pushNotification Boolean @default(true) @map("push_notification") createdAt DateTime @default(now()) @map("created_at") updatedAt DateTime @updatedAt @map("updated_at") user User @relation(fields: [userId], references: [id], onDelete: Cascade) @@map("user_settings") } model Course { id String @id @default(uuid()) title String subtitle String? // 课程副标题 description String? coverImage String? @map("cover_image") type String @default("system") // ✅ 新增:system | single status String @default("published") // ✅ 新增:published | draft deletedAt DateTime? @map("deleted_at") // ✅ 新增:软删除时间戳 totalNodes Int @default(0) @map("total_nodes") createdAt DateTime @default(now()) @map("created_at") updatedAt DateTime @updatedAt @map("updated_at") chapters CourseChapter[] nodes CourseNode[] userCourses UserCourse[] @@map("courses") } model CourseChapter { id String @id @default(uuid()) courseId String @map("course_id") title String orderIndex Int @map("order_index") createdAt DateTime @default(now()) @map("created_at") course Course @relation(fields: [courseId], references: [id], onDelete: Cascade) nodes CourseNode[] @@unique([courseId, orderIndex]) @@map("course_chapters") } model CourseNode { id String @id @default(uuid()) courseId String @map("course_id") chapterId String? @map("chapter_id") // 可选,支持无章节的节点 title String subtitle String? orderIndex Int @map("order_index") duration Int? // 预估时长(分钟) unlockCondition String? @map("unlock_condition") // 解锁条件 createdAt DateTime @default(now()) @map("created_at") course Course @relation(fields: [courseId], references: [id], onDelete: Cascade) chapter CourseChapter? @relation(fields: [chapterId], references: [id], onDelete: SetNull) slides NodeSlide[] learningProgress UserLearningProgress[] @@unique([courseId, orderIndex]) @@map("course_nodes") } model NodeSlide { id String @id @default(uuid()) nodeId String @map("node_id") slideType String @map("slide_type") // text | image | quiz | interactive orderIndex Int @map("order_index") content Json // 存储卡片内容(灵活结构) effect String? // fade_in | typewriter | slide_up interaction String? // tap_to_reveal | zoom | parallax createdAt DateTime @default(now()) @map("created_at") node CourseNode @relation(fields: [nodeId], references: [id], onDelete: Cascade) @@map("node_slides") } model UserLearningProgress { id String @id @default(uuid()) userId String @map("user_id") nodeId String @map("node_id") status String @default("not_started") // not_started | in_progress | completed startedAt DateTime? @map("started_at") completedAt DateTime? @map("completed_at") totalStudyTime Int @default(0) @map("total_study_time") // 总学习时长(秒) currentSlide Int @default(0) @map("current_slide") // 当前学习到的幻灯片位置 completionRate Int @default(0) @map("completion_rate") // 完成度(%) createdAt DateTime @default(now()) @map("created_at") updatedAt DateTime @updatedAt @map("updated_at") user User @relation(fields: [userId], references: [id], onDelete: Cascade) node CourseNode @relation(fields: [nodeId], references: [id], onDelete: Cascade) @@unique([userId, nodeId]) @@map("user_learning_progress") } model UserAchievement { id String @id @default(uuid()) userId String @map("user_id") achievementType String @map("achievement_type") // lesson_completed | course_completed achievementData Json @map("achievement_data") // 存储成就详情 createdAt DateTime @default(now()) @map("created_at") user User @relation(fields: [userId], references: [id], onDelete: Cascade) @@map("user_achievements") } model UserCourse { id String @id @default(uuid()) userId String @map("user_id") courseId String @map("course_id") lastOpenedAt DateTime? @map("last_opened_at") // ✅ 新增:最近打开时间,用于排序 createdAt DateTime @default(now()) @map("created_at") updatedAt DateTime @updatedAt @map("updated_at") user User @relation(fields: [userId], references: [id], onDelete: Cascade) course Course @relation(fields: [courseId], references: [id], onDelete: Cascade) @@unique([userId, courseId]) @@map("user_courses") }