refactor: 去重器改用 API 并修复 tag 唯一性约束处理

- deduplicator: 从直接数据库查询改为调用 /api/webhook/check-duplicates API
- database-ingestor: 使用 JSON 文件传参避免 curl 编码问题
- webhook: 修复 tag name 唯一性约束冲突,更新时删除旧关联重建
- 添加 check-duplicates API 端点用于批量去重检测
- 适配 ProjectTag 显式关联表的数据查询逻辑
- ProjectCard: 修复 getProjectIcon 空值处理

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
2026-01-06 14:21:10 +08:00
co-authored by Claude
parent 7baf547bf3
commit 0b9573072f
7 changed files with 425 additions and 71 deletions
+28 -4
View File
@@ -40,7 +40,11 @@ export async function getProjects(options?: {
prisma.project.findMany({
where,
include: {
tags: true,
tags: {
include: {
tag: true,
},
},
links: true,
},
orderBy: {
@@ -52,8 +56,14 @@ export async function getProjects(options?: {
prisma.project.count({ where }),
])
// Transform tags to flatten the structure
const transformedProjects = projects.map((project) => ({
...project,
tags: project.tags.map((pt) => pt.tag),
}))
return {
projects,
projects: transformedProjects,
pagination: {
page,
limit,
@@ -64,13 +74,27 @@ export async function getProjects(options?: {
}
export async function getProjectBySlug(slug: string) {
return prisma.project.findUnique({
const project = await prisma.project.findUnique({
where: { slug },
include: {
tags: true,
tags: {
include: {
tag: true,
},
},
links: true,
},
})
if (!project) {
return null
}
// Transform tags to flatten the structure
return {
...project,
tags: project.tags.map((pt) => pt.tag),
}
}
export async function getAllTags() {