casualroom/apps/fenghuo/db/generated/prisma/schema.prisma

566 lines
19 KiB
Plaintext
Raw Normal View History

2025-07-28 07:50:50 +08:00
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")
}