@@ -16,7 +16,7 @@ use std::collections::HashSet;
1616use tauri:: State ;
1717
1818use crate :: ai_protocol:: TextFilterDecision ;
19- use crate :: analysis:: analyze_session_opt;
19+ use crate :: analysis:: { analyze_session_opt, SessionAnalysis } ;
2020use crate :: commands:: { normalize_title, AppState } ;
2121use crate :: db:: Db ;
2222use crate :: db_sessions:: SESSION_STATUS_RECORDING ;
@@ -53,25 +53,15 @@ fn load_note_material(
5353 Ok ( ( session, segments, ocr_blocks) )
5454}
5555
56- /// 结构渲染接线(v0.7.6 REQ-177/178,预览/落库/AI 复核三出口共用)。
57- ///
58- /// @ai-context: 在 refresh_screen_points 之后调用——净化/配图/警示行先落定,
59- /// 结构层在其上叠加章节标题与词汇表块;预览与落库同函数同口径
60- /// (REQ-081 单一管线双出口契约)。
61- /// @ai-context: 输入为会话原料(segments/ocr_blocks)——章节检测/大纲标题/
62- /// 术语表均为纯本地规则(analysis/outline/glossary 复用)——
63- /// 不依赖云端 AI(本地优先铁律);失败不阻断转笔记主链路
64- /// (分析失败按空结构处理,不抛错)。
65- /// @ai-context: pub(crate)(v0.7.6 审查修复):commands_ai.rs AI 复核出口
66- /// 复用——复核后预览与落库同含结构层(REQ-081 三出口一致)。
67- pub ( crate ) fn apply_note_structure (
68- result : & mut NoteFilterResult ,
56+ /// 结构渲染分析(纯本地:章节/术语——apply_note_structure 与
57+ /// build_rule_draft_with_analysis 共用,审查修复 2026-08-21:消除双跑)。
58+ fn analyze_for_structure (
6959 db : & Db ,
7060 session : & Session ,
7161 segments : & [ SessionSegment ] ,
7262 ocr_blocks : & [ SessionOcrBlock ] ,
7363 env : & PurifyEnv ,
74- ) {
64+ ) -> SessionAnalysis {
7565 // 档案驱动:章节检测/术语表按档案开关(网课开、口播关——analysis 内部门控)
7666 let kind = session
7767 . profile
@@ -94,7 +84,41 @@ pub(crate) fn apply_note_structure(
9484 events,
9585 screens : Vec :: new ( ) ,
9686 } ;
97- let analysis = analyze_session_opt ( & detail, kind, & env. symbol ) ;
87+ analyze_session_opt ( & detail, kind, & env. symbol )
88+ }
89+
90+ /// 结构渲染接线(v0.7.6 REQ-177/178,预览/落库/AI 复核三出口共用)。
91+ ///
92+ /// @ai-context: 在 refresh_screen_points 之后调用——净化/配图/警示行先落定,
93+ /// 结构层在其上叠加章节标题与词汇表块;预览与落库同函数同口径
94+ /// (REQ-081 单一管线双出口契约)。
95+ /// @ai-context: 输入为会话原料(segments/ocr_blocks)——章节检测/大纲标题/
96+ /// 术语表均为纯本地规则(analysis/outline/glossary 复用)——
97+ /// 不依赖云端 AI(本地优先铁律);失败不阻断转笔记主链路
98+ /// (分析失败按空结构处理,不抛错)。
99+ /// @ai-context: pub(crate)(v0.7.6 审查修复):commands_ai.rs AI 复核出口
100+ /// 复用——复核后预览与落库同含结构层(REQ-081 三出口一致)。
101+ pub ( crate ) fn apply_note_structure (
102+ result : & mut NoteFilterResult ,
103+ db : & Db ,
104+ session : & Session ,
105+ segments : & [ SessionSegment ] ,
106+ ocr_blocks : & [ SessionOcrBlock ] ,
107+ env : & PurifyEnv ,
108+ ) {
109+ let analysis = analyze_for_structure ( db, session, segments, ocr_blocks, env) ;
110+ apply_note_structure_with_analysis ( result, session, ocr_blocks, env, & analysis) ;
111+ }
112+
113+ /// 结构渲染接线(复用外部分析结果——精修任务避免双跑 analyze,审查修复
114+ /// 2026-08-21:build_rule_draft_with_analysis 提供一次分析供结构层 + 任务共用)。
115+ pub ( crate ) fn apply_note_structure_with_analysis (
116+ result : & mut NoteFilterResult ,
117+ _session : & Session ,
118+ ocr_blocks : & [ SessionOcrBlock ] ,
119+ env : & PurifyEnv ,
120+ analysis : & SessionAnalysis ,
121+ ) {
98122 let outline = detect_outline_smart ( ocr_blocks, & result. ocr_screens , & OutlineConfig :: default ( ) ) ;
99123 let _ = render_note_structure (
100124 result,
@@ -119,6 +143,19 @@ pub(crate) fn build_rule_draft(
119143 id : i64 ,
120144 title : Option < String > ,
121145) -> Result < NoteFilterResult , String > {
146+ Ok ( build_rule_draft_with_analysis ( db, ui_junk, env, data_dir, id, title) ?. 0 )
147+ }
148+
149+ /// 构建规则草稿 + 结构分析(审查修复 2026-08-21:分析与结构渲染一次完成并
150+ /// 返回 analysis——AI 精修任务直接复用章节/术语,消除二次 analyze 双跑)。
151+ pub ( crate ) fn build_rule_draft_with_analysis (
152+ db : & Db ,
153+ ui_junk : & UiJunkList ,
154+ env : & PurifyEnv ,
155+ data_dir : & std:: path:: Path ,
156+ id : i64 ,
157+ title : Option < String > ,
158+ ) -> Result < ( NoteFilterResult , SessionAnalysis ) , String > {
122159 let ( session, segments, ocr_blocks) = load_note_material ( db, id) ?;
123160 let fallback = format ! ( "{}(会话)" , session. title) ;
124161 let title = normalize_title ( title. unwrap_or_default ( ) , & fallback) ;
@@ -132,8 +169,9 @@ pub(crate) fn build_rule_draft(
132169 crate :: note_filter:: refresh_screen_points ( & mut result) ;
133170 // v0.7.6(REQ-177/178):结构渲染——章节标题 + 词汇表块(纯本地增强层;
134171 // 无结构数据/分析失败 → 原样输出不阻断,见 apply_note_structure)
135- apply_note_structure ( & mut result, db, & session, & segments, & ocr_blocks, env) ;
136- Ok ( result)
172+ let analysis = analyze_for_structure ( db, & session, & segments, & ocr_blocks, env) ;
173+ apply_note_structure_with_analysis ( & mut result, & session, & ocr_blocks, env, & analysis) ;
174+ Ok ( ( result, analysis) )
137175}
138176
139177/// 会话 → 笔记核心(v0.7.1 提取:单条与批量共用同一管线)。
0 commit comments