Skip to content

Commit 8613629

Browse files
committed
chore(rust): 删旧视频档案四命令及连带死符号
1 parent bd85dc4 commit 8613629

10 files changed

Lines changed: 22 additions & 224 deletions

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

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -277,15 +277,11 @@ pub fn handle() -> impl Fn(tauri::ipc::Invoke<tauri::Wry>) -> bool + Send + Sync
277277
// 视频类型档案(REQ-043,v0.5.0 M1:混合检测 + 记忆偏好 + 档案导出)
278278
crate::commands_video::video_profiles,
279279
crate::commands_video::detect_video_profile,
280-
crate::commands_video::remember_video_profile,
281280
crate::commands_video::video_profile_memory,
282-
crate::commands_video::video_profile_by_kind,
283-
// v0.9.0 M1(REQ-188):四维解耦 command(矩阵查询/旧档案映射/形态记忆)
281+
// v0.9.0 M1(REQ-188):四维解耦 command(矩阵查询/形态记忆)
284282
crate::commands_video::video_profile_for_spec,
285-
crate::commands_video::video_profile_spec_by_kind,
286283
crate::commands_video::remember_video_profile_form,
287-
// v0.9.0 M3(REQ-190):领域标签检测 + hotwords 预热
288-
crate::commands_video::detect_video_domain,
284+
// v0.9.0 M3(REQ-190):hotwords 预热
289285
crate::commands_video::preheat_domain_hotwords,
290286
// v0.13.6(REQ-220/222):细目选项表 + 领域记忆(coarse+细目多选)
291287
crate::commands_video::list_domain_fine,

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

Lines changed: 2 additions & 90 deletions
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,8 @@ use tauri::State;
1010

1111
use crate::commands::AppState;
1212
use crate::video_profile::{
13-
apply_profile_memory, builtin_profiles, profile_by_kind, vote_detect, DetectResult,
14-
ObservedSignals, ProfileKind, ProfileMemory, VideoProfile,
13+
apply_profile_memory, builtin_profiles, vote_detect, DetectResult, ObservedSignals,
14+
ProfileMemory, VideoProfile,
1515
};
1616
use crate::video_profile_spec::{ContentForm, ProfileSpec};
1717

@@ -128,50 +128,6 @@ pub fn detect_video_profile(
128128
result
129129
}
130130

131-
/// 领域标签检测(REQ-190:平台分区 > 用户确认 > 标题词 > 术语频率)。
132-
///
133-
/// @param title - 窗口标题(来源②标题领域词)
134-
/// @param platformTags - 平台分区标签(来源①——B站分区/本地目录名)
135-
/// @param userConfirmed - 用户已确认领域(来源③——检测卡下拉;kebab-case)
136-
/// @param termFreq - 会话中术语频率词(来源④——自动补全)
137-
/// @param ocrTags - 画面内 OCR 标签(REQ-191 通用化通道——任何平台画面标签
138-
/// 都算;与 platformTags 合并入平台来源)
139-
#[tauri::command]
140-
pub fn detect_video_domain(
141-
title: Option<String>,
142-
platform_tags: Option<Vec<String>>,
143-
user_confirmed: Option<String>,
144-
term_freq: Option<Vec<String>>,
145-
ocr_tags: Option<Vec<String>>,
146-
) -> crate::video_profile_domain::DomainDetection {
147-
let user = user_confirmed.and_then(|s| {
148-
crate::video_profile_domain::DomainKind::parse(&s.chars().take(30).collect::<String>())
149-
});
150-
// OCR 标签通用化(REQ-191):画面内标签与平台标签同为强信号来源——
151-
// 经 platform_adapter 通用通道合并(词表映射扩展,不依赖平台枚举)
152-
let mut platform = platform_tags.unwrap_or_default();
153-
for t in ocr_tags.unwrap_or_default() {
154-
if !platform.contains(&t) {
155-
platform.push(t);
156-
}
157-
}
158-
// 平台标签 → 领域(通用通道);无平台信号 → 其余来源(标题/用户/术语)
159-
let from_ocr = crate::platform_adapter::ocr_tags_to_domain(&platform);
160-
if from_ocr.kind.is_some() {
161-
return from_ocr;
162-
}
163-
crate::video_profile_domain::detect_domain(&crate::video_profile_domain::DomainSignals {
164-
title: title.map(|t| t.chars().take(200).collect()),
165-
platform_tags: Vec::new(),
166-
user_confirmed: user,
167-
term_freq: term_freq.unwrap_or_default()
168-
.into_iter()
169-
.map(|t| t.chars().take(50).collect())
170-
.collect(),
171-
asr_opening: None,
172-
})
173-
}
174-
175131
/// 领域 → hotwords 预热(REQ-190 作用链:VocabManager 通道——注入共享词表,
176132
/// ASR 术语命中率↑;幂等去重)。
177133
///
@@ -284,37 +240,6 @@ pub fn list_domain_fine() -> Vec<(String, Vec<crate::video_profile_domain_fine::
284240
.collect()
285241
}
286242

287-
/// 记录用户确认/修改:窗口标题 → 档案(记忆偏好,下次同标题直接生效)。
288-
///
289-
/// @param title - 窗口标题(记忆匹配键,完整标题入库)
290-
/// @param kind - 档案标识(kebab-case;非法值回退 Lecture)
291-
#[tauri::command]
292-
pub fn remember_video_profile(
293-
state: State<'_, AppState>,
294-
title: String,
295-
kind: String,
296-
) -> Result<(), String> {
297-
let title = title.trim().to_string();
298-
if title.is_empty() {
299-
return Err("窗口标题为空,无法记忆档案偏好".to_string());
300-
}
301-
let title = title.chars().take(200).collect::<String>();
302-
let kind = ProfileKind::parse(&kind.chars().take(KIND_MAX_CHARS).collect::<String>());
303-
let path = state.profile_memory_path.clone();
304-
let memory = state.profile_memory.clone();
305-
// 锁内 read-modify-write(与词表同模式,防 TOCTOU 文件竞争)
306-
{
307-
let mut guard = memory
308-
.lock()
309-
.map_err(|e| format!("档案记忆锁中毒: {}", e))?;
310-
guard.remember(&title, kind);
311-
guard
312-
.save(&path)
313-
.map_err(|e| format!("保存档案记忆失败: {}", e))?;
314-
}
315-
Ok(())
316-
}
317-
318243
/// 读取当前档案记忆(诊断/展示用)。
319244
#[tauri::command]
320245
pub fn video_profile_memory(state: State<'_, AppState>) -> ProfileMemory {
@@ -325,12 +250,6 @@ pub fn video_profile_memory(state: State<'_, AppState>) -> ProfileMemory {
325250
.unwrap_or_default()
326251
}
327252

328-
/// 按标识查单档案(前端"检测为:网课(可改)"下拉用;非法值回退 Lecture)。
329-
#[tauri::command]
330-
pub fn video_profile_by_kind(kind: String) -> VideoProfile {
331-
profile_by_kind(ProfileKind::parse(&kind.chars().take(KIND_MAX_CHARS).collect::<String>()))
332-
}
333-
334253
// ── v0.9.0 M1(REQ-188):四维解耦 command(检测卡 v2 消费端;旧命令零改动)──
335254

336255
/// 按四维规格查参数矩阵(形态 × 画面档 → 采样/OCR/存储/模板)。
@@ -353,13 +272,6 @@ pub fn video_profile_for_spec(form: Option<String>, tier: Option<String>) -> Vid
353272
crate::video_profile_spec::profile_for_spec(&spec)
354273
}
355274

356-
/// 旧档案 → 四维规格(记忆库 kind 映射迁移/旧会话解读;检测卡 v2 展示用)。
357-
#[tauri::command]
358-
pub fn video_profile_spec_by_kind(kind: String) -> ProfileSpec {
359-
let kind = ProfileKind::parse(&kind.chars().take(KIND_MAX_CHARS).collect::<String>());
360-
crate::video_profile_spec::spec_from_kind(kind)
361-
}
362-
363275
/// 记录用户确认/修改(四维形态版,REQ-188):记忆偏好存新形态(form 字段),
364276
/// kind 兼容字段存代表旧类——消费端 v1/v2 双通道读取均有效。
365277
///

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

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ fn quadrant1_high_conf_same_kind_memory_wins() {
3535
// Arrange:强网课信号(高置信 Lecture)+ 记忆同为 Lecture
3636
let memory = {
3737
let mut m = ProfileMemory::default();
38-
m.remember("高等数学", ProfileKind::Lecture);
38+
m.remember_form("高等数学", ContentForm::Lecture);
3939
m
4040
};
4141
// Act:检测 → 记忆后置判定
@@ -54,7 +54,7 @@ fn quadrant2_high_conf_conflict_detection_wins() {
5454
// Arrange:强实操信号(高置信 HandsOn)+ 记忆为 Lecture(用户上次裁决冲突)
5555
let memory = {
5656
let mut m = ProfileMemory::default();
57-
m.remember("实操演练", ProfileKind::Lecture);
57+
m.remember_form("实操演练", ContentForm::Lecture);
5858
m
5959
};
6060
// Act
@@ -75,7 +75,7 @@ fn quadrant3_low_conf_memory_wins() {
7575
assert!(vote_detect(&s).needs_confirmation, "前置条件:信号冲突需确认");
7676
let memory = {
7777
let mut m = ProfileMemory::default();
78-
m.remember("课程", ProfileKind::Lecture);
78+
m.remember_form("课程", ContentForm::Lecture);
7979
m
8080
};
8181
// Act
@@ -98,7 +98,7 @@ fn no_signal_memory_fallback_wins() {
9898
assert!(base.needs_confirmation, "前置条件:无信号需确认");
9999
let memory = {
100100
let mut m = ProfileMemory::default();
101-
m.remember("某无关标题", ProfileKind::Lecture);
101+
m.remember_form("某无关标题", ContentForm::Lecture);
102102
m
103103
};
104104
// Act
@@ -129,7 +129,7 @@ fn quadrant1_series_key_cross_episode_memory_wins() {
129129
// Arrange:P1 确认 Lecture → 存系列键;P5 强网课信号(剥系列名后高置信)
130130
let memory = {
131131
let mut m = ProfileMemory::default();
132-
m.remember("高等数学 微积分课程 网课教学 P1", ProfileKind::Lecture);
132+
m.remember_form("高等数学 微积分课程 网课教学 P1", ContentForm::Lecture);
133133
m
134134
};
135135
assert!(memory.entries[0].is_series, "前置条件:系列键标记");
@@ -151,7 +151,7 @@ fn apply_preserves_domain_and_detection_candidates() {
151151
// Arrange:强实操信号 + 冲突记忆(Lecture)
152152
let memory = {
153153
let mut m = ProfileMemory::default();
154-
m.remember("实操演练", ProfileKind::Lecture);
154+
m.remember_form("实操演练", ContentForm::Lecture);
155155
m
156156
};
157157
let base = vote_detect(&strong_hands_on_signals());

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

Lines changed: 0 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,6 @@
1414
1515
use serde::{Deserialize, Serialize};
1616

17-
use crate::video_profile_domain::{detect_domain, DomainSignals};
18-
1917
/// 平台标识(前端从窗口标题/进程名推断;None=无平台信号——零回归)。
2018
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
2119
pub enum PlatformKind {
@@ -141,22 +139,6 @@ pub fn adapt_local(title: Option<&str>) -> PlatformHints {
141139
PlatformHints { platform_tags: Vec::new(), path_segments: segments }
142140
}
143141

144-
/// OCR 标签通用化(③):画面内标签/标题卡文字 → 领域投票。
145-
///
146-
/// @ai-context: 不依赖平台枚举——任何平台画面内的分类标签(B站分区/网课
147-
/// "课程章节"/视频标题卡)都是通用 OCR 信号;经领域词表映射
148-
/// 投给对应领域("知识科普|经济管理" 中"经济管理"命中经济领域)。
149-
pub fn ocr_tags_to_domain(texts: &[String]) -> crate::video_profile_domain::DomainDetection {
150-
let signals = DomainSignals {
151-
title: None,
152-
platform_tags: texts.to_vec(),
153-
user_confirmed: None,
154-
term_freq: Vec::new(),
155-
asr_opening: None,
156-
};
157-
detect_domain(&signals)
158-
}
159-
160142
/// 分区标签形态判定:B站分区名特征(2-8 字中文/已知分区词;防标题正文误判)。
161143
fn is_category_like(s: &str) -> bool {
162144
let chars = s.chars().count();

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

Lines changed: 0 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -83,23 +83,6 @@ fn local_path_segments_extracted() {
8383
assert!(!h.path_segments.iter().any(|s| s.contains(".mp4")));
8484
}
8585

86-
#[test]
87-
fn ocr_tags_to_domain_generalized() {
88-
// Arrange:画面内分区标签 OCR(会话 33 实证:`知识科普|经济管理`)
89-
let d = ocr_tags_to_domain(&["知识科普".to_string(), "经济管理".to_string()]);
90-
// Act/Assert:不依赖平台枚举——通用 OCR 信号命中经济领域
91-
assert_eq!(d.kind, Some(crate::video_profile_domain::DomainKind::Economy));
92-
assert_eq!(d.source, "platform");
93-
}
94-
95-
#[test]
96-
fn ocr_tags_unknown_text_no_domain() {
97-
// Arrange:画面内非分类文字(防骗提示/标题卡正文——无领域种子词)
98-
let d = ocr_tags_to_domain(&["谨防诈骗".to_string(), "小马的故事".to_string()]);
99-
// Act/Assert:无领域命中(诚实空——不误判)
100-
assert_eq!(d.kind, None);
101-
}
102-
10386
#[test]
10487
fn bilibili_episode_ocr_parsed() {
10588
// Arrange/Act/Assert:B站 选集按钮 OCR(P分P/总集数 → 合集信息;证据增强)

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

Lines changed: 0 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -101,15 +101,6 @@ impl ProfileMemory {
101101
best.map(|(_, kind)| kind)
102102
}
103103

104-
/// 记录用户确认(关键词已存在则覆盖档案;新增追加)。
105-
///
106-
/// @ai-context: v0.7.2(REQ-152):标题可识别系列 → 存**系列键**(is_series=true,
107-
/// 同系列各集共享);否则存完整标题(现状行为零回归)。
108-
pub fn remember(&mut self, keyword: &str, kind: ProfileKind) {
109-
let form = kind.to_form();
110-
self.remember_with_form(keyword, kind, form);
111-
}
112-
113104
/// 记录用户确认(四维形态优先版,REQ-188):kind 存代表旧类(消费端兼容),
114105
/// form 存新形态(检测卡 v2 下次直接生效——同标题/同系列)。
115106
///

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

Lines changed: 1 addition & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
//! - 画面档独立决定采样/OCR/存储(tier_params 表)
1010
//! - 维度独立降级:形态 unknown 时画面档照常生效
1111
//! @ai-context: 纯逻辑模块(无 IO/DB),矩阵数据在 video_profile_spec_data.rs;
12-
//! 旧 13 类保留为兼容层(ProfileKind::to_form/default_tier 映射),
12+
//! 旧 13 类保留为兼容层(ProfileKind::to_form 映射),
1313
//! profile_by_kind 消费端契约零改动(见 video_profile.rs)。
1414
1515
use serde::{Deserialize, Serialize};
@@ -181,26 +181,6 @@ impl ProfileKind {
181181
ProfileKind::Unknown => None,
182182
}
183183
}
184-
185-
/// 旧 13 类 → 默认画面档(映射表第三列;迁移/旧会话零回归用)。
186-
pub fn default_tier(self) -> VisualTier {
187-
match self {
188-
// lecture 中档(板书时升档由会话中重评驱动);whiteboard 画面=主体 → 高
189-
ProfileKind::Lecture => VisualTier::Medium,
190-
ProfileKind::Whiteboard => VisualTier::Rich,
191-
// 实操中-高:hands-on 中档(跟练/游戏教程画面价值更高)
192-
ProfileKind::HandsOn => VisualTier::Medium,
193-
ProfileKind::FollowAlong | ProfileKind::GameTutorial => VisualTier::Rich,
194-
// 解说低档(动画升中由重评驱动——会话 33 实证)
195-
ProfileKind::TalkingHead => VisualTier::Low,
196-
ProfileKind::Interview | ProfileKind::Meeting => VisualTier::Low,
197-
ProfileKind::Exercise | ProfileKind::Coding => VisualTier::Rich,
198-
ProfileKind::Podcast => VisualTier::None,
199-
// v0.13.6:直播独立形态——浅画面(OCR 待命,不再短路画面链)
200-
ProfileKind::Live => VisualTier::Low,
201-
ProfileKind::Unknown => VisualTier::Medium,
202-
}
203-
}
204184
}
205185

206186
/// 按四维规格查参数矩阵:形态 → 产物模板 + 后处理;画面档 → 采样/OCR/存储。
@@ -212,17 +192,6 @@ pub fn profile_for_spec(spec: &ProfileSpec) -> VideoProfile {
212192
let form = spec.form.unwrap_or(ContentForm::Lecture);
213193
crate::video_profile_spec_data::resolve_profile(form, spec.visual_tier)
214194
}
215-
216-
/// 旧档案 → 四维规格(记忆库 kind 映射/旧会话解读用;Unknown → 默认规格)。
217-
pub fn spec_from_kind(kind: ProfileKind) -> ProfileSpec {
218-
ProfileSpec {
219-
form: kind.to_form(),
220-
visual_tier: kind.default_tier(),
221-
domain: None,
222-
language: LanguageTag::Zh,
223-
}
224-
}
225-
226195
/// 形态 → 默认档位(无任何信号时的新会话起点;解说/对话/会议/直播/影视低档、
227196
/// 实操中档——直播/影视有画面但价值低,不开天窗也不短路)。
228197
pub fn default_tier_for_form(form: ContentForm) -> VisualTier {

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

Lines changed: 0 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -73,26 +73,6 @@ fn mapping_13_to_7_follows_framework_table() {
7373
assert_eq!(ProfileKind::Unknown.to_form(), None);
7474
}
7575

76-
#[test]
77-
fn mapping_default_tier_follows_framework_table() {
78-
// Assert:画面档默认(映射表第三列)
79-
assert_eq!(ProfileKind::Lecture.default_tier(), VisualTier::Medium);
80-
assert_eq!(ProfileKind::Whiteboard.default_tier(), VisualTier::Rich);
81-
assert_eq!(ProfileKind::HandsOn.default_tier(), VisualTier::Medium);
82-
assert_eq!(ProfileKind::FollowAlong.default_tier(), VisualTier::Rich);
83-
assert_eq!(ProfileKind::GameTutorial.default_tier(), VisualTier::Rich);
84-
assert_eq!(ProfileKind::TalkingHead.default_tier(), VisualTier::Low);
85-
assert_eq!(ProfileKind::Interview.default_tier(), VisualTier::Low);
86-
assert_eq!(ProfileKind::Meeting.default_tier(), VisualTier::Low);
87-
assert_eq!(ProfileKind::Exercise.default_tier(), VisualTier::Rich);
88-
assert_eq!(ProfileKind::Coding.default_tier(), VisualTier::Rich);
89-
assert_eq!(ProfileKind::Podcast.default_tier(), VisualTier::None);
90-
// v0.13.6:直播独立形态——浅画面,OCR 待命(不再短路画面链)
91-
assert_eq!(ProfileKind::Live.default_tier(), VisualTier::Low);
92-
// unknown 走默认中档(参数不阻塞)
93-
assert_eq!(ProfileKind::Unknown.default_tier(), VisualTier::Medium);
94-
}
95-
9676
// ── 参数矩阵(形态 → 模板/后处理;画面档 → 采样/权重/存储)──
9777

9878
#[test]
@@ -200,21 +180,6 @@ fn none_tier_skips_ocr_chain() {
200180
assert!((profile.signal_weights.ocr_weight - 0.0).abs() < 1e-6);
201181
}
202182

203-
// ── 旧档案 → 四维规格(记忆库 kind 映射/旧会话解读)──
204-
205-
#[test]
206-
fn spec_from_legacy_kind_maps_both_dimensions() {
207-
// Arrange/Act:旧 talking-head(会话 33 检测前的状态)
208-
let spec = spec_from_kind(ProfileKind::TalkingHead);
209-
// Assert:形态=解说 + 默认档=低(动画升中由会话中重评驱动)
210-
assert_eq!(spec.form, Some(ContentForm::Explainer));
211-
assert_eq!(spec.visual_tier, VisualTier::Low);
212-
// 旧 unknown → 默认规格(识别中:形态 None + 中档)
213-
let unknown = spec_from_kind(ProfileKind::Unknown);
214-
assert_eq!(unknown.form, None);
215-
assert_eq!(unknown.visual_tier, VisualTier::Medium);
216-
}
217-
218183
// ── JSON 契约(检测卡 v2 / 会话落库传输)──
219184

220185
#[test]

0 commit comments

Comments
 (0)