'use client'; import { useMutation, useQueryClient } from '@tanstack/react-query'; import { useState } from 'react'; import { AppModal } from '@/components/ui/app-modal'; import { activatePagesDeployment, uploadPagesDeployment, } from '@/features/pages/api/pages'; import { PrimaryButton, ResourceField, ResourceInput, SecondaryButton, } from '@/features/shared/components/resource-primitives'; import { deploymentsQueryKey, projectQueryKey, projectsQueryKey, } from '../utils'; interface PagesDeploymentUploadModalProps { isOpen: boolean; onClose: () => void; projectId: number; } export function PagesDeploymentUploadModal({ isOpen, onClose, projectId, }: PagesDeploymentUploadModalProps) { const queryClient = useQueryClient(); const [file, setFile] = useState(null); const [rootDir, setRootDir] = useState(''); const [entryFile, setEntryFile] = useState('index.html'); const [uploadProgress, setUploadProgress] = useState(null); const [errorMessage, setErrorMessage] = useState(null); const resetForm = () => { setFile(null); setRootDir(''); setEntryFile('index.html'); setUploadProgress(null); setErrorMessage(null); }; const handleClose = () => { resetForm(); onClose(); }; const uploadMutation = useMutation({ mutationFn: async ({ shouldActivate }: { shouldActivate: boolean }) => { if (!file) { throw new Error('请选择 zip 文件'); } setUploadProgress(0); setErrorMessage(null); const deployment = await uploadPagesDeployment( projectId, file, rootDir, entryFile, (percent) => { setUploadProgress(percent); }, ); if (shouldActivate) { await activatePagesDeployment(projectId, deployment.id); } return deployment; }, onSuccess: () => { resetForm(); queryClient.invalidateQueries({ queryKey: deploymentsQueryKey(projectId), }); queryClient.invalidateQueries({ queryKey: projectQueryKey(projectId), }); queryClient.invalidateQueries({ queryKey: projectsQueryKey, }); onClose(); }, onError: (error) => { setUploadProgress(null); setErrorMessage(error instanceof Error ? error.message : '上传失败'); }, }); const handleUploadOnly = () => { uploadMutation.mutate({ shouldActivate: false }); }; const handleUploadAndDeploy = () => { uploadMutation.mutate({ shouldActivate: true }); }; return ( 取消 {uploadMutation.isPending && !uploadMutation.variables?.shouldActivate ? `上传中 (${uploadProgress ?? 0}%)...` : '上传'} {uploadMutation.isPending && uploadMutation.variables?.shouldActivate ? `上传并部署中 (${uploadProgress ?? 0}%)...` : '上传并部署'} } >
setFile(event.target.files?.[0] ?? null)} /> setRootDir(event.target.value)} placeholder="例如: build" /> setEntryFile(event.target.value)} /> {uploadProgress !== null && (
上传进度 {uploadProgress}%
)}
); }