feat(frontend): integrate GraphRAG scored evaluation results
- Add getUnifiedEvaluationResults API function - Extend ReviewPointsListProps with flowType, scoredResults, scoredSummary - Add ScoredResultCard rendering for graphrag flow_type - Modify reviews.tsx loader to call unified API - Add scored evaluation component imports Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,46 @@
|
||||
import React from 'react';
|
||||
|
||||
interface FieldResultItem {
|
||||
field_path: string;
|
||||
evaluation_as: string;
|
||||
weight: number;
|
||||
scored: number;
|
||||
status: string; // 'filled' | 'placeholder'
|
||||
value: string;
|
||||
page?: string;
|
||||
ai_feedback?: string;
|
||||
}
|
||||
|
||||
interface FieldResultListProps {
|
||||
items: FieldResultItem[];
|
||||
}
|
||||
|
||||
export function FieldResultList({ items }: FieldResultListProps) {
|
||||
return (
|
||||
<div className="field-result-list">
|
||||
{items.map((item) => (
|
||||
<div
|
||||
key={item.field_path}
|
||||
className={`field-result-item field-result-item--${item.status}`}
|
||||
>
|
||||
<div className="field-result-item__header">
|
||||
<span className="field-result-item__name">
|
||||
{item.status === 'filled' ? '✅' : '⚠️'} {item.evaluation_as}
|
||||
</span>
|
||||
<span className="field-result-item__score">
|
||||
{item.scored}/{item.weight}
|
||||
</span>
|
||||
</div>
|
||||
<div className="field-result-item__value">
|
||||
{item.value}
|
||||
</div>
|
||||
{item.ai_feedback && (
|
||||
<div className="field-result-item__feedback">
|
||||
💬 {item.ai_feedback}
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
import React from 'react';
|
||||
|
||||
interface ScoreBarProps {
|
||||
score: number; // Actual score (e.g., 3 for 3/5)
|
||||
fullScore: number; // Max score (e.g., 5)
|
||||
percentage: number; // 0.0-1.0
|
||||
passed: boolean;
|
||||
}
|
||||
|
||||
export function ScoreBar({ score, fullScore, percentage, passed }: ScoreBarProps) {
|
||||
const pct = Math.round(percentage * 100);
|
||||
|
||||
return (
|
||||
<div className="score-bar" data-passed={passed}>
|
||||
<div className="score-bar__header">
|
||||
<span className="score-bar__percentage">{pct}%</span>
|
||||
<span className={`score-bar__status ${passed ? 'passed' : 'failed'}`}>
|
||||
{passed ? '✅ 通过' : '❌ 未通过'}
|
||||
</span>
|
||||
</div>
|
||||
<div className="score-bar__track">
|
||||
<div
|
||||
className={`score-bar__fill ${passed ? 'passed' : 'failed'}`}
|
||||
style={{ width: `${pct}%` }}
|
||||
/>
|
||||
</div>
|
||||
<div className="score-bar__footer">
|
||||
得分 {score.toFixed(1)} / 满分 {fullScore.toFixed(1)}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
@@ -0,0 +1,56 @@
|
||||
import React from 'react';
|
||||
import { ScoreBar } from './ScoreBar';
|
||||
import { FieldResultList } from './FieldResultList';
|
||||
|
||||
interface ScoredResultCardProps {
|
||||
result: {
|
||||
evaluation_point_id: number;
|
||||
code: string;
|
||||
name: string;
|
||||
passed: boolean;
|
||||
machine_score: number; // e.g., 3
|
||||
score: number; // e.g., 5 (full score from evaluation_points)
|
||||
percentage: number;
|
||||
total_score: number; // e.g., 60
|
||||
total_weight: number; // e.g., 100
|
||||
field_results: Array<{
|
||||
field_path: string;
|
||||
evaluation_as: string;
|
||||
weight: number;
|
||||
scored: number;
|
||||
status: string;
|
||||
value: string;
|
||||
page?: string;
|
||||
ai_feedback?: string;
|
||||
}>;
|
||||
missing_fields?: string[];
|
||||
ai_suggestion?: string;
|
||||
};
|
||||
}
|
||||
|
||||
export function ScoredResultCard({ result }: ScoredResultCardProps) {
|
||||
return (
|
||||
<div className="scored-result-card" data-passed={result.passed}>
|
||||
<div className="scored-result-card__header">
|
||||
<span className="scored-result-card__code">{result.code}</span>
|
||||
<span className="scored-result-card__name">{result.name}</span>
|
||||
</div>
|
||||
|
||||
<ScoreBar
|
||||
score={result.machine_score}
|
||||
fullScore={result.score}
|
||||
percentage={result.percentage}
|
||||
passed={result.passed}
|
||||
/>
|
||||
|
||||
<FieldResultList items={result.field_results} />
|
||||
|
||||
{result.ai_suggestion && (
|
||||
<div className="scored-result-card__suggestion">
|
||||
<strong>💡 建议:</strong>
|
||||
<span>{result.ai_suggestion}</span>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
export { ScoreBar } from './ScoreBar';
|
||||
export { FieldResultList } from './FieldResultList';
|
||||
export { ScoredResultCard } from './ScoredResultCard';
|
||||
Reference in New Issue
Block a user