gongxiangp2/prisma/schema.prisma

445 lines
16 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.

// This is your Prisma schema file,
// learn more about it in the docs: https://pris.ly/d/prisma-schema
generator client {
provider = "prisma-client-js"
binaryTargets = ["native", "linux-musl-openssl-3.0.x"]
previewFeatures = []
engineType = "library"
}
datasource db {
provider = "postgresql"
url = env("DATABASE_URL")
}
model User {
id String @id @default(uuid())
email String @unique
username String @unique
password String
department String @default("") // 用户部门(保留,向后兼容)
departmentId String? // 部门ID(外键关联,阶段二新增)
departmentRef Department? @relation("UserDepartment", fields: [departmentId], references: [id])
managedDepartment String? // 管理员负责的部门(如果是部门管理员)
role Role @default(USER)
isActive Boolean @default(false) // 是否激活,默认未激活(保留,向后兼容)
canDownload Boolean @default(true) // 是否允许下载,默认允许
isSuperAdmin Boolean @default(false) // 是否是超级管理员(最多4个)
// 钉钉登录相关字段
dingtalkUserId String? @unique // 钉钉userId
loginType String @default("normal") // 登录类型:normal/dingtalk
realName String? // 真实姓名
phone String? @unique // 手机号
avatar String? // 头像URL
// 用户状态管理(阶段一新增)
status String @default("pending") // pending/active/suspended/archived
lastLoginAt DateTime? // 最后登录时间
lastLoginIp String? // 最后登录IP
loginCount Int @default(0) // 登录次数
archivedAt DateTime? // 归档时间(软删除标记)
// 人员状态管理(新增:在职/离职/转岗等)
employmentStatus String? @default("active") // active/on_leave/resigned/transferred(在职/请假/离职/转岗)
resignationDate DateTime? // 离职日期
transferDate DateTime? // 转岗日期
transferToDeptId String? // 转岗目标部门ID
transferToDept Department? @relation("UserTransferDepartment", fields: [transferToDeptId], references: [id])
employmentNote String? // 人员状态备注(离职原因、转岗说明等)
statusChangedBy String? // 状态变更操作人ID
statusChangedAt DateTime? // 状态变更时间
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
materials Material[]
likes MaterialLike[]
favorites MaterialFavorite[]
downloadLogs MaterialDownloadLog[]
materialLogs MaterialLog[]
// 部门管理关联(阶段三新增)
managedDepartments Department[] @relation("DepartmentManager")
// 素材移交关联(新增)
materialTransfersFrom MaterialTransfer[] @relation("MaterialTransferFromUser")
materialTransfersTo MaterialTransfer[] @relation("MaterialTransferToUser")
materialTransfersAsOperator MaterialTransfer[] @relation("MaterialTransferOperator")
@@index([status])
@@index([isActive])
@@index([archivedAt])
@@index([departmentId])
@@index([employmentStatus])
@@index([transferToDeptId])
@@map("users")
}
model Material {
id String @id @default(uuid())
previewUrl String // S3 URL for preview image
productModel String // SPU
categoryName String // 使用店铺
sceneName String // 场景类别
platformName String @default("") // 平台分类(可选)
productCategoryName String @default("") // 品类分类(可选)
materialType String @default("3DMAX") // 素材类型
renderer String @default("CR") // 渲染器
authorName String // 作者花名
zipFileName String @default("") // 压缩包文件名
zipFilePath String @default("") // 本地压缩包路径
zipFileSize BigInt @default(0) // 压缩包文件大小(字节)
downloadCount Int @default(0) // 下载次数
likeCount Int @default(0) // 点赞次数
displayImages String[] @default([]) // 展示图片URLs数组
deletedAt DateTime? // 软删除时间戳
uploadId String? @unique // 上传ID(唯一约束,用于分片上传)
// 视频相关字段(2.2.3版本新增)
videoSourceUrl String? // 原始视频URL
videoPreview540Url String? // 540p预览视频URL
videoPreviewClipUrl String? // 视频片段URL
videoCoverUrl String? // 视频封面URL
videoProcessingStatus String? // 视频处理状态:pending/processing/completed/failed(可为空)
videoDuration Int? // 视频时长(秒)
transcodeLastError String? @map("transcodelasterror") // 转码最后一次错误信息
transcodeAttempts Int? @map("transcodeattempts") // 转码尝试次数
// 任务-详情相关字段(新增)
taskNo String? @unique @map("task_no") // 任务号(唯一,格式:TASK+12-18位数字,或 TASK+12-18位数字-2位子任务号)
taskStatus String? @map("task_status") // 任务状态:uploading/completed/fetched
taskFetchedAt DateTime? @map("task_fetched_at") // 外部系统获取时间
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
userId String
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
// 素材移交相关(新增)
originalOwnerId String? // 原始所有者ID(移交后保留记录)
transferredAt DateTime? // 移交时间
transferredBy String? // 移交操作人ID
transferNote String? // 移交备注说明
likes MaterialLike[]
favorites MaterialFavorite[]
downloadLogs MaterialDownloadLog[]
logs MaterialLog[]
skus MaterialSku[]
transfers MaterialTransfer[] // 移交历史记录
assets MaterialAsset[] // 产品全案资产
@@index([userId])
@@index([createdAt])
@@index([categoryName])
@@index([sceneName])
@@index([platformName])
@@index([productCategoryName])
@@index([materialType])
@@index([downloadCount])
@@index([likeCount])
@@index([deletedAt])
@@index([videoProcessingStatus])
@@index([originalOwnerId])
@@index([transferredAt])
@@index([taskNo])
@@index([taskStatus])
@@map("materials")
}
model MaterialLike {
id String @id @default(uuid())
materialId String
userId String
createdAt DateTime @default(now())
material Material @relation(fields: [materialId], references: [id], onDelete: Cascade)
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
@@unique([materialId, userId])
@@index([materialId])
@@index([userId])
@@map("material_likes")
}
model MaterialFavorite {
id String @id @default(uuid())
materialId String
userId String
createdAt DateTime @default(now())
material Material @relation(fields: [materialId], references: [id], onDelete: Cascade)
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
@@unique([materialId, userId])
@@index([materialId])
@@index([userId])
@@map("material_favorites")
}
model MaterialDownloadLog {
id String @id @default(uuid())
materialId String
userId String
downloadedAt DateTime @default(now())
material Material @relation(fields: [materialId], references: [id], onDelete: Cascade)
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
@@index([materialId])
@@index([userId])
@@index([downloadedAt])
@@index([materialId, userId, downloadedAt])
@@map("material_download_logs")
}
model MaterialLog {
id String @id @default(uuid())
materialId String
userId String
action String // UPLOAD, UPDATE, DELETE 等
changes String? // JSON 格式的变更记录
timestamp DateTime @default(now())
material Material @relation(fields: [materialId], references: [id], onDelete: Cascade)
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
@@index([materialId])
@@index([userId])
@@index([timestamp])
@@map("material_logs")
}
// SKU 表(用于标准模型类型)
model MaterialSku {
id String @id @default(uuid())
materialId String @map("material_id")
skuName String @map("sku_name")
previewUrl String? @map("preview_url") // 预览图URL(可选)
filePath String @map("file_path") // 压缩包文件路径
fileName String? @map("file_name") // 压缩包文件名(可选,用于显示)
fileSize BigInt @default(0) @map("file_size")
sortOrder Int @default(0) @map("sort_order")
deletedAt DateTime? @map("deleted_at") // 软删除时间戳
createdAt DateTime @default(now()) @map("created_at")
updatedAt DateTime @updatedAt @map("updated_at")
material Material @relation(fields: [materialId], references: [id], onDelete: Cascade)
@@index([materialId])
@@index([sortOrder])
@@index([deletedAt])
@@map("material_skus")
}
model ProductCategory {
id String @id @default(uuid())
name String @unique
createdAt DateTime @default(now())
@@map("product_categories")
}
model Category {
id String @id @default(uuid())
name String @unique
createdAt DateTime @default(now())
@@map("categories")
}
model Scene {
id String @id @default(uuid())
name String @unique
createdAt DateTime @default(now())
@@map("scenes")
}
model Platform {
id String @id @default(uuid())
name String @unique
createdAt DateTime @default(now())
@@map("platforms")
}
model SystemSettings {
id String @id @default(uuid())
headerBgColor String @default("#1f2937")
headerLogoUrl String @default("http://s3.1080p.hk/shuzhou/2025/05/18/8ebadf0a7cc34eaea00e8619b8efb827.png")
loginLogoUrl String @default("http://s3.1080p.hk/shuzhou/2025/05/18/8ebadf0a7cc34eaea00e8619b8efb827.png")
siteName String @default("由壹点3D素材")
s3Endpoint String @default("")
s3AccessKey String @default("")
s3SecretKey String @default("")
s3Bucket String @default("")
s3Region String @default("us-east-1")
s3PublicUrl String @default("")
// 系统维护通知
maintenanceEnabled Boolean @default(false) @map("maintenance_enabled") // 是否启用维护通知
maintenanceMessage String? @map("maintenance_message") // 维护通知内容
maintenanceStartTime DateTime? @map("maintenance_start_time") // 维护开始时间
maintenanceEndTime DateTime? @map("maintenance_end_time") // 维护结束时间
updatedAt DateTime @updatedAt
createdAt DateTime @default(now())
@@map("system_settings")
}
model Department {
id String @id @default(uuid())
name String @unique // 部门名称(保留,向后兼容)
createdAt DateTime @default(now())
// 部门层级结构(阶段三新增)
code String? @unique // 部门编码(可选,如:DEPT-001)
parentId String? // 父部门ID(支持层级结构)
parent Department? @relation("DepartmentHierarchy", fields: [parentId], references: [id])
children Department[] @relation("DepartmentHierarchy")
level Int @default(1) // 层级:1=一级部门,2=二级部门,3=三级部门
managerId String? // 部门负责人ID(部门管理员)
manager User? @relation("DepartmentManager", fields: [managerId], references: [id])
status String @default("active") // active/disabled/archived(部门状态)
description String? // 部门描述
sortOrder Int @default(0) // 排序字段
updatedAt DateTime @updatedAt
// 关联用户(阶段二新增)
users User[] @relation("UserDepartment")
// 转岗用户关联(新增)
transferredUsers User[] @relation("UserTransferDepartment")
@@index([parentId])
@@index([status])
@@index([level])
@@index([managerId])
@@map("departments")
}
model Danmaku {
id String @id @default(uuid())
content String
username String
userId String
createdAt DateTime @default(now())
@@index([createdAt])
@@map("danmakus")
}
model DepartmentMaterialPermission {
id String @id @default(uuid())
department String // 部门名称(保留,向后兼容)
materialType String // 素材类型
canView Boolean @default(false) // 是否可见(默认不允许)
canDownload Boolean @default(false) // 是否可下载(默认不允许)
canShare Boolean @default(true) // 是否可分享(默认允许)
canDownloadSource Boolean @default(false) @map("can_download_source") // 是否可下载源文件(PSD)
linkedToDepartment String? // 关联到的部门(如果有关联,则从关联部门读取权限)
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
@@unique([department, materialType])
@@index([department])
@@index([materialType])
@@index([linkedToDepartment])
@@map("department_material_permissions")
}
enum Role {
USER // 普通用户
ADMIN // 管理员(保留,向后兼容,建议迁移到SYSTEM_ADMIN)
DEPT_ADMIN // 部门管理员(阶段四新增)
SYSTEM_ADMIN // 系统管理员(阶段四新增)
}
// 素材移交历史记录表(新增)
model MaterialTransfer {
id String @id @default(uuid())
materialId String // 素材ID
fromUserId String // 移交前所有者ID
toUserId String // 移交后所有者ID
transferredBy String // 移交操作人ID
transferNote String? // 移交备注说明
transferredAt DateTime @default(now()) // 移交时间
material Material @relation(fields: [materialId], references: [id], onDelete: Cascade)
fromUser User @relation("MaterialTransferFromUser", fields: [fromUserId], references: [id])
toUser User @relation("MaterialTransferToUser", fields: [toUserId], references: [id])
operator User @relation("MaterialTransferOperator", fields: [transferredBy], references: [id])
@@index([materialId])
@@index([fromUserId])
@@index([toUserId])
@@index([transferredAt])
@@map("material_transfers")
}
// 产品全案资产表(新增)
model MaterialAsset {
id String @id @default(uuid())
materialId String @map("material_id")
assetType String @map("asset_type") // main/sku/detail/psd/preview/zip(产品全案:main主图/sku/detail详情页/psd;3D原图:preview预览图/sku/zip压缩包)
fileUrl String @map("file_url") // S3 URL 或本地路径
fileName String? @map("file_name") // 原始文件名
fileSize BigInt @default(0) @map("file_size")
sortOrder Int @default(0) @map("sort_order")
createdAt DateTime @default(now()) @map("created_at")
updatedAt DateTime @updatedAt @map("updated_at")
material Material @relation(fields: [materialId], references: [id], onDelete: Cascade)
@@index([materialId])
@@index([assetType])
@@index([sortOrder])
@@map("material_assets")
}
// API 密钥表(新增)
model ApiKey {
id String @id @default(uuid())
name String // 密钥名称(如:任务系统)
key String @unique // 密钥值(32位随机字符串)
isActive Boolean @default(true) @map("is_active") // 是否启用
createdBy String @map("created_by") // 创建人ID
lastUsedAt DateTime? @map("last_used_at") // 最后使用时间
createdAt DateTime @default(now()) @map("created_at")
updatedAt DateTime @updatedAt @map("updated_at")
callLogs ApiCallLog[]
@@index([key])
@@index([isActive])
@@map("api_keys")
}
// API 调用日志表(新增)
model ApiCallLog {
id String @id @default(uuid())
apiKeyId String @map("api_key_id")
endpoint String // 调用的接口路径
method String // HTTP 方法
taskNo String? @map("task_no") // 任务号(如有)
statusCode Int @map("status_code") // 响应状态码
duration Int // 耗时(毫秒)
ipAddress String? @map("ip_address") // 调用方IP
userAgent String? @map("user_agent") // User-Agent
createdAt DateTime @default(now()) @map("created_at")
apiKey ApiKey @relation(fields: [apiKeyId], references: [id], onDelete: Cascade)
@@index([apiKeyId])
@@index([taskNo])
@@index([createdAt])
@@map("api_call_logs")
}