Files
AIChatRoom/frontend/src/pages/DiscussionHistory.tsx

246 lines
7.3 KiB
TypeScript
Raw Normal View History

/**
*
*/
import React, { useEffect, useState } from 'react'
import {
Table, Card, Tag, Typography, Space, Button,
Modal, List, Descriptions, Progress, Empty
} from 'antd'
import {
CheckCircleOutlined, CloseCircleOutlined,
EyeOutlined, RobotOutlined
} from '@ant-design/icons'
import { discussionApi } from '../services/api'
import type { DiscussionResult } from '../types'
import dayjs from 'dayjs'
const { Title, Text, Paragraph } = Typography
const DiscussionHistory: React.FC = () => {
const [discussions, setDiscussions] = useState<DiscussionResult[]>([])
const [total, setTotal] = useState(0)
const [loading, setLoading] = useState(false)
const [detailVisible, setDetailVisible] = useState(false)
const [selectedDiscussion, setSelectedDiscussion] = useState<DiscussionResult | null>(null)
const fetchDiscussions = async (page = 1, pageSize = 20) => {
setLoading(true)
try {
const result = await discussionApi.list(undefined, pageSize)
setDiscussions(result.discussions)
setTotal(result.total)
} catch (e) {
console.error('Failed to fetch discussions:', e)
} finally {
setLoading(false)
}
}
useEffect(() => {
fetchDiscussions()
}, [])
const showDetail = (record: DiscussionResult) => {
setSelectedDiscussion(record)
setDetailVisible(true)
}
const columns = [
{
title: '讨论目标',
dataIndex: 'objective',
key: 'objective',
width: 300,
ellipsis: true
},
{
title: '状态',
dataIndex: 'consensus_reached',
key: 'consensus_reached',
width: 120,
render: (reached: boolean, record: DiscussionResult) => (
<Space>
{reached ? (
<Tag color="success" icon={<CheckCircleOutlined />}></Tag>
) : (
<Tag color="default" icon={<CloseCircleOutlined />}></Tag>
)}
</Space>
)
},
{
title: '置信度',
dataIndex: 'confidence',
key: 'confidence',
width: 120,
render: (confidence: number) => (
<Progress
percent={Math.round(confidence * 100)}
size="small"
strokeColor={confidence >= 0.8 ? '#52c41a' : confidence >= 0.5 ? '#faad14' : '#ff4d4f'}
/>
)
},
{
title: '轮数',
dataIndex: 'total_rounds',
key: 'total_rounds',
width: 80
},
{
title: '消息数',
dataIndex: 'total_messages',
key: 'total_messages',
width: 80
},
{
title: '参与Agent',
dataIndex: 'participating_agents',
key: 'participating_agents',
width: 150,
render: (agents: string[]) => (
<Text type="secondary">{agents.length} </Text>
)
},
{
title: '时间',
dataIndex: 'created_at',
key: 'created_at',
width: 180,
render: (time: string) => dayjs(time).format('YYYY-MM-DD HH:mm')
},
{
title: '操作',
key: 'actions',
width: 80,
render: (_: unknown, record: DiscussionResult) => (
<Button
type="link"
icon={<EyeOutlined />}
onClick={() => showDetail(record)}
>
</Button>
)
}
]
return (
<div style={{ marginLeft: 200 }}>
<Title level={2}></Title>
<Card>
<Table
dataSource={discussions}
columns={columns}
rowKey="discussion_id"
loading={loading}
pagination={{
total,
pageSize: 20,
showTotal: (t) => `${t} 条记录`
}}
/>
</Card>
{/* 详情弹窗 */}
<Modal
title="讨论详情"
open={detailVisible}
onCancel={() => setDetailVisible(false)}
footer={null}
width={800}
>
{selectedDiscussion && (
<div>
<Descriptions bordered column={2}>
<Descriptions.Item label="讨论目标" span={2}>
{selectedDiscussion.objective}
</Descriptions.Item>
<Descriptions.Item label="状态">
{selectedDiscussion.consensus_reached ? (
<Tag color="success"></Tag>
) : (
<Tag color="default"></Tag>
)}
</Descriptions.Item>
<Descriptions.Item label="置信度">
<Progress
percent={Math.round(selectedDiscussion.confidence * 100)}
size="small"
style={{ width: 150 }}
/>
</Descriptions.Item>
<Descriptions.Item label="总轮数">
{selectedDiscussion.total_rounds}
</Descriptions.Item>
<Descriptions.Item label="总消息数">
{selectedDiscussion.total_messages}
</Descriptions.Item>
<Descriptions.Item label="结束原因" span={2}>
{selectedDiscussion.end_reason || '无'}
</Descriptions.Item>
<Descriptions.Item label="开始时间">
{dayjs(selectedDiscussion.created_at).format('YYYY-MM-DD HH:mm:ss')}
</Descriptions.Item>
<Descriptions.Item label="结束时间">
{selectedDiscussion.completed_at
? dayjs(selectedDiscussion.completed_at).format('YYYY-MM-DD HH:mm:ss')
: '进行中'}
</Descriptions.Item>
</Descriptions>
<Card title="结果摘要" style={{ marginTop: 16 }}>
<Paragraph>{selectedDiscussion.summary || '暂无摘要'}</Paragraph>
</Card>
<Card title="行动项" style={{ marginTop: 16 }}>
{selectedDiscussion.action_items.length > 0 ? (
<List
dataSource={selectedDiscussion.action_items}
renderItem={(item) => (
<List.Item>
<CheckCircleOutlined style={{ color: '#52c41a', marginRight: 8 }} />
{item}
</List.Item>
)}
/>
) : (
<Empty description="暂无行动项" />
)}
</Card>
<Card title="未解决问题" style={{ marginTop: 16 }}>
{selectedDiscussion.unresolved_issues.length > 0 ? (
<List
dataSource={selectedDiscussion.unresolved_issues}
renderItem={(item) => (
<List.Item>
<CloseCircleOutlined style={{ color: '#faad14', marginRight: 8 }} />
{item}
</List.Item>
)}
/>
) : (
<Empty description="无未解决问题" />
)}
</Card>
<Card title="Agent贡献" style={{ marginTop: 16 }}>
<Space wrap>
{Object.entries(selectedDiscussion.agent_contributions).map(([agentId, count]) => (
<Tag key={agentId} icon={<RobotOutlined />}>
{agentId}: {count}
</Tag>
))}
</Space>
</Card>
</div>
)}
</Modal>
</div>
)
}
export default DiscussionHistory