feat(api-db): add ai notification and admin models

This commit is contained in:
2026-04-04 13:04:21 +08:00
parent 96cbb8ab30
commit 011fa1f301
2 changed files with 185 additions and 25 deletions
+1 -2
View File
@@ -1,5 +1,4 @@
// This file was generated by Prisma, and assumes you have installed the following: // Prisma CLI 配置(TodoList
// npm install --save-dev prisma dotenv
import "dotenv/config"; import "dotenv/config";
import { defineConfig } from "prisma/config"; import { defineConfig } from "prisma/config";
+184 -23
View File
@@ -43,16 +43,34 @@ enum AttachmentType {
LINK LINK
} }
enum AiChannel {
USER_KEY
ASTRBOT
PUBLIC_POOL
}
enum NotificationChannel {
EMAIL
WEB_PUSH
}
enum NotificationStatus {
PENDING
SENT
FAILED
CANCELED
}
model User { model User {
id String @id @default(cuid()) id String @id @default(cuid())
email String @unique email String @unique
nickname String? nickname String?
avatarUrl String? avatarUrl String?
status UserStatus @default(ACTIVE) status UserStatus @default(ACTIVE)
defaultStorageQuotaMb Int @default(100) defaultStorageQuotaMb Int @default(100)
usedStorageBytes BigInt @default(0) usedStorageBytes BigInt @default(0)
createdAt DateTime @default(now()) createdAt DateTime @default(now())
updatedAt DateTime @updatedAt updatedAt DateTime @updatedAt
identities AuthIdentity[] identities AuthIdentity[]
refreshTokens RefreshToken[] refreshTokens RefreshToken[]
security UserSecurity? security UserSecurity?
@@ -63,6 +81,12 @@ model User {
syncOperations SyncOperation[] syncOperations SyncOperation[]
syncCursors SyncCursor[] syncCursors SyncCursor[]
taskTombstones TaskTombstone[] taskTombstones TaskTombstone[]
aiProviderBindings AiProviderBinding[]
aiUsageLogs AiUsageLog[]
notificationRules NotificationRule[]
notificationJobs NotificationJob[]
createdAdminTokens AdminToken[]
auditLogs AuditLog[]
@@map("users") @@map("users")
} }
@@ -110,22 +134,24 @@ model RefreshToken {
} }
model Task { model Task {
id String @id @default(cuid()) id String @id @default(cuid())
userId String userId String
title String title String
contentJson Json? contentJson Json?
contentText String? contentText String?
priority TaskPriority @default(MEDIUM) priority TaskPriority @default(MEDIUM)
status TaskStatus @default(TODO) status TaskStatus @default(TODO)
ddl DateTime? ddl DateTime?
completedAt DateTime? completedAt DateTime?
version Int @default(1) version Int @default(1)
createdAt DateTime @default(now()) createdAt DateTime @default(now())
updatedAt DateTime @updatedAt updatedAt DateTime @updatedAt
user User @relation(fields: [userId], references: [id], onDelete: Cascade) user User @relation(fields: [userId], references: [id], onDelete: Cascade)
taskTags TaskTag[] taskTags TaskTag[]
attachments Attachment[] attachments Attachment[]
activityLogs TaskActivityLog[] activityLogs TaskActivityLog[]
notificationJobs NotificationJob[]
notificationRules NotificationRule[]
@@index([userId, status]) @@index([userId, status])
@@index([userId, ddl]) @@index([userId, ddl])
@@ -240,3 +266,138 @@ model TaskTombstone {
@@index([userId, deletedAt]) @@index([userId, deletedAt])
@@map("task_tombstones") @@map("task_tombstones")
} }
model AiProviderBinding {
id String @id @default(cuid())
userId String
channel AiChannel
providerName String
model String?
encryptedApiKey String?
endpoint String?
isDefault Boolean @default(false)
isEnabled Boolean @default(true)
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
@@index([userId, isEnabled])
@@map("ai_provider_bindings")
}
model AiPublicPoolConfig {
id String @id @default(cuid())
enabled Boolean @default(false)
providerName String?
model String?
encryptedApiKey String?
endpoint String?
rpmLimit Int @default(60)
dailyTokenLimit Int @default(0)
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
@@map("ai_public_pool_config")
}
model AiUsageLog {
id String @id @default(cuid())
userId String?
channel AiChannel
providerName String?
model String?
promptTokens Int @default(0)
completionTokens Int @default(0)
totalTokens Int @default(0)
latencyMs Int?
success Boolean @default(true)
errorCode String?
createdAt DateTime @default(now())
user User? @relation(fields: [userId], references: [id], onDelete: SetNull)
@@index([userId, createdAt])
@@index([channel, createdAt])
@@map("ai_usage_logs")
}
model NotificationRule {
id String @id @default(cuid())
userId String
taskId String?
channel NotificationChannel @default(EMAIL)
advanceMinutes Int @default(60)
enabled Boolean @default(true)
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
task Task? @relation(fields: [taskId], references: [id], onDelete: SetNull)
jobs NotificationJob[]
@@index([userId, enabled])
@@index([taskId])
@@map("notification_rules")
}
model NotificationJob {
id String @id @default(cuid())
userId String
taskId String?
ruleId String?
channel NotificationChannel
scheduledAt DateTime
sentAt DateTime?
status NotificationStatus @default(PENDING)
retryCount Int @default(0)
errorMessage String?
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
task Task? @relation(fields: [taskId], references: [id], onDelete: SetNull)
rule NotificationRule? @relation(fields: [ruleId], references: [id], onDelete: SetNull)
@@index([status, scheduledAt])
@@index([userId, createdAt])
@@map("notification_jobs")
}
model SystemSetting {
id String @id @default(cuid())
key String @unique
value Json
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
@@map("system_settings")
}
model AdminToken {
id String @id @default(cuid())
tokenHash String @unique
name String
expiresAt DateTime
lastUsedAt DateTime?
revokedAt DateTime?
createdAt DateTime @default(now())
createdByUserId String?
createdByUser User? @relation(fields: [createdByUserId], references: [id], onDelete: SetNull)
@@index([expiresAt])
@@map("admin_tokens")
}
model AuditLog {
id String @id @default(cuid())
actorUserId String?
action String
targetType String
targetId String?
meta Json?
ip String?
userAgent String?
createdAt DateTime @default(now())
actorUser User? @relation(fields: [actorUserId], references: [id], onDelete: SetNull)
@@index([action, createdAt])
@@index([actorUserId, createdAt])
@@map("audit_logs")
}