From 7193901bc4cfcc41b4e29f678869801aa133d96a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=BB=9D=E5=B0=98?= <237809796@qq.com> Date: Sat, 1 Aug 2026 16:04:31 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BF=AE=E5=A4=8D:=20IPC=20update=5Fproject/ta?= =?UTF-8?q?sk=20=E5=AE=9E=E4=BD=93=E6=A0=A1=E9=AA=8C(false=E2=86=92Err=20?= =?UTF-8?q?=E6=B2=BB=E5=81=87=E6=88=90=E5=8A=9F)+=20status=20=E7=99=BD?= =?UTF-8?q?=E5=90=8D=E5=8D=95=E7=A1=AE=E8=AE=A4(B-260801-01)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src-tauri/src/commands/project.rs | 13 ++++++++++++- src-tauri/src/commands/task.rs | 20 +++++++++++++++++--- 2 files changed, 29 insertions(+), 4 deletions(-) diff --git a/src-tauri/src/commands/project.rs b/src-tauri/src/commands/project.rs index 2a597c9..7063db5 100644 --- a/src-tauri/src/commands/project.rs +++ b/src-tauri/src/commands/project.rs @@ -299,6 +299,13 @@ pub async fn get_project( } /// 更新项目单个字段(字段名走 df-storage 白名单校验) +/// +/// B-260801-01(P0-1):0 行(id 不存在 / 已软删)→ 返 Err 而非假成功。原实现无视 +/// update_field 返回值恒返 Ok(true),前端误以为成功但库无变更(UI/DB 不一致)。 +/// +/// 返回值保持 bool(成功恒 true):前端 api 包装 `Promise` 契约不变零破坏, +/// title 不在 IPC 返回值——IPC 调用点(projects store)不展示带返回值的 toast, +/// title 仅供 AI 工具卡片路径(ai/tools/project.rs),IPC 路径返 title 为冗余。 #[tauri::command] pub async fn update_project( state: State<'_, AppState>, @@ -306,11 +313,15 @@ pub async fn update_project( field: String, value: String, ) -> Result { - state + // B-260801-01(P0-1):update_field 返 affected>0;false = id 不存在或已软删(0 行)。 + let updated = state .projects .update_field(&id, &field, &value) .await .map_err(err_str)?; + if !updated { + return Err(format!("项目 ID {id} 不存在或已删除")); + } // F-260620: path 字段变更后立即 reload 白名单(新绑定/重绑目录即时生效,防 AI 误弹窗) if field == "path" { state.reload_allowed_dirs().await; diff --git a/src-tauri/src/commands/task.rs b/src-tauri/src/commands/task.rs index aa91234..4108d32 100644 --- a/src-tauri/src/commands/task.rs +++ b/src-tauri/src/commands/task.rs @@ -330,7 +330,15 @@ pub async fn create_task( Ok(record) } -/// 更新任务单个字段(字段名走 df-storage 白名单校验;status 值走枚举校验) +/// 更新任务单个字段(字段名走 df-storage 白名单校验;status 值走枚举校验)。 +/// +/// B-260801-01(P0-1):0 行(id 不存在 / 已软删)→ 返 Err 而非 false,杜绝「假成功」 +/// (前端 updateTask 仅 await 不读 bool,但 store.runWithCatch 把 Err 转 toast,用户能感知; +/// 若返 false 则 store 静默忽略,本地状态前端手动改但库无变更,造成 UI 与 DB 不一致)。 +/// +/// 返回值保持 bool(成功恒 true):前端 api 包装 `Promise` 契约不变零破坏, +/// title 不在 IPC 返回值——IPC 唯一调用点(Tasks.vue 优先级改)不展示带返回值的 toast, +/// title 仅供 AI 工具卡片路径(已修见 ai/tools/task.rs),IPC 路径返 title 为冗余。 #[tauri::command] pub async fn update_task( state: State<'_, AppState>, @@ -398,11 +406,17 @@ pub async fn update_task( } // 空字符串 = None(解除父),合法放行 } - state + // B-260801-01(P0-1):update_field 返 affected>0;false = id 不存在或已软删(0 行)。 + // 不可静默返 false——前端 store.runWithCatch 把 Err 转 toast,而 false 会被忽略致假成功。 + let updated = state .tasks .update_field(&id, &field, &value) .await - .map_err(err_str) + .map_err(err_str)?; + if !updated { + return Err(format!("任务 ID {id} 不存在或已删除")); + } + Ok(true) } /// 删除任务(软删 → 回收站,可恢复)。对标 delete_project(SET deleted_at=now)。