import { Modal, Form, Input, InputNumber, Select, Tag, Space, Button, message } from 'antd'; import { PlusOutlined } from '@ant-design/icons'; import { useState, useEffect } from 'react'; import type { ExpansionPlanData, Character } from '../types'; import { characterApi } from '../services/api'; const { TextArea } = Input; interface ExpansionPlanEditorProps { visible: boolean; planData: ExpansionPlanData | null; projectId: string; onSave: (data: ExpansionPlanData) => Promise; onCancel: () => void; } export default function ExpansionPlanEditor({ visible, planData, projectId, onSave, onCancel }: ExpansionPlanEditorProps) { const [form] = Form.useForm(); const [loading, setLoading] = useState(false); // 关键事件标签输入 const [keyEventInput, setKeyEventInput] = useState(''); const [keyEvents, setKeyEvents] = useState([]); // 角色列表和选择 const [availableCharacters, setAvailableCharacters] = useState([]); const [characters, setCharacters] = useState([]); const [loadingCharacters, setLoadingCharacters] = useState(false); // 加载项目角色列表 useEffect(() => { if (visible && projectId) { loadCharacters(); } }, [visible, projectId]); const loadCharacters = async () => { try { setLoadingCharacters(true); setAvailableCharacters([]); // 重置为空数组 const response = await characterApi.getCharacters(projectId); console.log('加载到的角色数据:', response); // API返回的是 {total, items} 格式,需要提取items let chars: Character[] = []; if (Array.isArray(response)) { chars = response; } else if (response && typeof response === 'object' && 'items' in response && Array.isArray((response as any).items)) { chars = (response as any).items; } else { console.error('角色API返回格式异常:', response); message.warning('角色数据格式异常'); } setAvailableCharacters(chars); console.log('设置的角色列表:', chars); } catch (error: any) { console.error('加载角色列表失败:', error); setAvailableCharacters([]); message.error('加载角色列表失败: ' + (error?.message || '未知错误')); } finally { setLoadingCharacters(false); } }; // 当planData变化时更新状态 useEffect(() => { if (planData) { setKeyEvents(planData.key_events || []); setCharacters(planData.character_focus || []); form.setFieldsValue({ emotional_tone: planData.emotional_tone, narrative_goal: planData.narrative_goal, conflict_type: planData.conflict_type, estimated_words: planData.estimated_words }); } else { // 重置状态 setKeyEvents([]); setCharacters([]); form.resetFields(); } }, [planData, form, visible]); const handleAddKeyEvent = () => { if (keyEventInput.trim()) { setKeyEvents([...keyEvents, keyEventInput.trim()]); setKeyEventInput(''); } }; const handleAddCharacter = (characterName: string) => { if (characterName && !characters.includes(characterName)) { setCharacters([...characters, characterName]); } }; const handleSubmit = async () => { try { setLoading(true); const values = await form.validateFields(); // 验证至少有一个关键事件 if (keyEvents.length === 0) { message.warning('请至少添加一个关键事件'); setLoading(false); return; } // 验证至少有一个角色 if (characters.length === 0) { message.warning('请至少添加一个涉及角色'); setLoading(false); return; } const updatedPlan: ExpansionPlanData = { key_events: keyEvents, character_focus: characters, emotional_tone: values.emotional_tone, narrative_goal: values.narrative_goal, conflict_type: values.conflict_type, estimated_words: values.estimated_words, scenes: planData?.scenes || null }; await onSave(updatedPlan); // message.success('规划信息保存成功'); } catch (error) { console.error('保存失败:', error); message.error('保存失败,请重试'); } finally { setLoading(false); } }; const handleCancel = () => { form.resetFields(); setKeyEvents([]); setCharacters([]); setKeyEventInput(''); onCancel(); }; return ( 取消 , ]} >
{/* 关键事件 */} setKeyEventInput(e.target.value)} onPressEnter={handleAddKeyEvent} /> {keyEvents.map((event, idx) => ( { e.preventDefault(); setKeyEvents(keyEvents.filter((_, i) => i !== idx)); }} color="purple" style={{ marginBottom: 8 }} > #{idx + 1} {event} ))} {/* 涉及角色 */} {/* 冲突类型 */} {/* 预估字数 */} `${value} 字`} parser={(value) => value?.replace(' 字', '') as any} /> {/* 叙事目标 */}