566 lines
19 KiB
Plaintext
Executable File
566 lines
19 KiB
Plaintext
Executable File
generator client {
|
||
provider = "prisma-client-js"
|
||
binaryTargets = ["native", "debian-openssl-3.0.x"]
|
||
output = "../generated/prisma"
|
||
}
|
||
|
||
datasource db {
|
||
provider = "postgres"
|
||
url = env("DATABASE_URL")
|
||
}
|
||
|
||
model User {
|
||
id String @id @default(cuid())
|
||
name String
|
||
username String? @unique
|
||
displayUsername String? @map("display_username")
|
||
email String @unique
|
||
emailVerified Boolean @default(false)
|
||
image String?
|
||
createdAt DateTime @default(now())
|
||
updatedAt DateTime @updatedAt
|
||
|
||
password String?
|
||
|
||
deletedAt DateTime?
|
||
|
||
// 关联关系
|
||
organizationId String? @map("organization_id")
|
||
organization Organization? @relation(fields: [organizationId], references: [id])
|
||
posts Post[]
|
||
userActions UserAction[]
|
||
roles Role[]
|
||
resources Resource[] @relation("UserResources")
|
||
|
||
// 团队和组织关联
|
||
members Member[] @relation("UserMembers")
|
||
teamMembers TeamMember[] @relation("UserTeamMembers")
|
||
invitations Invitation[] @relation("UserInvitations")
|
||
|
||
// Better Auth 关联关系
|
||
sessions Session[]
|
||
accounts Account[]
|
||
|
||
oauthAccessTokens oauthAccessToken[] @relation("UserOAuthAccessTokens")
|
||
oauthConsents oauthConsent[] @relation("UserOAuthConsents")
|
||
|
||
// SSO Provider 关联关系
|
||
ssoProviders ssoProvider[] @relation("UserSsoProviders")
|
||
|
||
metadata Json?
|
||
|
||
@@index([organizationId, deletedAt]) // 优化组织用户查询
|
||
@@map("users")
|
||
}
|
||
|
||
// 支持树形结构的组织模型
|
||
model Organization {
|
||
id String @id @default(cuid())
|
||
name String
|
||
slug String? @unique // URL友好的标识符
|
||
description String?
|
||
logo String?
|
||
// 树形结构字段
|
||
parentId String? @map("parent_id")
|
||
parent Organization? @relation("OrganizationHierarchy", fields: [parentId], references: [id])
|
||
children Organization[] @relation("OrganizationHierarchy")
|
||
|
||
// 路径字段,用于快速查询整个路径 (例如: "1.2.3")
|
||
path String?
|
||
level Int @default(0) // 层级深度
|
||
order Float @default(0) // 同级排序
|
||
|
||
createdAt DateTime @default(now())
|
||
updatedAt DateTime @updatedAt
|
||
deletedAt DateTime?
|
||
|
||
// 关联关系
|
||
posts Post[]
|
||
users User[]
|
||
terms Term[]
|
||
profiles Profile[]
|
||
|
||
// 团队和组织成员关联
|
||
members Member[] @relation("OrganizationMembers")
|
||
teams Team[] @relation("OrganizationTeams")
|
||
invitations Invitation[] @relation("OrganizationInvitations")
|
||
|
||
// 活跃会话关联
|
||
activeSessions Session[] @relation("ActiveOrganization")
|
||
|
||
// SSO Provider 关联关系
|
||
ssoProviders ssoProvider[] @relation("OrganizationSsoProviders")
|
||
|
||
metadata Json?
|
||
|
||
@@index([parentId])
|
||
@@index([path])
|
||
@@index([level, order])
|
||
@@index([deletedAt]) // 活跃组织查询优化
|
||
@@map("organizations")
|
||
}
|
||
|
||
// 支持多媒体内容和文件管理的帖子模型(多态设计)
|
||
model Post {
|
||
id String @id @default(cuid())
|
||
|
||
// 基本信息
|
||
type String
|
||
title String
|
||
content String? // 文本内容(可选,文件类型可能只有文件信息)
|
||
excerpt String? // 摘要
|
||
|
||
// 树形结构字段(支持帖子回复、评论等层级关系,也支持文件夹结构)
|
||
parentId String? @map("parent_id")
|
||
parent Post? @relation("PostHierarchy", fields: [parentId], references: [id])
|
||
children Post[] @relation("PostHierarchy")
|
||
|
||
// 路径字段,用于快速查询整个路径
|
||
path String?
|
||
level Int @default(0) // 层级深度(0为根帖子/根文件夹,1为一级回复/子文件)
|
||
order Float @default(0) // 同级排序
|
||
|
||
// 状态管理
|
||
status String // draft, published, archived, deleted
|
||
publishedAt DateTime?
|
||
visibility String @default("public") // public, private
|
||
|
||
// 统计数据
|
||
viewCount Int @default(0) // 浏览量统计
|
||
likeCount Int @default(0) // 点赞数统计
|
||
startCount Int @default(0) // 收藏数统计
|
||
commentCount Int @default(0) // 评论数统计
|
||
|
||
// 关联关系
|
||
authorId String? @map("author_id")
|
||
author User? @relation(fields: [authorId], references: [id])
|
||
organizationId String? @map("organization_id")
|
||
organization Organization? @relation(fields: [organizationId], references: [id])
|
||
|
||
createdAt DateTime @default(now())
|
||
updatedAt DateTime @updatedAt
|
||
deletedAt DateTime?
|
||
|
||
// 关联关系
|
||
userActions UserAction[]
|
||
terms Term[] // 帖子关联的标签(多对多)
|
||
// === 元数据字段(JSONB)- 存储不经常查询的字段 ===
|
||
metadata Json?
|
||
|
||
// === 优化的索引设计 ===
|
||
@@index([type, status, deletedAt]) // 核心查询组合
|
||
@@index([parentId, deletedAt, order]) // 目录内容查询优化
|
||
@@index([path, deletedAt]) // 路径查询优化
|
||
@@index([authorId, type, deletedAt, updatedAt]) // 用户文件查询优化
|
||
@@index([organizationId, type, deletedAt, publishedAt]) // 组织文件查询优化
|
||
@@index([metadata(ops: JsonbPathOps)], type: Gin) // GIN 索引支持 JSONB 查询
|
||
@@map("posts")
|
||
}
|
||
|
||
// 支持树形结构的分类体系模型
|
||
model Taxonomy {
|
||
id String @id @default(cuid())
|
||
name String
|
||
slug String @unique
|
||
description String?
|
||
postTypes String[] @default([]) // 适用文章类型
|
||
createdAt DateTime @default(now())
|
||
updatedAt DateTime @updatedAt
|
||
deletedAt DateTime?
|
||
terms Term[]
|
||
|
||
@@index([deletedAt, slug]) // 活跃分类查询优化
|
||
@@map("taxonomies")
|
||
}
|
||
|
||
// 支持树形结构的术语模型
|
||
model Term {
|
||
id String @id @default(cuid())
|
||
name String
|
||
slug String
|
||
description String?
|
||
|
||
// 树形结构字段
|
||
parentId String? @map("parent_id")
|
||
parent Term? @relation("TermHierarchy", fields: [parentId], references: [id])
|
||
children Term[] @relation("TermHierarchy")
|
||
|
||
// 路径字段,用于快速查询整个路径
|
||
path String?
|
||
level Int @default(0) // 层级深度
|
||
order Float @default(0) // 同级排序
|
||
|
||
// 关联关系
|
||
taxonomyId String @map("taxonomy_id")
|
||
taxonomy Taxonomy @relation(fields: [taxonomyId], references: [id])
|
||
|
||
createdAt DateTime @default(now())
|
||
updatedAt DateTime @updatedAt
|
||
deletedAt DateTime?
|
||
|
||
// 关联关系
|
||
posts Post[] // 术语关联的帖子(多对多)
|
||
organizations Organization[] // 术语关联的组织(多对多)
|
||
|
||
@@unique([taxonomyId, slug]) // 同一分类体系下的slug唯一
|
||
@@index([parentId])
|
||
@@index([path])
|
||
@@index([level, order])
|
||
@@index([taxonomyId, deletedAt]) // 分类术语查询优化
|
||
@@map("terms")
|
||
}
|
||
|
||
// 角色模型(可运行时创建)
|
||
model Role {
|
||
id String @id @default(cuid())
|
||
name String @unique // 角色名称
|
||
slug String @unique // URL友好标识符
|
||
description String? // 角色描述
|
||
permissions String[] // 权限代码数组,对应 SystemPermission 枚举值
|
||
|
||
// 角色类型
|
||
isSystem Boolean @default(false) // 是否为系统预设角色
|
||
isActive Boolean @default(true) // 是否启用
|
||
|
||
createdAt DateTime @default(now())
|
||
updatedAt DateTime @updatedAt
|
||
|
||
// 关联关系
|
||
users User[]
|
||
|
||
@@index([isSystem, isActive])
|
||
@@map("roles")
|
||
}
|
||
|
||
// 统一的用户行为表
|
||
model UserAction {
|
||
id String @id @default(cuid())
|
||
userId String? @map("user_id")
|
||
postId String? @map("post_id")
|
||
type String // 行为类型: 'view', 'like', 'favorite', 'download', 'share'
|
||
description String? // 行为描述
|
||
metadata String? // 额外数据(JSON格式)
|
||
ipAddress String? // IP地址
|
||
userAgent String? // 用户代理
|
||
user User? @relation(fields: [userId], references: [id], onDelete: Cascade)
|
||
post Post? @relation(fields: [postId], references: [id], onDelete: Cascade)
|
||
createdAt DateTime @default(now())
|
||
updatedAt DateTime @updatedAt
|
||
|
||
@@unique([userId, postId, type], name: "user_post_action_unique")
|
||
@@index([type, createdAt]) // 按行为类型和时间查询优化
|
||
@@index([postId])
|
||
@@index([userId, type, createdAt]) // 用户行为查询优化
|
||
@@map("user_actions")
|
||
}
|
||
|
||
// 系统配置模型
|
||
model SystemConfig {
|
||
id String @id @default(cuid())
|
||
key String @unique // 配置键
|
||
value String // 配置值(JSON字符串)
|
||
type String @default("string") // 配置类型: string, number, boolean, json
|
||
description String? // 配置描述
|
||
group String? // 配置分组
|
||
isPublic Boolean @default(false) // 是否为公开配置
|
||
createdAt DateTime @default(now())
|
||
updatedAt DateTime @updatedAt
|
||
|
||
@@index([group, isPublic]) // 配置分组查询优化
|
||
@@map("system_configs")
|
||
}
|
||
|
||
// ===人员信息===
|
||
model Profile {
|
||
// 基本信息
|
||
id String @id @default(cuid())
|
||
name String // 姓名
|
||
gender Int // 性别
|
||
idNum String // 身份证号
|
||
paperId String? // 证件号
|
||
avatar String? // 头像
|
||
command String? // 编制命令
|
||
birthday DateTime? // 生日
|
||
// 入职信息
|
||
hireDate DateTime? // 入职时间
|
||
relativeHireDate DateTime? // 相对入职时间
|
||
// 身份信息
|
||
identity String? // 身份
|
||
level String? // 等级
|
||
levelDate DateTime? // 等级时间
|
||
// 职务信息
|
||
dutyCode String // 职务代码
|
||
dutyLevel Int // 职务级别
|
||
dutyName String // 职务名称
|
||
|
||
// 关联关系
|
||
organizationId String @map("organization_id")
|
||
organization Organization @relation(fields: [organizationId], references: [id])
|
||
|
||
// 元数据 - 存储详细的、低频查询的信息
|
||
metadata Json?
|
||
|
||
createdAt DateTime @default(now())
|
||
updatedAt DateTime @updatedAt
|
||
deletedAt DateTime?
|
||
|
||
@@index([organizationId, deletedAt]) // 组织人员查询优化
|
||
@@index([hireDate])
|
||
@@index([level])
|
||
@@index([dutyCode, dutyLevel]) // 职务查询优化
|
||
@@map("profiles")
|
||
}
|
||
|
||
// ==== 媒体库
|
||
|
||
model Resource {
|
||
id String @id @default(cuid()) @map("id")
|
||
title String? @map("title")
|
||
description String? @map("description")
|
||
type String? @map("type")
|
||
fileId String? @unique
|
||
url String?
|
||
// 元数据
|
||
meta Json? @map("meta")
|
||
// 处理状态控制
|
||
status String?
|
||
createdAt DateTime? @default(now()) @map("created_at")
|
||
updatedAt DateTime? @updatedAt @map("updated_at")
|
||
createdBy String? @map("created_by")
|
||
updatedBy String? @map("updated_by")
|
||
deletedAt DateTime? @map("deleted_at")
|
||
isPublic Boolean? @default(true) @map("is_public")
|
||
|
||
owner User? @relation("UserResources", fields: [ownerId], references: [id])
|
||
ownerId String? @map("owner_id")
|
||
|
||
// 索引
|
||
@@index([type])
|
||
@@index([createdAt])
|
||
@@map("resource")
|
||
}
|
||
|
||
// 组织成员表
|
||
model Member {
|
||
id String @id @default(cuid())
|
||
userId String @map("user_id")
|
||
organizationId String @map("organization_id")
|
||
role String // 用户在组织中的角色
|
||
createdAt DateTime @default(now())
|
||
|
||
// 关联关系
|
||
user User @relation("UserMembers", fields: [userId], references: [id], onDelete: Cascade)
|
||
organization Organization @relation("OrganizationMembers", fields: [organizationId], references: [id], onDelete: Cascade)
|
||
|
||
@@unique([userId, organizationId]) // 一个用户在一个组织中只能有一个成员记录
|
||
@@index([organizationId, role])
|
||
@@index([userId])
|
||
@@map("members")
|
||
}
|
||
|
||
// 团队表
|
||
model Team {
|
||
id String @id @default(cuid())
|
||
name String // 团队名称
|
||
organizationId String @map("organization_id")
|
||
createdAt DateTime @default(now())
|
||
updatedAt DateTime @updatedAt
|
||
|
||
// 关联关系
|
||
organization Organization @relation("OrganizationTeams", fields: [organizationId], references: [id], onDelete: Cascade)
|
||
teamMembers TeamMember[] @relation("TeamMembers")
|
||
invitations Invitation[] @relation("TeamInvitations")
|
||
|
||
// 活跃会话关联
|
||
activeSessions Session[] @relation("ActiveTeam")
|
||
|
||
@@index([organizationId])
|
||
@@map("teams")
|
||
}
|
||
|
||
// 团队成员表
|
||
model TeamMember {
|
||
id String @id @default(cuid())
|
||
teamId String @map("team_id")
|
||
userId String @map("user_id")
|
||
createdAt DateTime @default(now())
|
||
|
||
// 关联关系
|
||
team Team @relation("TeamMembers", fields: [teamId], references: [id], onDelete: Cascade)
|
||
user User @relation("UserTeamMembers", fields: [userId], references: [id], onDelete: Cascade)
|
||
|
||
@@unique([teamId, userId]) // 一个用户在一个团队中只能有一个成员记录
|
||
@@index([teamId])
|
||
@@index([userId])
|
||
@@map("team_members")
|
||
}
|
||
|
||
// 邀请表
|
||
model Invitation {
|
||
id String @id @default(cuid())
|
||
email String // 被邀请人的邮箱地址
|
||
inviterId String @map("inviter_id")
|
||
organizationId String @map("organization_id")
|
||
teamId String? @map("team_id") // 可选的团队ID
|
||
role String // 用户在组织中的角色
|
||
status String // 邀请状态 (pending, accepted, rejected, expired)
|
||
expiresAt DateTime // 邀请过期时间
|
||
createdAt DateTime @default(now())
|
||
|
||
// 关联关系
|
||
inviter User @relation("UserInvitations", fields: [inviterId], references: [id], onDelete: Cascade)
|
||
organization Organization @relation("OrganizationInvitations", fields: [organizationId], references: [id], onDelete: Cascade)
|
||
team Team? @relation("TeamInvitations", fields: [teamId], references: [id], onDelete: Cascade)
|
||
|
||
@@index([email, status])
|
||
@@index([organizationId, status])
|
||
@@index([teamId, status])
|
||
@@index([expiresAt])
|
||
@@map("invitations")
|
||
}
|
||
|
||
// ==== Better Auth Standard Models ====
|
||
|
||
model Session {
|
||
id String @id @default(cuid())
|
||
expiresAt DateTime
|
||
token String @unique
|
||
createdAt DateTime @default(now())
|
||
updatedAt DateTime @updatedAt
|
||
ipAddress String?
|
||
userAgent String?
|
||
userId String
|
||
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
|
||
|
||
// 活跃组织和团队字段
|
||
activeOrganizationId String? @map("active_organization_id")
|
||
activeTeamId String? @map("active_team_id")
|
||
|
||
// 关联关系
|
||
activeOrganization Organization? @relation("ActiveOrganization", fields: [activeOrganizationId], references: [id])
|
||
activeTeam Team? @relation("ActiveTeam", fields: [activeTeamId], references: [id])
|
||
|
||
@@map("session")
|
||
}
|
||
|
||
model Account {
|
||
id String @id @default(cuid())
|
||
accountId String
|
||
providerId String
|
||
userId String
|
||
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
|
||
idToken String?
|
||
accessToken String?
|
||
refreshToken String?
|
||
accessTokenExpiresAt DateTime?
|
||
refreshTokenExpiresAt DateTime?
|
||
scope String?
|
||
password String?
|
||
createdAt DateTime @default(now())
|
||
updatedAt DateTime @updatedAt
|
||
|
||
@@unique([providerId, accountId])
|
||
@@map("account")
|
||
}
|
||
|
||
model Verification {
|
||
id String @id @default(cuid())
|
||
identifier String @unique
|
||
value String
|
||
expiresAt DateTime
|
||
createdAt DateTime @default(now())
|
||
updatedAt DateTime @updatedAt
|
||
|
||
@@map("verification")
|
||
}
|
||
|
||
// ==== OIDC Provider Models ====
|
||
|
||
// OAuth 应用程序
|
||
model oauthApplication {
|
||
id String @id @default(cuid())
|
||
clientId String @unique @map("client_id") // OAuth 客户端的唯一标识符
|
||
clientSecret String? @map("client_secret") // 客户端密钥,对于使用 PKCE 的公共客户端为可选
|
||
name String // OAuth 客户端名称
|
||
redirectURLs String @map("redirect_urls") // 以逗号分隔的重定向 URL 列表
|
||
metadata String? // OAuth 客户端的附加元数据
|
||
type String // OAuth 客户端类型(例如 Web、移动)
|
||
disabled Boolean @default(false) // 指示客户端是否被禁用
|
||
userId String? @map("user_id") // 拥有客户端的用户 ID(可选)
|
||
createdAt DateTime @default(now()) @map("created_at")
|
||
updatedAt DateTime @updatedAt @map("updated_at")
|
||
|
||
@@index([clientId])
|
||
@@index([userId])
|
||
@@index([disabled])
|
||
@@map("oauth_applications")
|
||
}
|
||
|
||
// OAuth 访问令牌
|
||
model oauthAccessToken {
|
||
id String @id @default(cuid())
|
||
accessToken String @map("access_token") // 向客户端颁发的访问令牌
|
||
refreshToken String @map("refresh_token") // 向客户端发出的刷新令牌
|
||
accessTokenExpiresAt DateTime @map("access_token_expires_at") // 访问令牌的到期日期
|
||
refreshTokenExpiresAt DateTime @map("refresh_token_expires_at") // 刷新令牌的到期日期
|
||
clientId String @map("client_id") // OAuth 客户端的 ID
|
||
userId String @map("user_id") // 与令牌关联的用户的 ID
|
||
scopes String // 授予范围的逗号分隔列表
|
||
createdAt DateTime @default(now()) @map("created_at")
|
||
updatedAt DateTime @updatedAt @map("updated_at")
|
||
|
||
user User @relation("UserOAuthAccessTokens", fields: [userId], references: [id], onDelete: Cascade)
|
||
|
||
@@index([accessToken])
|
||
@@index([refreshToken])
|
||
@@index([clientId])
|
||
@@index([userId])
|
||
@@index([accessTokenExpiresAt])
|
||
@@index([refreshTokenExpiresAt])
|
||
@@map("oauth_access_tokens")
|
||
}
|
||
|
||
// OAuth 同意
|
||
model oauthConsent {
|
||
id String @id @default(cuid())
|
||
userId String @map("user_id") // 同意用户的 ID
|
||
clientId String @map("client_id") // OAuth 客户端的 ID
|
||
scopes String // 同意的范围的逗号分隔列表
|
||
consentGiven Boolean @map("consent_given") // 表明是否已获得同意
|
||
createdAt DateTime @default(now()) @map("created_at")
|
||
updatedAt DateTime @updatedAt @map("updated_at")
|
||
// 关联关系
|
||
user User @relation("UserOAuthConsents", fields: [userId], references: [id], onDelete: Cascade)
|
||
|
||
@@unique([userId, clientId]) // 一个用户对一个客户端只能有一个同意记录
|
||
@@index([userId])
|
||
@@index([clientId])
|
||
@@index([consentGiven])
|
||
@@map("oauth_consents")
|
||
}
|
||
|
||
// SSO 提供程序
|
||
model ssoProvider {
|
||
id String @id @default(cuid())
|
||
issuer String // 发行者标识符
|
||
domain String // 提供商的域名
|
||
oidcConfig String? // OIDC 配置(JSON 字符串)
|
||
samlConfig String? // SAML 配置(JSON 字符串)
|
||
userId String? @map("user_id") // 用户 ID
|
||
providerId String @unique @map("provider_id") // 提供商 ID,用于识别提供商并生成重定向 URL
|
||
organizationId String? @map("organization_id") // 组织 ID,如果提供商与组织相关联
|
||
createdAt DateTime @default(now()) @map("created_at")
|
||
updatedAt DateTime @updatedAt @map("updated_at")
|
||
|
||
// 关联关系
|
||
user User? @relation("UserSsoProviders", fields: [userId], references: [id], onDelete: Cascade)
|
||
organization Organization? @relation("OrganizationSsoProviders", fields: [organizationId], references: [id], onDelete: Cascade)
|
||
|
||
@@index([providerId])
|
||
@@index([userId])
|
||
@@index([organizationId])
|
||
@@index([domain])
|
||
@@index([issuer])
|
||
@@map("sso_providers")
|
||
}
|