Skip to content

Commit d7921d8

Browse files
committed
refactor(rust): 拆 types.rs 第 3 步 — 笔记与学习循环域
1 parent d548522 commit d7921d8

3 files changed

Lines changed: 283 additions & 275 deletions

File tree

‎app/src-tauri/src/types.rs‎

Lines changed: 3 additions & 273 deletions
Original file line numberDiff line numberDiff line change
@@ -12,9 +12,12 @@ use serde::{Deserialize, Serialize};
1212
mod types_session;
1313
#[path = "types_knowledge.rs"]
1414
mod types_knowledge;
15+
#[path = "types_note.rs"]
16+
mod types_note;
1517

1618
pub use types_session::*;
1719
pub use types_knowledge::*;
20+
pub use types_note::*;
1821

1922
/// 单条 ASR 转写片段。
2023
///
@@ -98,267 +101,6 @@ pub struct NoteDraft {
98101
pub markdown: String,
99102
}
100103

101-
/// 数据库中的笔记记录。
102-
///
103-
/// @ai-context: 对应 SQLite notes 表;source 记录来源(manual=手动 / classroom=课堂助手联动)。
104-
/// @ai-context: v0.7.1(会话体验批次):session_id 为来源会话关联(可空——手动笔记/旧数据无关联;
105-
/// 删除会话时 SET NULL 保笔记,见 db.rs 迁移)。
106-
/// @ai-context: v0.7.5(REQ-171):rule_version 为生成该笔记的净化规则版本
107-
/// ("note-rules-x.y.z";None=旧笔记/手动笔记,诚实降级不猜);
108-
/// purify_stats 为净化统计 JSON(各过滤原因计数 + 净化计数,
109-
/// 与预览统计口径一致——可回答"用哪版规则、滤了什么")。
110-
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
111-
pub struct Note {
112-
pub id: i64,
113-
pub title: String,
114-
pub content: String,
115-
/// 来源:manual | classroom
116-
pub source: String,
117-
/// 来源会话 id(v0.7.1;None=手动笔记/未关联/旧数据)
118-
#[serde(default)]
119-
pub session_id: Option<i64>,
120-
/// 生成规则的版本标识(REQ-171;None=旧数据/手动笔记)
121-
#[serde(default)]
122-
pub rule_version: Option<String>,
123-
/// 净化统计 JSON(REQ-171;None=旧数据/手动笔记)
124-
#[serde(default)]
125-
pub purify_stats: Option<String>,
126-
/// 标签 JSON 数组(v0.10.0;默认 `[]`)
127-
#[serde(default = "default_tags")]
128-
pub tags: String,
129-
/// 属性 JSON 对象(v0.10.0;扩展位,None=无)
130-
#[serde(default)]
131-
pub properties: Option<String>,
132-
/// 置顶标记(v0.10.0;0=未置顶,1=置顶——置顶笔记在树/列表置顶区按更新时间定序)
133-
#[serde(default)]
134-
pub pin: i64,
135-
/// 所属笔记组 id(v0.11.0 REQ-195;None=未归组/旧数据——不猜不填)
136-
#[serde(default)]
137-
pub group_id: Option<i64>,
138-
/// 创建时间(Unix 秒)
139-
pub created_at: i64,
140-
/// 更新时间(Unix 秒)
141-
pub updated_at: i64,
142-
}
143-
144-
fn default_tags() -> String {
145-
"[]".to_string()
146-
}
147-
148-
/// 新建笔记的入参(不含 id 与时间戳,由数据层填充)。
149-
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
150-
pub struct NewNote {
151-
pub title: String,
152-
pub content: String,
153-
pub source: String,
154-
/// 来源会话 id(v0.7.1;None=手动笔记;前端 create_note 可不传——serde default)
155-
#[serde(default)]
156-
pub session_id: Option<i64>,
157-
/// 生成规则的版本标识(REQ-171;None=手动笔记/旧路径)
158-
#[serde(default)]
159-
pub rule_version: Option<String>,
160-
/// 净化统计 JSON(REQ-171;None=手动笔记/旧路径)
161-
#[serde(default)]
162-
pub purify_stats: Option<String>,
163-
/// 标签 JSON 数组(v0.10.0;None=空数组)
164-
#[serde(default)]
165-
pub tags: Option<String>,
166-
/// 属性 JSON 对象(v0.10.0;扩展位,None=无)
167-
#[serde(default)]
168-
pub properties: Option<String>,
169-
/// 所属笔记组 id(v0.11.0 REQ-195;前端可不传——组归属由组化接线写入)
170-
#[serde(default)]
171-
pub group_id: Option<i64>,
172-
}
173-
174-
// ────────────────────────────────────────────────────────────
175-
// 笔记组类型(v0.11.0 REQ-195;v4 §7.4 统一产物层)
176-
// ────────────────────────────────────────────────────────────
177-
178-
/// 笔记组(组是唯一容器;terrain 区分两种形成方式,v4 §7.4)。
179-
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
180-
#[serde(rename_all = "camelCase")]
181-
pub struct NoteGroup {
182-
pub id: i64,
183-
pub name: String,
184-
/// 地形:container(结构在内容里)/ feed(结构在行为里)
185-
pub terrain: String,
186-
/// 组类别:course 课程组 / topic 主题组 / standalone 独立组
187-
pub kind: String,
188-
/// DomainKind kebab-case(主题组归组依据;None=未命中/课程组/独立组)
189-
pub domain_tag: Option<String>,
190-
/// 形成来源:route(路由)/ series(系列检测)/ manual(用户自建)
191-
pub source: String,
192-
/// series_detect 系列名(课程组幂等键;其余 None)
193-
pub series_key: Option<String>,
194-
/// 路由理由 JSON(REQ-198:命中信号明细,可见可改)
195-
pub route_reason: Option<String>,
196-
/// 用户改判标记(REQ-198:修改即记忆;0=自动路由,1=已改判)
197-
#[serde(default)]
198-
pub route_overridden: i64,
199-
/// 组内笔记数(list 查询填充;单查为 0)
200-
#[serde(default)]
201-
pub note_count: i64,
202-
/// v0.14 B(视觉系统):组级颜色(色板 id;None=未设置——笔记未显式定义时继承组色)
203-
#[serde(default)]
204-
pub color: Option<String>,
205-
/// 置顶标记(REQ-315 v0.20.11 批 6;0=未置顶,1=置顶——组列表置顶区第一条件;
206-
/// 与 notes.pin 同语义同措辞「置顶」,数据字段名沿 notes 先例不复刻改名)
207-
#[serde(default)]
208-
pub pin: i64,
209-
pub created_at: i64,
210-
pub updated_at: i64,
211-
}
212-
213-
/// 新建笔记组的入参(不含 id 与时间戳,由数据层填充)。
214-
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
215-
#[serde(rename_all = "camelCase")]
216-
pub struct NewNoteGroup {
217-
pub name: String,
218-
pub terrain: String,
219-
pub kind: String,
220-
#[serde(default)]
221-
pub domain_tag: Option<String>,
222-
#[serde(default)]
223-
pub source: String,
224-
#[serde(default)]
225-
pub series_key: Option<String>,
226-
#[serde(default)]
227-
pub route_reason: Option<String>,
228-
}
229-
230-
/// 组删除影响面(v0.14.1:get_group_delete_impact 返回——确认弹窗数据源)。
231-
///
232-
/// @ai-context: 删除语义已裁决(规格 §2.1 影响面确认后级联):notes/fragments
233-
/// SET NULL(移入"全部"),flashcards/settlements/contracts CASCADE
234-
/// (级联删——弹窗明示数量),knowledge_links 无 FK 到 note_groups
235-
/// (悬空引用必须命令层显式清理)。
236-
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
237-
#[serde(rename_all = "camelCase")]
238-
pub struct GroupDeleteImpact {
239-
pub notes: i64,
240-
pub fragments: i64,
241-
pub cards: i64,
242-
pub settlements: i64,
243-
pub contracts: i64,
244-
pub system_refs: i64,
245-
}
246-
247-
// ────────────────────────────────────────────────────────────
248-
// 命令结果(REQ-316 v0.20.12 批 7:空组自动清理留痕——前端 toast 数据源)
249-
// ────────────────────────────────────────────────────────────
250-
251-
/// 删除笔记结果(批 7:autoCleanedGroups=删除使组变空后自动清理的路由组标题;
252-
/// 无清理时为空数组——前端零变化,不打扰)。
253-
#[derive(Debug, Clone, Default, Serialize, Deserialize, PartialEq)]
254-
#[serde(rename_all = "camelCase")]
255-
pub struct DeleteNoteResult {
256-
pub deleted: bool,
257-
pub auto_cleaned_groups: Vec<String>,
258-
}
259-
260-
/// 笔记移组结果(批 7:autoCleanedGroups=源组变空被自动清理时留痕)。
261-
#[derive(Debug, Clone, Default, Serialize, Deserialize, PartialEq)]
262-
#[serde(rename_all = "camelCase")]
263-
pub struct MoveNoteResult {
264-
pub moved: bool,
265-
pub auto_cleaned_groups: Vec<String>,
266-
}
267-
268-
/// 删除碎片结果(批 7:autoCleanedGroups=碎片源组变空被自动清理时留痕)。
269-
#[derive(Debug, Clone, Default, Serialize, Deserialize, PartialEq)]
270-
#[serde(rename_all = "camelCase")]
271-
pub struct DeleteFragmentResult {
272-
pub deleted: bool,
273-
pub auto_cleaned_groups: Vec<String>,
274-
}
275-
276-
/// 碎片移组结果(批 7:autoCleanedGroups=碎片源组变空被自动清理时留痕)。
277-
#[derive(Debug, Clone, Default, Serialize, Deserialize, PartialEq)]
278-
#[serde(rename_all = "camelCase")]
279-
pub struct MoveFragmentResult {
280-
pub moved: bool,
281-
pub auto_cleaned_groups: Vec<String>,
282-
}
283-
284-
/// 碎片升笔记结果(批 7:note=新建笔记(旧返回契约原样前置);autoCleanedGroups=
285-
/// 碎片源组变空被自动清理时留痕)。
286-
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
287-
#[serde(rename_all = "camelCase")]
288-
pub struct PromoteNoteResult {
289-
pub note: Note,
290-
#[serde(default)]
291-
pub auto_cleaned_groups: Vec<String>,
292-
}
293-
294-
// ────────────────────────────────────────────────────────────
295-
// 碎片类型(v0.11.1 feed 进料口;v4 契约:碎片不是笔记,身份诚实)
296-
// ────────────────────────────────────────────────────────────
297-
298-
/// 碎片(feed 地形原料层;几句话+可选示范画面,防"假燃料"死法)。
299-
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
300-
#[serde(rename_all = "camelCase")]
301-
pub struct Fragment {
302-
pub id: i64,
303-
pub text: String,
304-
/// 图片相对路径(data_dir/fragments/ 下;None=纯文本碎片)
305-
pub image_path: Option<String>,
306-
/// DomainKind kebab-case(自动归组依据;None=未命中)
307-
pub domain_tag: Option<String>,
308-
/// 所属 feed 主题组(None=未归组——结算面兜底)
309-
pub group_id: Option<i64>,
310-
/// manual / clipboard
311-
pub source: String,
312-
/// active / archived(v0.11.3 组结算归档标记)
313-
pub status: String,
314-
pub created_at: i64,
315-
}
316-
317-
// ────────────────────────────────────────────────────────────
318-
// 闪卡类型(v0.11.2 学习循环统一;绑定粒度=组,v4 契约二)
319-
// ────────────────────────────────────────────────────────────
320-
321-
/// 闪卡(提取优先:front 线索 → 回忆 → back 验证)。
322-
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
323-
#[serde(rename_all = "camelCase")]
324-
pub struct Flashcard {
325-
pub id: i64,
326-
/// 绑定组(学习单元——复习/自测/结算都按组,契约二)
327-
pub group_id: i64,
328-
/// 来源笔记(None=碎片卡/旧数据)
329-
pub note_id: Option<i64>,
330-
/// 来源碎片(None=笔记卡)
331-
pub fragment_id: Option<i64>,
332-
pub front: String,
333-
pub back: String,
334-
/// 内容分型预埋(N13):fact 先做;action/model 留接口不做
335-
pub kind: String,
336-
/// CardState 序列化(scheduler 契约;损坏回退新卡状态——诚实降级)
337-
pub state_json: String,
338-
/// 到期时刻(Unix 毫秒;due_at ≤ now 进复习队列)
339-
pub due_at: i64,
340-
pub created_at: i64,
341-
}
342-
343-
/// 周契约(v0.11.4 REQ-200;弹性承诺呈现层——用户自设本周目标,非打卡 KPI)。
344-
///
345-
/// @ai-context: 无 streak 无惩罚——契约只记录承诺本身,完成度由
346-
/// review_logs 周聚合实时计算(week_contract.rs 纯函数)。
347-
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
348-
#[serde(rename_all = "camelCase")]
349-
pub struct WeekContract {
350-
pub id: i64,
351-
/// 绑定组(契约粒度=组——与学习循环绑定粒度一致,契约二)
352-
pub group_id: i64,
353-
/// 周界:周一零点(UTC Unix 秒)
354-
pub week_start: i64,
355-
/// 本周承诺复习天数(1..7)
356-
pub target_days: i64,
357-
/// 本周承诺复习卡数(有界)
358-
pub target_cards: i64,
359-
pub created_at: i64,
360-
}
361-
362104
/// 会话 OCR 块(关键帧画面文字 / 字幕区文字)。
363105
///
364106
/// @ai-context: region 取 subtitle | full(ADR-005:字幕区高频采样 vs 全帧低频采样)。
@@ -452,18 +194,6 @@ pub struct SessionScreen {
452194
pub structure: Vec<ScreenStructure>,
453195
}
454196

455-
/// 笔记列表排序模式(v0.10.0)。
456-
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
457-
#[serde(rename_all = "kebab-case")]
458-
pub enum NoteSortMode {
459-
/// 按更新时间倒序(默认)
460-
UpdatedDesc,
461-
/// 置顶优先 + 按更新时间倒序
462-
PinFirst,
463-
/// 按创建时间倒序
464-
CreatedDesc,
465-
}
466-
467197
/// 决策/应用记录(v0.13.3 REQ-208;一表两面,kind 区分)。
468198
///
469199
/// @ai-context: 对应 knowledge_decisions 表——decision=思辨面(决策),application=学习面

0 commit comments

Comments
 (0)