优化: 所有剩余UI/UX待办一批完成(持久化+AuditLog+解耦+total+原12大改+P2)

持久化(P1-c):新建 usePersistedRef composable,Tasks/AuditLog/ProjectDetail 等接入 localStorage

AuditLog(P1-d):后端 list_tool_executions 加 WHERE 筛选+返 {items,total,has_more},前端对接+长列折叠+筛选持久化

数据源解耦(P1-g):ProjectDetail projectTasks 按 project_id 独立加载 + ChatInput @项目联想独立加载(不读 store.tasks 当前页)

GitChanges(12a):后端 get_module_commits 加 git rev-list --count 返 total,前端显真实总数

原12大改:Dashboard 统计卡压底行(1)/Projects 列表卡片视图(2)/project_event 埋点排序(3)/TaskDetail 重设计(4)/IdeaDetail 重设计(5)/KnowledgeDetail 重设计(6)/界面持久化+侧栏Ctrl+B+审批数字键(7)/ProjectDetail 三栏改两栏(10)

P2打磨:文件浏览器(FileTree去重/FilePreview行号.md Diff/selectedFilePath归位)/settings反馈(假保存/端口校验)/AI会话(try-catch/scrollIntoView)/后端计数(move_queue事件/timeline total/workflow分页/import_batch分块)/杂项(TopBar/ConfirmDialog键盘/CIStatus i18n/ToolResultBody/ModuleNode/ApprovalDialog全选)
This commit is contained in:
lxy
2026-08-02 13:11:06 +08:00
parent caaabf0c15
commit f736f435bc
70 changed files with 2645 additions and 576 deletions
+30 -6
View File
@@ -279,6 +279,9 @@ struct GitStatus {
changed_files: Vec<GitChangedFile>,
/// 最近 10 条提交
recent_commits: Vec<GitRecentCommit>,
/// 当前 HEAD 的全量提交数(`git rev-list --count HEAD`)。
/// 前端历史 Tab 徽标 / 分支栏计数用它,而非 recent_commits.len()(后者受分页限制)。
total_commits: i64,
/// 该目录是否为 Git 仓库(无 .git 时 false,其余字段空)
is_git_repo: bool,
}
@@ -289,6 +292,7 @@ fn empty_status() -> GitStatus {
branch: String::new(),
changed_files: Vec::new(),
recent_commits: Vec::new(),
total_commits: 0,
is_git_repo: false,
}
}
@@ -447,10 +451,19 @@ fn run_git_status(dir: &str) -> GitStatus {
}
}
// 4) 全量提交计数:`git rev-list --count HEAD`(供前端历史 Tab 徽标真实总数,
// 非 recent_commits.len() 后者上限 50)。命令失败 → 退化为 recent_commits 长度。
let total_commits = run_git_cmd(path, &["rev-list", "--count", "HEAD"], timeout)
.map(|s| s.trim().to_string())
.filter(|s| !s.is_empty())
.and_then(|s| s.parse::<i64>().ok())
.unwrap_or(recent_commits.len() as i64);
GitStatus {
branch,
changed_files,
recent_commits,
total_commits,
is_git_repo: true,
}
}
@@ -949,7 +962,8 @@ fn collect_git_status_map(dir: &str) -> HashMap<String, String> {
}
/// 查询工程 Git 提交历史(分页,按时间倒序)。
/// 返回 { commits: [{ hash, subject, timestamp }], has_more: bool }。
/// 返回 { commits: [{ hash, subject, timestamp, author }], has_more: bool, total: i64 }。
/// total = `git rev-list --count HEAD` 的全量提交数,供前端徽标真实总数(commits.len() 受分页限制)。
#[tauri::command]
pub async fn get_module_commits(
state: State<'_, AppState>,
@@ -969,7 +983,7 @@ pub async fn get_module_commits(
.ok_or_else(|| format!("工程 {module_id} 不存在"))?;
let path = std::path::Path::new(&module.path);
if !path.join(".git").exists() {
return Ok(serde_json::json!({ "commits": [], "has_more": false }));
return Ok(serde_json::json!({ "commits": [], "has_more": false, "total": 0 }));
}
let skip = skip.unwrap_or(0);
let fetch = limit.unwrap_or(50);
@@ -978,16 +992,18 @@ pub async fn get_module_commits(
let dir = module.path.clone();
let dir_for_git = dir.clone();
// git 命令在 spawn_blocking 中执行(阻塞 IO 不污染 async runtime),10s 超时
let commits: Vec<serde_json::Value> = tokio::task::spawn_blocking(move || -> Vec<serde_json::Value> {
let (commits, total): (Vec<serde_json::Value>, i64) = tokio::task::spawn_blocking(move || -> (Vec<serde_json::Value>, i64) {
let path = std::path::Path::new(&dir_for_git);
let timeout = std::time::Duration::from_secs(10);
let out = run_git_cmd(
std::path::Path::new(&dir_for_git),
path,
&[
"log",
&format!("--skip={}", skip),
&format!("-{}", fetch_plus),
"--format=%h %ct %an %s",
],
std::time::Duration::from_secs(10),
timeout,
)
.unwrap_or_default();
let mut commits: Vec<serde_json::Value> = Vec::new();
@@ -1010,7 +1026,14 @@ pub async fn get_module_commits(
}));
}
}
commits
// 全量提交计数(`git rev-list --count HEAD`):前端历史 Tab 徽标真实总数。
// 命令失败 → 退化为 0(前端会显示 0,但 has_more 仍可驱动分页)。
let total = run_git_cmd(path, &["rev-list", "--count", "HEAD"], timeout)
.map(|s| s.trim().to_string())
.filter(|s| !s.is_empty())
.and_then(|s| s.parse::<i64>().ok())
.unwrap_or(0);
(commits, total)
})
.await
.map_err(|e| format!("提交历史查询任务失败: {e}"))?;
@@ -1023,6 +1046,7 @@ pub async fn get_module_commits(
Ok(serde_json::json!({
"commits": returned,
"has_more": has_more,
"total": total,
}))
}