99//! @ai-context: inner 函数统一收 &Db(commands_groups/commands_settlement 先例)
1010//! ——内存库单测直连,不构造重量级 AppState。
1111
12- use serde:: { Deserialize , Serialize } ;
12+ use serde:: Deserialize ;
1313use tauri:: State ;
1414
1515use crate :: commands:: { normalize_title, AppState } ;
1616use crate :: db:: { unix_seconds, Db } ;
17- use crate :: goal_interview:: {
18- assemble_declaration, derive_criteria, horizon_end_secs,
19- } ;
20- use crate :: goal_progress:: { build_report, progress_statement, GoalProgressReport , GoalSignals } ;
21- use crate :: goal_rules:: graduation_readiness;
17+ use crate :: goal_interview:: { derive_criteria, horizon_end_secs} ;
18+ use crate :: goal_progress:: GoalSignals ;
2219use crate :: goal_schema:: {
2320 Goal , GoalIntent , GoalMilestone , NewGoal , NewMilestone , SuccessCriteria , CRITERIA_GROUP_SETTLED ,
2421 CRITERIA_MANUAL , MILESTONE_DONE , MILESTONE_IN_PROGRESS , MILESTONE_PENDING , MILESTONE_SKIPPED ,
2522 TIER_DEFAULT ,
2623} ;
2724use crate :: video_profile_domain:: DomainKind ;
2825
26+ /// 读侧视图层(5 个视图 DTO + 3 条读命令 + 3 个读 inner;0 emit)。
27+ /// `pub(crate)`:注册清单在 app_commands.rs(crate 根的兄弟模块)按 `commands_goals::views::x` 解析。
28+ #[ path = "commands_goals_views.rs" ]
29+ pub ( crate ) mod views;
30+
2931/// 一周秒数(草案 due_at 换算:第 N 周 = created_at + N*7d)。
3032const WEEK_SECS : i64 = 7 * 86_400 ;
3133/// 访谈答案文本上限(防御超大 payload;chips/填空兜底的答案均为短文本)。
@@ -75,61 +77,6 @@ pub struct GoalMilestoneInput {
7577 pub due_weeks : usize ,
7678}
7779
78- /// 目标卡视图(列表项:单行折叠=名称/状态/一句话进度/可毕业徽标)。
79- #[ derive( Debug , Clone , Serialize ) ]
80- #[ serde( rename_all = "camelCase" ) ]
81- pub struct GoalCardView {
82- pub goal : Goal ,
83- /// 一句话进度("62% · 里程碑 2/4")
84- pub statement : String ,
85- pub percent : f64 ,
86- pub milestone_done : usize ,
87- pub milestone_total : usize ,
88- /// 🎓 可毕业(判据配方全达标——状态必须 active)
89- pub ready : bool ,
90- }
91-
92- /// 目标详情视图(详情页一次取全:里程碑/组/判据/进度/可毕业)。
93- #[ derive( Debug , Clone , Serialize ) ]
94- #[ serde( rename_all = "camelCase" ) ]
95- pub struct GoalDetailView {
96- pub goal : Goal ,
97- /// 判据检查(可毕业明细——毕业确认仪式数据源)
98- pub criteria : Vec < ReadinessView > ,
99- pub progress : GoalProgressView ,
100- pub milestones : Vec < GoalMilestone > ,
101- pub groups : Vec < GoalGroupView > ,
102- /// 宣言回显(重新访谈/详情页展示)
103- pub declaration : String ,
104- }
105-
106- /// 目标绑定组视图(详情关联组区)。
107- #[ derive( Debug , Clone , Serialize ) ]
108- #[ serde( rename_all = "camelCase" ) ]
109- pub struct GoalGroupView {
110- pub id : i64 ,
111- pub name : String ,
112- }
113-
114- /// 判据检查视图。
115- #[ derive( Debug , Clone , Serialize ) ]
116- #[ serde( rename_all = "camelCase" ) ]
117- pub struct ReadinessView {
118- pub label : String ,
119- pub met : bool ,
120- pub detail : String ,
121- }
122-
123- /// 进度视图(现算信号 + 一句话进度 + 可毕业判定)。
124- #[ derive( Debug , Clone , Serialize ) ]
125- #[ serde( rename_all = "camelCase" ) ]
126- pub struct GoalProgressView {
127- pub progress : GoalProgressReport ,
128- pub statement : String ,
129- pub ready : bool ,
130- pub checks : Vec < ReadinessView > ,
131- }
132-
13380/// 新建目标(访谈确认后一步创建——status=active,无 draft 仪式)。
13481#[ tauri:: command]
13582pub fn create_goal ( state : State < ' _ , AppState > , input : GoalCreateInput ) -> Result < Goal , String > {
@@ -139,24 +86,6 @@ pub fn create_goal(state: State<'_, AppState>, input: GoalCreateInput) -> Result
13986 Ok ( goal)
14087}
14188
142- /// 全部目标卡(列表;每卡现算进度——聚合皆毫秒级查询)。
143- #[ tauri:: command]
144- pub fn list_goals ( state : State < ' _ , AppState > ) -> Result < Vec < GoalCardView > , String > {
145- list_goals_inner ( & state. db )
146- }
147-
148- /// 目标详情(里程碑/绑定组/判据/进度一次取全)。
149- #[ tauri:: command]
150- pub fn get_goal_detail ( state : State < ' _ , AppState > , id : i64 ) -> Result < GoalDetailView , String > {
151- get_goal_detail_inner ( & state. db , id)
152- }
153-
154- /// 进度刷新(详情页动作后局部刷新;与 get_goal_detail 同口径)。
155- #[ tauri:: command]
156- pub fn get_goal_progress ( state : State < ' _ , AppState > , id : i64 ) -> Result < GoalProgressView , String > {
157- get_goal_progress_inner ( & state. db , id)
158- }
159-
16089/// 编辑目标(名称/领域/时限——重访谈走 update_goal_interview)。
16190#[ tauri:: command]
16291pub fn update_goal (
@@ -373,85 +302,6 @@ pub(crate) fn create_goal_inner(db: &Db, input: &GoalCreateInput) -> Result<Goal
373302 Ok ( goal)
374303}
375304
376- pub ( crate ) fn list_goals_inner ( db : & Db ) -> Result < Vec < GoalCardView > , String > {
377- let goals = db. list_goals ( ) . map_err ( |e| e. to_string ( ) ) ?;
378- let mut cards = Vec :: new ( ) ;
379- for goal in goals {
380- let ( statement, percent, done, total, ready) = goal_card_metrics ( db, & goal) ?;
381- cards. push ( GoalCardView {
382- goal,
383- statement,
384- percent,
385- milestone_done : done,
386- milestone_total : total,
387- ready,
388- } ) ;
389- }
390- Ok ( cards)
391- }
392-
393- pub ( crate ) fn get_goal_detail_inner ( db : & Db , id : i64 ) -> Result < GoalDetailView , String > {
394- require_goal ( db, id) ?;
395- let goal = db
396- . get_goal ( id)
397- . map_err ( |e| e. to_string ( ) ) ?
398- . ok_or_else ( || format ! ( "目标不存在: {}" , id) ) ?;
399- let milestones = db. list_milestones ( id) . map_err ( |e| e. to_string ( ) ) ?;
400- let group_ids = db. list_goal_group_ids ( id) . map_err ( |e| e. to_string ( ) ) ?;
401- let mut groups = Vec :: new ( ) ;
402- for gid in group_ids {
403- if let Some ( g) = db. get_group ( gid) . map_err ( |e| e. to_string ( ) ) ? {
404- groups. push ( GoalGroupView { id : gid, name : g. name } ) ;
405- }
406- }
407- let signals = collect_signals ( db, id) ?;
408- let progress = build_report ( & signals) ;
409- let statement = progress_statement ( & progress) ;
410- let criteria = parse_criteria ( & goal) ?;
411- let ready = graduation_readiness ( & goal. status , & progress, & criteria) ;
412- let intent: GoalIntent = serde_json:: from_str ( & goal. intent_json ) . unwrap_or_default ( ) ;
413- let declaration = assemble_declaration (
414- & goal. name ,
415- intent. scenario . as_deref ( ) ,
416- intent. criteria_statement . as_deref ( ) ,
417- & criteria. statement ,
418- intent. non_scope . as_deref ( ) ,
419- intent. horizon . as_deref ( ) ,
420- ) ;
421- Ok ( GoalDetailView {
422- goal,
423- criteria : ready. checks . into_iter ( ) . map ( client_check) . collect ( ) ,
424- progress : GoalProgressView {
425- progress,
426- statement,
427- ready : ready. ready ,
428- checks : vec ! [ ] ,
429- } ,
430- milestones,
431- groups,
432- declaration,
433- } )
434- }
435-
436- pub ( crate ) fn get_goal_progress_inner ( db : & Db , id : i64 ) -> Result < GoalProgressView , String > {
437- require_goal ( db, id) ?;
438- let goal = db
439- . get_goal ( id)
440- . map_err ( |e| e. to_string ( ) ) ?
441- . ok_or_else ( || format ! ( "目标不存在: {}" , id) ) ?;
442- let signals = collect_signals ( db, id) ?;
443- let progress = build_report ( & signals) ;
444- let statement = progress_statement ( & progress) ;
445- let criteria = parse_criteria ( & goal) ?;
446- let ready = graduation_readiness ( & goal. status , & progress, & criteria) ;
447- Ok ( GoalProgressView {
448- progress,
449- statement,
450- ready : ready. ready ,
451- checks : ready. checks . into_iter ( ) . map ( client_check) . collect ( ) ,
452- } )
453- }
454-
455305pub ( crate ) fn update_goal_inner (
456306 db : & Db ,
457307 id : i64 ,
@@ -636,23 +486,6 @@ fn build_intent(input: &GoalCreateInput) -> GoalIntent {
636486 }
637487}
638488
639- /// 目标卡指标(现算;判据 JSON 损坏 → ready=false 诚实降级不崩溃)。
640- fn goal_card_metrics ( db : & Db , goal : & Goal ) -> Result < ( String , f64 , usize , usize , bool ) , String > {
641- let signals = collect_signals ( db, goal. id ) ?;
642- let progress = build_report ( & signals) ;
643- let ready = match parse_criteria ( goal) {
644- Ok ( criteria) => graduation_readiness ( & goal. status , & progress, & criteria) . ready ,
645- Err ( _) => false ,
646- } ;
647- Ok ( (
648- progress_statement ( & progress) ,
649- progress. percent ,
650- progress. milestone_done ,
651- progress. milestone_total ,
652- ready,
653- ) )
654- }
655-
656489/// 进度信号收集(详情/列表共用——口径单一;lifecycle 命令组复用)。
657490pub ( crate ) fn collect_signals ( db : & Db , goal_id : i64 ) -> Result < GoalSignals , String > {
658491 db. goal_progress_signals ( goal_id, unix_seconds ( ) ) . map_err ( |e| e. to_string ( ) )
@@ -663,11 +496,6 @@ pub(crate) fn parse_criteria(goal: &Goal) -> Result<SuccessCriteria, String> {
663496 serde_json:: from_str ( & goal. success_criteria_json ) . map_err ( |e| e. to_string ( ) )
664497}
665498
666- /// ReadinessCheck → 客户端视图。
667- fn client_check ( c : crate :: goal_rules:: ReadinessCheck ) -> ReadinessView {
668- ReadinessView { label : c. label , met : c. met , detail : c. detail }
669- }
670-
671499#[ cfg( test) ]
672500#[ path = "commands_goals_tests.rs" ]
673501mod tests;
0 commit comments