修复: IPC update_project/task 实体校验(false→Err 治假成功)+ status 白名单确认(B-260801-01)
This commit is contained in:
@@ -299,6 +299,13 @@ pub async fn get_project(
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// 更新项目单个字段(字段名走 df-storage 白名单校验)
|
/// 更新项目单个字段(字段名走 df-storage 白名单校验)
|
||||||
|
///
|
||||||
|
/// B-260801-01(P0-1):0 行(id 不存在 / 已软删)→ 返 Err 而非假成功。原实现无视
|
||||||
|
/// update_field 返回值恒返 Ok(true),前端误以为成功但库无变更(UI/DB 不一致)。
|
||||||
|
///
|
||||||
|
/// 返回值保持 bool(成功恒 true):前端 api 包装 `Promise<boolean>` 契约不变零破坏,
|
||||||
|
/// title 不在 IPC 返回值——IPC 调用点(projects store)不展示带返回值的 toast,
|
||||||
|
/// title 仅供 AI 工具卡片路径(ai/tools/project.rs),IPC 路径返 title 为冗余。
|
||||||
#[tauri::command]
|
#[tauri::command]
|
||||||
pub async fn update_project(
|
pub async fn update_project(
|
||||||
state: State<'_, AppState>,
|
state: State<'_, AppState>,
|
||||||
@@ -306,11 +313,15 @@ pub async fn update_project(
|
|||||||
field: String,
|
field: String,
|
||||||
value: String,
|
value: String,
|
||||||
) -> Result<bool, String> {
|
) -> Result<bool, String> {
|
||||||
state
|
// B-260801-01(P0-1):update_field 返 affected>0;false = id 不存在或已软删(0 行)。
|
||||||
|
let updated = state
|
||||||
.projects
|
.projects
|
||||||
.update_field(&id, &field, &value)
|
.update_field(&id, &field, &value)
|
||||||
.await
|
.await
|
||||||
.map_err(err_str)?;
|
.map_err(err_str)?;
|
||||||
|
if !updated {
|
||||||
|
return Err(format!("项目 ID {id} 不存在或已删除"));
|
||||||
|
}
|
||||||
// F-260620: path 字段变更后立即 reload 白名单(新绑定/重绑目录即时生效,防 AI 误弹窗)
|
// F-260620: path 字段变更后立即 reload 白名单(新绑定/重绑目录即时生效,防 AI 误弹窗)
|
||||||
if field == "path" {
|
if field == "path" {
|
||||||
state.reload_allowed_dirs().await;
|
state.reload_allowed_dirs().await;
|
||||||
|
|||||||
@@ -330,7 +330,15 @@ pub async fn create_task(
|
|||||||
Ok(record)
|
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<boolean>` 契约不变零破坏,
|
||||||
|
/// title 不在 IPC 返回值——IPC 唯一调用点(Tasks.vue 优先级改)不展示带返回值的 toast,
|
||||||
|
/// title 仅供 AI 工具卡片路径(已修见 ai/tools/task.rs),IPC 路径返 title 为冗余。
|
||||||
#[tauri::command]
|
#[tauri::command]
|
||||||
pub async fn update_task(
|
pub async fn update_task(
|
||||||
state: State<'_, AppState>,
|
state: State<'_, AppState>,
|
||||||
@@ -398,11 +406,17 @@ pub async fn update_task(
|
|||||||
}
|
}
|
||||||
// 空字符串 = None(解除父),合法放行
|
// 空字符串 = None(解除父),合法放行
|
||||||
}
|
}
|
||||||
state
|
// B-260801-01(P0-1):update_field 返 affected>0;false = id 不存在或已软删(0 行)。
|
||||||
|
// 不可静默返 false——前端 store.runWithCatch 把 Err 转 toast,而 false 会被忽略致假成功。
|
||||||
|
let updated = state
|
||||||
.tasks
|
.tasks
|
||||||
.update_field(&id, &field, &value)
|
.update_field(&id, &field, &value)
|
||||||
.await
|
.await
|
||||||
.map_err(err_str)
|
.map_err(err_str)?;
|
||||||
|
if !updated {
|
||||||
|
return Err(format!("任务 ID {id} 不存在或已删除"));
|
||||||
|
}
|
||||||
|
Ok(true)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// 删除任务(软删 → 回收站,可恢复)。对标 delete_project(SET deleted_at=now)。
|
/// 删除任务(软删 → 回收站,可恢复)。对标 delete_project(SET deleted_at=now)。
|
||||||
|
|||||||
Reference in New Issue
Block a user