ai写作修改

This commit is contained in:
董宏凯 committed 2026-06-02 20:36:22 +08:00
1 parent 30410b0a93
commit 7efedc7b44
23 files changed
+1355 -16

No files matched your search

@@ -0,0 +1,79 @@
import { useEffect, useRef } from 'react';
import { Brain, PenLine } from 'lucide-react';
import type { StreamingDraftSection } from '../../types/ai-writing';
interface DraftGeneratingViewProps {
sections: StreamingDraftSection[];
}
/** 思考过程框:纯只读展示,跟随内容自动滚到底(仅操作 DOM,不触发 setState) */
function ThinkingBox({ text, done }: { text: string; done: boolean }) {
const preRef = useRef<HTMLPreElement>(null);
useEffect(() => {
if (preRef.current) preRef.current.scrollTop = preRef.current.scrollHeight;
}, [text]);
return (
<div className="rounded-lg border border-amber-200 dark:border-amber-900 bg-amber-50/50 dark:bg-amber-950/20 overflow-hidden">
<div className="flex items-center gap-1.5 px-2.5 py-1.5 bg-amber-100/40 dark:bg-amber-900/30">
<Brain className="size-3 text-amber-500 shrink-0" />
<span className="text-[11px] font-medium text-amber-600 dark:text-amber-400">思考过程</span>
</div>
<pre
ref={preRef}
className="text-[10px] font-mono leading-relaxed px-2.5 py-2 text-amber-700/70 dark:text-amber-300/60 whitespace-pre-wrap max-h-40 overflow-y-auto italic"
>
{text}
{!done && (
<span className="inline-block w-0.5 h-3 bg-amber-400 ml-0.5 align-text-bottom animate-[blink_1s_step-end_infinite]" />
)}
</pre>
</div>
);
}
/** 「内容生成中」骨架屏:闪烁的占位行,提示正文正在右侧实时生成 */
function GeneratingSkeleton() {
return (
<div className="rounded-xl border bg-card shadow-sm p-4">
<div className="flex items-center gap-2 mb-3">
<PenLine className="size-3.5 text-primary animate-pulse" />
<span className="text-xs font-medium text-foreground">内容生成中…</span>
<span className="text-[11px] text-muted-foreground ml-auto">正文已在右侧实时显示</span>
</div>
<div className="space-y-2.5">
<div className="h-3 rounded bg-muted/70 animate-pulse w-[92%]" />
<div className="h-3 rounded bg-muted/70 animate-pulse w-full" />
<div className="h-3 rounded bg-muted/70 animate-pulse w-[85%]" />
<div className="h-3 rounded bg-muted/70 animate-pulse w-[70%]" />
</div>
<style>{`
@keyframes blink {
0%, 100% { opacity: 1; }
50% { opacity: 0; }
}
`}</style>
</div>
);
}
/**
* 作家写作 / 按意见修改阶段,左侧的轻量「生成中」视图。
*
* 刻意不再逐章节渲染流式正文(那套 DraftStreamingView 含逐 chunk 的平滑
* scrollIntoView 等重型操作):正文已在右侧实时显示,左侧只需告知"正在生成",
* 若模型有思考过程则一并展示。这样左侧每个 chunk 的渲染开销极小,避免更新风暴。
*/
export function DraftGeneratingView({ sections }: DraftGeneratingViewProps) {
// 按章节顺序拼接非空思考内容;是否仍在思考以"存在未完成章节"近似
const ordered = [...sections].sort((a, b) => a.sectionIndex - b.sectionIndex);
const thinking = ordered.map((s) => s.thinkingText).filter(Boolean).join('\n\n');
const thinkingDone = sections.length > 0 && sections.every((s) => s.isDone);
return (
<div className="px-4 pb-4 space-y-3">
{thinking && <ThinkingBox text={thinking} done={thinkingDone} />}
<GeneratingSkeleton />
</div>
);
}