Files
seclusion/apps/api/prisma/schema.prisma
charilezhou 3119460f13 feat(plop): 优化生成器支持 Prisma 关联关系
- 支持一对多/多对一关系定义并生成到 Prisma schema
- 简化流程:查询关联配置根据关系自动预填
- 修复 Handlebars 模板 HTML 转义导致的乱码问题
- 修复 controller 模板缺少 Prisma 导入的问题
- 新增页面模板 (page.hbs) 生成前端页面
- 添加 FindAllParams/PaginationQueryDto 索引签名修复类型兼容

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-19 17:30:18 +08:00

232 lines
6.2 KiB
Plaintext
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

generator client {
provider = "prisma-client-js"
}
datasource db {
provider = "postgresql"
url = env("DATABASE_URL")
}
model User {
id String @id @default(cuid(2))
email String
password String
name String?
avatarId String? // 头像文件 ID
isSuperAdmin Boolean @default(false) // 超级管理员标记
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
deletedAt DateTime?
roles UserRole[]
uploadFiles File[] @relation("FileUploader")
// 复合唯一约束:未删除用户邮箱唯一,已删除用户邮箱可重复
@@unique([email, deletedAt])
@@map("users")
}
// 文件表
model File {
id String @id @default(cuid(2))
filename String // 原始文件名
objectName String // MinIO 中的对象名
mimeType String // MIME 类型
size Int // 文件大小(字节)
purpose String // 用途: avatar, attachment 等
uploaderId String // 上传者 ID
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
deletedAt DateTime?
uploader User @relation("FileUploader", fields: [uploaderId], references: [id])
@@index([uploaderId])
@@index([purpose])
@@map("files")
}
// 角色表
model Role {
id String @id @default(cuid(2))
code String @unique // 角色编码: admin, user
name String // 角色名称
description String?
isSystem Boolean @default(false) // 系统内置角色不可删
isEnabled Boolean @default(true)
sort Int @default(0)
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
deletedAt DateTime?
users UserRole[]
permissions RolePermission[]
menus RoleMenu[]
@@map("roles")
}
// 权限表
model Permission {
id String @id @default(cuid(2))
code String @unique // 权限编码: user:create
name String
description String?
resource String // 资源: user
action String // 操作: create
isEnabled Boolean @default(true)
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
deletedAt DateTime?
roles RolePermission[]
@@index([resource])
@@map("permissions")
}
// 菜单表
model Menu {
id String @id @default(cuid(2))
parentId String?
code String @unique
name String
type String @default("menu") // dir / menu / button
path String?
icon String? // Lucide 图标名
isExternal Boolean @default(false)
isHidden Boolean @default(false)
isEnabled Boolean @default(true)
isStatic Boolean @default(false) // 静态/动态菜单
sort Int @default(0)
meta Json?
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
deletedAt DateTime?
parent Menu? @relation("MenuTree", fields: [parentId], references: [id])
children Menu[] @relation("MenuTree")
roles RoleMenu[]
@@index([parentId])
@@map("menus")
}
// 用户-角色关联表
model UserRole {
id String @id @default(cuid(2))
userId String
roleId String
createdAt DateTime @default(now())
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
role Role @relation(fields: [roleId], references: [id], onDelete: Cascade)
@@unique([userId, roleId])
@@map("user_roles")
}
// 角色-权限关联表
model RolePermission {
id String @id @default(cuid(2))
roleId String
permissionId String
createdAt DateTime @default(now())
role Role @relation(fields: [roleId], references: [id], onDelete: Cascade)
permission Permission @relation(fields: [permissionId], references: [id], onDelete: Cascade)
@@unique([roleId, permissionId])
@@map("role_permissions")
}
// 角色-菜单关联表
model RoleMenu {
id String @id @default(cuid(2))
roleId String
menuId String
createdAt DateTime @default(now())
role Role @relation(fields: [roleId], references: [id], onDelete: Cascade)
menu Menu @relation(fields: [menuId], references: [id], onDelete: Cascade)
@@unique([roleId, menuId])
@@map("role_menus")
}
// ============ 教学管理模块 ============
// 教师表
model Teacher {
id String @id @default(cuid(2))
teacherNo String @unique // 工号
name String
gender String? // male / female
phone String?
email String?
subject String? // 任教科目
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
deletedAt DateTime?
// 关系
headOfClasses Class[] @relation("HeadTeacher") // 作为班主任的班级(一对一的反向)
teachClasses ClassTeacher[] // 任课班级(多对多)
@@map("teachers")
}
// 班级表
model Class {
id String @id @default(cuid(2))
code String @unique // 班级代码
name String // 班级名称
grade String? // 年级
headTeacherId String? // 班主任 ID一对一
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
deletedAt DateTime?
// 关系
headTeacher Teacher? @relation("HeadTeacher", fields: [headTeacherId], references: [id])
students Student[] // 班级学生(一对多)
teachers ClassTeacher[] // 任课教师(多对多)
@@index([headTeacherId])
@@map("classes")
}
// 学生表
model Student {
id String @id @default(cuid(2))
studentNo String @unique // 学号
name String
gender String? // male / female
phone String?
email String?
classId String? // 所属班级(多对一)
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
deletedAt DateTime?
// 关系
class Class? @relation(fields: [classId], references: [id])
@@index([classId])
@@map("students")
}
// 班级-教师关联表(多对多:任课关系)
model ClassTeacher {
id String @id @default(cuid(2))
classId String
teacherId String
createdAt DateTime @default(now())
class Class @relation(fields: [classId], references: [id], onDelete: Cascade)
teacher Teacher @relation(fields: [teacherId], references: [id], onDelete: Cascade)
@@unique([classId, teacherId])
@@map("class_teachers")
}