修复: ai-chat 交互体验批(草稿备份/图片放大/目标完成态/淘汰边界条)

- 输入侧:编辑消息不再静默销毁草稿(备份/回填)、补全浮层滚随、贴图 loading 态+并发上限复核、mention 失焦收口、富文本图文同粘、上传失败提示
- 消息流:图片点击 lightbox 放大、复制钮 focus 可见、复制为图片降级文案据实、JSON 块恢复可选、bucketSig 改哈希防长会话卡顿、user 长消息折叠、工具卡流式滚尾
- 会话框架:后台任务面板入点外/Esc 收起编排、恢复任务行级 busy+失败 toast、菜单底部翻转、搜索态统一清、归档禁改名对齐、listbox 语义+方向键、状态点 title、窄侧栏容器查询
- 跨端:删除目标不再抹其余目标完成态(前后端 GoalEntry 全量传递+失败回滚)
- 边界条:MESSAGE_CAP 滚动淘汰不再静默,头部一键补齐完整会话,历史定位文案据实区分
This commit is contained in:
lxy
2026-10-25 22:32:49 +08:00
parent 3caf2d047f
commit 62776a30f1
38 changed files with 3848 additions and 2778 deletions
@@ -1141,17 +1141,17 @@ pub async fn ai_conversation_set_pinned(
///
/// 接收前端 UI 增删后的目标列表,持久化到 DB 并同步更新内存 per_conv 状态。
/// goals 是完整替换(非增量),前端增/删后传全量 new Vec。
// 跨端修复(走查批E):签名 Vec<String> → Vec<GoalEntry>。原实现把前端载荷逐条
// GoalEntry::new 重置 active,已完成目标(status="completed")的完成态被抹。
// 前端 GoalsPanel 同步改传完整 GoalEntry[](text/status,snake_case),反序列化缺
// status 时 serde default 补 active(见 mod.rs GoalEntry 定义),旧载荷兼容。
#[tauri::command]
pub async fn ai_update_conversation_goals(
state: State<'_, AppState>,
conversation_id: String,
goals: Vec<String>,
goals: Vec<crate::commands::ai::GoalEntry>,
) -> Result<(), String> {
// 前端传回的 string[] 转为 GoalEntry(假设全部 active)
let goal_entries: Vec<crate::commands::ai::GoalEntry> = goals.into_iter()
.map(|g| crate::commands::ai::GoalEntry::new(g))
.collect();
let goals_json = serde_json::to_string(&goal_entries).map_err(|e| format!("序列化目标列表失败: {e}"))?;
let goals_json = serde_json::to_string(&goals).map_err(|e| format!("序列化目标列表失败: {e}"))?;
// 写 DB
state.ai_conversations
.update_field(&conversation_id, "pinned_goals", &goals_json)
@@ -1160,7 +1160,7 @@ pub async fn ai_update_conversation_goals(
// 同步内存 per_conv(若已加载)
let mut session = state.ai_session.lock().await;
if let Some(conv) = session.per_conv.get_mut(&conversation_id) {
conv.pinned_goals = goal_entries;
conv.pinned_goals = goals;
}
Ok(())
}