feat(frontend): add batch processing and review features
- Add batch processing API and mode - Add deep read mode for full-text analysis - Add document selector and switcher components - Add review page with editorial and methodology assessment - Add capacity indicator and usage info modal - Add custom hooks for batch tasks and chat modes - Update layouts and routing - Add TypeScript types for chat features
This commit is contained in:
192
frontend/src/components/review/EditorialReview.tsx
Normal file
192
frontend/src/components/review/EditorialReview.tsx
Normal file
@@ -0,0 +1,192 @@
|
||||
import { Card, Collapse, Space, Typography, Tag, Alert, Empty, List, Divider } from 'antd';
|
||||
import {
|
||||
CheckCircleOutlined,
|
||||
WarningOutlined,
|
||||
CloseCircleOutlined,
|
||||
FileTextOutlined,
|
||||
} from '@ant-design/icons';
|
||||
import type { EditorialReview as EditorialReviewType, EditorialItem } from '../../api/reviewApi';
|
||||
import ScoreCard from './ScoreCard';
|
||||
|
||||
const { Title, Text, Paragraph } = Typography;
|
||||
const { Panel } = Collapse;
|
||||
|
||||
interface EditorialReviewProps {
|
||||
data: EditorialReviewType;
|
||||
}
|
||||
|
||||
/**
|
||||
* 稿约规范性评估详情组件
|
||||
* 展示11个评估标准的详细结果
|
||||
*/
|
||||
const EditorialReview = ({ data }: EditorialReviewProps) => {
|
||||
if (!data) {
|
||||
return <Empty description="暂无评估数据" />;
|
||||
}
|
||||
|
||||
// 获取状态图标和颜色
|
||||
const getStatusDisplay = (status: 'pass' | 'warning' | 'fail') => {
|
||||
const config = {
|
||||
pass: {
|
||||
icon: <CheckCircleOutlined />,
|
||||
color: 'success' as const,
|
||||
text: '通过',
|
||||
},
|
||||
warning: {
|
||||
icon: <WarningOutlined />,
|
||||
color: 'warning' as const,
|
||||
text: '警告',
|
||||
},
|
||||
fail: {
|
||||
icon: <CloseCircleOutlined />,
|
||||
color: 'error' as const,
|
||||
text: '不通过',
|
||||
},
|
||||
};
|
||||
return config[status];
|
||||
};
|
||||
|
||||
// 统计数据
|
||||
const stats = {
|
||||
total: data.items.length,
|
||||
pass: data.items.filter((item) => item.status === 'pass').length,
|
||||
warning: data.items.filter((item) => item.status === 'warning').length,
|
||||
fail: data.items.filter((item) => item.status === 'fail').length,
|
||||
};
|
||||
|
||||
return (
|
||||
<Card title={
|
||||
<Space>
|
||||
<FileTextOutlined />
|
||||
<span>稿约规范性评估详情</span>
|
||||
</Space>
|
||||
}>
|
||||
<Space direction="vertical" size="large" style={{ width: '100%' }}>
|
||||
{/* 总体评分 */}
|
||||
<ScoreCard
|
||||
title="总体评分"
|
||||
score={data.overall_score}
|
||||
description="稿约规范性综合评分"
|
||||
size="large"
|
||||
/>
|
||||
|
||||
{/* 总结 */}
|
||||
<Alert
|
||||
message="评估总结"
|
||||
description={data.summary}
|
||||
type="info"
|
||||
showIcon
|
||||
/>
|
||||
|
||||
{/* 统计信息 */}
|
||||
<Card size="small">
|
||||
<Space size="large">
|
||||
<div>
|
||||
<Text type="secondary">评估标准:</Text>
|
||||
<Text strong style={{ fontSize: 16, marginLeft: 8 }}>{stats.total}</Text>
|
||||
</div>
|
||||
<Divider type="vertical" />
|
||||
<div>
|
||||
<Text type="success">通过:</Text>
|
||||
<Text strong style={{ fontSize: 16, marginLeft: 8, color: '#52c41a' }}>{stats.pass}</Text>
|
||||
</div>
|
||||
<Divider type="vertical" />
|
||||
<div>
|
||||
<Text type="warning">警告:</Text>
|
||||
<Text strong style={{ fontSize: 16, marginLeft: 8, color: '#faad14' }}>{stats.warning}</Text>
|
||||
</div>
|
||||
<Divider type="vertical" />
|
||||
<div>
|
||||
<Text type="danger">不通过:</Text>
|
||||
<Text strong style={{ fontSize: 16, marginLeft: 8, color: '#f5222d' }}>{stats.fail}</Text>
|
||||
</div>
|
||||
</Space>
|
||||
</Card>
|
||||
|
||||
{/* 详细评估结果 */}
|
||||
<Card title="详细评估(11项标准)" size="small">
|
||||
<Collapse defaultActiveKey={data.items.map((_, index) => index.toString())}>
|
||||
{data.items.map((item: EditorialItem, index: number) => {
|
||||
const statusDisplay = getStatusDisplay(item.status);
|
||||
|
||||
return (
|
||||
<Panel
|
||||
header={
|
||||
<Space>
|
||||
<Tag icon={statusDisplay.icon} color={statusDisplay.color}>
|
||||
{statusDisplay.text}
|
||||
</Tag>
|
||||
<Text strong>{item.criterion}</Text>
|
||||
<Text type="secondary">({item.score}分)</Text>
|
||||
</Space>
|
||||
}
|
||||
key={index}
|
||||
>
|
||||
<Space direction="vertical" size="middle" style={{ width: '100%' }}>
|
||||
{/* 评分 */}
|
||||
<div>
|
||||
<Text strong>评分:</Text>
|
||||
<Text style={{ fontSize: 18, marginLeft: 8, color: '#1890ff' }}>
|
||||
{item.score} / 100
|
||||
</Text>
|
||||
</div>
|
||||
|
||||
{/* 问题列表 */}
|
||||
{item.issues && item.issues.length > 0 && (
|
||||
<div>
|
||||
<Text strong style={{ color: '#f5222d' }}>发现的问题:</Text>
|
||||
<List
|
||||
size="small"
|
||||
bordered
|
||||
dataSource={item.issues}
|
||||
renderItem={(issue: string) => (
|
||||
<List.Item>
|
||||
<CloseCircleOutlined style={{ color: '#f5222d', marginRight: 8 }} />
|
||||
{issue}
|
||||
</List.Item>
|
||||
)}
|
||||
style={{ marginTop: 8 }}
|
||||
/>
|
||||
</div>
|
||||
)}
|
||||
|
||||
{/* 改进建议 */}
|
||||
{item.suggestions && item.suggestions.length > 0 && (
|
||||
<div>
|
||||
<Text strong style={{ color: '#52c41a' }}>改进建议:</Text>
|
||||
<List
|
||||
size="small"
|
||||
bordered
|
||||
dataSource={item.suggestions}
|
||||
renderItem={(suggestion: string) => (
|
||||
<List.Item>
|
||||
<CheckCircleOutlined style={{ color: '#52c41a', marginRight: 8 }} />
|
||||
{suggestion}
|
||||
</List.Item>
|
||||
)}
|
||||
style={{ marginTop: 8 }}
|
||||
/>
|
||||
</div>
|
||||
)}
|
||||
|
||||
{/* 无问题提示 */}
|
||||
{(!item.issues || item.issues.length === 0) && item.status === 'pass' && (
|
||||
<Alert
|
||||
message="该项检查通过,无需修改"
|
||||
type="success"
|
||||
showIcon
|
||||
/>
|
||||
)}
|
||||
</Space>
|
||||
</Panel>
|
||||
);
|
||||
})}
|
||||
</Collapse>
|
||||
</Card>
|
||||
</Space>
|
||||
</Card>
|
||||
);
|
||||
};
|
||||
|
||||
export default EditorialReview;
|
||||
|
||||
Reference in New Issue
Block a user