import React, { useState, useEffect, useCallback } from 'react'; import { PlusIcon, PencilIcon, TrashIcon, EyeIcon, ArrowUpIcon, ArrowDownIcon, CheckIcon, XMarkIcon, CpuChipIcon } from '@heroicons/react/24/outline'; import { AiClassificationService } from '../services/aiClassificationService'; import { AiClassification, AiClassificationFormData, AiClassificationFormErrors, AiClassificationPreview, DEFAULT_FORM_DATA, validateClassificationForm, hasFormErrors, classificationToFormData, formDataToCreateRequest, formDataToUpdateRequest, } from '../types/aiClassification'; import { LoadingSpinner } from '../components/LoadingSpinner'; import { ErrorMessage } from '../components/ErrorMessage'; import { EmptyState } from '../components/EmptyState'; import { AiClassificationFormDialog } from '../components/AiClassificationFormDialog'; import { AiClassificationPreviewDialog } from '../components/AiClassificationPreviewDialog'; import { DeleteConfirmDialog } from '../components/DeleteConfirmDialog'; /** * AI分类设置页面 * 遵循前端开发规范的组件设计,实现分类的CRUD操作和实时预览 */ const AiClassificationSettings: React.FC = () => { // 状态管理 const [classifications, setClassifications] = useState([]); const [loading, setLoading] = useState(true); const [error, setError] = useState(null); const [showCreateDialog, setShowCreateDialog] = useState(false); const [showEditDialog, setShowEditDialog] = useState(false); const [showDeleteDialog, setShowDeleteDialog] = useState(false); const [showPreviewDialog, setShowPreviewDialog] = useState(false); const [editingClassification, setEditingClassification] = useState(null); const [deletingClassificationId, setDeletingClassificationId] = useState(null); const [preview, setPreview] = useState(null); const [previewLoading, setPreviewLoading] = useState(false); // 表单状态 const [formData, setFormData] = useState(DEFAULT_FORM_DATA); const [formErrors, setFormErrors] = useState({}); const [submitting, setSubmitting] = useState(false); // 加载分类列表 const loadClassifications = useCallback(async () => { try { setLoading(true); setError(null); const result = await AiClassificationService.getAllClassificationsIncludingInactive(); setClassifications(result); } catch (err) { setError(err instanceof Error ? err.message : '加载分类列表失败'); } finally { setLoading(false); } }, []); // 生成预览 const generatePreview = useCallback(async () => { try { setPreviewLoading(true); const result = await AiClassificationService.generatePreview(); setPreview(result); } catch (err) { console.error('生成预览失败:', err); } finally { setPreviewLoading(false); } }, []); // 初始化 useEffect(() => { loadClassifications(); }, [loadClassifications]); // 处理创建分类 const handleCreate = async () => { const errors = validateClassificationForm(formData); setFormErrors(errors); if (hasFormErrors(errors)) { return; } try { setSubmitting(true); const request = formDataToCreateRequest(formData); await AiClassificationService.createClassification(request); // 重新加载列表 await loadClassifications(); // 关闭对话框并重置表单 setShowCreateDialog(false); setFormData(DEFAULT_FORM_DATA); setFormErrors({}); } catch (err) { setFormErrors({ general: err instanceof Error ? err.message : '创建失败' }); } finally { setSubmitting(false); } }; // 处理编辑分类 const handleEdit = async () => { if (!editingClassification) return; const errors = validateClassificationForm(formData); setFormErrors(errors); if (hasFormErrors(errors)) { return; } try { setSubmitting(true); const request = formDataToUpdateRequest(formData); await AiClassificationService.updateClassification(editingClassification.id, request); // 重新加载列表 await loadClassifications(); // 关闭对话框并重置状态 setShowEditDialog(false); setEditingClassification(null); setFormData(DEFAULT_FORM_DATA); setFormErrors({}); } catch (err) { setFormErrors({ general: err instanceof Error ? err.message : '更新失败' }); } finally { setSubmitting(false); } }; // 处理删除分类 const handleDelete = async () => { if (!deletingClassificationId) return; try { setSubmitting(true); await AiClassificationService.deleteClassification(deletingClassificationId); // 重新加载列表 await loadClassifications(); // 关闭对话框并重置状态 setShowDeleteDialog(false); setDeletingClassificationId(null); } catch (err) { setError(err instanceof Error ? err.message : '删除失败'); } finally { setSubmitting(false); } }; // 处理切换状态 const handleToggleStatus = async (id: string) => { try { await AiClassificationService.toggleClassificationStatus(id); await loadClassifications(); } catch (err) { setError(err instanceof Error ? err.message : '切换状态失败'); } }; // 处理移动排序 const handleMoveUp = async (classification: AiClassification) => { const currentIndex = classifications.findIndex(c => c.id === classification.id); if (currentIndex <= 0) return; // 重新分配所有分类的排序顺序 const reorderedIds = [...classifications]; // 交换当前项和上一项的位置 [reorderedIds[currentIndex], reorderedIds[currentIndex - 1]] = [reorderedIds[currentIndex - 1], reorderedIds[currentIndex]]; // 生成新的排序更新 const updates = reorderedIds.map((item, index) => ({ id: item.id, sort_order: index + 1, // 从1开始排序 })); try { await AiClassificationService.updateSortOrders(updates); await loadClassifications(); } catch (err) { setError(err instanceof Error ? err.message : '调整排序失败'); } }; const handleMoveDown = async (classification: AiClassification) => { const currentIndex = classifications.findIndex(c => c.id === classification.id); if (currentIndex >= classifications.length - 1) return; // 重新分配所有分类的排序顺序 const reorderedIds = [...classifications]; // 交换当前项和下一项的位置 [reorderedIds[currentIndex], reorderedIds[currentIndex + 1]] = [reorderedIds[currentIndex + 1], reorderedIds[currentIndex]]; // 生成新的排序更新 const updates = reorderedIds.map((item, index) => ({ id: item.id, sort_order: index + 1, // 从1开始排序 })); try { await AiClassificationService.updateSortOrders(updates); await loadClassifications(); } catch (err) { setError(err instanceof Error ? err.message : '调整排序失败'); } }; // 打开创建对话框 const openCreateDialog = () => { // 设置新分类的排序顺序为最大值+1 const maxSortOrder = classifications.length > 0 ? Math.max(...classifications.map(c => c.sort_order)) : 0; setFormData({ ...DEFAULT_FORM_DATA, sort_order: maxSortOrder + 1, }); setFormErrors({}); setShowCreateDialog(true); }; // 打开编辑对话框 const openEditDialog = (classification: AiClassification) => { setEditingClassification(classification); setFormData(classificationToFormData(classification)); setFormErrors({}); setShowEditDialog(true); }; // 打开删除确认对话框 const openDeleteDialog = (id: string) => { setDeletingClassificationId(id); setShowDeleteDialog(true); }; // 打开预览对话框 const openPreviewDialog = async () => { setShowPreviewDialog(true); await generatePreview(); }; // 渲染加载状态 if (loading) { return (
); } // 渲染错误状态 if (error) { return (
); } return (
{/* 美观的页面头部 */}

AI分类设置

管理视频AI分类规则和提示词

{/* 分类列表 - 优化卡片设计和布局 */} {classifications.length === 0 ? ( ) : (
{/* 列表标题 */}

分类列表 ({classifications.length})

{/* 美观的分类卡片网格 - 优化滚动 */}
{classifications.map((classification, index) => (
{/* 装饰性背景 */}
{/* 美观的卡片头部 */}

{classification.name}

{classification.is_active ? '激活' : '禁用'} #{classification.sort_order}
{/* 提示词预览 */}

{classification.prompt_text}

{/* 描述 */} {classification.description && (

{classification.description}

)} {/* 时间信息 */}
{new Date(classification.created_at).toLocaleDateString()}
{/* 操作按钮组 - 优化为更精致的设计 */}
{/* 排序按钮组 */}
{/* 状态切换按钮 */} {/* 编辑按钮 */} {/* 删除按钮 */}
))}
)} {/* 创建分类对话框 */} { setShowCreateDialog(false); setFormData(DEFAULT_FORM_DATA); setFormErrors({}); }} /> {/* 编辑分类对话框 */} { setShowEditDialog(false); setEditingClassification(null); setFormData(DEFAULT_FORM_DATA); setFormErrors({}); }} /> {/* 删除确认对话框 */} c.id === deletingClassificationId)?.name : undefined } deleting={submitting} onConfirm={handleDelete} onCancel={() => { setShowDeleteDialog(false); setDeletingClassificationId(null); }} /> {/* 预览对话框 */} { setShowPreviewDialog(false); setPreview(null); }} />
); }; export default AiClassificationSettings;