perf(logs): 日志事件按窗口合并推送,抽屉改为虚拟滚动
- 后端 LogSink 把逐行事件按 16 KiB / 100 ms 合并成一条 log 事件,文件写入保持即时;后台 tick 与析构 flush 保证低输出和收尾都不丢尾部 - 前端新增 LogViewer:固定行高虚拟滚动、跟随底部/回到最新,增量按 rAF 合并,长日志 DOM 节点数恒定 - 日志抽屉改为行缓冲(lib/logLines)+ 可见窗口计算(lib/logWindow) - 详情区改 flex 布局,日志面板吃掉剩余高度,回到最新按钮不再被裁到面板外 - 测试:Rust 单元 52→57,Vitest 13→28,Playwright 4→5(1500 行虚拟滚动) - 文档:README 补充合并推送与虚拟滚动,新增 ADR-0008
This commit is contained in:
@@ -5,7 +5,7 @@ TaskPilot 是一个面向 **Windows 单机** 的本地定时任务管理平台
|
||||
- 单用户、单实例,只监听 `127.0.0.1`
|
||||
- 三类任务:Python/Shell 脚本、HTTP 请求、二进制进程
|
||||
- SQLite 持久化,重启后任务与历史仍在
|
||||
- 运行日志实时推送(SSE),断线自动回退轮询
|
||||
- 运行日志实时推送(SSE),按窗口合并事件;断线自动回退轮询,长日志用虚拟滚动展示
|
||||
- 前端零外部依赖:样式与脚本随包自带;界面字体可选,未生成时自动回退系统字体
|
||||
|
||||
> 根目录的 `task_pilot.html` 只是最初的单文件视觉原型,正式入口是 React 应用。
|
||||
@@ -184,6 +184,11 @@ queued ──► running ──► succeeded / failed / timed_out / cancelled
|
||||
- **单行 256 KiB** 上限:超出部分丢弃、继续读到行尾,避免内存无界增长。
|
||||
- 保留期(默认 30 天)与总容量(默认 512 MiB)清理;**跳过正在写入的日志**。
|
||||
- 读取按 64 KiB 分块且对齐 UTF-8 边界;`complete` 只在"运行结束且读到文件末尾"时为真。
|
||||
- **合并推送**:子进程输出按行写入文件后,先在内存里按 **100 ms / 16 KiB** 窗口合并,
|
||||
每个窗口只发一条 SSE `log` 事件(偏移仍严格连续);低输出时由后台任务按时推,
|
||||
运行结束时在 `LogSink` 析构里兜底 flush,不会丢尾部。
|
||||
- **虚拟滚动**:日志抽屉只渲染视口附近的行(固定行高 20 px),几万行时 DOM 节点数恒定;
|
||||
增量先并进行缓冲、一帧最多重渲染一次。往上翻时停止跟随并显示「回到最新」。长行横向滚动、不折行。
|
||||
- **输出编码**:默认 `auto` = 逐行先按 UTF-8 解码,失败回退到系统 ANSI 代码页(简体中文为 GBK)。
|
||||
可用 `TASK_PILOT_LOG_ENCODING=gbk|utf-8|windows-1251` 强制。
|
||||
- **脱敏**:环境变量/Header 名包含 `SECRET`、`TOKEN`、`PASSWORD`、`PASS`、`API_KEY`、
|
||||
@@ -422,6 +427,9 @@ React (Vite) ──fetch──► Axum router ──security::api_guard(Origin +
|
||||
| `components/TaskEditorModal.tsx` | 三类动态表单、Cron 预览、虚拟环境状态条 |
|
||||
| `components/DirectoryPickerDialog.tsx` | 页面内目录浏览器 |
|
||||
| `components/RunLogDrawer.tsx` | 运行历史、日志、取消、下载、SSE |
|
||||
| `components/LogViewer.tsx` | 日志虚拟滚动、跟随底部/回到最新 |
|
||||
| `lib/logLines.ts` | 增量日志的行缓冲(残行拼接、CRLF 归一) |
|
||||
| `lib/logWindow.ts` | 可见行窗口计算 |
|
||||
| `api/client.ts` | 类型化客户端、令牌缓存、403 重试 |
|
||||
| `lib/taskForm.ts` | Zod 校验与表单 ↔ API 载荷映射 |
|
||||
|
||||
@@ -483,10 +491,10 @@ uv run --with fonttools --with brotli tools/build-fonts.py
|
||||
|
||||
| 层 | 覆盖 |
|
||||
| --- | --- |
|
||||
| Rust 单元(52) | Cron、虚拟环境解析与探测、执行器(编码/截断/清理/句柄归属)、安全、目录列举 |
|
||||
| Rust 单元(57) | Cron、虚拟环境解析与探测、执行器(编码/截断/清理/句柄归属/日志合并推送)、安全、目录列举 |
|
||||
| Rust 集成(30) | 任务 CRUD 与校验、运行生命周期、取消与超时、日志分块、调度恢复、统计与调度接口、重启对账 |
|
||||
| 前端 Vitest(13) | 仪表盘渲染、表单载荷、虚拟环境状态、目录浏览器(进入/取消/错误)、下次触发时间 |
|
||||
| Playwright(4) | 真实任务执行与日志、编辑/停用/删除、窄屏、**无外部网络渲染**(拦截所有外部请求) |
|
||||
| 前端 Vitest(28) | 仪表盘渲染、表单载荷、虚拟环境状态、目录浏览器、下次触发时间、日志行切分/窗口计算/虚拟滚动 |
|
||||
| Playwright(5) | 真实任务执行与日志、编辑/停用/删除、窄屏、**无外部网络渲染**、1500 行日志的虚拟滚动 |
|
||||
| Python 自检(14 项) | `tools/verify.py` 覆盖 API 全链路 |
|
||||
|
||||
---
|
||||
@@ -530,6 +538,7 @@ uv run --with fonttools --with brotli tools/build-fonts.py
|
||||
- [ADR-0005:由后端提供系统文件夹选择](docs/decisions/0005-folder-picker.md)
|
||||
- [ADR-0006:视觉风格对齐主题并自托管字体](docs/decisions/0006-visual-theme-and-offline-fonts.md)
|
||||
- [ADR-0007:运行期可靠性优化](docs/decisions/0007-runtime-reliability.md)
|
||||
- [ADR-0008:日志合并推送与虚拟滚动](docs/decisions/0008-log-streaming-and-virtualization.md)
|
||||
|
||||
## 开发计划
|
||||
|
||||
|
||||
Reference in New Issue
Block a user