feat: 实现 Agent Park AI 项目导航网站核心功能
完成 Next.js 14+ 全栈应用的 MVP 实现,包含以下功能: ## 项目设置 - 初始化 Next.js 14+ 项目,配置 TypeScript 严格模式 - 配置 Tailwind CSS、ESLint、Prettier 代码质量工具 - 集成 shadcn/ui 组件库和 next-intl 国际化方案 ## 数据层 - 配置 PostgreSQL + Prisma ORM - 定义 Project、Tag、ExternalLink 数据模型 - 实现种子数据脚本(5个AI项目) ## 用户故事 1:浏览和搜索 AI 项目 - 实现首页,展示热门标签云和精选项目 - 实现项目列表页,支持搜索和标签筛选 - 创建 TagCloud、ProjectCard、ProjectList、SearchBar 组件 - 实现 ISR 缓存策略优化性能 ## 用户故事 2:查看项目详细信息 - 实现项目详情页,显示完整信息 - 创建 ExternalLinkCard 组件展示外部链接 - 实现安全的 target="_blank" 外链跳转 ## 用户故事 4:数据更新和管理 - 实现 webhook API 端点接收 n8n 数据推送 - 实现 API Key 身份验证 - 支持部分成功模式的批量数据处理 - 完善的错误处理和日志记录 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,77 @@
|
||||
import { z } from 'zod'
|
||||
|
||||
// ================================
|
||||
// Enums
|
||||
// ================================
|
||||
|
||||
export const ProjectStatusEnum = z.enum(['ACTIVE', 'ARCHIVED'])
|
||||
export const LinkTypeEnum = z.enum(['WEBSITE', 'GITHUB', 'HUGGINGFACE', 'PAPER'])
|
||||
|
||||
// ================================
|
||||
// Base Schemas
|
||||
// ================================
|
||||
|
||||
export const ExternalLinkSchema = z.object({
|
||||
type: LinkTypeEnum,
|
||||
url: z.string().url('Invalid URL format'),
|
||||
title: z.string().max(200).optional()
|
||||
})
|
||||
|
||||
export const TagSchema = z.object({
|
||||
name: z.string().min(1).max(50),
|
||||
nameEn: z.string().max(50).optional()
|
||||
})
|
||||
|
||||
// ================================
|
||||
// Project Schemas
|
||||
// ================================
|
||||
|
||||
export const ProjectBaseSchema = z.object({
|
||||
name: z.string().min(1).max(200),
|
||||
nameEn: z.string().max(200).optional(),
|
||||
description: z.string().min(10).max(500),
|
||||
descriptionEn: z.string().max(500).optional(),
|
||||
content: z.string().max(10000).optional(),
|
||||
contentEn: z.string().max(10000).optional(),
|
||||
status: ProjectStatusEnum.default('ACTIVE'),
|
||||
source: z.string().max(100).optional()
|
||||
})
|
||||
|
||||
export const ProjectInputSchema = ProjectBaseSchema.extend({
|
||||
tags: z.array(TagSchema).min(1, 'At least one tag is required').max(10),
|
||||
links: z.array(ExternalLinkSchema).min(1, 'At least one link is required').max(10)
|
||||
})
|
||||
|
||||
// ================================
|
||||
// Webhook Schemas
|
||||
// ================================
|
||||
|
||||
export const WebhookAuthSchema = z.object({
|
||||
apiKey: z.string().min(32, 'Invalid API key format')
|
||||
})
|
||||
|
||||
export const WebhookPayloadSchema = WebhookAuthSchema.extend({
|
||||
projects: z.array(ProjectInputSchema).min(1).max(100)
|
||||
})
|
||||
|
||||
// ================================
|
||||
// Query Schemas
|
||||
// ================================
|
||||
|
||||
export const ProjectQuerySchema = z.object({
|
||||
search: z.string().max(100).optional(),
|
||||
tags: z.array(z.string()).optional(),
|
||||
status: ProjectStatusEnum.optional(),
|
||||
page: z.coerce.number().int().positive().default(1),
|
||||
limit: z.coerce.number().int().positive().max(100).default(20)
|
||||
})
|
||||
|
||||
// ================================
|
||||
// Types
|
||||
// ================================
|
||||
|
||||
export type ExternalLink = z.infer<typeof ExternalLinkSchema>
|
||||
export type Tag = z.infer<typeof TagSchema>
|
||||
export type ProjectInput = z.infer<typeof ProjectInputSchema>
|
||||
export type WebhookPayload = z.infer<typeof WebhookPayloadSchema>
|
||||
export type ProjectQuery = z.infer<typeof ProjectQuerySchema>
|
||||
Reference in New Issue
Block a user