fix(ai): 修复分析结果 JSON 嵌套 bug
Some checks failed
CI / rust-check (push) Has been cancelled
CI / rust-test (push) Has been cancelled
CI / frontend-build (push) Has been cancelled
CI / security-audit (push) Has been cancelled

- replay_cached 直接回放纯文本,不再包装 JSON 壳
- complete_analysis 跳过已完成的记录,防止缓存命中时覆写
- 前端 AnalysisContent 增加 extractPlainText 递归解析 JSON
This commit is contained in:
iven
2026-05-05 19:45:36 +08:00
parent 8a0c9670e6
commit 1f91dcc5cc
2 changed files with 23 additions and 10 deletions

View File

@@ -60,9 +60,23 @@ const SUGGESTION_STATUS_CONFIG: Record<string, { color: string; text: string }>
// 分析结果渲染Markdown 风格)
// ---------------------------------------------------------------------------
/** 递归提取 JSON 嵌套中的实际文本内容 */
function extractPlainText(raw: string): string {
try {
const parsed = JSON.parse(raw);
if (typeof parsed === 'object' && parsed !== null && typeof parsed.content === 'string') {
return extractPlainText(parsed.content);
}
return raw;
} catch {
return raw;
}
}
function AnalysisContent({ content, isDark }: { content: string; isDark: boolean }) {
const text = extractPlainText(content);
// 简单的 Markdown 风格渲染
const lines = content.split('\n');
const lines = text.split('\n');
const rendered = lines.map((line, i) => {
// 标题行
if (line.startsWith('### ')) {

View File

@@ -128,20 +128,14 @@ impl AnalysisService {
Ok((stream, analysis_id, provider_name))
}
/// 将缓存结果构造为一次性 Stream模拟 SSE 单条返回
/// 将缓存结果构造为一次性 Stream直接回放纯文本,不额外包装 JSON
fn replay_cached(
&self,
content: String,
metadata: serde_json::Value,
_metadata: serde_json::Value,
) -> Pin<Box<dyn Stream<Item = AiResult<String>> + Send>> {
use futures::stream;
let payload = serde_json::json!({
"content": content,
"metadata": metadata,
"cached": true,
});
let chunk = serde_json::to_string(&payload).unwrap_or_default();
Box::pin(stream::once(async move { Ok(chunk) }))
Box::pin(stream::once(async move { Ok(content) }))
}
/// 更新分析记录为完成
@@ -156,6 +150,11 @@ impl AnalysisService {
.await?
.ok_or_else(|| AiError::AnalysisNotFound(analysis_id.to_string()))?;
// 缓存回放时记录已是 completed跳过重复更新
if entity.status == "completed" {
tracing::debug!(analysis = %analysis_id, "分析已完成,跳过重复 complete");
return Ok(());
}
let mut active: ai_analysis::ActiveModel = entity.into();
active.status = Set("completed".into());
active.result_content = Set(Some(content));