feat(ai写作): 草稿局部修改只改命中章节,支持改章节标题,修改时右侧流式重写
用户在草稿确认填修改意见(user_revise)时,按章节定位只重写命中章节、 其余字节级保留;新增范围识别区分「改标题」与「改正文」,改标题同步回写 outline 使其持久生效(修复改章节标题不生效);整体性/结构性意见自动回退 整篇重写。前端新增 isRevising:修改时右侧先恢复初始占位(清空旧稿), 重写流到达后实时展示被改章节的流式重写。 Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
1 parent
42f55251f2
commit
c117e296cb
6 files changed
+125
-51
No files matched your search
@@ -41,10 +41,23 @@ export function AIWritingDraftPanel() {
|
||||
const showCompletedDraftView = isDraftEditable || isHistoryMode;
|
||||
|
||||
const writingStatus = writing?.state.status;
|
||||
const streamingSectionCount = writing?.state.streamingDraftSections.length ?? 0;
|
||||
|
||||
// 按用户意见修改中、且重写流还没开始(无任何流式章节):右侧先恢复初始空占位,
|
||||
// 把旧稿清掉;一旦重写流式 chunk 到达(streamingDraftSections 非空)就走下面的
|
||||
// 流式预览,实时展示重写过程;draft_ready 后 isRevising 置回 false 显示新成稿。
|
||||
if (writing?.state.isRevising && streamingSectionCount === 0) {
|
||||
return (
|
||||
<div className="h-full bg-muted/10 border-l">
|
||||
<DraftWaitingPlaceholder />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
// 仅当章节仍在累积时走流式 Markdown;draft_ready 清空 sections 后即使 status 尚未切走也进画布
|
||||
const isActivelyStreamingDraft =
|
||||
(writingStatus === 'writing_draft' || writingStatus === 'revising') &&
|
||||
(writing?.state.streamingDraftSections.length ?? 0) > 0;
|
||||
streamingSectionCount > 0;
|
||||
|
||||
const streamingMarkdown = isActivelyStreamingDraft && writing
|
||||
? assembleStreamingDraftMarkdown(
|
||||
|
||||
@@ -70,6 +70,7 @@ const INITIAL_STATE: AIWritingState = {
|
||||
streamingReviewItems: [],
|
||||
revisionSummary: null,
|
||||
pendingRevisionContext: null,
|
||||
isRevising: false,
|
||||
};
|
||||
|
||||
export { INITIAL_STATE };
|
||||
@@ -118,7 +119,8 @@ export function reducer(prev: AIWritingState, action: Action): AIWritingState {
|
||||
...(ns === 'writing_outline' ? { outlineStreamingText: '', outlineThinkingText: '' } : {}),
|
||||
...(ns === 'writing_draft' ? { streamingDraftSections: [], streamingDraftTitle: '' } : {}),
|
||||
...(ns === 'reviewing' ? { streamingReviewItems: [] } : {}),
|
||||
...(ns === 'revising' ? { streamingDraftSections: [], streamingDraftTitle: '' } : {}),
|
||||
// 进入「修改」:右侧画布恢复初始空占位(isRevising),不再显示旧稿/流式重写
|
||||
...(ns === 'revising' ? { streamingDraftSections: [], streamingDraftTitle: '', isRevising: true } : {}),
|
||||
completedInterventions: [...prev.completedInterventions, action.record],
|
||||
...(action.pendingRevisionContext ? { pendingRevisionContext: action.pendingRevisionContext } : {}),
|
||||
};
|
||||
@@ -357,6 +359,8 @@ function handleEvent(prev: AIWritingState, event: ProgressEvent): AIWritingState
|
||||
streamingDraftTitle: '',
|
||||
revisionSummary: summary,
|
||||
pendingRevisionContext: null,
|
||||
// 修改完成:解除右侧空占位,展示新成稿
|
||||
isRevising: false,
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -389,4 +389,7 @@ export interface AIWritingState {
|
||||
skippedIssues: ReviewIssue[];
|
||||
oldWordCount: number;
|
||||
} | null;
|
||||
/** 是否正按用户意见修改中(revising 提交起 → draft_ready 止)。
|
||||
* 为 true 时右侧画布恢复初始空占位,不展示旧稿 / 流式重写过程。 */
|
||||
isRevising: boolean;
|
||||
}
|
||||
Reference in new issue
Block a user