import { NextRequest, NextResponse } from 'next/server'; import { writeFile, mkdir } from 'fs/promises'; import { ProjectService, ProjectFileService, CriteriaItemService } from '@/lib/services/database'; import { getUploadAbsolutePath, getUploadRelativePath, getUploadDirPath, generateUniqueFileName, isValidFileType, isValidFileSize } from '@/lib/utils/file-path'; export async function POST(request: NextRequest) { try { const formData = await request.formData(); const projectTitle = formData.get('projectTitle') as string; const projectDescription = formData.get('projectDescription') as string; const file = formData.get('file') as File; console.log('🚀 開始處理檔案上傳...'); console.log('📝 專案標題:', projectTitle); console.log('📋 專案描述:', projectDescription); console.log('📁 上傳文件:', file ? file.name : '無'); // 驗證必填欄位 if (!projectTitle?.trim()) { return NextResponse.json( { success: false, error: '請填寫專案標題' }, { status: 400 } ); } if (!file) { return NextResponse.json( { success: false, error: '請上傳文件' }, { status: 400 } ); } // 驗證檔案類型 if (!isValidFileType(file.type)) { return NextResponse.json( { success: false, error: '不支援的檔案類型' }, { status: 400 } ); } // 驗證檔案大小(100MB) if (!isValidFileSize(file.size, 100)) { return NextResponse.json( { success: false, error: '檔案大小超過 100MB 限制' }, { status: 400 } ); } // 獲取預設評分標準模板 const templates = await CriteriaItemService.getAllTemplates(); if (!templates || templates.length === 0) { return NextResponse.json( { success: false, error: '未找到評分標準,請先設定評分標準' }, { status: 400 } ); } const templateId = templates[0].id; console.log('📊 使用評分標準模板 ID:', templateId); // 創建專案記錄 const projectData = { user_id: 1, // 暫時使用固定用戶 ID template_id: templateId, title: projectTitle, description: projectDescription || null, status: 'uploading' as const, // 初始狀態為上傳中 analysis_started_at: null, analysis_completed_at: null }; console.log('💾 創建專案記錄...'); const projectResult = await ProjectService.create(projectData); const projectId = (projectResult as any).insertId; console.log('✅ 專案記錄創建成功,ID:', projectId); // 準備檔案儲存 const uploadDir = getUploadDirPath(projectId); await mkdir(uploadDir, { recursive: true }); // 生成唯一檔案名稱 const uniqueFileName = generateUniqueFileName(file.name); const filePath = getUploadAbsolutePath(projectId, uniqueFileName); const relativeFilePath = getUploadRelativePath(projectId, uniqueFileName); // 儲存檔案 console.log('💾 儲存檔案到:', filePath); console.log('📁 相對路徑:', relativeFilePath); const bytes = await file.arrayBuffer(); await writeFile(filePath, Buffer.from(bytes)); // 創建檔案記錄 const fileExtension = file.name.split('.').pop(); const fileData = { project_id: projectId, original_name: file.name, file_name: uniqueFileName, file_path: relativeFilePath, // 使用相對路徑 file_size: file.size, file_type: fileExtension || '', mime_type: file.type, upload_status: 'completed' as const, upload_progress: 100 }; console.log('💾 創建檔案記錄...'); await ProjectFileService.create(fileData); console.log('✅ 檔案記錄創建成功'); // 更新專案狀態為 completed(檔案上傳完成) console.log('🔄 更新專案狀態為 completed...'); await ProjectService.update(projectId, { status: 'completed' }); console.log('✅ 專案狀態更新完成'); return NextResponse.json({ success: true, data: { projectId, fileName: file.name, fileSize: file.size, fileType: file.type }, message: '檔案上傳成功' }); } catch (error) { console.error('❌ 檔案上傳失敗:', error); return NextResponse.json( { success: false, error: '檔案上傳失敗,請稍後再試' }, { status: 500 } ); } }