'use client'; import {zodResolver} from '@hookform/resolvers/zod'; import {useMutation, useQueryClient} from '@tanstack/react-query'; import {useEffect} from 'react'; import {useForm} from 'react-hook-form'; import {AppModal} from '@/components/ui/app-modal'; import {createPagesProject, updatePagesProject,} from '@/features/pages/api/pages'; import type {PagesProject} from '@/features/pages/types'; import { PrimaryButton, ResourceField, ResourceInput, SecondaryButton, ToggleField, } from '@/features/shared/components/resource-primitives'; import {projectQueryKey, projectsQueryKey} from '../utils'; import {type PagesProjectFormValues, pagesProjectSchema} from '../schemas'; interface PagesProjectEditorModalProps { isOpen: boolean; onClose: () => void; project?: PagesProject | null; onSaved?: (project: PagesProject, mode: 'create' | 'update') => void; } function toFormValues(project?: PagesProject | null): PagesProjectFormValues { if (!project) { return { name: '', slug: '', description: '', spa_fallback_enabled: false, spa_fallback_path: '/index.html', api_proxy_enabled: false, api_proxy_path: '', api_proxy_pass: '', api_proxy_rewrite: '', root_dir: '', entry_file: 'index.html', }; } return { name: project.name, slug: project.slug, description: project.description || '', spa_fallback_enabled: project.spa_fallback_enabled, spa_fallback_path: project.spa_fallback_path, api_proxy_enabled: project.api_proxy_enabled || false, api_proxy_path: project.api_proxy_path || '', api_proxy_pass: project.api_proxy_pass || '', api_proxy_rewrite: project.api_proxy_rewrite || '', root_dir: project.root_dir || '', entry_file: project.entry_file || 'index.html', }; } export function PagesProjectEditorModal({ isOpen, onClose, project, onSaved, }: PagesProjectEditorModalProps) { const queryClient = useQueryClient(); const form = useForm({ resolver: zodResolver(pagesProjectSchema), defaultValues: toFormValues(project), }); useEffect(() => { if (isOpen) { form.reset(toFormValues(project)); } }, [form, project, isOpen]); const mutation = useMutation({ mutationFn: (values: PagesProjectFormValues) => { const payload = { name: values.name.trim(), slug: values.slug?.trim() || '', description: values.description?.trim() || '', enabled: project ? project.enabled : true, spa_fallback_enabled: values.spa_fallback_enabled, spa_fallback_path: values.spa_fallback_enabled ? values.spa_fallback_path.trim() : project ? project.spa_fallback_path : '/index.html', api_proxy_enabled: values.api_proxy_enabled, api_proxy_path: values.api_proxy_enabled ? values.api_proxy_path.trim() : '', api_proxy_pass: values.api_proxy_enabled ? values.api_proxy_pass.trim() : '', api_proxy_rewrite: values.api_proxy_enabled ? values.api_proxy_rewrite.trim() : '', root_dir: values.root_dir?.trim() || '', entry_file: values.entry_file?.trim() || 'index.html', }; return project ? updatePagesProject(project.id, payload) : createPagesProject(payload); }, onSuccess: (savedProject) => { onClose(); if (project) { queryClient.invalidateQueries({ queryKey: projectQueryKey(project.id), }); } queryClient.invalidateQueries({ queryKey: projectsQueryKey }); onSaved?.(savedProject, project ? 'update' : 'create'); }, }); const handleSubmit = form.handleSubmit((values) => { mutation.mutate(values); }); const spaFallbackEnabled = form.watch('spa_fallback_enabled'); const apiProxyEnabled = form.watch('api_proxy_enabled'); return ( 取消 {mutation.isPending ? '保存中...' : project ? '保存修改' : '创建项目'} } >
form.setValue('spa_fallback_enabled', checked, { shouldValidate: true, }) } /> form.setValue('api_proxy_enabled', checked, { shouldValidate: true, }) } /> {apiProxyEnabled && ( <> )} {mutation.isError ? (

{mutation.error instanceof Error ? mutation.error.message : '操作失败,请稍后重试。'}

) : null}
); }