1212 */
1313import { useCallback , useEffect , useState } from "react" ;
1414import { invoke , convertFileSrc } from "@tauri-apps/api/core" ;
15- import type { NoteFilterResult , TextFilterDecision , TextFilterReview , TextFilterStatus } from "../types" ;
15+ import type { Note , NoteFilterResult , TextFilterDecision , TextFilterReview , TextFilterStatus } from "../types" ;
1616import AiRefineCard from "./AiRefineCard" ;
1717
1818const btn : React . CSSProperties = { padding : "5px 10px" , cursor : "pointer" , fontSize : 12 } ;
@@ -79,6 +79,9 @@ export default function NotePreviewView({ sessionId }: { sessionId: number }) {
7979 const [ aiDecisions , setAiDecisions ] = useState < TextFilterDecision [ ] > ( [ ] ) ;
8080 // v0.7.3(REQ-160):屏配图 baseUrl(图集同款)
8181 const [ baseUrl , setBaseUrl ] = useState ( "" ) ;
82+ // 2026-08-21:AI 精修采纳后预览联动——采纳成功 → 拉取笔记(精修版)就地展示,
83+ // 解决「精修成功但预览无变化、看起来没被使用」的体验缺口(原 onApplied 未接线)
84+ const [ adopted , setAdopted ] = useState < Note | null > ( null ) ;
8285
8386 const load = useCallback ( async ( ) => {
8487 try {
@@ -89,6 +92,17 @@ export default function NotePreviewView({ sessionId }: { sessionId: number }) {
8992 }
9093 } , [ sessionId ] ) ;
9194
95+ /** AI 精修采纳联动:拉取精修版笔记内容展示(规则版经「回到规则版预览」恢复) */
96+ const handleRefineApplied = useCallback ( async ( noteId : number ) => {
97+ try {
98+ const note = await invoke < Note > ( "get_note" , { id : noteId } ) ;
99+ setAdopted ( note ) ;
100+ setStatus ( `AI 精修版已落库为笔记 #${ noteId } ——预览已切换为精修内容` ) ;
101+ } catch ( e ) {
102+ setStatus ( `已落库为笔记 #${ noteId } ,但读取内容失败: ${ e } ` ) ;
103+ }
104+ } , [ ] ) ;
105+
92106 useEffect ( ( ) => {
93107 void load ( ) ;
94108 void invoke < TextFilterStatus > ( "text_filter_status" ) . then ( setAiStatus ) . catch ( ( ) => undefined ) ;
@@ -191,8 +205,9 @@ export default function NotePreviewView({ sessionId }: { sessionId: number }) {
191205 < button
192206 style = { { ...btn , borderRadius : 6 , background : "#0d9488" , color : "#fff" , border : "none" } }
193207 onClick = { ( ) => void saveToNote ( ) }
208+ title = "仅将规则版草稿落库为笔记;AI 精修版请用下方精修卡内的「采纳落库」"
194209 >
195- 📝 一键落库
210+ 📝 一键落库(规则版)
196211 </ button >
197212 < button
198213 style = { { ...btn , borderRadius : 6 , border : "1px solid #e5e7eb" } }
@@ -201,8 +216,9 @@ export default function NotePreviewView({ sessionId }: { sessionId: number }) {
201216 { showFiltered ? "收起被过滤对照" : `被过滤对照(${ preview . filtered . length } )` }
202217 </ button >
203218 </ div >
204- { /* v0.8.0 M2(REQ-141/145):AI 精修卡——预估确认/异步任务/diff 预览/采纳落库 */ }
205- < AiRefineCard sessionId = { sessionId } />
219+ { /* v0.8.0 M2(REQ-141/145):AI 精修卡——预估确认/异步任务/diff 预览/采纳落库;
220+ 采纳成功 → onApplied 联动切换预览为精修版(2026-08-21 体验修复) */ }
221+ < AiRefineCard sessionId = { sessionId } onApplied = { ( id ) => void handleRefineApplied ( id ) } />
206222 { status && < p style = { { fontSize : 12 , color : "#2563eb" , marginBottom : 6 } } > { status } </ p > }
207223 { aiMeta && (
208224 < p style = { { fontSize : 11 , color : "#6b7280" , marginBottom : 6 } } >
@@ -211,14 +227,32 @@ export default function NotePreviewView({ sessionId }: { sessionId: number }) {
211227 </ p >
212228 ) }
213229
214- { /* 过滤后笔记正文 */ }
215- < div
216- style = { { fontSize : 13 , lineHeight : 1.6 , background : "#fff" , border : "1px solid #e5e7eb" , borderRadius : 8 , padding : 12 } }
217- dangerouslySetInnerHTML = { { __html : renderMarkdown ( preview . markdown , baseUrl ) } }
218- />
230+ { /* 正文:采纳精修后展示精修版(可回到规则版);否则展示规则版草稿 */ }
231+ { adopted ? (
232+ < div style = { { border : "1px solid #a7f3d0" , borderRadius : 8 , background : "#ecfdf5" , padding : 10 , marginBottom : 8 } } >
233+ < div style = { { display : "flex" , alignItems : "center" , gap : 8 , marginBottom : 6 } } >
234+ < span style = { { fontWeight : 600 , fontSize : 12 , color : "#047857" } } > ✨ AI 精修版 · 笔记 #{ adopted . id } </ span >
235+ < button
236+ style = { { ...btn , borderRadius : 6 , border : "1px solid #d1d5db" , background : "#fff" } }
237+ onClick = { ( ) => setAdopted ( null ) }
238+ >
239+ 回到规则版预览
240+ </ button >
241+ </ div >
242+ < div
243+ style = { { fontSize : 13 , lineHeight : 1.6 , background : "#fff" , border : "1px solid #d1fae5" , borderRadius : 6 , padding : 12 } }
244+ dangerouslySetInnerHTML = { { __html : renderMarkdown ( adopted . content , baseUrl ) } }
245+ />
246+ </ div >
247+ ) : (
248+ < div
249+ style = { { fontSize : 13 , lineHeight : 1.6 , background : "#fff" , border : "1px solid #e5e7eb" , borderRadius : 8 , padding : 12 } }
250+ dangerouslySetInnerHTML = { { __html : renderMarkdown ( preview . markdown , baseUrl ) } }
251+ />
252+ ) }
219253
220254 { /* 被过滤内容对照(可复查误杀——来源定位原料) */ }
221- { showFiltered && (
255+ { showFiltered && ! adopted && (
222256 < div style = { { marginTop : 10 , border : "1px solid #fee2e2" , borderRadius : 8 , padding : 10 , background : "#fff7f7" } } >
223257 < div style = { { fontSize : 12 , fontWeight : 600 , color : "#b91c1c" , marginBottom : 6 } } >
224258 被过滤内容(原料层未动——如属误杀请在产物/笔记中人工补回)
0 commit comments