Files
agent-park/prisma/schema.prisma
T
mzaxdandClaude e3e72006b0 feat: 新增项目发现任务系统并修复代码审查发现的高优先级问题
新增功能:
- 新增 ProjectDiscoveryTask 数据模型,支持异步项目探索任务管理
- 新增 /api/discovery/tasks CRUD API,支持任务创建、查询和状态更新
- 新增 /api/discovery/tasks/:id/complete API,完成探索并自动创建项目
- 新增 discovery-service 服务层,封装多级去重和标签处理逻辑
- 新增 discover-projects 命令,支持批量探索项目
- 新增 PROJECT_CONTENT_STANDARD.md 内容标准模板

代码质量修复:
- 修复状态转换验证未使用问题,防止非法状态转换
- 修复 explorationData 类型安全问题,使用 z.record(z.unknown()) 替代 z.any()
- 添加事务保护到 complete API,确保项目创建和任务状态更新的原子性

代码重构:
- 将 webhook/projects 的去重逻辑迁移到 discovery-service
- 统一探索任务相关的验证模式到 validations.ts

Co-Authored-By: Claude <noreply@anthropic.com>
2026-01-17 15:44:33 +08:00

147 lines
3.4 KiB
Plaintext
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
// 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"]
}
datasource db {
provider = "postgresql"
url = env("DATABASE_URL")
}
// ================================
// Enums
// ================================
enum ProjectStatus {
ACTIVE
ARCHIVED
}
enum LinkType {
WEBSITE
GITHUB
HUGGINGFACE
PAPER
}
enum TaskStatus {
PENDING
IN_PROGRESS
COMPLETED
FAILED
}
// ================================
// 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
// Relations
tags ProjectTag[]
links ExternalLink[]
discoveryTasks ProjectDiscoveryTask[]
// 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")
}