234 lines
5.7 KiB
Plaintext
234 lines
5.7 KiB
Plaintext
// This is your Prisma schema file,
|
|
// learn more about it in the docs: https://pris.ly/d/prisma-schema
|
|
|
|
// Looking for ways to speed up your queries, or scale easily with your serverless or edge functions?
|
|
// Try Prisma Accelerate: https://pris.ly/cli/accelerate-init
|
|
|
|
generator client {
|
|
provider = "prisma-client-js"
|
|
}
|
|
|
|
datasource db {
|
|
provider = "postgresql"
|
|
url = env("DATABASE_URL")
|
|
}
|
|
|
|
// 用户表
|
|
model User {
|
|
id String @id @default(cuid())
|
|
email String @unique
|
|
name String?
|
|
password String
|
|
avatar String?
|
|
isAdmin Boolean @default(false) // 是否为管理员
|
|
isActive Boolean @default(true) // 是否启用
|
|
hasSeenHelp Boolean @default(false) // 是否已查看使用帮助
|
|
createdAt DateTime @default(now())
|
|
updatedAt DateTime @updatedAt
|
|
|
|
// 关系
|
|
ownedTrees FamilyTree[] @relation("TreeOwner")
|
|
collaborations TreeCollaborator[]
|
|
activityLogs ActivityLog[]
|
|
loginLogs LoginLog[]
|
|
}
|
|
|
|
// 家族树表
|
|
model FamilyTree {
|
|
id String @id @default(cuid())
|
|
name String
|
|
description String?
|
|
rootMemberId String?
|
|
ownerId String
|
|
createdAt DateTime @default(now())
|
|
updatedAt DateTime @updatedAt
|
|
|
|
// 关系
|
|
owner User @relation("TreeOwner", fields: [ownerId], references: [id], onDelete: Cascade)
|
|
members FamilyMember[]
|
|
collaborators TreeCollaborator[]
|
|
activityLogs ActivityLog[]
|
|
|
|
@@index([ownerId])
|
|
}
|
|
|
|
// 协作者表
|
|
model TreeCollaborator {
|
|
id String @id @default(cuid())
|
|
treeId String
|
|
userId String
|
|
role Role @default(VIEWER)
|
|
invitedBy String
|
|
invitedAt DateTime @default(now())
|
|
|
|
// 关系
|
|
tree FamilyTree @relation(fields: [treeId], references: [id], onDelete: Cascade)
|
|
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
|
|
|
|
@@unique([treeId, userId])
|
|
@@index([treeId])
|
|
@@index([userId])
|
|
}
|
|
|
|
enum Role {
|
|
OWNER
|
|
EDITOR
|
|
VIEWER
|
|
}
|
|
|
|
// 家族成员表
|
|
model FamilyMember {
|
|
id String @id @default(cuid())
|
|
treeId String
|
|
|
|
// 基本信息
|
|
surname String
|
|
givenName String
|
|
fullName String
|
|
gender Gender
|
|
generation Int
|
|
generationName String?
|
|
courtesyName String?
|
|
artName String?
|
|
posthumousName String?
|
|
rank Int?
|
|
isFounder Boolean @default(false)
|
|
|
|
// 日期
|
|
birthDate String?
|
|
deathDate String?
|
|
isLunarDate Boolean @default(false)
|
|
|
|
// 地点
|
|
ancestralHome String?
|
|
birthPlace String?
|
|
deathPlace String?
|
|
burialPlace String?
|
|
|
|
// 联系方式
|
|
phone String?
|
|
telephone String?
|
|
email String?
|
|
address String?
|
|
occupation String?
|
|
|
|
// 关系
|
|
fatherId String?
|
|
motherId String?
|
|
spouseIds String[] @default([])
|
|
childrenIds String[] @default([])
|
|
|
|
// 配偶父母信息
|
|
spouseFatherName String?
|
|
spouseMotherName String?
|
|
|
|
// 内容
|
|
bio String?
|
|
tags String[] @default([])
|
|
avatarUrl String?
|
|
avatarImageId String?
|
|
photoIds String[] @default([]) // 已弃用,用于兼容
|
|
photos Json? @default("[]") // 新格式:[{ url, caption, uploadedAt }]
|
|
stories Json? @default("[]") // 家族故事
|
|
|
|
// 元数据
|
|
createdAt DateTime @default(now())
|
|
updatedAt DateTime @updatedAt
|
|
|
|
// 关系
|
|
tree FamilyTree @relation(fields: [treeId], references: [id], onDelete: Cascade)
|
|
|
|
// 索引优化
|
|
@@index([treeId])
|
|
@@index([fatherId])
|
|
@@index([motherId])
|
|
@@index([treeId, generation]) // 复合索引:按树和世代查询
|
|
@@index([treeId, createdAt]) // 复合索引:按树和创建时间查询
|
|
@@index([fullName]) // 姓名搜索索引
|
|
@@index([surname]) // 姓氏筛选索引
|
|
}
|
|
|
|
enum Gender {
|
|
MALE
|
|
FEMALE
|
|
}
|
|
|
|
// 操作日志表
|
|
model ActivityLog {
|
|
id String @id @default(cuid())
|
|
treeId String
|
|
userId String
|
|
action Action
|
|
entityType EntityType
|
|
entityId String?
|
|
entityName String?
|
|
changes Json?
|
|
timestamp DateTime @default(now())
|
|
|
|
// 关系
|
|
tree FamilyTree @relation(fields: [treeId], references: [id], onDelete: Cascade)
|
|
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
|
|
|
|
@@index([treeId])
|
|
@@index([userId])
|
|
@@index([timestamp])
|
|
}
|
|
|
|
enum Action {
|
|
CREATE
|
|
UPDATE
|
|
DELETE
|
|
IMPORT
|
|
EXPORT
|
|
ERROR
|
|
}
|
|
|
|
enum EntityType {
|
|
MEMBER
|
|
PHOTO
|
|
STORY
|
|
SETTINGS
|
|
TREE
|
|
}
|
|
|
|
// 成员历史版本表
|
|
model MemberHistory {
|
|
id String @id @default(cuid())
|
|
memberId String
|
|
treeId String
|
|
version Int // 版本号
|
|
|
|
// 保存成员的完整快照
|
|
snapshot Json // 成员的所有字段
|
|
|
|
// 变更信息
|
|
changedBy String // 修改者ID
|
|
changedAt DateTime @default(now())
|
|
changeType Action // CREATE, UPDATE, DELETE
|
|
changes Json? // 具体变更的字段 { field: { old: ..., new: ... } }
|
|
|
|
@@index([memberId])
|
|
@@index([treeId])
|
|
@@index([changedAt])
|
|
@@unique([memberId, version])
|
|
}
|
|
|
|
// 登录日志表
|
|
model LoginLog {
|
|
id String @id @default(cuid())
|
|
userId String
|
|
email String
|
|
userName String?
|
|
ip String?
|
|
userAgent String?
|
|
success Boolean @default(true)
|
|
message String? // 失败原因
|
|
createdAt DateTime @default(now())
|
|
|
|
// 关系
|
|
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
|
|
|
|
@@index([userId])
|
|
@@index([createdAt])
|
|
}
|