diff --git a/apps/api/prisma.config.ts b/apps/api/prisma.config.ts index 8f3a0eb..d2c3b82 100644 --- a/apps/api/prisma.config.ts +++ b/apps/api/prisma.config.ts @@ -1,5 +1,4 @@ -// This file was generated by Prisma, and assumes you have installed the following: -// npm install --save-dev prisma dotenv +// Prisma CLI 配置(TodoList) import "dotenv/config"; import { defineConfig } from "prisma/config"; diff --git a/apps/api/prisma/schema.prisma b/apps/api/prisma/schema.prisma index 1c02f47..838df48 100644 --- a/apps/api/prisma/schema.prisma +++ b/apps/api/prisma/schema.prisma @@ -43,16 +43,34 @@ enum AttachmentType { LINK } +enum AiChannel { + USER_KEY + ASTRBOT + PUBLIC_POOL +} + +enum NotificationChannel { + EMAIL + WEB_PUSH +} + +enum NotificationStatus { + PENDING + SENT + FAILED + CANCELED +} + model User { - id String @id @default(cuid()) - email String @unique + id String @id @default(cuid()) + email String @unique nickname String? avatarUrl String? - status UserStatus @default(ACTIVE) - defaultStorageQuotaMb Int @default(100) - usedStorageBytes BigInt @default(0) - createdAt DateTime @default(now()) - updatedAt DateTime @updatedAt + status UserStatus @default(ACTIVE) + defaultStorageQuotaMb Int @default(100) + usedStorageBytes BigInt @default(0) + createdAt DateTime @default(now()) + updatedAt DateTime @updatedAt identities AuthIdentity[] refreshTokens RefreshToken[] security UserSecurity? @@ -63,6 +81,12 @@ model User { syncOperations SyncOperation[] syncCursors SyncCursor[] taskTombstones TaskTombstone[] + aiProviderBindings AiProviderBinding[] + aiUsageLogs AiUsageLog[] + notificationRules NotificationRule[] + notificationJobs NotificationJob[] + createdAdminTokens AdminToken[] + auditLogs AuditLog[] @@map("users") } @@ -110,22 +134,24 @@ model RefreshToken { } model Task { - id String @id @default(cuid()) - userId String - title String - contentJson Json? - contentText String? - priority TaskPriority @default(MEDIUM) - status TaskStatus @default(TODO) - ddl DateTime? - completedAt DateTime? - version Int @default(1) - createdAt DateTime @default(now()) - updatedAt DateTime @updatedAt - user User @relation(fields: [userId], references: [id], onDelete: Cascade) - taskTags TaskTag[] - attachments Attachment[] - activityLogs TaskActivityLog[] + id String @id @default(cuid()) + userId String + title String + contentJson Json? + contentText String? + priority TaskPriority @default(MEDIUM) + status TaskStatus @default(TODO) + ddl DateTime? + completedAt DateTime? + version Int @default(1) + createdAt DateTime @default(now()) + updatedAt DateTime @updatedAt + user User @relation(fields: [userId], references: [id], onDelete: Cascade) + taskTags TaskTag[] + attachments Attachment[] + activityLogs TaskActivityLog[] + notificationJobs NotificationJob[] + notificationRules NotificationRule[] @@index([userId, status]) @@index([userId, ddl]) @@ -240,3 +266,138 @@ model TaskTombstone { @@index([userId, deletedAt]) @@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") +}