Files
ftb-project-management/docs/superpowers/specs/2026-06-16-project-delete-design.md
Script Generator cad190d83b feat: 项目模块加删除按钮(仅超管 + 无版本可删)
- useProductStore 加 deleteProject(productId, projectId) action
- ProjectRow 行右侧加三点菜单(MoreHorizontal)+ 下拉项「删除项目」
- 项目下有版本时菜单项 disabled + tooltip「项目下还有 N 个版本,不可删除」
- 仅有 project:delete 权限的角色(默认仅超管)能看到三点 icon
- 点击删除 → confirm → 调 deleteProject

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-06-17 11:11:19 +08:00

103 lines
3.4 KiB
Markdown
Raw Permalink 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.

# 项目删除功能设计
## Context
项目模块当前没有删除入口。本期补齐"删除项目"功能,并对应权限点。
## 决策摘要
| 项 | 决策 |
|---|---|
| 删除条件 | 项目下**有任何版本**均不可删(最严格,避免误删带数据的项目) |
| 按钮位置 | 项目行右侧三点菜单hover 显示),菜单项"删除项目" |
| 不可删提示 | 菜单项 disabled + tooltip "项目下还有 N 个版本,不可删除" |
| 权限点 | `project:delete`(已存在于 `lib/permissions.ts` |
| 默认能删的角色 | 仅超管 `role-admin`PM/dev/test/design 都不含此权限) |
| 二次确认 | 浏览器原生 `confirm('确认删除项目「{name}」?')` |
| 卡片整体可点 | 保留——三点 icon `e.stopPropagation()` 避免冒泡 |
## 实施清单
**(1) `apps/web/stores/useProductStore.ts`** — 加 `deleteProject` action
```ts
deleteProject: (productId: string, projectId: string) => void;
// 实现:找到产品,从 projects 数组移除目标项目,写回 localStorage
deleteProject: (productId, projectId) => {
const overview = get().overview.map((p) =>
p.id === productId
? { ...p, projects: p.projects.filter((proj) => proj.id !== projectId) }
: p
);
set({ overview });
saveLocal(overview);
},
```
**(2) `apps/web/app/projects/page.tsx`** — `ProjectRow` 加三点菜单
```tsx
const canDelete = useHasPermission('project:delete');
const versionCount = proj.versions.length;
const canActuallyDelete = canDelete && versionCount === 0;
// 行右侧
{canDelete && (
<DropdownMenu>
<MenuItem
disabled={!canActuallyDelete}
title={versionCount > 0 ? `项目下还有 ${versionCount} 个版本,不可删除` : ''}
onClick={() => handleDelete(proj)}
danger
>
删除项目
</MenuItem>
</DropdownMenu>
)}
```
下拉菜单沿用 versions/page.tsx 已有的 dropdown 写法(`MoreHorizontal` icon + 绝对定位 + `fixed inset-0` overlay 关闭)。
**handleDelete**
```tsx
const handleDelete = (proj: ProjectWithContext) => {
if (!confirm(`确认删除项目「${proj.name}」?此操作不可恢复。`)) return;
deleteProject(proj.productId, proj.id);
};
```
**(3) 权限默认值不动**
- `lib/permissions.ts` 第 33 行 `std4('project')` 已包含 `project:delete`
- `DEFAULT_ROLE_PERMISSIONS`:超管 `['*']` 自动通过PM 默认不含此权限(与"仅超管能删"一致)
- 无需修改
## 数据流
```
ProjectRow
├─ useHasPermission('project:delete') ─→ 决定三点菜单是否显示
└─ proj.versions.length ─→ 决定菜单项是否可点
└─ disabled + tooltip
点击「删除」 ─→ confirm ─→ useProductStore.deleteProject()
└─ 列表自动重渲zustand 响应式)
```
## 验证
1. `pnpm type-check` 0 错误
2. `pnpm build` 14+1 个页面成功
3. 登录陈十(超管 `13200132008/Ftb@2024`
- hover 项目行右侧出现三点 icon
- 点开菜单看到"删除项目"
- 项目下有版本:菜单项灰色 + 鼠标悬停 tooltip "项目下还有 N 个版本,不可删除"
- 项目下无版本:菜单项可点 → confirm → 项目消失
4. 登录李四(开发 `13900139002/Ftb@2024`):项目行右侧无三点 icon`project:delete` 权限)
5. 登录张三PM `13800138001/Ftb@2024`):同上,无三点 icon