feat: add AIEvent model to database schema
This commit is contained in:
+166
-207
@@ -1,6 +1,3 @@
|
||||
// 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"
|
||||
previewFeatures = ["postgresqlExtensions"]
|
||||
@@ -11,13 +8,153 @@ datasource db {
|
||||
url = env("DATABASE_URL")
|
||||
}
|
||||
|
||||
// ================================
|
||||
// Enums
|
||||
// ================================
|
||||
model external_links {
|
||||
id String @id
|
||||
type LinkType
|
||||
url String
|
||||
title String?
|
||||
projectId String
|
||||
projects projects @relation(fields: [projectId], references: [id], onDelete: Cascade)
|
||||
|
||||
enum ProjectStatus {
|
||||
ACTIVE
|
||||
ARCHIVED
|
||||
@@unique([projectId, url])
|
||||
@@index([projectId], map: "idx_link_projectId")
|
||||
@@index([type], map: "idx_link_type")
|
||||
@@index([type, url], map: "idx_link_type_url")
|
||||
@@index([url], map: "idx_link_url")
|
||||
}
|
||||
|
||||
model keyword_cloud_error_logs {
|
||||
id Int @id @default(autoincrement())
|
||||
quarter String
|
||||
keyword String?
|
||||
errorType String
|
||||
errorMessage String
|
||||
rawData Json?
|
||||
createdAt DateTime @default(now())
|
||||
|
||||
@@index([errorType], map: "idx_keywordCloudErrorLog_errorType")
|
||||
@@index([quarter], map: "idx_keywordCloudErrorLog_quarter")
|
||||
}
|
||||
|
||||
model keywords {
|
||||
id Int @id @default(autoincrement())
|
||||
word String
|
||||
trendScore Int
|
||||
quarterId Int
|
||||
description String
|
||||
descriptionEn String?
|
||||
detailPoints Json
|
||||
detailPointsEn Json?
|
||||
visualConfig Json
|
||||
createdAt DateTime @default(now())
|
||||
updatedAt DateTime
|
||||
quarters quarters @relation(fields: [quarterId], references: [id], onDelete: Cascade)
|
||||
|
||||
@@index([quarterId], map: "idx_keyword_quarterId")
|
||||
@@index([trendScore], map: "idx_keyword_trendScore")
|
||||
@@index([word], map: "idx_keyword_word")
|
||||
}
|
||||
|
||||
model project_discovery_tasks {
|
||||
id String @id
|
||||
status TaskStatus @default(PENDING)
|
||||
sourceUrl String
|
||||
sourceType String @default("manual")
|
||||
explorationData Json?
|
||||
explorationSummary String?
|
||||
errorMessage String?
|
||||
retryCount Int @default(0)
|
||||
lastRetryAt DateTime?
|
||||
projectId String?
|
||||
createdAt DateTime @default(now())
|
||||
startedAt DateTime?
|
||||
completedAt DateTime?
|
||||
updatedAt DateTime
|
||||
projects projects? @relation(fields: [projectId], references: [id])
|
||||
|
||||
@@index([projectId], map: "idx_task_project_id")
|
||||
@@index([sourceUrl], map: "idx_task_source_url")
|
||||
@@index([status, createdAt], map: "idx_task_status_created")
|
||||
}
|
||||
|
||||
model project_tags {
|
||||
projectId String
|
||||
tagId String
|
||||
projects projects @relation(fields: [projectId], references: [id], onDelete: Cascade)
|
||||
tags tags @relation(fields: [tagId], references: [id], onDelete: Cascade)
|
||||
|
||||
@@id([projectId, tagId])
|
||||
@@index([tagId])
|
||||
}
|
||||
|
||||
model projects {
|
||||
id String @id
|
||||
name String
|
||||
nameEn String?
|
||||
slug String @unique
|
||||
description String
|
||||
descriptionEn String?
|
||||
content String?
|
||||
contentEn String?
|
||||
status ProjectStatus @default(ACTIVE)
|
||||
source String?
|
||||
createdAt DateTime @default(now())
|
||||
updatedAt DateTime
|
||||
embedding Unsupported("vector")?
|
||||
embeddingUpdatedAt DateTime?
|
||||
external_links external_links[]
|
||||
project_discovery_tasks project_discovery_tasks[]
|
||||
project_tags project_tags[]
|
||||
|
||||
@@index([embedding], map: "idx_project_embedding_cosine")
|
||||
@@index([slug], map: "idx_project_slug")
|
||||
@@index([status, createdAt], map: "idx_project_status_createdAt")
|
||||
}
|
||||
|
||||
model quarters {
|
||||
id Int @id @default(autoincrement())
|
||||
quarter String @unique
|
||||
title String
|
||||
titleEn String?
|
||||
subtitle String?
|
||||
subtitleEn String?
|
||||
displayOrder Int @default(0)
|
||||
isActive Boolean @default(true)
|
||||
createdAt DateTime @default(now())
|
||||
updatedAt DateTime
|
||||
keywords keywords[]
|
||||
|
||||
@@index([displayOrder], map: "idx_quarter_displayOrder")
|
||||
@@index([quarter], map: "idx_quarter_quarter")
|
||||
}
|
||||
|
||||
model tags {
|
||||
id String @id
|
||||
name String @unique
|
||||
nameEn String?
|
||||
slug String @unique
|
||||
createdAt DateTime @default(now())
|
||||
project_tags project_tags[]
|
||||
|
||||
@@index([slug], map: "idx_tag_slug")
|
||||
}
|
||||
|
||||
model visual_style_rules {
|
||||
id Int @id @default(autoincrement())
|
||||
name String @unique
|
||||
minScore Int
|
||||
maxScore Int
|
||||
color String
|
||||
size String
|
||||
border String
|
||||
rotation String?
|
||||
priority Int @default(0)
|
||||
enabled Boolean @default(true)
|
||||
createdAt DateTime @default(now())
|
||||
updatedAt DateTime
|
||||
|
||||
@@index([enabled], map: "idx_visualStyleRule_enabled")
|
||||
@@index([minScore, maxScore], map: "idx_visualStyleRule_scoreRange")
|
||||
}
|
||||
|
||||
enum LinkType {
|
||||
@@ -27,6 +164,11 @@ enum LinkType {
|
||||
PAPER
|
||||
}
|
||||
|
||||
enum ProjectStatus {
|
||||
ACTIVE
|
||||
ARCHIVED
|
||||
}
|
||||
|
||||
enum TaskStatus {
|
||||
PENDING
|
||||
IN_PROGRESS
|
||||
@@ -35,206 +177,23 @@ enum TaskStatus {
|
||||
}
|
||||
|
||||
// ================================
|
||||
// Models
|
||||
// AI Timeline System Models
|
||||
// ================================
|
||||
|
||||
model Project {
|
||||
id String @id @default(cuid())
|
||||
name String
|
||||
nameEn String?
|
||||
slug String @unique
|
||||
description String
|
||||
descriptionEn String?
|
||||
content String? @db.Text
|
||||
contentEn String? @db.Text
|
||||
status ProjectStatus @default(ACTIVE)
|
||||
source String?
|
||||
createdAt DateTime @default(now())
|
||||
updatedAt DateTime @updatedAt
|
||||
model AIEvent {
|
||||
id String @id @default(cuid())
|
||||
title String
|
||||
titleEn String?
|
||||
eventDate DateTime
|
||||
description String
|
||||
descriptionEn String?
|
||||
imageUrl String
|
||||
sourceUrl String?
|
||||
|
||||
// Relations
|
||||
tags ProjectTag[]
|
||||
links ExternalLink[]
|
||||
discoveryTasks ProjectDiscoveryTask[]
|
||||
createdAt DateTime @default(now())
|
||||
updatedAt DateTime @updatedAt
|
||||
|
||||
// Indexes
|
||||
@@index([status, createdAt], map: "idx_project_status_createdAt")
|
||||
@@index([slug], map: "idx_project_slug")
|
||||
@@map("projects")
|
||||
}
|
||||
|
||||
model Tag {
|
||||
id String @id @default(cuid())
|
||||
name String @unique
|
||||
nameEn String?
|
||||
slug String @unique
|
||||
createdAt DateTime @default(now())
|
||||
|
||||
// Relations
|
||||
projects ProjectTag[]
|
||||
|
||||
// Indexes
|
||||
@@index([slug], map: "idx_tag_slug")
|
||||
@@map("tags")
|
||||
}
|
||||
|
||||
model ExternalLink {
|
||||
id String @id @default(cuid())
|
||||
type LinkType
|
||||
url String
|
||||
title String?
|
||||
projectId String
|
||||
|
||||
// Relations
|
||||
project Project @relation(fields: [projectId], references: [id], onDelete: Cascade)
|
||||
|
||||
// Indexes
|
||||
@@index([projectId], map: "idx_link_projectId")
|
||||
@@index([type], map: "idx_link_type")
|
||||
@@index([url], map: "idx_link_url")
|
||||
@@index([type, url], map: "idx_link_type_url")
|
||||
@@unique([projectId, url])
|
||||
@@map("external_links")
|
||||
}
|
||||
|
||||
// Project-Tag many-to-many relationship table
|
||||
model ProjectTag {
|
||||
projectId String
|
||||
tagId String
|
||||
|
||||
project Project @relation(fields: [projectId], references: [id], onDelete: Cascade)
|
||||
tag Tag @relation(fields: [tagId], references: [id], onDelete: Cascade)
|
||||
|
||||
@@id([projectId, tagId])
|
||||
@@index([tagId])
|
||||
@@map("project_tags")
|
||||
}
|
||||
|
||||
// Project Discovery Task model
|
||||
model ProjectDiscoveryTask {
|
||||
id String @id @default(cuid())
|
||||
status TaskStatus @default(PENDING)
|
||||
|
||||
// 原始数据(仅URL)
|
||||
sourceUrl String
|
||||
sourceType String @default("manual")
|
||||
|
||||
// 探索结果
|
||||
explorationData Json?
|
||||
explorationSummary String? @db.Text
|
||||
|
||||
// 错误处理
|
||||
errorMessage String? @db.Text
|
||||
retryCount Int @default(0)
|
||||
lastRetryAt DateTime?
|
||||
|
||||
// 关联
|
||||
projectId String?
|
||||
project Project? @relation(fields: [projectId], references: [id])
|
||||
|
||||
// 时间戳
|
||||
createdAt DateTime @default(now())
|
||||
startedAt DateTime?
|
||||
completedAt DateTime?
|
||||
updatedAt DateTime @updatedAt
|
||||
|
||||
// 索引
|
||||
@@index([status, createdAt], map: "idx_task_status_created")
|
||||
@@index([sourceUrl], map: "idx_task_source_url")
|
||||
@@index([projectId], map: "idx_task_project_id")
|
||||
@@map("project_discovery_tasks")
|
||||
}
|
||||
|
||||
// ================================
|
||||
// Keyword Cloud System Models
|
||||
// ================================
|
||||
|
||||
// 季度元数据表
|
||||
model Quarter {
|
||||
id Int @id @default(autoincrement())
|
||||
quarter String @unique // "2023-Q1", "2023-Q2"
|
||||
title String @db.Text // "2023年第一季度"
|
||||
titleEn String? @db.Text // "Q1 2023"
|
||||
subtitle String? @db.Text // "聊天界面的黎明"
|
||||
subtitleEn String? @db.Text // "The dawn of chat interface"
|
||||
displayOrder Int @default(0) // 前端排序
|
||||
isActive Boolean @default(true) // 是否显示
|
||||
keywords Keyword[]
|
||||
createdAt DateTime @default(now())
|
||||
updatedAt DateTime @updatedAt
|
||||
|
||||
@@index([quarter], map: "idx_quarter_quarter")
|
||||
@@index([displayOrder], map: "idx_quarter_displayOrder")
|
||||
@@map("quarters")
|
||||
}
|
||||
|
||||
// 关键词核心数据表
|
||||
model Keyword {
|
||||
id Int @id @default(autoincrement())
|
||||
word String // "ChatGPT"
|
||||
trendScore Int // 0-100, 从 Google Trends 获取
|
||||
|
||||
// 外键关联
|
||||
quarterId Int
|
||||
quarter Quarter @relation(fields: [quarterId], references: [id], onDelete: Cascade)
|
||||
|
||||
// 内容字段(支持中英双语)
|
||||
description String @db.Text // AI 生成的一句话描述
|
||||
descriptionEn String? @db.Text // 英文描述
|
||||
detailPoints Json // JSON 数组: ["要点1", "要点2", "要点3"]
|
||||
detailPointsEn Json? // 英文版要点
|
||||
|
||||
// 视觉样式配置
|
||||
visualConfig Json // {color, size, rotation, border}
|
||||
|
||||
// 元数据
|
||||
createdAt DateTime @default(now())
|
||||
updatedAt DateTime @updatedAt
|
||||
|
||||
@@index([quarterId], map: "idx_keyword_quarterId")
|
||||
@@index([trendScore], map: "idx_keyword_trendScore")
|
||||
@@index([word], map: "idx_keyword_word")
|
||||
@@map("keywords")
|
||||
}
|
||||
|
||||
// 视觉样式规则配置表
|
||||
model VisualStyleRule {
|
||||
id Int @id @default(autoincrement())
|
||||
name String @unique // "热门大词-金色"
|
||||
|
||||
// 分数区间
|
||||
minScore Int // 90
|
||||
maxScore Int // 100
|
||||
|
||||
// 视觉属性
|
||||
color String // "primary", "secondary", "accent"
|
||||
size String // "text-5xl", "text-3xl", "text-xl"
|
||||
border String // "border-4", "border-2"
|
||||
rotation String? // "rotate-1", "rotate-2", null
|
||||
|
||||
// 控制
|
||||
priority Int @default(0) // 优先级,分数重叠时按优先级
|
||||
enabled Boolean @default(true) // 是否启用
|
||||
|
||||
createdAt DateTime @default(now())
|
||||
updatedAt DateTime @updatedAt
|
||||
|
||||
@@index([enabled], map: "idx_visualStyleRule_enabled")
|
||||
@@index([minScore, maxScore], map: "idx_visualStyleRule_scoreRange")
|
||||
@@map("visual_style_rules")
|
||||
}
|
||||
|
||||
// 错误日志表
|
||||
model KeywordCloudErrorLog {
|
||||
id Int @id @default(autoincrement())
|
||||
quarter String // "2023-Q1"
|
||||
keyword String? // "ChatGPT"
|
||||
errorType String // "INVALID_DATA", "API_ERROR", "DB_ERROR"
|
||||
errorMessage String @db.Text // 详细错误信息
|
||||
rawData Json? // 原始数据便于调试
|
||||
createdAt DateTime @default(now())
|
||||
|
||||
@@index([quarter], map: "idx_keywordCloudErrorLog_quarter")
|
||||
@@index([errorType], map: "idx_keywordCloudErrorLog_errorType")
|
||||
@@map("keyword_cloud_error_logs")
|
||||
@@index([eventDate(sort: Desc)])
|
||||
@@index([createdAt])
|
||||
@@map("ai_events")
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user