主要修复: - 修复批量上传闭包陷阱,防止文件丢失 - 添加 fileName 参数传递原始文件名,保留正确扩展名 - 添加取消检查回调,改进批量上传取消功能 其他改进: - 优化搜索功能和管理后台 - 添加 FRP 故障诊断文档 - 更新环境验证和网络检测
421 lines
15 KiB
Plaintext
421 lines
15 KiB
Plaintext
generator client {
|
|
provider = "prisma-client-js"
|
|
previewFeatures = []
|
|
binaryTargets = ["native", "linux-musl-openssl-3.0.x"]
|
|
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
|
|
role Role @default(USER)
|
|
isActive Boolean @default(false)
|
|
canDownload Boolean @default(true)
|
|
createdAt DateTime @default(now())
|
|
updatedAt DateTime @updatedAt
|
|
department String @default("")
|
|
dingtalkUserId String?
|
|
loginType String @default("normal")
|
|
realName String?
|
|
phone String?
|
|
avatar String?
|
|
managedDepartment String?
|
|
isSuperAdmin Boolean @default(false)
|
|
departmentId String?
|
|
employmentStatus String? @default("active")
|
|
resignationDate DateTime?
|
|
transferDate DateTime?
|
|
transferToDeptId String?
|
|
employmentNote String?
|
|
statusChangedBy String?
|
|
statusChangedAt DateTime?
|
|
status String @default("pending")
|
|
lastLoginAt DateTime?
|
|
lastLoginIp String?
|
|
loginCount Int @default(0)
|
|
archivedAt DateTime?
|
|
managedDepartments Department[] @relation("DepartmentManager")
|
|
downloadLogs MaterialDownloadLog[]
|
|
favorites MaterialFavorite[]
|
|
likes MaterialLike[]
|
|
materialLogs MaterialLog[]
|
|
materialTransfersFrom MaterialTransfer[] @relation("MaterialTransferFromUser")
|
|
materialTransfersTo MaterialTransfer[] @relation("MaterialTransferToUser")
|
|
materialTransfersAsOperator MaterialTransfer[] @relation("MaterialTransferOperator")
|
|
materials Material[]
|
|
departmentRef Department? @relation("UserDepartment", fields: [departmentId], references: [id])
|
|
transferToDept Department? @relation("UserTransferDepartment", fields: [transferToDeptId], references: [id])
|
|
|
|
@@index([status])
|
|
@@index([archivedAt])
|
|
@@index([departmentId])
|
|
@@index([employmentStatus])
|
|
@@index([transferToDeptId])
|
|
@@map("users")
|
|
}
|
|
|
|
model Material {
|
|
id String @id @default(uuid())
|
|
previewUrl String
|
|
productModel String
|
|
categoryName String
|
|
sceneName String
|
|
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)
|
|
createdAt DateTime @default(now())
|
|
updatedAt DateTime @updatedAt
|
|
userId String
|
|
displayImages String[] @default([])
|
|
platformName String @default("")
|
|
uploadId String?
|
|
videoSourceUrl String?
|
|
videoPreview540Url String?
|
|
videoPreviewClipUrl String?
|
|
videoCoverUrl String?
|
|
videoDuration Int?
|
|
videoProcessingStatus String?
|
|
transcodeLastError String? @map("transcodelasterror")
|
|
transcodeAttempts Int? @map("transcodeattempts")
|
|
deletedAt DateTime?
|
|
productCategoryName String @default("")
|
|
originalOwnerId String?
|
|
transferredAt DateTime?
|
|
transferredBy String?
|
|
transferNote String?
|
|
taskNo String? @map("task_no")
|
|
taskStatus String? @map("task_status")
|
|
taskFetchedAt DateTime? @map("task_fetched_at")
|
|
assets MaterialAsset[]
|
|
downloadLogs MaterialDownloadLog[]
|
|
favorites MaterialFavorite[]
|
|
likes MaterialLike[]
|
|
logs MaterialLog[]
|
|
skus MaterialSku[]
|
|
transfers MaterialTransfer[]
|
|
transcodeProgresses VideoTranscodeProgress[] @relation("MaterialTranscodeProgress")
|
|
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
|
|
|
|
@@index([userId])
|
|
@@index([createdAt])
|
|
@@index([categoryName])
|
|
@@index([sceneName])
|
|
@@index([platformName])
|
|
@@index([productCategoryName])
|
|
@@index([materialType])
|
|
@@index([downloadCount])
|
|
@@index([likeCount])
|
|
@@index([deletedAt])
|
|
@@index([originalOwnerId])
|
|
@@index([transferredAt])
|
|
@@index([taskNo])
|
|
@@index([taskStatus])
|
|
@@index([productModel])
|
|
@@index([authorName])
|
|
@@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
|
|
changes String?
|
|
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")
|
|
}
|
|
|
|
model MaterialSku {
|
|
id String @id @default(uuid())
|
|
materialId String @map("material_id")
|
|
skuName String @map("sku_name")
|
|
filePath String @map("file_path")
|
|
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")
|
|
fileName String? @map("file_name")
|
|
previewUrl String? @map("preview_url")
|
|
deletedAt DateTime? @map("deleted_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")
|
|
siteName String @default("由壹点3D素材")
|
|
updatedAt DateTime @updatedAt
|
|
createdAt DateTime @default(now())
|
|
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")
|
|
s3AccessKey String @default("")
|
|
s3Bucket String @default("")
|
|
s3Endpoint String @default("")
|
|
s3PublicUrl String @default("")
|
|
s3Region String @default("us-east-1")
|
|
s3SecretKey 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")
|
|
|
|
@@map("system_settings")
|
|
}
|
|
|
|
model Department {
|
|
id String @id @default(uuid())
|
|
name String @unique
|
|
createdAt DateTime @default(now())
|
|
parentId String?
|
|
level Int @default(1)
|
|
status String @default("active")
|
|
managerId String?
|
|
code String? @unique
|
|
description String?
|
|
sortOrder Int @default(0)
|
|
updatedAt DateTime @updatedAt
|
|
manager User? @relation("DepartmentManager", fields: [managerId], references: [id])
|
|
parent Department? @relation("DepartmentHierarchy", fields: [parentId], references: [id])
|
|
children Department[] @relation("DepartmentHierarchy")
|
|
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)
|
|
linkedToDepartment String?
|
|
createdAt DateTime @default(now())
|
|
updatedAt DateTime @updatedAt
|
|
canDownloadSource Boolean @default(false) @map("can_download_source")
|
|
|
|
@@unique([department, materialType])
|
|
@@index([department])
|
|
@@index([materialType])
|
|
@@index([linkedToDepartment])
|
|
@@map("department_material_permissions")
|
|
}
|
|
|
|
model MaterialTransfer {
|
|
id String @id @default(uuid())
|
|
materialId String
|
|
fromUserId String
|
|
toUserId String
|
|
transferredBy String
|
|
transferNote String?
|
|
transferredAt DateTime @default(now())
|
|
fromUser User @relation("MaterialTransferFromUser", fields: [fromUserId], references: [id])
|
|
material Material @relation(fields: [materialId], references: [id], onDelete: Cascade)
|
|
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")
|
|
fileUrl String @map("file_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")
|
|
}
|
|
|
|
model ApiKey {
|
|
id String @id @default(uuid())
|
|
name String
|
|
key String @unique
|
|
isActive Boolean @default(true) @map("is_active")
|
|
createdBy String @map("created_by")
|
|
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")
|
|
}
|
|
|
|
model ApiCallLog {
|
|
id String @id @default(uuid())
|
|
apiKeyId String @map("api_key_id")
|
|
endpoint String
|
|
method String
|
|
taskNo String? @map("task_no")
|
|
statusCode Int @map("status_code")
|
|
duration Int
|
|
ipAddress String? @map("ip_address")
|
|
userAgent String? @map("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")
|
|
}
|
|
|
|
model VideoTranscodeProgress {
|
|
id String @id @default(uuid())
|
|
materialId String @map("material_id")
|
|
stage String
|
|
progress Int @default(0)
|
|
status String @default("waiting") @map("status")
|
|
priority Int @default(0)
|
|
startedAt DateTime @default(now()) @map("started_at")
|
|
completedAt DateTime? @map("completed_at")
|
|
errorMessage String? @map("error_message")
|
|
retryCount Int @default(0) @map("retry_count")
|
|
lastHeartbeat DateTime? @map("last_heartbeat")
|
|
createdAt DateTime @default(now()) @map("created_at")
|
|
updatedAt DateTime @updatedAt @map("updated_at")
|
|
material Material @relation("MaterialTranscodeProgress", fields: [materialId], references: [id], onDelete: Cascade)
|
|
|
|
@@unique([materialId, stage])
|
|
@@index([status])
|
|
@@index([priority, status])
|
|
@@index([materialId])
|
|
@@index([lastHeartbeat])
|
|
@@map("video_transcode_progresses")
|
|
}
|
|
|
|
enum Role {
|
|
USER
|
|
ADMIN
|
|
DEPT_ADMIN
|
|
SYSTEM_ADMIN
|
|
}
|