import { ClipboardCheck, MessageSquare, Plus, Search, Trash2 } from 'lucide-react' import { useEffect, useState } from 'react' import { Button } from '@/components/ui/button' import { ExpressionReviewer } from '@/components/expression-reviewer' import { Input } from '@/components/ui/input' import { Label } from '@/components/ui/label' import { ScrollArea } from '@/components/ui/scroll-area' import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue, } from '@/components/ui/select' import { useToast } from '@/hooks/use-toast' import { batchDeleteExpressions, deleteExpression, getChatList, getExpressionDetail, getExpressionList, getExpressionStats, getReviewStats, } from '@/lib/expression-api' import { BatchDeleteConfirmDialog, DeleteConfirmDialog, ExpressionCreateDialog, ExpressionDetailDialog, ExpressionEditDialog, } from './ExpressionDialogs' import { ExpressionList } from './ExpressionList' import type { ChatInfo, Expression } from '@/types/expression' import type { StatsData } from './types' /** * 表达方式管理主页面 */ export function ExpressionManagementPage() { const [expressions, setExpressions] = useState([]) const [loading, setLoading] = useState(true) const [total, setTotal] = useState(0) const [page, setPage] = useState(1) const [pageSize, setPageSize] = useState(20) const [search, setSearch] = useState('') const [selectedExpression, setSelectedExpression] = useState(null) const [isDetailDialogOpen, setIsDetailDialogOpen] = useState(false) const [isEditDialogOpen, setIsEditDialogOpen] = useState(false) const [isCreateDialogOpen, setIsCreateDialogOpen] = useState(false) const [deleteConfirmExpression, setDeleteConfirmExpression] = useState(null) const [selectedIds, setSelectedIds] = useState>(new Set()) const [isBatchDeleteDialogOpen, setIsBatchDeleteDialogOpen] = useState(false) const [stats, setStats] = useState({ total: 0, recent_7days: 0, chat_count: 0, top_chats: {} }) const [chatList, setChatList] = useState([]) const [chatNameMap, setChatNameMap] = useState>(new Map()) const [isReviewerOpen, setIsReviewerOpen] = useState(false) const [uncheckedCount, setUncheckedCount] = useState(0) const { toast } = useToast() // 加载表达方式列表 const loadExpressions = async () => { try { setLoading(true) const result = await getExpressionList({ page, page_size: pageSize, search: search || undefined, }) if (result.success) { setExpressions(result.data.data) setTotal(result.data.total) } else { toast({ title: '加载失败', description: result.error, variant: 'destructive', }) } } catch (error) { toast({ title: '加载失败', description: error instanceof Error ? error.message : '无法加载表达方式', variant: 'destructive', }) } finally { setLoading(false) } } // 加载统计数据 const loadStats = async () => { try { const result = await getExpressionStats() if (result.success) { setStats(result.data) } else { console.error('加载统计数据失败:', result.error) } } catch (error) { console.error('加载统计数据失败:', error) } } // 加载审核统计 const loadReviewStats = async () => { try { const result = await getReviewStats() if (result.success) { setUncheckedCount(result.data.unchecked) } } catch (error) { console.error('加载审核统计失败:', error) } } // 加载聚天列表 const loadChatList = async () => { try { const result = await getChatList() if (result.success) { setChatList(result.data) const nameMap = new Map() result.data.forEach((chat: ChatInfo) => { nameMap.set(chat.chat_id, chat.chat_name) }) setChatNameMap(nameMap) } } catch (error) { console.error('加载聚天列表失败:', error) } } // 初始加载 useEffect(() => { loadExpressions() loadReviewStats() loadStats() loadChatList() // eslint-disable-next-line react-hooks/exhaustive-deps }, [page, pageSize, search]) // 查看详情 const handleViewDetail = async (expression: Expression) => { try { const result = await getExpressionDetail(expression.id) if (result.success) { setSelectedExpression(result.data) setIsDetailDialogOpen(true) } else { toast({ title: '加载详情失败', description: result.error, variant: 'destructive', }) } } catch (error) { toast({ title: '加载详情失败', description: error instanceof Error ? error.message : '无法加载表达方式详情', variant: 'destructive', }) } } // 编辑表达方式 const handleEdit = (expression: Expression) => { setSelectedExpression(expression) setIsEditDialogOpen(true) } // 删除表达方式 const handleDelete = async () => { if (!deleteConfirmExpression) return try { const result = await deleteExpression(deleteConfirmExpression.id) if (result.success) { toast({ title: '删除成功', description: `已删除表达方式: ${deleteConfirmExpression.situation}`, }) setDeleteConfirmExpression(null) loadExpressions() loadStats() } else { toast({ title: '删除失败', description: result.error, variant: 'destructive', }) } } catch (error) { toast({ title: '删除失败', description: error instanceof Error ? error.message : '无法删除表达方式', variant: 'destructive', }) } } // 切换单个选择 const toggleSelect = (id: number) => { const newSelected = new Set(selectedIds) if (newSelected.has(id)) { newSelected.delete(id) } else { newSelected.add(id) } setSelectedIds(newSelected) } // 全选/取消全选 const toggleSelectAll = () => { if (selectedIds.size === expressions.length && expressions.length > 0) { setSelectedIds(new Set()) } else { setSelectedIds(new Set(expressions.map(e => e.id))) } } // 批量删除 const handleBatchDelete = async () => { try { const result = await batchDeleteExpressions(Array.from(selectedIds)) if (result.success) { toast({ title: '批量删除成功', description: `已删除 ${selectedIds.size} 个表达方式`, }) setSelectedIds(new Set()) setIsBatchDeleteDialogOpen(false) loadExpressions() loadStats() } else { toast({ title: '批量删除失败', description: result.error, variant: 'destructive', }) } } catch (error) { toast({ title: '批量删除失败', description: error instanceof Error ? error.message : '无法批量删除表达方式', variant: 'destructive', }) } } // 页面跳转 const handleJumpToPage = (jumpToPage: string) => { const targetPage = parseInt(jumpToPage) const totalPages = Math.ceil(total / pageSize) if (targetPage >= 1 && targetPage <= totalPages) { setPage(targetPage) } } return (
{/* 页面标题 */}

表达方式

管理麦麦的表达方式和话术模板

{/* 统计卡片 */}
总数量
{stats.total}
近7天新增
{stats.recent_7days}
关联聊天数
{stats.chat_count}
{/* 搜索和批量操作 */}
setSearch(e.target.value)} className="pl-9" />
{/* 批量操作工具栏 */}
{selectedIds.size > 0 && ( 已选择 {selectedIds.size} 个表达方式 )}
{selectedIds.size > 0 && ( <> )}
{/* 表达方式列表 */} setDeleteConfirmExpression(expression)} onToggleSelect={toggleSelect} onToggleSelectAll={toggleSelectAll} onPageChange={setPage} onJumpToPage={handleJumpToPage} />
{/* 详情对话框 */} {/* 创建对话框 */} { loadExpressions() loadStats() setIsCreateDialogOpen(false) }} /> {/* 编辑对话框 */} { loadExpressions() loadStats() setIsEditDialogOpen(false) }} /> {/* 删除确认对话框 */} setDeleteConfirmExpression(null)} onConfirm={handleDelete} /> {/* 批量删除确认对话框 */} {/* 表达方式审核器 */} { setIsReviewerOpen(open) if (!open) { loadExpressions() loadStats() loadReviewStats() } }} />
) }