refactor: 清理IndexedDB相关代码,统一使用后端ZIP存储
- 移除前端废弃的loadZipFile/saveZipFile函数 - ProjectDetail使用scanStoredZipFile替代loadZipFile - RecycleBin移除手动删除ZIP文件逻辑 - 后端permanently_delete_project自动清理ZIP文件
This commit is contained in:
parent
f640bfbaba
commit
c54212a8c9
|
|
@ -294,6 +294,14 @@ async def permanently_delete_project(
|
||||||
if project.owner_id != current_user.id:
|
if project.owner_id != current_user.id:
|
||||||
raise HTTPException(status_code=403, detail="无权永久删除此项目")
|
raise HTTPException(status_code=403, detail="无权永久删除此项目")
|
||||||
|
|
||||||
|
# 如果是ZIP类型项目,删除关联的ZIP文件和元数据
|
||||||
|
if project.source_type == "zip":
|
||||||
|
try:
|
||||||
|
await delete_project_zip(id)
|
||||||
|
print(f"[Project] 已删除项目 {id} 的ZIP文件")
|
||||||
|
except Exception as e:
|
||||||
|
print(f"[Warning] 删除ZIP文件失败: {e}")
|
||||||
|
|
||||||
await db.delete(project)
|
await db.delete(project)
|
||||||
await db.commit()
|
await db.commit()
|
||||||
return {"message": "项目已永久删除"}
|
return {"message": "项目已永久删除"}
|
||||||
|
|
|
||||||
|
|
@ -25,9 +25,9 @@ import {
|
||||||
GitBranch
|
GitBranch
|
||||||
} from "lucide-react";
|
} from "lucide-react";
|
||||||
import { api } from "@/shared/config/database";
|
import { api } from "@/shared/config/database";
|
||||||
import { runRepositoryAudit, scanZipFile } from "@/features/projects/services";
|
import { runRepositoryAudit, scanStoredZipFile } from "@/features/projects/services";
|
||||||
import type { Project, AuditTask, CreateProjectForm } from "@/shared/types";
|
import type { Project, AuditTask, CreateProjectForm } from "@/shared/types";
|
||||||
import { loadZipFile } from "@/shared/utils/zipStorage";
|
import { hasZipFile } from "@/shared/utils/zipStorage";
|
||||||
import { isRepositoryProject, getSourceTypeLabel } from "@/shared/utils/projectUtils";
|
import { isRepositoryProject, getSourceTypeLabel } from "@/shared/utils/projectUtils";
|
||||||
import { toast } from "sonner";
|
import { toast } from "sonner";
|
||||||
import CreateTaskDialog from "@/components/audit/CreateTaskDialog";
|
import CreateTaskDialog from "@/components/audit/CreateTaskDialog";
|
||||||
|
|
@ -173,18 +173,17 @@ export default function ProjectDetail() {
|
||||||
setScanning(false);
|
setScanning(false);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// 没有仓库地址,尝试从IndexedDB加载保存的ZIP文件
|
// 没有仓库地址,尝试使用后端存储的ZIP文件
|
||||||
try {
|
try {
|
||||||
setScanning(true);
|
setScanning(true);
|
||||||
const file = await loadZipFile(id);
|
const hasFile = await hasZipFile(id);
|
||||||
|
|
||||||
if (file) {
|
if (hasFile) {
|
||||||
console.log('找到保存的ZIP文件,开始启动审计...');
|
console.log('找到后端存储的ZIP文件,开始启动审计...');
|
||||||
try {
|
try {
|
||||||
// 启动ZIP文件审计
|
// 使用后端存储的ZIP文件启动审计
|
||||||
const taskId = await scanZipFile({
|
const taskId = await scanStoredZipFile({
|
||||||
projectId: id,
|
projectId: id,
|
||||||
zipFile: file,
|
|
||||||
excludePatterns: ['node_modules/**', '.git/**', 'dist/**', 'build/**'],
|
excludePatterns: ['node_modules/**', '.git/**', 'dist/**', 'build/**'],
|
||||||
createdBy: 'local-user'
|
createdBy: 'local-user'
|
||||||
});
|
});
|
||||||
|
|
@ -206,7 +205,6 @@ export default function ProjectDetail() {
|
||||||
} else {
|
} else {
|
||||||
setScanning(false);
|
setScanning(false);
|
||||||
toast.warning('此项目未配置仓库地址,也未上传ZIP文件。请先在项目设置中配置仓库地址,或通过"新建任务"上传ZIP文件。');
|
toast.warning('此项目未配置仓库地址,也未上传ZIP文件。请先在项目设置中配置仓库地址,或通过"新建任务"上传ZIP文件。');
|
||||||
// 不自动打开对话框,让用户自己选择
|
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('启动审计失败:', error);
|
console.error('启动审计失败:', error);
|
||||||
|
|
|
||||||
|
|
@ -18,7 +18,6 @@ import {
|
||||||
import { api } from "@/shared/config/database";
|
import { api } from "@/shared/config/database";
|
||||||
import type { Project } from "@/shared/types";
|
import type { Project } from "@/shared/types";
|
||||||
import { toast } from "sonner";
|
import { toast } from "sonner";
|
||||||
import { deleteZipFile } from "@/shared/utils/zipStorage";
|
|
||||||
import { isRepositoryProject, getSourceTypeBadge } from "@/shared/utils/projectUtils";
|
import { isRepositoryProject, getSourceTypeBadge } from "@/shared/utils/projectUtils";
|
||||||
|
|
||||||
export default function RecycleBin() {
|
export default function RecycleBin() {
|
||||||
|
|
@ -75,16 +74,9 @@ export default function RecycleBin() {
|
||||||
if (!selectedProject) return;
|
if (!selectedProject) return;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
// 删除项目数据
|
// 删除项目数据(后端会同时删除关联的ZIP文件)
|
||||||
await api.permanentlyDeleteProject(selectedProject.id);
|
await api.permanentlyDeleteProject(selectedProject.id);
|
||||||
|
|
||||||
// 删除保存的ZIP文件(如果有)
|
|
||||||
try {
|
|
||||||
await deleteZipFile(selectedProject.id);
|
|
||||||
} catch (error) {
|
|
||||||
console.error('删除ZIP文件失败:', error);
|
|
||||||
}
|
|
||||||
|
|
||||||
toast.success(`项目 "${selectedProject.name}" 已永久删除`);
|
toast.success(`项目 "${selectedProject.name}" 已永久删除`);
|
||||||
setShowPermanentDeleteDialog(false);
|
setShowPermanentDeleteDialog(false);
|
||||||
setSelectedProject(null);
|
setSelectedProject(null);
|
||||||
|
|
|
||||||
|
|
@ -91,29 +91,4 @@ export function formatFileSize(bytes: number): string {
|
||||||
return `${bytes} B`;
|
return `${bytes} B`;
|
||||||
}
|
}
|
||||||
|
|
||||||
// ============ 兼容旧API(已废弃,保留以避免编译错误) ============
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @deprecated 使用 uploadZipFile 代替
|
|
||||||
*/
|
|
||||||
export async function saveZipFile(projectId: string, file: File): Promise<void> {
|
|
||||||
const result = await uploadZipFile(projectId, file);
|
|
||||||
if (!result.success) {
|
|
||||||
throw new Error(result.message || '保存ZIP文件失败');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @deprecated 使用 getZipFileInfo 代替
|
|
||||||
*/
|
|
||||||
export async function loadZipFile(projectId: string): Promise<File | null> {
|
|
||||||
// 后端不再返回文件内容,只返回元数据
|
|
||||||
// 如果需要文件,应该在创建任务时直接使用后端存储的文件
|
|
||||||
const info = await getZipFileInfo(projectId);
|
|
||||||
if (info.has_file && info.original_filename) {
|
|
||||||
// 返回一个虚拟的File对象,仅包含元数据
|
|
||||||
const blob = new Blob([], { type: 'application/zip' });
|
|
||||||
return new File([blob], info.original_filename, { type: 'application/zip' });
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue