import React, { useState, useEffect } from 'react'; import { invoke } from '@tauri-apps/api/core'; import { useProjectStore } from '../store/projectStore'; import { ProjectFormData, ProjectFormErrors } from '../types/project'; import { InteractiveInput } from './InteractiveInput'; import { InteractiveButton } from './InteractiveButton'; import { Folder, X } from 'lucide-react'; interface ProjectFormProps { initialData?: Partial; onSubmit: (data: ProjectFormData) => Promise; onCancel: () => void; isEdit?: boolean; } /** * 项目表单组件 * 遵循 Tauri 开发规范的表单设计模式 */ export const ProjectForm: React.FC = ({ initialData, onSubmit, onCancel, isEdit = false }) => { const { isLoading, validateProjectPath, getDefaultProjectName } = useProjectStore(); const [formData, setFormData] = useState({ name: initialData?.name || '', path: initialData?.path || '', description: initialData?.description || '' }); const [errors, setErrors] = useState({}); const [isValidatingPath, setIsValidatingPath] = useState(false); // 验证表单 const validateForm = (): boolean => { const newErrors: ProjectFormErrors = {}; if (!formData.name.trim()) { newErrors.name = '项目名称不能为空'; } else if (formData.name.length > 100) { newErrors.name = '项目名称不能超过100个字符'; } if (!formData.path.trim()) { newErrors.path = '项目路径不能为空'; } if (formData.description.length > 500) { newErrors.description = '项目描述不能超过500个字符'; } setErrors(newErrors); return Object.keys(newErrors).length === 0; }; // 选择目录 const handleSelectDirectory = async () => { try { const selectedPath = await invoke('select_directory'); if (selectedPath) { setFormData(prev => ({ ...prev, path: selectedPath })); // 如果项目名称为空,尝试从路径获取默认名称 if (!formData.name.trim()) { try { const defaultName = await getDefaultProjectName(selectedPath); if (defaultName) { setFormData(prev => ({ ...prev, name: defaultName })); } } catch (error) { console.warn('获取默认项目名称失败:', error); } } } } catch (error) { console.error('选择目录失败:', error); } }; // 验证路径 const handlePathValidation = async (path: string) => { if (!path.trim()) return; setIsValidatingPath(true); try { const isValid = await validateProjectPath(path); if (!isValid) { setErrors(prev => ({ ...prev, path: '无效的项目路径或没有访问权限' })); } else { setErrors(prev => { const { path: _, ...rest } = prev; return rest; }); } } catch (error) { setErrors(prev => ({ ...prev, path: '路径验证失败' })); } finally { setIsValidatingPath(false); } }; // 路径变化时验证 useEffect(() => { if (formData.path && !isEdit) { const timeoutId = setTimeout(() => { handlePathValidation(formData.path); }, 500); return () => clearTimeout(timeoutId); } }, [formData.path, isEdit]); // 处理表单提交 const handleSubmit = async (e: React.FormEvent) => { e.preventDefault(); if (!validateForm()) { return; } try { await onSubmit(formData); } catch (error) { console.error('提交表单失败:', error); } }; return (
{/* 模态框头部 */}

{isEdit ? '编辑项目' : '新建项目'}

{isEdit ? '修改项目信息' : '创建一个新的视频项目'}

{/* 模态框内容 */}
{/* 项目名称 */} setFormData(prev => ({ ...prev, name: value }))} placeholder="为您的项目起一个好听的名字" error={errors.name} maxLength={100} required autoFocus /> {/* 项目路径 */}
setFormData(prev => ({ ...prev, path: value }))} placeholder="选择项目存储位置" error={errors.path} success={!errors.path && formData.path && !isValidatingPath ? "路径有效" : undefined} loading={isValidatingPath} disabled={isEdit} required />
{!isEdit && (
} className="whitespace-nowrap" > 浏览文件夹
)}
{isEdit ? '编辑模式下无法修改项目路径' : '选择一个空文件夹或新建文件夹作为项目目录'}
{/* 项目描述 */}