Files
GEOAgentArticleOptimizer/src/components/cases/article-case-detail.tsx
T
2026-07-08 13:59:26 +08:00

150 lines
4.5 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
"use client";
import type {
ArticleCaseInputPayload,
ArticleResultVersionPayload,
OptimizationResultVersion,
} from "../../lib/cases/types";
interface ArticleCaseDetailProps {
input: unknown;
version: OptimizationResultVersion | null;
}
const platformLabels: Record<string, string> = {
official_site: "官网文章",
media_article: "媒体稿",
comparison_review: "对比评测",
recommendation_list: "推荐榜单",
};
export function ArticleCaseDetail({ input, version }: ArticleCaseDetailProps) {
const payload = isArticleInput(input) ? input : null;
const result = isArticleResult(version?.payload) ? version.payload : null;
return (
<>
<section className="panel stack">
<div className="panel-heading">文章输入</div>
{payload ? (
<>
<div className="case-meta-grid">
<MetaItem label="标题" value={payload.source_title || "未填写"} />
<MetaItem
label="目标平台"
value={platformLabels[payload.publish_platform] ?? payload.publish_platform}
/>
<MetaItem
label="补充要求"
value={payload.user_instructions || "无"}
/>
<MetaItem
label="图片输入"
value={
payload.image_inputs.length > 0
? `${payload.image_inputs.length} 条`
: "无"
}
/>
</div>
<pre className="copy-result">{payload.source_body}</pre>
{payload.image_inputs.length > 0 ? (
<div className="tag-row">
{payload.image_inputs.map((item, index) => (
<span className="tag" key={`${item.content}-${index}`}>
{item.type === "link" ? "链接" : "描述"}{item.content}
</span>
))}
</div>
) : null}
</>
) : (
<p className="empty-panel">没有保存输入。</p>
)}
</section>
{payload?.fact_card ? (
<section className="panel stack">
<div className="panel-heading">事实卡</div>
<pre className="case-json-preview">
{JSON.stringify(payload.fact_card, null, 2)}
</pre>
</section>
) : null}
<section className="panel stack">
<div className="panel-heading">优化稿</div>
{result ? (
<>
<article className="preview">
<h2>{result.article.title}</h2>
<p>{result.article.summary}</p>
<pre className="case-markdown-preview">
{result.article.body_markdown}
</pre>
</article>
<section className="stack">
<h3>质量报告</h3>
<div className="qa-list">
{result.qa_report.checks.map((check) => (
<div className="qa-item" key={check.rule_id}>
<div className="qa-title-row">
<strong>{check.rule_id}</strong>
<span className={`status-pill ${check.status}`}>
{check.status}
</span>
</div>
<p>{check.reason}</p>
<small>{check.evidence}</small>
</div>
))}
</div>
</section>
<section className="stack">
<h3>导出文件</h3>
<div className="export-row">
{Object.entries(result.export_paths).map(([name, path]) => (
<a className="download-link" href={path} key={name}>
{name}
</a>
))}
</div>
</section>
</>
) : (
<p className="empty-panel">
{version?.error_summary ?? "当前版本没有优化稿。"}
</p>
)}
</section>
</>
);
}
function MetaItem({ label, value }: { label: string; value: string }) {
return (
<div>
<span>{label}</span>
<strong>{value}</strong>
</div>
);
}
function isArticleInput(value: unknown): value is ArticleCaseInputPayload {
return (
value !== null &&
typeof value === "object" &&
"source_body" in value &&
"publish_platform" in value
);
}
function isArticleResult(value: unknown): value is ArticleResultVersionPayload {
return (
value !== null &&
typeof value === "object" &&
"article" in value &&
"qa_report" in value
);
}