@@ -25,6 +25,8 @@ pub(crate) const TITLE_MAX_CHARS: usize = 100;
2525const CONTENT_MAX_CHARS : usize = 200_000 ;
2626/// 搜索关键词最大长度。
2727const KEYWORD_MAX_CHARS : usize = 100 ;
28+ /// 标签最大长度(防超长标签字符串)。
29+ const TAG_MAX_CHARS : usize = 50 ;
2830/// 一键流水线最大图片数。
2931const MAX_IMAGES : usize = 20 ;
3032/// 拼接输入段/块数量上限(防恶意超大列表拖垮拼接)。
@@ -194,6 +196,8 @@ pub async fn save_draft_as_note(state: State<'_, AppState>, draft: NoteDraft) ->
194196 session_id : None ,
195197 rule_version : None ,
196198 purify_stats : None ,
199+ tags : None ,
200+ properties : None ,
197201 } ;
198202 state. db . create_note ( & new) . map_err ( |e| e. to_string ( ) )
199203}
@@ -261,6 +265,8 @@ pub async fn process_to_note(
261265 session_id : None ,
262266 rule_version : None ,
263267 purify_stats : None ,
268+ tags : None ,
269+ properties : None ,
264270 } )
265271 . map_err ( |e| e. to_string ( ) )
266272 } )
@@ -280,14 +286,22 @@ pub async fn create_note(state: State<'_, AppState>, new: NewNote) -> Result<Not
280286 // 手动笔记无净化规则版本/统计(None 诚实降级——REQ-171 口径)
281287 rule_version : None ,
282288 purify_stats : None ,
289+ tags : None ,
290+ properties : None ,
283291 } ;
284292 state. db . create_note ( & new) . map_err ( |e| e. to_string ( ) )
285293}
286294
287- /// 列出全部笔记(REQ-004)。
295+ /// 列出全部笔记(REQ-004;v0.10.0 支持排序模式 )。
288296#[ tauri:: command]
289- pub async fn list_notes ( state : State < ' _ , AppState > ) -> Result < Vec < Note > , String > {
290- state. db . list_notes ( ) . map_err ( |e| e. to_string ( ) )
297+ pub async fn list_notes (
298+ state : State < ' _ , AppState > ,
299+ sort_mode : Option < crate :: types:: NoteSortMode > ,
300+ ) -> Result < Vec < Note > , String > {
301+ match sort_mode {
302+ Some ( mode) => state. db . list_notes_sorted ( & mode) . map_err ( |e| e. to_string ( ) ) ,
303+ None => state. db . list_notes ( ) . map_err ( |e| e. to_string ( ) ) ,
304+ }
291305}
292306
293307/// 读取单条笔记(REQ-004)。
@@ -308,21 +322,32 @@ pub async fn update_note(
308322 id : i64 ,
309323 title : String ,
310324 content : String ,
325+ create_version : Option < bool > ,
311326) -> Result < bool , String > {
312327 if id <= 0 {
313328 return Err ( "无效的笔记 id" . to_string ( ) ) ;
314329 }
315330 let title = truncate_chars ( title, TITLE_MAX_CHARS ) ;
316331 let content = truncate_chars ( content, CONTENT_MAX_CHARS ) ;
317- state
318- . db
319- . versioned_save (
320- id,
321- & content,
322- crate :: note_version:: NoteVersionSource :: UserEdit ,
323- & crate :: note_version:: VersionMeta :: default ( ) ,
324- )
325- . map_err ( |e| e. to_string ( ) ) ?;
332+ // v0.10.1 F2:轻量保存(自动保存/失焦/任务勾选回写)——只刷新内容不建版本
333+ // (v0.10.0 状态一致性规则:版本快照只在显式保存/AI 采纳时建立)
334+ if create_version == Some ( false ) {
335+ return state. db . update_note ( id, & title, & content) . map_err ( |e| e. to_string ( ) ) ;
336+ }
337+ // v0.10.1 F3:内容去重——与最新版本相同则跳过 versioned_save
338+ // (防 Ctrl+S 空保存/重复保存污染版本时间线;无版本时照常建链)
339+ let latest = state. db . latest_version_content ( id) . map_err ( |e| e. to_string ( ) ) ?;
340+ if latest. as_deref ( ) != Some ( content. as_str ( ) ) {
341+ state
342+ . db
343+ . versioned_save (
344+ id,
345+ & content,
346+ crate :: note_version:: NoteVersionSource :: UserEdit ,
347+ & crate :: note_version:: VersionMeta :: default ( ) ,
348+ )
349+ . map_err ( |e| e. to_string ( ) ) ?;
350+ }
326351 state
327352 . db
328353 . update_note ( id, & title, & content)
@@ -339,11 +364,54 @@ pub async fn delete_note(state: State<'_, AppState>, id: i64) -> Result<bool, St
339364 state. db . delete_note ( id) . map_err ( |e| e. to_string ( ) )
340365}
341366
342- /// 搜索笔记(REQ-004;关键词截断——TD-005)。
367+ /// 搜索笔记(REQ-004;关键词截断——TD-005;v0.10.0 支持按标签过滤 )。
343368#[ tauri:: command]
344- pub async fn search_notes ( state : State < ' _ , AppState > , keyword : String ) -> Result < Vec < Note > , String > {
369+ pub async fn search_notes (
370+ state : State < ' _ , AppState > ,
371+ keyword : String ,
372+ tag : Option < String > ,
373+ ) -> Result < Vec < Note > , String > {
374+ // 按标签过滤优先
375+ if let Some ( t) = tag {
376+ return state
377+ . db
378+ . search_notes_by_tag ( & truncate_chars ( t, TAG_MAX_CHARS ) )
379+ . map_err ( |e| e. to_string ( ) ) ;
380+ }
345381 state
346382 . db
347383 . search_notes ( & truncate_chars ( keyword, KEYWORD_MAX_CHARS ) )
348384 . map_err ( |e| e. to_string ( ) )
349385}
386+
387+ /// 更新笔记标签(v0.10.0)。
388+ #[ tauri:: command]
389+ pub async fn update_note_tags (
390+ state : State < ' _ , AppState > ,
391+ id : i64 ,
392+ tags : String ,
393+ ) -> Result < bool , String > {
394+ if id <= 0 {
395+ return Err ( "无效的笔记 id" . to_string ( ) ) ;
396+ }
397+ state
398+ . db
399+ . update_note_tags ( id, & tags)
400+ . map_err ( |e| e. to_string ( ) )
401+ }
402+
403+ /// 更新笔记固定状态(v0.10.0)。
404+ #[ tauri:: command]
405+ pub async fn update_note_pin (
406+ state : State < ' _ , AppState > ,
407+ id : i64 ,
408+ pin : i64 ,
409+ ) -> Result < bool , String > {
410+ if id <= 0 {
411+ return Err ( "无效的笔记 id" . to_string ( ) ) ;
412+ }
413+ state
414+ . db
415+ . update_note_pin ( id, pin)
416+ . map_err ( |e| e. to_string ( ) )
417+ }
0 commit comments