包含: - furniture-3d-system:Next.js 16 全栈应用(资产中心、产品管理、3D装配动画) - autocad-plugin:AutoCAD 家具导出插件源码 - 资产中心改造:编辑弹窗化、删除功能、Toast反馈、自定义Select组件 Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
6.9 KiB
资产中心编辑弹窗化 + 删除功能 + Toast 反馈 实施计划
For Claude: REQUIRED SUB-SKILL: Use superpowers:executing-plans to implement this plan task-by-task.
Goal: 将资产族编辑从内联改为弹窗、在编辑弹窗中加入删除功能、将反馈提示从 inline 横幅改为 Toast。
Architecture: 前端全栈改造——后端补 DELETE API(repository → service → route),前端补 delete API 调用、将内联编辑改为 Modal 弹窗、复用 DeleteConfirmDialog 处理删除确认、用 useToast 替换 feedback 状态。
Tech Stack: Next.js 16 (API Routes) + Prisma 7 + React 19 + useToast + DeleteConfirmDialog + Modal
改动范围概览
| 层级 | 文件 | 改动 |
|---|---|---|
| Repository | src/server/repositories/asset-family.repository.ts |
加 delete 方法 |
| Repository | src/server/repositories/asset-variant.repository.ts |
加 delete 方法 |
| Service | src/server/services/asset-center.service.ts |
加 deleteFamily、deleteVariant |
| API Route | src/app/api/asset-center/families/[id]/route.ts |
加 DELETE handler |
| API Route | src/app/api/asset-center/variants/[id]/route.ts |
加 DELETE handler |
| 前端 API | src/lib/open-product/platform-api.ts |
加 deleteAssetFamily、deleteAssetVariant |
| 前端页面 | src/app/asset-center/AssetCenterClient.tsx |
主要改动:弹窗化 + 删除 + Toast |
Task 1: 后端 — Repository 层添加 delete 方法
Files:
- Modify:
src/server/repositories/asset-family.repository.ts - Modify:
src/server/repositories/asset-variant.repository.ts
Step 1: 在 asset-family.repository.ts 添加 deleteById 方法
在 repository class 中添加:
async deleteById(id: string): Promise<void> {
await this.prisma.assetFamily.delete({ where: { id } })
}
Step 2: 在 asset-variant.repository.ts 添加 deleteById 方法
同样添加:
async deleteById(id: string): Promise<void> {
await this.prisma.assetVariant.delete({ where: { id } })
}
说明: AssetVariant 已有 onDelete: Cascade 关联 AssetFamily,删除族会自动级联删除其所有规格款。
Task 2: 后端 — Service 层添加 delete 方法
Files:
- Modify:
src/server/services/asset-center.service.ts
Step 1: 在 AssetCenterService 添加 deleteFamily 方法
async deleteFamily(id: string): Promise<void> {
const existing = await assetFamilyRepository.findById(id)
if (!existing) {
throw new AppError(ErrorCode.ASSET_FAMILY_NOT_FOUND, '资产族不存在')
}
// Prisma 级联:删除族会自动删除其下所有规格款
await assetFamilyRepository.deleteById(id)
}
Step 2: 在 AssetCenterService 添加 deleteVariant 方法
async deleteVariant(id: string): Promise<void> {
const existing = await assetVariantRepository.findById(id)
if (!existing) {
throw new AppError(ErrorCode.ASSET_VARIANT_NOT_FOUND, '规格款不存在')
}
await assetVariantRepository.deleteById(id)
}
Task 3: 后端 — API Route 层添加 DELETE handler
Files:
- Modify:
src/app/api/asset-center/families/[id]/route.ts - Modify:
src/app/api/asset-center/variants/[id]/route.ts
Step 1: 在 families/[id]/route.ts 添加 DELETE handler
export async function DELETE(
request: NextRequest,
context: { params: Promise<{ id: string }> },
) {
return handleRequest(
request,
async (ctx) => {
const { id } = await context.params
try {
await assetCenterService.deleteFamily(id)
return jsonSuccess({ success: true }, 200, ctx.requestId)
} catch (error) {
if (error instanceof AppError) {
return jsonError(error.code, error.message, error.statusCode, ctx.requestId)
}
throw error
}
},
{ requireAuth: true },
)
}
Step 2: 在 variants/[id]/route.ts 添加 DELETE handler
同上模式,调用 assetCenterService.deleteVariant(id)。
Task 4: 前端 — platform-api.ts 添加删除调用
Files:
- Modify:
src/lib/open-product/platform-api.ts
Step 1: 添加 deleteAssetFamily 和 deleteAssetVariant
export async function deleteAssetFamily(id: string): Promise<void> {
await requestPlatform<{ success: boolean }>(`/api/asset-center/families/${id}`, {
method: 'DELETE',
})
}
export async function deleteAssetVariant(id: string): Promise<void> {
await requestPlatform<{ success: boolean }>(`/api/asset-center/variants/${id}`, {
method: 'DELETE',
})
}
Task 5: 前端 — AssetCenterClient.tsx 核心改造
Files:
- Modify:
src/app/asset-center/AssetCenterClient.tsx
这是最大的改动任务,包含三个子目标:
5a. 反馈系统:feedback 状态 → useToast
- 删除
feedbackstate 和showSuccess/showError函数 - 导入
useToast,改用toast.success()/toast.error() - 删除
PlatformSplitLayout的feedbackprop - 在组件底部添加
<ToastContainer toasts={toast.toasts} onClose={toast.removeToast} />
5b. 资产族编辑:内联 → 弹窗
- 删除
editingFamilyId、editFamilyForm、startEditFamily、cancelEditFamily相关代码 - 新增
familyModalOpen、familyModalMode(create/edit)、familyForm、editingFamilyId状态 - 点击编辑铅笔图标时打开 Modal 弹窗(而非展开内联表单)
- 弹窗底部放"取消"和"保存"按钮
- 删除按钮放在弹窗 footer 左侧(仅编辑模式显示),点击触发 DeleteConfirmDialog
- 新建资产族也改为弹窗(保持一致体验)
5c. 规格款弹窗添加删除按钮
- 在现有规格款编辑弹窗的 footer 左侧添加删除按钮(仅编辑模式)
- 点击后弹出 DeleteConfirmDialog,确认后调用
deleteAssetVariant - 删除成功后从列表移除、关闭弹窗、Toast 提示
5d. 新增状态管理
新增状态:
// 资产族弹窗
const [familyModalOpen, setFamilyModalOpen] = useState(false)
const [familyModalMode, setFamilyModalMode] = useState<'create' | 'edit'>('create')
const [familyForm, setFamilyForm] = useState({
type: 'BOARD' as AssetFamilyDTO['type'],
code: '', name: '', description: '', roles: '', available: false,
})
const [editingFamilyId, setEditingFamilyId] = useState<string | null>(null)
// 删除确认弹窗
const [deleteTarget, setDeleteTarget] = useState<{
type: 'family' | 'variant'
id: string
name: string
cascadeCount?: number
} | null>(null)
Task 6: 类型检查 + 浏览器验证
Step 1: 运行 npx tsc --noEmit 确认无类型错误
Step 2: 浏览器验证:
- 点击编辑资产族 → 弹窗打开 → 编辑保存 → Toast 提示
- 弹窗内点击删除 → DeleteConfirmDialog 弹出 → 确认删除 → Toast 提示 + 列表更新
- 规格款编辑弹窗 → 点击删除 → 确认 → Toast + 列表更新
- 新建资产族弹窗 → 创建 → Toast 提示