generator client { provider = "prisma-client-js" } datasource db { provider = "mysql" } model Category { id Int @id @default(autoincrement()) name String @db.VarChar(50) slug String @unique @db.VarChar(50) icon String? @db.VarChar(100) parentId Int? @map("parent_id") sortOrder Int @default(0) @map("sort_order") createdAt DateTime @default(now()) @map("created_at") updatedAt DateTime @updatedAt @map("updated_at") tools Tool[] pendingTools PendingTool[] parent Category? @relation("CategoryToCategory", fields: [parentId], references: [id]) children Category[] @relation("CategoryToCategory") @@map("categories") } model SkillCategory { id Int @id @default(autoincrement()) name String @db.VarChar(50) slug String @unique @db.VarChar(50) icon String? @db.VarChar(100) parentId Int? @map("parent_id") sortOrder Int @default(0) @map("sort_order") createdAt DateTime @default(now()) @map("created_at") updatedAt DateTime @updatedAt @map("updated_at") skills Skill[] pendingSkills PendingSkill[] parent SkillCategory? @relation("SkillCategoryToSkillCategory", fields: [parentId], references: [id]) children SkillCategory[] @relation("SkillCategoryToSkillCategory") @@map("skill_categories") } model Tool { id Int @id @default(autoincrement()) name String @db.VarChar(100) slug String @unique @db.VarChar(100) categoryId Int @map("category_id") description String @db.Text logoUrl String? @map("logo_url") @db.VarChar(255) websiteUrl String @map("website_url") @db.VarChar(255) pricingModel PricingModel @default(freemium) @map("pricing_model") pricingDetail String? @map("pricing_detail") @db.VarChar(200) features Json? tags Json? viewCount Int @default(0) @map("view_count") status Status @default(draft) createdAt DateTime @default(now()) @map("created_at") updatedAt DateTime @updatedAt @map("updated_at") category Category @relation(fields: [categoryId], references: [id]) favorites Favorite[] browsingHistory BrowsingHistory[] reviews Review[] collectionItems CollectionItem[] @@index([categoryId, status]) @@fulltext([name, description]) @@map("tools") } model PendingTool { id Int @id @default(autoincrement()) name String @db.VarChar(100) slug String? @db.VarChar(100) categoryId Int? @map("category_id") description String? @db.Text logoUrl String? @map("logo_url") @db.VarChar(255) websiteUrl String? @map("website_url") @db.VarChar(255) pricingModel PricingModel? @default(freemium) @map("pricing_model") pricingDetail String? @map("pricing_detail") @db.VarChar(200) features Json? tags Json? sourceUrl String? @map("source_url") @db.VarChar(255) status PendingStatus @default(pending) createdAt DateTime @default(now()) @map("created_at") updatedAt DateTime @updatedAt @map("updated_at") category Category? @relation(fields: [categoryId], references: [id]) @@map("pending_tools") } model Skill { id Int @id @default(autoincrement()) name String @db.VarChar(100) slug String @unique @db.VarChar(100) categoryId Int @map("category_id") description String @db.Text logoUrl String? @map("logo_url") @db.VarChar(255) sourceUrl String @map("source_url") @db.VarChar(255) sourceType String @default("gitee") @map("source_type") @db.VarChar(20) rating Float @default(0) @db.Float features Json? tags Json? viewCount Int @default(0) @map("view_count") status Status @default(draft) createdAt DateTime @default(now()) @map("created_at") updatedAt DateTime @updatedAt @map("updated_at") category SkillCategory @relation(fields: [categoryId], references: [id]) favorites Favorite[] browsingHistory BrowsingHistory[] reviews Review[] collectionItems CollectionItem[] skillReview SkillReview? lastReviewedAt DateTime? @map("last_reviewed_at") githubStarsHistory Json? @map("github_stars_history") @@index([categoryId, status]) @@map("skills") } model PendingSkill { id Int @id @default(autoincrement()) name String @db.VarChar(100) slug String? @db.VarChar(100) categoryId Int? @map("category_id") description String? @db.Text logoUrl String? @map("logo_url") @db.VarChar(255) sourceUrl String? @map("source_url") @db.VarChar(255) sourceType String? @map("source_type") @db.VarChar(20) rating Float @default(0) @db.Float features Json? tags Json? status PendingStatus @default(pending) createdAt DateTime @default(now()) @map("created_at") updatedAt DateTime @updatedAt @map("updated_at") category SkillCategory? @relation(fields: [categoryId], references: [id]) @@map("pending_skills") } enum PricingModel { free freemium paid subscription } enum Status { draft published } enum PendingStatus { pending approved rejected } model SystemConfig { id Int @id @default(autoincrement()) key String @unique @db.VarChar(50) value Json @@map("system_configs") } model User { id Int @id @default(autoincrement()) email String @unique @db.VarChar(255) passwordHash String? @db.VarChar(255) name String? @db.VarChar(100) avatarUrl String? oauthProvider String? @db.VarChar(50) oauthId String? @unique @db.VarChar(255) role String @default("user") @db.VarChar(20) roleId Int? @map("role_id") createdAt DateTime @default(now()) @map("created_at") updatedAt DateTime @updatedAt @map("updated_at") assignedRole Role? @relation(fields: [roleId], references: [id]) favorites Favorite[] browsingHistory BrowsingHistory[] reviews Review[] collections Collection[] @@unique([oauthProvider, oauthId]) @@map("users") } model Role { id Int @id @default(autoincrement()) name String @db.VarChar(50) slug String @unique @db.VarChar(50) isSystem Boolean @default(false) @map("is_system") createdAt DateTime @default(now()) @map("created_at") updatedAt DateTime @updatedAt @map("updated_at") permissions RolePermission[] users User[] @@map("roles") } model Permission { id Int @id @default(autoincrement()) groupName String @map("group_name") @db.VarChar(50) name String @db.VarChar(50) key String @unique @db.VarChar(80) sortOrder Int @default(0) @map("sort_order") createdAt DateTime @default(now()) @map("created_at") rolePermissions RolePermission[] @@index([groupName, sortOrder]) @@map("permissions") } model RolePermission { roleId Int @map("role_id") permissionId Int @map("permission_id") role Role @relation(fields: [roleId], references: [id], onDelete: Cascade) permission Permission @relation(fields: [permissionId], references: [id], onDelete: Cascade) @@id([roleId, permissionId]) @@map("role_permissions") } model Favorite { id Int @id @default(autoincrement()) userId Int @map("user_id") toolId Int? @map("tool_id") skillId Int? @map("skill_id") createdAt DateTime @default(now()) @map("created_at") user User @relation(fields: [userId], references: [id], onDelete: Cascade) tool Tool? @relation(fields: [toolId], references: [id], onDelete: Cascade) skill Skill? @relation(fields: [skillId], references: [id], onDelete: Cascade) @@unique([userId, toolId]) @@unique([userId, skillId]) @@index([userId]) @@map("favorites") } model BrowsingHistory { id Int @id @default(autoincrement()) userId Int @map("user_id") toolId Int? @map("tool_id") skillId Int? @map("skill_id") viewedAt DateTime @default(now()) @updatedAt @map("viewed_at") user User @relation(fields: [userId], references: [id], onDelete: Cascade) tool Tool? @relation(fields: [toolId], references: [id], onDelete: Cascade) skill Skill? @relation(fields: [skillId], references: [id], onDelete: Cascade) @@unique([userId, toolId]) @@unique([userId, skillId]) @@index([userId, viewedAt]) @@map("browsing_histories") } model Review { id Int @id @default(autoincrement()) userId Int @map("user_id") toolId Int? @map("tool_id") skillId Int? @map("skill_id") rating Int? comment String @db.Text createdAt DateTime @default(now()) @map("created_at") user User @relation(fields: [userId], references: [id], onDelete: Cascade) tool Tool? @relation(fields: [toolId], references: [id], onDelete: Cascade) skill Skill? @relation(fields: [skillId], references: [id], onDelete: Cascade) @@unique([userId, toolId]) @@unique([userId, skillId]) @@index([toolId, createdAt]) @@index([skillId, createdAt]) @@map("reviews") } model Collection { id Int @id @default(autoincrement()) userId Int @map("user_id") name String @db.VarChar(50) description String? @db.Text sortOrder Int @default(0) @map("sort_order") createdAt DateTime @default(now()) @map("created_at") updatedAt DateTime @updatedAt @map("updated_at") user User @relation(fields: [userId], references: [id], onDelete: Cascade) items CollectionItem[] @@index([userId]) @@map("collections") } model CollectionItem { id Int @id @default(autoincrement()) collectionId Int @map("collection_id") toolId Int? @map("tool_id") skillId Int? @map("skill_id") addedAt DateTime @default(now()) @map("added_at") collection Collection @relation(fields: [collectionId], references: [id], onDelete: Cascade) tool Tool? @relation(fields: [toolId], references: [id], onDelete: Cascade) skill Skill? @relation(fields: [skillId], references: [id], onDelete: Cascade) @@unique([collectionId, toolId]) @@unique([collectionId, skillId]) @@index([collectionId]) @@map("collection_items") } model DailyReport { id Int @id @default(autoincrement()) date DateTime @unique @db.Date title String @db.VarChar(200) summary String? @db.Text hotCount Int @default(0) @map("hot_count") coverUrl String? @map("cover_url") @db.VarChar(255) status Status @default(draft) createdAt DateTime @default(now()) @map("created_at") updatedAt DateTime @updatedAt @map("updated_at") items DailyReportItem[] @@index([date]) @@index([status]) @@map("daily_reports") } model DailyReportItem { id Int @id @default(autoincrement()) reportId Int @map("report_id") sortOrder Int @default(0) @map("sort_order") category String @default("tech") @db.VarChar(20) title String @db.VarChar(200) summary String? @db.Text detail String? @db.Text sourceUrl String? @map("source_url") @db.VarChar(500) imageUrl String? @map("image_url") @db.VarChar(255) hotScore Int @default(0) @map("hot_score") createdAt DateTime @default(now()) @map("created_at") report DailyReport @relation(fields: [reportId], references: [id], onDelete: Cascade) @@index([reportId, sortOrder]) @@map("daily_report_items") } model SkillReview { id Int @id @default(autoincrement()) skillId Int @unique @map("skill_id") skill Skill @relation(fields: [skillId], references: [id]) capability Float devExp Float @map("dev_exp") costLicense Float @map("cost_license") community Float performance Float overall Float reviews Json longArticle String? @map("long_article") @db.Text videoScript String? @map("video_script") @db.Text socialCards Json? @map("social_cards") status ReviewStatus @default(DRAFT) reviewedAt DateTime @updatedAt @map("reviewed_at") createdAt DateTime @default(now()) @map("created_at") @@index([skillId]) @@index([overall]) @@map("skill_reviews") } model ReviewGenerationLog { id Int @id @default(autoincrement()) skillId Int @map("skill_id") status String @db.VarChar(20) prompt String @db.Text response String? @db.Text error String? @db.Text createdAt DateTime @default(now()) @map("created_at") @@index([skillId]) @@map("review_generation_logs") } enum ReviewStatus { DRAFT PUBLISHED REJECTED OUTDATED }