import { useState, useEffect, useCallback } from 'react'; import { Button, Modal, Form, Input, message, Card, Space, Tag, Popconfirm, Empty, Typography, Row, Col, theme, } from 'antd'; import { PlusOutlined, EditOutlined, DeleteOutlined, StarOutlined, StarFilled, } from '@ant-design/icons'; import { useStore } from '../store'; import { writingStyleApi } from '../services/api'; import type { WritingStyle, WritingStyleCreate, WritingStyleUpdate } from '../types'; const { TextArea } = Input; const { Text, Paragraph } = Typography; export default function WritingStyles() { const { currentProject } = useStore(); const [styles, setStyles] = useState([]); const [loading, setLoading] = useState(false); const [isCreateModalOpen, setIsCreateModalOpen] = useState(false); const [isEditModalOpen, setIsEditModalOpen] = useState(false); const [editingStyle, setEditingStyle] = useState(null); const [createForm] = Form.useForm(); const [editForm] = Form.useForm(); const { token } = theme.useToken(); const isMobile = window.innerWidth <= 768; // 卡片网格配置 const gridConfig = { gutter: isMobile ? 8 : 16, // 卡片之间的间距 xs: 24, sm: 24, md: 12, lg: 8, xl: 6, }; // 加载风格列表 - 如果有项目则加载项目风格(包含默认标记),否则加载用户风格 useEffect(() => { loadStyles(); // eslint-disable-next-line react-hooks/exhaustive-deps }, [currentProject?.id]); const loadStyles = useCallback(async () => { try { setLoading(true); // 如果有当前项目,使用项目API获取(包含is_default标记) // 否则使用用户API获取(所有风格的is_default都是false) const response = currentProject?.id ? await writingStyleApi.getProjectStyles(currentProject.id) : await writingStyleApi.getUserStyles(); // 排序:默认风格优先显示 const sortedStyles = (response.styles || []).sort((a, b) => { // 默认风格排在最前面 if (a.is_default && !b.is_default) return -1; if (!a.is_default && b.is_default) return 1; // 其他按原有顺序(order_index) return 0; }); setStyles(sortedStyles); } catch { message.error('加载风格列表失败'); } finally { setLoading(false); } }, [currentProject?.id]); const handleCreate = async (values: { name: string; description?: string; prompt_content: string }) => { try { const createData: WritingStyleCreate = { name: values.name, style_type: 'custom', description: values.description, prompt_content: values.prompt_content, }; await writingStyleApi.createStyle(createData); message.success('创建成功'); setIsCreateModalOpen(false); createForm.resetFields(); await loadStyles(); } catch { message.error('创建失败'); } }; const handleEdit = (style: WritingStyle) => { setEditingStyle(style); editForm.setFieldsValue({ name: style.name, description: style.description, prompt_content: style.prompt_content, }); setIsEditModalOpen(true); }; const handleUpdate = async (values: WritingStyleUpdate) => { if (!editingStyle) return; try { await writingStyleApi.updateStyle(editingStyle.id, values); message.success('更新成功'); setIsEditModalOpen(false); editForm.resetFields(); setEditingStyle(null); await loadStyles(); } catch { message.error('更新失败'); } }; const handleDelete = async (styleId: number) => { try { await writingStyleApi.deleteStyle(styleId); message.success('删除成功'); await loadStyles(); } catch { message.error('删除失败'); } }; const handleSetDefault = async (styleId: number) => { if (!currentProject?.id) { message.warning('请先选择项目'); return; } try { await writingStyleApi.setDefaultStyle(styleId, currentProject.id); message.success('设置默认风格成功'); await loadStyles(); } catch { message.error('设置失败'); } }; const showCreateModal = () => { createForm.resetFields(); setIsCreateModalOpen(true); }; const getStyleTypeColor = (styleType: string) => { return styleType === 'preset' ? 'blue' : 'purple'; }; const getStyleTypeLabel = (styleType: string) => { return styleType === 'preset' ? '预设' : '自定义'; }; return (

写作风格管理

{styles.length === 0 ? ( ) : ( {styles.map((style) => ( !style.is_default && handleSetDefault(style.id)} style={{ cursor: style.is_default ? 'default' : 'pointer' }} > {style.is_default ? ( ) : ( )} , style.user_id !== null && handleEdit(style)} style={{ fontSize: 18, cursor: style.user_id === null ? 'not-allowed' : 'pointer', color: style.user_id === null ? token.colorTextQuaternary : undefined }} />, handleDelete(style.id)} okText="确定" cancelText="取消" disabled={style.user_id === null} > , ]} >
{style.name} {getStyleTypeLabel(style.style_type)} {style.is_default && 默认} {style.description && ( {style.description} )} {style.prompt_content}
))}
)}
{/* 创建自定义风格 Modal */} { setIsCreateModalOpen(false); createForm.resetFields(); }} footer={null} centered width={isMobile ? 'calc(100vw - 32px)' : 600} style={isMobile ? { maxWidth: 'calc(100vw - 32px)', margin: '0 16px' } : undefined} >