From 18e3ee18daec6a1fcdc93cfa3c5592baadf2e9c6 Mon Sep 17 00:00:00 2001 From: zyc <1439655764@qq.com> Date: Tue, 14 Apr 2026 13:46:31 +0800 Subject: [PATCH] =?UTF-8?q?fix:=20=E5=88=A0=E9=99=A4=E9=A1=B9=E7=9B=AE?= =?UTF-8?q?=E6=97=B6=E5=85=88=E6=B8=85=E7=90=86=E5=85=B3=E8=81=94=E6=95=B0?= =?UTF-8?q?=E6=8D=AE=EF=BC=8C=E9=81=BF=E5=85=8D=E5=A4=96=E9=94=AE=E7=BA=A6?= =?UTF-8?q?=E6=9D=9F=E6=8A=A5=E9=94=99?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 删除项目前清理 userProjectPermissions、projectRepos、OKR 数据 - 修复 admin 和普通路由两处删除逻辑 Co-Authored-By: Claude Opus 4.6 (1M context) --- backend/src/routes/admin.ts | 13 ++++++++++++- backend/src/routes/projects.ts | 13 +++++++++++++ 2 files changed, 25 insertions(+), 1 deletion(-) diff --git a/backend/src/routes/admin.ts b/backend/src/routes/admin.ts index c4e4fc6..c2e2037 100644 --- a/backend/src/routes/admin.ts +++ b/backend/src/routes/admin.ts @@ -5,7 +5,7 @@ import { eq, desc } from 'drizzle-orm'; import { v4 as uuid } from 'uuid'; import bcrypt from 'bcrypt'; import { db } from '../db/index'; -import { users, authorMappings, syncLogs, projects, projectRepos, gitCommits, gitPRs, userProjectPermissions } from '../db/schema'; +import { users, authorMappings, syncLogs, projects, projectRepos, gitCommits, gitPRs, userProjectPermissions, objectives, keyResults, krLogs } from '../db/schema'; import { requireRole } from '../middleware/role'; import { AppError } from '../middleware/error-handler'; @@ -178,6 +178,17 @@ adminRoutes.patch('/admin/projects/:id', zValidator('json', updateProjectSchema) adminRoutes.delete('/admin/projects/:id', async (c) => { const id = c.req.param('id'); + await db.delete(userProjectPermissions).where(eq(userProjectPermissions.projectId, id)); + await db.delete(projectRepos).where(eq(projectRepos.projectId, id)); + const objs = await db.select().from(objectives).where(eq(objectives.projectId, id)); + for (const obj of objs) { + const krs = await db.select().from(keyResults).where(eq(keyResults.objectiveId, obj.id)); + for (const kr of krs) { + await db.delete(krLogs).where(eq(krLogs.krId, kr.id)); + } + await db.delete(keyResults).where(eq(keyResults.objectiveId, obj.id)); + } + await db.delete(objectives).where(eq(objectives.projectId, id)); await db.delete(projects).where(eq(projects.id, id)); return c.json({ code: 0, data: null, message: 'success' }); }); diff --git a/backend/src/routes/projects.ts b/backend/src/routes/projects.ts index 4f456fb..6a164d7 100644 --- a/backend/src/routes/projects.ts +++ b/backend/src/routes/projects.ts @@ -76,6 +76,19 @@ projectRoutes.delete('/projects/:id', requireRole('admin'), async (c) => { const id = c.req.param('id'); + // 先清理关联数据(外键约束) + await db.delete(userProjectPermissions).where(eq(userProjectPermissions.projectId, id)); + await db.delete(projectRepos).where(eq(projectRepos.projectId, id)); + // 清理 OKR:KR logs → KR → Objectives + const objs = await db.select().from(objectives).where(eq(objectives.projectId, id)); + for (const obj of objs) { + const krs = await db.select().from(keyResults).where(eq(keyResults.objectiveId, obj.id)); + for (const kr of krs) { + await db.delete(krLogs).where(eq(krLogs.krId, kr.id)); + } + await db.delete(keyResults).where(eq(keyResults.objectiveId, obj.id)); + } + await db.delete(objectives).where(eq(objectives.projectId, id)); await db.delete(projects).where(eq(projects.id, id)); return c.json({ code: 0, data: null, message: 'success' }); }