import React, { useCallback, useEffect, useState } from 'react'; import { App, Avatar, Button, Card, Col, Divider, Empty, Input, Row, Segmented, Space, Tag, Typography, } from 'antd'; import { ArrowRightOutlined, ClockCircleOutlined, DeleteOutlined, EditOutlined, PlusOutlined, TeamOutlined, UserOutlined, } from '@ant-design/icons'; import { useLocation, useNavigate } from 'react-router-dom'; import apiClient from '../utils/apiClient'; import { API_ENDPOINTS, buildApiUrl } from '../config/api'; import ActionButton from '../components/ActionButton'; import CenterPager from '../components/CenterPager'; import MeetingFormDrawer from '../components/MeetingFormDrawer'; import meetingCacheService from '../services/meetingCacheService'; import tools from '../utils/tools'; import useSystemPageSize from '../hooks/useSystemPageSize'; import './MeetingCenterPage.css'; import '../components/MeetingInfoCard.css'; const { Title, Text, Paragraph } = Typography; const FILTER_OPTIONS = [ { label: '全部', value: 'all' }, { label: '我发起', value: 'created' }, { label: '我参与', value: 'attended' }, ]; const ROLE_META = { creator: { label: '我发起', tagClass: 'console-tag-soft-blue', }, attendee: { label: '我参与', tagClass: 'console-tag-soft-green', }, }; const STATUS_META = { completed: { label: '已完成', tagClass: 'console-tag-soft-green', accent: '#52c41a', }, failed: { label: '失败', tagClass: 'console-tag-soft-red', accent: '#ff4d4f', }, transcribing: { label: '转写中', tagClass: 'console-tag-soft-blue', accent: '#1677ff', }, summarizing: { label: '总结中', tagClass: 'console-tag-soft-orange', accent: '#fa8c16', }, pending: { label: '待处理', tagClass: 'console-tag-soft-default', accent: '#cbd5e1', }, }; const getStatusMeta = (meeting) => { const status = meeting?.overall_status || 'pending'; return STATUS_META[status] || STATUS_META.pending; }; const getSummaryPreview = (summary) => { if (!summary) return ''; return tools.stripMarkdown(summary).replace(/\s+/g, ' ').trim(); }; const MeetingCenterPage = ({ user }) => { const navigate = useNavigate(); const location = useLocation(); const { message, modal } = App.useApp(); const [meetings, setMeetings] = useState([]); const [loading, setLoading] = useState(false); const [keyword, setKeyword] = useState(''); const [searchValue, setSearchValue] = useState(''); const [filterType, setFilterType] = useState('all'); const [page, setPage] = useState(1); const { pageSize, isReady: pageSizeReady } = useSystemPageSize(10, { suspendUntilReady: true }); const [total, setTotal] = useState(0); const [formDrawerOpen, setFormDrawerOpen] = useState(false); const [editingMeetingId, setEditingMeetingId] = useState(null); const loadMeetings = useCallback(async (nextPage = page, nextKeyword = keyword, nextFilter = filterType, options = {}) => { const { forceRefresh = false } = options; const filterKey = meetingCacheService.generateFilterKey(user.user_id, nextFilter, nextKeyword, []); if (!forceRefresh) { const cachedPage = meetingCacheService.getPage(filterKey, nextPage); if (cachedPage) { setMeetings(cachedPage.meetings || []); setTotal(cachedPage.pagination?.total || 0); setLoading(false); return; } } setLoading(true); try { const res = await apiClient.get(buildApiUrl(API_ENDPOINTS.MEETINGS.LIST), { params: { user_id: user.user_id, page: nextPage, page_size: pageSize, filter_type: nextFilter, search: nextKeyword || undefined, }, }); const nextMeetings = res.data.meetings || []; const nextPagination = { page: res.data.page || nextPage, total: res.data.total || 0, has_more: Boolean(res.data.has_more), }; meetingCacheService.setPage(filterKey, nextPage, nextMeetings, nextPagination); setMeetings(nextMeetings); setTotal(nextPagination.total); } catch (error) { message.error(error?.response?.data?.message || '加载会议失败'); } finally { setLoading(false); } }, [filterType, keyword, message, page, pageSize, user.user_id]); useEffect(() => { meetingCacheService.clearAll(); }, [pageSize]); useEffect(() => { if (!pageSizeReady || !pageSize) { return; } loadMeetings(page, keyword, filterType); }, [filterType, keyword, loadMeetings, page, pageSize, pageSizeReady]); useEffect(() => { if (location.state?.openCreate) { setEditingMeetingId(null); setFormDrawerOpen(true); navigate(location.pathname, { replace: true, state: {} }); } }, [location.pathname, location.state, navigate]); const handleDeleteMeeting = (meeting) => { modal.confirm({ title: '删除会议', content: `确定删除「${meeting.title}」吗?`, okText: '删除', okType: 'danger', onOk: async () => { try { await apiClient.delete(buildApiUrl(API_ENDPOINTS.MEETINGS.DELETE(meeting.meeting_id))); message.success('会议已删除'); meetingCacheService.clearAll(); const nextPage = page > 1 && meetings.length === 1 ? page - 1 : page; setPage(nextPage); loadMeetings(nextPage, keyword, filterType, { forceRefresh: true }); } catch (error) { message.error(error?.response?.data?.message || '删除失败'); } }, }); }; return (