Files
writer-work-flow/apps/web/components/review/AcceptPanel.tsx
Yaojia Wang c51623836f fix+feat(ux): 已存草稿显示已保存(Q6) + AI 推理动画指示器(A)
- Q6 bug: useAutosave 加 initialSavedText,进页种入已存草稿时初始即「已保存」,修「加载已存草稿却显示尚未保存」的误导。
- A: 新 ThinkingIndicator(三点波动,motion-safe 尊重 reduced-motion)接入审稿进行中/验收中/回炉中三处静态文案,长等待看得见在工作。
2026-06-21 18:05:55 +02:00

114 lines
3.7 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 { AcceptResponse } from "@/lib/api/types";
import { buildAcceptPreview } from "@/lib/review/accept-preview";
import { ThinkingIndicator } from "@/components/ThinkingIndicator";
interface AcceptPanelProps {
conflictCount: number;
unresolvedCount: number;
// R3当前伏笔建议数验收前清单提醒只读不自动落库
foreshadowCount: number;
accepting: boolean;
result: AcceptResponse | null;
onAccept: () => void;
}
// 验收 gateUX §9 / §8.4):未决禁验收(置灰 + 文案),验收后呈现「本次将更新」清单。
export function AcceptPanel({
conflictCount,
unresolvedCount,
foreshadowCount,
accepting,
result,
onAccept,
}: AcceptPanelProps) {
const blocked = unresolvedCount > 0;
const preview = buildAcceptPreview({
conflictCount,
foreshadowSuggestions: foreshadowCount,
});
if (result) {
return (
<div className="rounded border border-pass/50 bg-panel p-4">
<h3 className="mb-2 text-sm font-semibold text-pass"></h3>
<ul className="space-y-1 text-xs text-ink-soft">
<li>
<span className="font-mono text-ink">v{result.accepted_version}</span>
</li>
<li>
{result.digest_added ? "已新增一行" : "未变更"}
</li>
<li>
<span className="font-mono text-ink">
{result.decisions_recorded}
</span>{" "}
</li>
{result.review_id ? (
<li className="truncate">
<span className="font-mono">{result.review_id}</span>
</li>
) : null}
</ul>
</div>
);
}
return (
<div className="rounded border border-line bg-panel p-4">
{blocked ? (
<p className="mb-2 text-xs text-conflict" role="status">
{unresolvedCount}
</p>
) : (
<>
<p className="mb-2 text-xs text-ink-soft">
{conflictCount === 0
? "无冲突,可直接验收。"
: "全部冲突已裁决,可验收本章。"}
</p>
{/* R3验收前「本次将更新」清单预期落库口径以验收回执为准。 */}
<div className="mb-3 rounded border border-line/70 bg-bg/50 p-3">
<h4 className="mb-1.5 text-xs font-semibold text-ink">
</h4>
<ul className="space-y-1.5">
{preview.map((item) => (
<li key={item.label} className="flex gap-2 text-xs text-ink-soft">
<span className="text-cinnabar" aria-hidden="true">
</span>
<span>
<span className="text-ink">{item.label}</span>
<span className="text-ink-soft">{item.detail}</span>
</span>
</li>
))}
</ul>
<p className="mt-2 text-[11px] text-ink-soft/70">
</p>
</div>
</>
)}
<button
type="button"
onClick={onAccept}
disabled={blocked || accepting}
aria-disabled={blocked || accepting}
className="w-full rounded bg-cinnabar px-4 py-2 text-sm text-panel hover:opacity-90 disabled:cursor-not-allowed disabled:opacity-40"
>
{accepting ? (
<ThinkingIndicator label="验收中" className="justify-center" />
) : (
"全部处理完 → 验收本章"
)}
</button>
</div>
);
}