Spaces:
Sleeping
Sleeping
| import React, { useState } from 'react'; | |
| import { Prompt } from '../../types'; | |
| import Input from '../common/Input'; | |
| import TextArea from '../common/TextArea'; | |
| import Button from '../common/Button'; | |
| interface PromptFormProps { | |
| initialPrompt?: Partial<Prompt>; | |
| onSubmit: (prompt: { title: string; content: string; tags: string[] }) => void; | |
| onCancel: () => void; | |
| } | |
| const PromptForm: React.FC<PromptFormProps> = ({ | |
| initialPrompt = {}, | |
| onSubmit, | |
| onCancel | |
| }) => { | |
| const [title, setTitle] = useState(initialPrompt.title || ''); | |
| const [content, setContent] = useState(initialPrompt.content || ''); | |
| const [tagInput, setTagInput] = useState(''); | |
| const [tags, setTags] = useState<string[]>(initialPrompt.tags || []); | |
| const [errors, setErrors] = useState({ | |
| title: '', | |
| content: '' | |
| }); | |
| const handleAddTag = () => { | |
| if (!tagInput.trim()) return; | |
| // 如果标签已存在,则不添加 | |
| if (tags.includes(tagInput.trim())) { | |
| setTagInput(''); | |
| return; | |
| } | |
| setTags([...tags, tagInput.trim()]); | |
| setTagInput(''); | |
| }; | |
| const handleKeyDown = (e: React.KeyboardEvent<HTMLInputElement>) => { | |
| if (e.key === 'Enter') { | |
| e.preventDefault(); | |
| handleAddTag(); | |
| } | |
| }; | |
| const handleRemoveTag = (tagToRemove: string) => { | |
| setTags(tags.filter(tag => tag !== tagToRemove)); | |
| }; | |
| const validate = (): boolean => { | |
| const newErrors = { | |
| title: '', | |
| content: '' | |
| }; | |
| if (!title.trim()) { | |
| newErrors.title = '请输入提示词标题'; | |
| } | |
| if (!content.trim()) { | |
| newErrors.content = '请输入提示词内容'; | |
| } | |
| setErrors(newErrors); | |
| return !newErrors.title && !newErrors.content; | |
| }; | |
| const handleSubmit = (e: React.FormEvent) => { | |
| e.preventDefault(); | |
| if (!validate()) return; | |
| onSubmit({ | |
| title: title.trim(), | |
| content: content.trim(), | |
| tags | |
| }); | |
| }; | |
| return ( | |
| <form onSubmit={handleSubmit} className="space-y-4"> | |
| <Input | |
| label="标题" | |
| placeholder="输入提示词标题" | |
| value={title} | |
| onChange={(e) => setTitle(e.target.value)} | |
| error={errors.title} | |
| required | |
| /> | |
| <TextArea | |
| label="内容" | |
| placeholder="输入提示词内容..." | |
| value={content} | |
| onChange={(e) => setContent(e.target.value)} | |
| error={errors.content} | |
| rows={10} | |
| className="max-h-80 overflow-y-auto" // 添加最大高度和滚动 | |
| required | |
| /> | |
| <div> | |
| <label className="block text-sm font-medium mb-1 text-gray-700"> | |
| 标签 | |
| </label> | |
| <div className="flex flex-wrap mb-2"> | |
| {tags.map((tag) => ( | |
| <div | |
| key={tag} | |
| className="ios-tag bg-blue-100 text-blue-800 flex items-center" | |
| > | |
| {tag} | |
| <button | |
| type="button" | |
| className="ml-1 text-blue-600 hover:text-blue-800" | |
| onClick={() => handleRemoveTag(tag)} | |
| > | |
| <svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round"> | |
| <line x1="18" y1="6" x2="6" y2="18"></line> | |
| <line x1="6" y1="6" x2="18" y2="18"></line> | |
| </svg> | |
| </button> | |
| </div> | |
| ))} | |
| </div> | |
| <div className="flex"> | |
| <Input | |
| placeholder="添加标签" | |
| value={tagInput} | |
| onChange={(e) => setTagInput(e.target.value)} | |
| onKeyDown={handleKeyDown} | |
| className="flex-1 mb-0" | |
| /> | |
| <Button | |
| type="button" | |
| variant="secondary" | |
| onClick={handleAddTag} | |
| className="ml-2" | |
| > | |
| 添加 | |
| </Button> | |
| </div> | |
| </div> | |
| <div className="flex justify-end space-x-3 mt-6"> | |
| <Button | |
| type="button" | |
| variant="secondary" | |
| onClick={onCancel} | |
| > | |
| 取消 | |
| </Button> | |
| <Button | |
| type="submit" | |
| variant="primary" | |
| > | |
| 保存 | |
| </Button> | |
| </div> | |
| </form> | |
| ); | |
| }; | |
| export default PromptForm; |