2024-09-03 20:19:33 +08:00
|
|
|
|
// This is your Prisma schema file,
|
|
|
|
|
// learn more about it in the docs: https://pris.ly/d/prisma-schema
|
|
|
|
|
|
|
|
|
|
generator client {
|
2024-12-30 08:26:40 +08:00
|
|
|
|
provider = "prisma-client-js"
|
2024-09-03 20:19:33 +08:00
|
|
|
|
}
|
|
|
|
|
|
2024-12-30 08:26:40 +08:00
|
|
|
|
// generator zod {
|
|
|
|
|
// provider = "zod-prisma-types"
|
|
|
|
|
// output = "../src/generated" // (default) the directory where generated zod schemas will be saved
|
|
|
|
|
// createModelTypes = true
|
|
|
|
|
// createRelationValuesTypes = true
|
|
|
|
|
// writeNullishInModelTypes = true
|
|
|
|
|
// createPartialTypes = false
|
|
|
|
|
// useMultipleFiles = false
|
|
|
|
|
// useTypeAssertions = true
|
|
|
|
|
// }
|
|
|
|
|
|
2024-09-03 20:19:33 +08:00
|
|
|
|
datasource db {
|
2024-12-30 08:26:40 +08:00
|
|
|
|
provider = "postgresql"
|
|
|
|
|
url = env("DATABASE_URL")
|
2024-09-03 20:19:33 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
model Taxonomy {
|
2024-12-30 13:44:30 +08:00
|
|
|
|
id String @id @default(cuid())
|
2024-12-30 08:26:40 +08:00
|
|
|
|
name String @unique
|
|
|
|
|
slug String @unique @map("slug")
|
|
|
|
|
deletedAt DateTime? @map("deleted_at")
|
|
|
|
|
createdAt DateTime @default(now()) @map("created_at")
|
|
|
|
|
terms Term[]
|
|
|
|
|
objectType String[] @map("object_type")
|
|
|
|
|
order Float? @map("order")
|
2024-09-03 20:19:33 +08:00
|
|
|
|
|
2024-12-30 08:26:40 +08:00
|
|
|
|
@@index([order, deletedAt])
|
|
|
|
|
@@map("taxonomy")
|
2024-09-03 20:19:33 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
model Term {
|
2024-12-30 13:44:30 +08:00
|
|
|
|
id String @id @default(cuid())
|
2024-12-30 08:26:40 +08:00
|
|
|
|
name String
|
|
|
|
|
taxonomy Taxonomy? @relation(fields: [taxonomyId], references: [id])
|
|
|
|
|
taxonomyId String? @map("taxonomy_id")
|
|
|
|
|
order Float? @map("order")
|
|
|
|
|
description String?
|
|
|
|
|
parentId String? @map("parent_id")
|
|
|
|
|
parent Term? @relation("ChildParent", fields: [parentId], references: [id], onDelete: Cascade)
|
|
|
|
|
children Term[] @relation("ChildParent")
|
|
|
|
|
ancestors TermAncestry[] @relation("DescendantToAncestor")
|
|
|
|
|
descendants TermAncestry[] @relation("AncestorToDescendant")
|
|
|
|
|
domainId String? @map("domain_id")
|
|
|
|
|
domain Department? @relation("TermDom", fields: [domainId], references: [id])
|
|
|
|
|
createdAt DateTime @default(now()) @map("created_at")
|
|
|
|
|
updatedAt DateTime @updatedAt @map("updated_at")
|
|
|
|
|
deletedAt DateTime? @map("deleted_at")
|
|
|
|
|
createdBy String? @map("created_by")
|
|
|
|
|
depts Department[] @relation("department_term")
|
|
|
|
|
hasChildren Boolean? @default(false) @map("has_children")
|
2024-12-30 13:44:30 +08:00
|
|
|
|
courses Course[] @relation("course_term")
|
2024-12-30 08:26:40 +08:00
|
|
|
|
|
|
|
|
|
@@index([name]) // 对name字段建立索引,以加快基于name的查找速度
|
|
|
|
|
@@index([parentId]) // 对parentId字段建立索引,以加快基于parentId的查找速度
|
|
|
|
|
@@map("term")
|
2024-09-03 20:19:33 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
model TermAncestry {
|
2024-12-30 13:44:30 +08:00
|
|
|
|
id String @id @default(cuid())
|
2024-12-30 08:26:40 +08:00
|
|
|
|
ancestorId String? @map("ancestor_id")
|
|
|
|
|
descendantId String @map("descendant_id")
|
|
|
|
|
relDepth Int @map("rel_depth")
|
|
|
|
|
ancestor Term? @relation("AncestorToDescendant", fields: [ancestorId], references: [id])
|
|
|
|
|
descendant Term @relation("DescendantToAncestor", fields: [descendantId], references: [id])
|
2024-09-03 20:19:33 +08:00
|
|
|
|
|
2024-12-30 08:26:40 +08:00
|
|
|
|
// 索引建议
|
|
|
|
|
@@index([ancestorId]) // 针对祖先的查询
|
|
|
|
|
@@index([descendantId]) // 针对后代的查询
|
|
|
|
|
@@index([ancestorId, descendantId]) // 组合索引,用于查询特定的祖先-后代关系
|
|
|
|
|
@@index([relDepth]) // 根据关系深度的查询
|
|
|
|
|
@@map("term_ancestry")
|
2024-09-03 20:19:33 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
model Staff {
|
2024-12-30 13:44:30 +08:00
|
|
|
|
id String @id @default(cuid())
|
2024-12-30 08:26:40 +08:00
|
|
|
|
showname String? @map("showname")
|
|
|
|
|
username String @unique @map("username")
|
|
|
|
|
avatar String? @map("avatar")
|
|
|
|
|
password String? @map("password")
|
|
|
|
|
phoneNumber String? @unique @map("phone_number")
|
|
|
|
|
|
|
|
|
|
domainId String? @map("domain_id")
|
|
|
|
|
deptId String? @map("dept_id")
|
|
|
|
|
|
2024-12-30 13:44:30 +08:00
|
|
|
|
domain Department? @relation("DomainStaff", fields: [domainId], references: [id])
|
|
|
|
|
department Department? @relation("DeptStaff", fields: [deptId], references: [id])
|
|
|
|
|
order Float?
|
2024-09-03 20:19:33 +08:00
|
|
|
|
|
2024-12-30 08:26:40 +08:00
|
|
|
|
createdAt DateTime @default(now()) @map("created_at")
|
|
|
|
|
updatedAt DateTime @updatedAt @map("updated_at")
|
|
|
|
|
enabled Boolean? @default(true)
|
|
|
|
|
deletedAt DateTime? @map("deleted_at")
|
|
|
|
|
officerId String? @map("officer_id")
|
2024-09-03 20:19:33 +08:00
|
|
|
|
|
2024-12-30 13:44:30 +08:00
|
|
|
|
watchedPost Post[] @relation("post_watch_staff")
|
|
|
|
|
visits Visit[]
|
|
|
|
|
posts Post[]
|
|
|
|
|
sentMsgs Message[] @relation("message_sender")
|
|
|
|
|
receivedMsgs Message[] @relation("message_receiver")
|
2024-12-30 08:26:40 +08:00
|
|
|
|
|
2024-12-30 13:44:30 +08:00
|
|
|
|
enrollments Enrollment[]
|
|
|
|
|
courseReviews CourseReview[]
|
|
|
|
|
teachedCourses CourseInstructor[]
|
2024-12-30 08:26:40 +08:00
|
|
|
|
|
|
|
|
|
@@index([officerId])
|
|
|
|
|
@@index([deptId])
|
|
|
|
|
@@index([domainId])
|
|
|
|
|
@@index([username])
|
|
|
|
|
@@index([order])
|
|
|
|
|
@@map("staff")
|
2024-09-03 20:19:33 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
model Department {
|
2024-12-30 13:44:30 +08:00
|
|
|
|
id String @id @default(cuid())
|
|
|
|
|
name String
|
|
|
|
|
order Float?
|
|
|
|
|
ancestors DeptAncestry[] @relation("DescendantToAncestor")
|
|
|
|
|
descendants DeptAncestry[] @relation("AncestorToDescendant")
|
|
|
|
|
parentId String? @map("parent_id")
|
|
|
|
|
parent Department? @relation("ChildParent", fields: [parentId], references: [id])
|
|
|
|
|
children Department[] @relation("ChildParent")
|
|
|
|
|
domainId String? @map("domain_id")
|
|
|
|
|
domainTerms Term[] @relation("TermDom")
|
|
|
|
|
deletedAt DateTime? @map("deleted_at")
|
|
|
|
|
isDomain Boolean? @default(false) @map("is_domain")
|
|
|
|
|
domainStaffs Staff[] @relation("DomainStaff")
|
|
|
|
|
deptStaffs Staff[] @relation("DeptStaff")
|
|
|
|
|
terms Term[] @relation("department_term")
|
|
|
|
|
|
|
|
|
|
watchedPost Post[] @relation("post_watch_dept")
|
|
|
|
|
hasChildren Boolean? @default(false) @map("has_children")
|
2024-12-30 08:26:40 +08:00
|
|
|
|
|
|
|
|
|
@@index([parentId])
|
|
|
|
|
@@index([isDomain])
|
|
|
|
|
@@index([name])
|
|
|
|
|
@@index([order])
|
|
|
|
|
@@map("department")
|
2024-09-03 20:19:33 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
model DeptAncestry {
|
2024-12-30 13:44:30 +08:00
|
|
|
|
id String @id @default(cuid())
|
2024-12-30 08:26:40 +08:00
|
|
|
|
ancestorId String? @map("ancestor_id")
|
|
|
|
|
descendantId String @map("descendant_id")
|
|
|
|
|
relDepth Int @map("rel_depth")
|
|
|
|
|
ancestor Department? @relation("AncestorToDescendant", fields: [ancestorId], references: [id])
|
|
|
|
|
descendant Department @relation("DescendantToAncestor", fields: [descendantId], references: [id])
|
|
|
|
|
|
|
|
|
|
// 索引建议
|
|
|
|
|
@@index([ancestorId]) // 针对祖先的查询
|
|
|
|
|
@@index([descendantId]) // 针对后代的查询
|
|
|
|
|
@@index([ancestorId, descendantId]) // 组合索引,用于查询特定的祖先-后代关系
|
|
|
|
|
@@index([relDepth]) // 根据关系深度的查询
|
|
|
|
|
@@map("dept_ancestry")
|
2024-09-03 20:19:33 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
model RoleMap {
|
2024-12-30 13:44:30 +08:00
|
|
|
|
id String @id @default(cuid())
|
2024-12-30 08:26:40 +08:00
|
|
|
|
objectId String @map("object_id")
|
|
|
|
|
roleId String @map("role_id")
|
|
|
|
|
domainId String? @map("domain_id")
|
|
|
|
|
objectType String @map("object_type")
|
|
|
|
|
role Role @relation(fields: [roleId], references: [id])
|
|
|
|
|
|
|
|
|
|
@@index([domainId])
|
|
|
|
|
@@index([objectId])
|
|
|
|
|
@@map("rolemap")
|
2024-09-03 20:19:33 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
model Role {
|
2024-12-30 13:44:30 +08:00
|
|
|
|
id String @id @default(cuid())
|
2024-12-30 08:26:40 +08:00
|
|
|
|
name String @unique @map("name")
|
|
|
|
|
permissions String[] @default([]) @map("permissions")
|
|
|
|
|
roleMaps RoleMap[]
|
|
|
|
|
system Boolean? @default(false) @map("system")
|
|
|
|
|
createdAt DateTime @default(now()) @map("created_at")
|
|
|
|
|
updatedAt DateTime @updatedAt @map("updated_at")
|
|
|
|
|
deletedAt DateTime? @map("deleted_at")
|
|
|
|
|
|
|
|
|
|
@@map("role")
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
model AppConfig {
|
2024-12-30 13:44:30 +08:00
|
|
|
|
id String @id @default(cuid())
|
2024-12-30 08:26:40 +08:00
|
|
|
|
slug String @unique
|
|
|
|
|
title String?
|
|
|
|
|
description String?
|
|
|
|
|
meta Json?
|
|
|
|
|
|
|
|
|
|
@@map("app_config")
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
model Post {
|
2024-12-30 13:44:30 +08:00
|
|
|
|
id String @id @default(cuid())
|
|
|
|
|
type String?
|
|
|
|
|
title String?
|
|
|
|
|
content String?
|
|
|
|
|
author Staff? @relation(fields: [authorId], references: [id])
|
|
|
|
|
authorId String?
|
|
|
|
|
domainId String?
|
|
|
|
|
referenceId String?
|
|
|
|
|
attachments String[] @default([])
|
|
|
|
|
createdAt DateTime @default(now())
|
|
|
|
|
updatedAt DateTime @updatedAt
|
|
|
|
|
visits Visit[]
|
|
|
|
|
watchableStaffs Staff[] @relation("post_watch_staff")
|
|
|
|
|
watchableDepts Department[] @relation("post_watch_dept")
|
2024-12-30 08:26:40 +08:00
|
|
|
|
|
|
|
|
|
parentId String?
|
|
|
|
|
parent Post? @relation("PostChildren", fields: [parentId], references: [id])
|
|
|
|
|
children Post[] @relation("PostChildren")
|
|
|
|
|
deletedAt DateTime? @map("deleted_at")
|
2024-12-30 13:44:30 +08:00
|
|
|
|
Lecture Lecture? @relation(fields: [lectureId], references: [id])
|
|
|
|
|
lectureId String?
|
2024-12-30 08:26:40 +08:00
|
|
|
|
|
|
|
|
|
// 复合索引
|
|
|
|
|
@@index([type, domainId]) // 类型和域组合查询
|
|
|
|
|
@@index([authorId, type]) // 作者和类型组合查询
|
|
|
|
|
@@index([referenceId, type]) // 引用ID和类型组合查询
|
|
|
|
|
@@index([parentId, type]) // 父级帖子和创建时间索引
|
|
|
|
|
// 时间相关索引
|
|
|
|
|
@@index([createdAt]) // 按创建时间倒序索引
|
|
|
|
|
@@index([updatedAt]) // 按更新时间倒序索引
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
model Message {
|
2024-12-30 13:44:30 +08:00
|
|
|
|
id String @id @default(cuid())
|
2024-12-30 08:26:40 +08:00
|
|
|
|
url String?
|
|
|
|
|
intent String?
|
|
|
|
|
option Json?
|
|
|
|
|
senderId String? @map("sender_id")
|
|
|
|
|
messageType String?
|
|
|
|
|
sender Staff? @relation(name: "message_sender", fields: [senderId], references: [id])
|
|
|
|
|
title String?
|
|
|
|
|
content String?
|
|
|
|
|
receivers Staff[] @relation("message_receiver")
|
|
|
|
|
visits Visit[]
|
|
|
|
|
createdAt DateTime @default(now()) @map("created_at")
|
|
|
|
|
updatedAt DateTime? @updatedAt @map("updated_at")
|
|
|
|
|
|
|
|
|
|
@@index([messageType, createdAt])
|
|
|
|
|
@@map("message")
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
model Visit {
|
2024-12-30 13:44:30 +08:00
|
|
|
|
id String @id @default(cuid())
|
|
|
|
|
visitType String? @map("visit_type")
|
2024-12-30 08:26:40 +08:00
|
|
|
|
visitorId String @map("visitor_id")
|
|
|
|
|
visitor Staff @relation(fields: [visitorId], references: [id])
|
2024-12-30 13:44:30 +08:00
|
|
|
|
postId String? @map("post_id")
|
2024-12-30 08:26:40 +08:00
|
|
|
|
post Post? @relation(fields: [postId], references: [id])
|
|
|
|
|
message Message? @relation(fields: [messageId], references: [id])
|
2024-12-30 13:44:30 +08:00
|
|
|
|
messageId String? @map("message_id")
|
2024-12-30 08:26:40 +08:00
|
|
|
|
views Int @default(1)
|
2024-12-30 13:44:30 +08:00
|
|
|
|
createdAt DateTime? @default(now()) @map("created_at")
|
|
|
|
|
updatedAt DateTime? @updatedAt @map("updated_at")
|
|
|
|
|
sourceIP String? @map("source_ip")
|
2024-12-30 08:26:40 +08:00
|
|
|
|
|
|
|
|
|
@@index([postId, visitType, visitorId])
|
|
|
|
|
@@index([messageId, visitType, visitorId])
|
|
|
|
|
@@map("visit")
|
2024-09-03 20:19:33 +08:00
|
|
|
|
}
|
2024-12-30 13:44:30 +08:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
model Course {
|
|
|
|
|
id String @id @default(cuid()) // 课程唯一标识符
|
|
|
|
|
title String // 课程标题
|
|
|
|
|
subTitle String? // 课程副标题(可选)
|
|
|
|
|
description String // 课程详细描述
|
|
|
|
|
thumbnail String? // 课程封面图片URL(可选)
|
|
|
|
|
level String // 课程难度等级
|
|
|
|
|
|
|
|
|
|
// 课程内容组织结构
|
|
|
|
|
terms Term[] @relation("course_term") // 课程学期
|
|
|
|
|
instructors CourseInstructor[] // 课程讲师团队
|
|
|
|
|
sections Section[] // 课程章节结构
|
|
|
|
|
enrollments Enrollment[] // 学生报名记录
|
|
|
|
|
reviews CourseReview[] // 学员课程评价
|
|
|
|
|
|
|
|
|
|
// 课程规划与目标设定
|
|
|
|
|
requirements String[] // 课程学习前置要求
|
|
|
|
|
objectives String[] // 具体的学习目标
|
|
|
|
|
skills String[] // 课程结束后可掌握的技能
|
|
|
|
|
audiences String[] // 目标受众群体描述
|
|
|
|
|
|
|
|
|
|
// 课程统计指标
|
|
|
|
|
totalDuration Int @default(0) // 课程总时长(分钟)
|
|
|
|
|
totalLectures Int @default(0) // 总课时数
|
|
|
|
|
averageRating Float @default(0) // 平均评分(1-5分)
|
|
|
|
|
numberOfReviews Int @default(0) // 评价总数
|
|
|
|
|
numberOfStudents Int @default(0) // 学习人数
|
|
|
|
|
completionRate Float @default(0) // 完课率(0-100%)
|
|
|
|
|
|
|
|
|
|
// 课程状态管理
|
|
|
|
|
status String // 课程状态(如:草稿/已发布/已归档)
|
|
|
|
|
isFeatured Boolean @default(false) // 是否为精选推荐课程
|
|
|
|
|
|
|
|
|
|
// 生命周期时间戳
|
|
|
|
|
createdAt DateTime @default(now()) // 创建时间
|
|
|
|
|
updatedAt DateTime @updatedAt // 最后更新时间
|
|
|
|
|
publishedAt DateTime? // 发布时间
|
|
|
|
|
archivedAt DateTime? // 归档时间
|
|
|
|
|
deletedAt DateTime? // 软删除时间
|
|
|
|
|
|
|
|
|
|
// 数据库索引优化
|
|
|
|
|
@@index([status]) // 课程状态索引,用于快速筛选
|
|
|
|
|
@@index([level]) // 难度等级索引,用于分类查询
|
|
|
|
|
@@index([isFeatured]) // 精选标记索引,用于首页推荐
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
model Section {
|
|
|
|
|
id String @id @default(cuid()) // 章节唯一标识符
|
|
|
|
|
title String // 章节标题
|
|
|
|
|
description String? // 章节描述(可选)
|
|
|
|
|
objectives String[] // 本章节的具体学习目标
|
|
|
|
|
order Float? @default(0) // 章节排序权重
|
|
|
|
|
|
|
|
|
|
// 关联关系
|
|
|
|
|
course Course @relation(fields: [courseId], references: [id], onDelete: Cascade)
|
|
|
|
|
courseId String // 所属课程ID
|
|
|
|
|
lectures Lecture[] // 包含的所有课时
|
|
|
|
|
|
|
|
|
|
// 章节统计数据
|
|
|
|
|
totalDuration Int @default(0) // 本章节总时长(分钟)
|
|
|
|
|
totalLectures Int @default(0) // 本章节课时总数
|
|
|
|
|
|
|
|
|
|
// 时间管理
|
|
|
|
|
createdAt DateTime @default(now()) // 创建时间
|
|
|
|
|
updatedAt DateTime @updatedAt // 更新时间
|
|
|
|
|
deletedAt DateTime? // 软删除时间
|
|
|
|
|
|
|
|
|
|
@@index([courseId, order]) // 复合索引:用于按课程ID和顺序快速查询
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
model Lecture {
|
|
|
|
|
id String @id @default(cuid()) // 课时唯一标识符
|
|
|
|
|
title String // 课时标题
|
|
|
|
|
description String? // 课时描述(可选)
|
|
|
|
|
order Float? @default(0) // 课时排序权重
|
|
|
|
|
duration Int // 学习时长(分钟)
|
|
|
|
|
type String // 课时类型(video/article)
|
|
|
|
|
|
|
|
|
|
// 课时内容
|
|
|
|
|
content String? // Markdown格式文章内容
|
|
|
|
|
videoUrl String? // 视频URL地址
|
|
|
|
|
videoThumbnail String? // 视频封面图URL
|
|
|
|
|
|
|
|
|
|
// 关联内容
|
|
|
|
|
resources Resource[] // 课时附属资源
|
|
|
|
|
section Section @relation(fields: [sectionId], references: [id], onDelete: Cascade)
|
|
|
|
|
sectionId String // 所属章节ID
|
|
|
|
|
comments Post[] // 课时评论
|
|
|
|
|
progress LectureProgress[] // 学习进度记录
|
|
|
|
|
|
|
|
|
|
// 时间管理
|
|
|
|
|
publishedAt DateTime? // 发布时间
|
|
|
|
|
createdAt DateTime @default(now()) // 创建时间
|
|
|
|
|
updatedAt DateTime @updatedAt // 更新时间
|
|
|
|
|
deletedAt DateTime? // 软删除时间
|
|
|
|
|
|
|
|
|
|
@@index([sectionId, order]) // 章节内课时排序索引
|
|
|
|
|
@@index([type, publishedAt]) // 课时类型和发布时间复合索引
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
model Enrollment {
|
|
|
|
|
id String @id @default(cuid()) // 报名记录唯一标识符
|
|
|
|
|
status String // 报名状态(如:进行中/已完成/已过期)
|
|
|
|
|
|
|
|
|
|
// 关联关系
|
|
|
|
|
student Staff @relation(fields: [studentId], references: [id])
|
|
|
|
|
studentId String // 学员ID
|
|
|
|
|
course Course @relation(fields: [courseId], references: [id])
|
|
|
|
|
courseId String // 课程ID
|
|
|
|
|
progress LectureProgress[] // 课时学习进度记录
|
|
|
|
|
|
|
|
|
|
// 学习数据统计
|
|
|
|
|
completionRate Float @default(0) // 课程完成度(0-100%)
|
|
|
|
|
lastAccessedAt DateTime? // 最后访问时间
|
|
|
|
|
|
|
|
|
|
// 时间管理
|
|
|
|
|
createdAt DateTime @default(now()) // 报名时间
|
|
|
|
|
updatedAt DateTime @updatedAt // 更新时间
|
|
|
|
|
completedAt DateTime? // 完课时间
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@@unique([studentId, courseId]) // 确保学员不会重复报名同一课程
|
|
|
|
|
@@index([status]) // 报名状态索引
|
|
|
|
|
@@index([completedAt]) // 完课时间索引
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
model LectureProgress {
|
|
|
|
|
id String @id @default(cuid()) // 进度记录唯一标识符
|
|
|
|
|
progress Float @default(0) // 完成进度(0-100%)
|
|
|
|
|
isCompleted Boolean @default(false) // 是否完成
|
|
|
|
|
|
|
|
|
|
// 关联关系
|
|
|
|
|
enrollment Enrollment @relation(fields: [enrollmentId], references: [id], onDelete: Cascade)
|
|
|
|
|
enrollmentId String // 报名记录ID
|
|
|
|
|
lecture Lecture @relation(fields: [lectureId], references: [id], onDelete: Cascade)
|
|
|
|
|
lectureId String // 课时ID
|
|
|
|
|
|
|
|
|
|
// 学习数据
|
|
|
|
|
lastPosition Int @default(0) // 视频播放位置(秒)
|
|
|
|
|
viewCount Int @default(0) // 观看次数
|
|
|
|
|
readCount Int @default(0) // 阅读次数
|
|
|
|
|
totalWatchTime Int @default(0) // 总观看时长(秒)
|
|
|
|
|
|
|
|
|
|
// 时间记录
|
|
|
|
|
lastWatchedAt DateTime? // 最后观看时间
|
|
|
|
|
createdAt DateTime @default(now()) // 创建时间
|
|
|
|
|
updatedAt DateTime @updatedAt // 更新时间
|
|
|
|
|
|
|
|
|
|
@@unique([enrollmentId, lectureId]) // 确保每个报名只有一条课时进度
|
|
|
|
|
@@index([isCompleted]) // 完成状态索引
|
|
|
|
|
@@index([lastWatchedAt]) // 最后观看时间索引
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
model CourseInstructor {
|
|
|
|
|
course Course @relation(fields: [courseId], references: [id])
|
|
|
|
|
courseId String // 课程ID
|
|
|
|
|
instructor Staff @relation(fields: [instructorId], references: [id])
|
|
|
|
|
instructorId String // 讲师ID
|
|
|
|
|
role String // 讲师角色
|
|
|
|
|
createdAt DateTime @default(now()) // 创建时间
|
|
|
|
|
order Float? @default(0) // 讲师显示顺序
|
|
|
|
|
|
|
|
|
|
@@id([courseId, instructorId]) // 联合主键
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
model CourseReview {
|
|
|
|
|
id String @id @default(cuid()) // 评价唯一标识符
|
|
|
|
|
rating Int // 评分(1-5星)
|
|
|
|
|
content String? // 评价内容
|
|
|
|
|
student Staff @relation(fields: [studentId], references: [id])
|
|
|
|
|
studentId String // 评价学员ID
|
|
|
|
|
course Course @relation(fields: [courseId], references: [id])
|
|
|
|
|
courseId String // 课程ID
|
|
|
|
|
helpfulCount Int @default(0) // 评价点赞数
|
|
|
|
|
createdAt DateTime @default(now()) // 评价时间
|
|
|
|
|
updatedAt DateTime @updatedAt // 更新时间
|
|
|
|
|
|
|
|
|
|
@@unique([studentId, courseId]) // 确保学员对同一课程只能评价一次
|
|
|
|
|
@@index([rating]) // 评分索引
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
model Resource {
|
|
|
|
|
id String @id @default(cuid()) // 资源唯一标识符
|
|
|
|
|
title String // 资源标题
|
|
|
|
|
description String? // 资源描述
|
|
|
|
|
type String // 资源类型
|
|
|
|
|
url String // 资源URL
|
|
|
|
|
|
|
|
|
|
fileType String? // 文件MIME类型
|
|
|
|
|
fileSize Int? // 文件大小(bytes)
|
|
|
|
|
|
|
|
|
|
lecture Lecture @relation(fields: [lectureId], references: [id], onDelete: Cascade)
|
|
|
|
|
lectureId String // 所属课时ID
|
|
|
|
|
downloadCount Int @default(0) // 下载次数
|
|
|
|
|
createdAt DateTime @default(now()) // 创建时间
|
|
|
|
|
updatedAt DateTime @updatedAt // 更新时间
|
|
|
|
|
|
|
|
|
|
@@index([lectureId, type]) // 课时资源类型复合索引
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
model Node {
|
|
|
|
|
id String @id @default(cuid())
|
|
|
|
|
title String
|
|
|
|
|
description String?
|
|
|
|
|
type String
|
|
|
|
|
// 节点之间的关系
|
|
|
|
|
sourceEdges NodeEdge[] @relation("from_node")
|
|
|
|
|
targetEdges NodeEdge[] @relation("to_node")
|
|
|
|
|
style Json?
|
|
|
|
|
position Json? // 存储节点在画布中的位置 {x: number, y: number}
|
|
|
|
|
data Json?
|
|
|
|
|
|
|
|
|
|
createdAt DateTime @default(now())
|
|
|
|
|
updatedAt DateTime @updatedAt
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 节点之间的关系
|
|
|
|
|
model NodeEdge {
|
|
|
|
|
id String @id @default(cuid())
|
|
|
|
|
// 关系的起点和终点
|
|
|
|
|
source Node @relation("from_node", fields: [sourceId], references: [id], onDelete: Cascade)
|
|
|
|
|
sourceId String
|
|
|
|
|
target Node @relation("to_node", fields: [targetId], references: [id], onDelete: Cascade)
|
|
|
|
|
targetId String
|
|
|
|
|
// 关系属性
|
|
|
|
|
type String?
|
|
|
|
|
label String?
|
|
|
|
|
description String?
|
|
|
|
|
// 自定义边的样式(可选)
|
|
|
|
|
style Json? // 存储边的样式,如 {color: string, strokeWidth: number}
|
|
|
|
|
createdAt DateTime @default(now())
|
|
|
|
|
updatedAt DateTime @updatedAt
|
|
|
|
|
|
|
|
|
|
@@unique([sourceId, targetId, type])
|
|
|
|
|
@@index([sourceId])
|
|
|
|
|
@@index([targetId])
|
|
|
|
|
}
|