Files
writer-work-flow/apps/web/lib/review/snippet.ts
Yaojia Wang d81583d5d1 feat(ux): R1+R2 审稿裁决人体学 — 冲突卡内联片段 + 分组/排序/跳下一条/主次按钮
R1: 新 lib/review/snippet.ts 从 where 解析段号取终稿命中段预览,ConflictCard 渲染引用块。
R2: 新 lib/review/grouping.ts 按 type 分组+严重度排序(仅改显示顺序,保留原始 index 守 conflict_index 不变量),组计数徽标、跳到下一条未裁决(环回)、采纳改法主按钮/忽略手改次级。
TDD: snippet 8 测 + grouping 10 测。前端门禁绿: lint/tsc/vitest 201/build。
2026-06-20 15:53:45 +02:00

28 lines
1.3 KiB
TypeScript
Raw Permalink 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.

// R1 · 冲突卡内联上下文片段UX §6.4)。
// `where` 是 LLM 给的文字定位(如「第 3 段主角忽然示弱」M2 无精确字符 offset。
// 这里按段级回放:从 where 解析 1-based 段号 → 取终稿对应段 → 截断成预览。
// 纯逻辑,与 ReviewReport.segmentText 同口径(空行切段),便于 node 环境单测。
// 预览窗口最大字符数(命中段超长时截断,避免撑爆卡片)。
const PREVIEW_MAX = 80;
// 从 where 文案解析 1-based 段号(「第 3 段」→ 3范围「第 46 段」取首个)。无则 null。
export function parseParagraphNo(where: string): number | null {
const match = where.match(/第\s*(\d+)/);
if (!match) return null;
const n = Number(match[1]);
return Number.isInteger(n) && n > 0 ? n : null;
}
// 取终稿第 N 段1-based正文预览无段号/越界/空段 → null卡片回退到「跳转」按钮
export function conflictSnippet(finalText: string, where: string): string | null {
const no = parseParagraphNo(where);
if (no === null) return null;
const paragraphs = finalText.split(/\n{2,}/);
const paragraph = paragraphs[no - 1]?.trim();
if (!paragraph) return null;
return paragraph.length <= PREVIEW_MAX
? paragraph
: `${paragraph.slice(0, PREVIEW_MAX)}`;
}