修复定时任务日志按钮无响应并增加执行历史 #199

Open
opened 2026-09-02 22:29:05 +08:00 by ila · 8 comments
Owner

阶段

待验收。实现提交 81c1a7ead226f1c814a7cffdcf29b5770aa21996 已于 2026-09-02 在线执行追加迁移并发布为 20260902-81c1a7e-r1;GoAuto/Nginx 已重启且自动核验通过,所有发布前关闭的定时任务保持关闭,等待登录 Admin 完成人工点击验收。

原始需求摘要

  • 来源:用户,2026-09-02。
  • 现象:Admin「系统管理 → 定时任务」勾选一条任务后点击「日志」没有反应。
  • 用户确认方向:修复无响应,并按所选定时任务提供可查询的持久化执行历史,不继续使用不可用的本机 WebSocket 实时页。
  • 关联:问题在 #198 上线后操作定时任务时发现,但属于既有通用定时任务模块缺陷;不改变 #198 的 AI 解析规则。

已确认代码与线上事实

基线:线上提交 aa2ecc6ef791d1ebbd9c4f0ee64c84816de046cc,核验时间 2026-09-02。

  1. web/src/views/schedule/index.vue 的 handleLog() 跳转路由名 job_log;线上 sys_menu.menu_name 与动态路由名实际为 JobLog,Vue Router 无法匹配,因此点击无界面反馈。
  2. handleLog() 未读取 ids,勾选任务与日志入口没有关联。
  3. web/src/views/schedule/log.vue 将 WebSocket 固定为 ws://127.0.0.1:8000,线上会错误连接采购员电脑本机;服务端定时任务日志广播代码也已注释。
  4. 当前日志页只有瞬时 WebSocket 消息,不保存历史记录,无法回答某次任务何时开始、成功/失败、耗时和脱敏错误。
  5. #198 当前 status=1,保持关闭;本单不得顺带启用或运行它。

目标范围

  1. 日志按钮只在恰好勾选一条任务时启用;跳转到真实 JobLog 路由并携带 jobId。
  2. 将旧日志页改为所选任务的分页执行历史:开始/结束时间、状态、耗时、触发方式和脱敏错误摘要。
  3. 新增通用 sys_job_execution_log 持久化表;Cron 执行开始写入 running,结束收敛为 succeeded 或 failed。
  4. 服务启动时将本实例重启前遗留的 running 记录安全收敛为 interrupted,避免永久显示执行中。
  5. 新增只读分页 API,按 jobId、状态和时间范围查询;服务端校验任务存在和访问权限。
  6. HTTP Job 与 GoAuto Exec Job 共用同一执行记录封装;日志写入失败不得把原业务任务误报成功,但必须写服务日志供排错。
  7. 删除定时任务后保留名称与调用目标快照,历史仍可审计;本单不自动清理历史数据。

非目标与安全边界

  • 不保存任务参数、AI Provider 原始响应、API Key、订单/地址/账号、SYB RawJSON 或其他业务载荷。
  • 错误摘要统一脱敏并限长;API 不返回堆栈、SQL、凭据或内部配置。
  • 不恢复旧 WebSocket 实时日志,不新增“立即执行”能力。
  • 不启用 #198 或其他关闭的定时任务,不创建采集任务、采购任务、订单,不执行 Android 动作或付款。
  • 不自动删除日志;保留期限另建工单评估。

数据与状态设计

追加迁移建议:1788357000000_sys_job_execution_log.go。

sys_job_execution_log:

  • id:主键;execution_id:唯一、不可猜测执行标识。
  • job_id、job_name_snapshot、invoke_target_snapshot。
  • trigger_type:本期固定 scheduled,为后续显式人工执行预留但本单不实现。
  • status:running | succeeded | failed | interrupted。
  • started_at、finished_at、duration_ms。
  • error_code、error_message:稳定错误码和限长脱敏摘要,成功时为空。
  • 索引:(job_id, started_at)、(status, started_at);不设级联外键,以保留已删除任务的历史。

迁移只建表、索引及必要只读 API/权限事实,不回填旧日志,不启用任何任务。迁移和权限写入需用户再次明确授权后才能执行。

API 与权限

  • GET /api/v1/sysjob/:id/execution-logs
  • 参数:pageIndex、pageSize(上限 100)、可选 status、startedFrom、startedTo。
  • 响应:任务基本信息、分页执行记录;不包含任务参数和原始错误。
  • 页面入口继续使用 job:sysJob:log;新 API 只授予已有该能力的角色。无权限时按钮隐藏且接口返回 403;任务不存在返回 404。

v1 低保真设计证据(已确认)

定时任务列表

[新增] [修改(单选)] [删除(有选择)] [日志(单选)]

☑ 5  SYB 异常规格 AI 解析  0 5 * * * *  关闭
  • 未选或多选:「日志」禁用。
  • 单选:「日志」启用,进入该任务的执行历史。

执行日志页

定时任务 / 执行日志
← 返回任务列表       SYB 异常规格 AI 解析(#5)

[状态:全部 v] [开始时间:____ 至 ____] [查询] [重置]

执行标识 | 开始时间 | 结束时间 | 状态 | 耗时 | 触发方式 | 错误摘要
---------|----------|----------|------|------|----------|---------
…        | …        | …        | 成功 | 2.3s | 定时调度 | —

                         < 1 / 3 >

状态覆盖:

  • 加载:表格 loading。
  • 空状态:该任务尚无执行记录;关闭任务属于正常空状态。
  • 失败:显示稳定错误码和脱敏摘要,不显示原始响应。
  • running:结束时间/耗时显示“执行中”。
  • interrupted:显示“服务重启前未完成”。
  • 无权限:不进入页面,由现有 401/403 机制处理。

验收标准

  • 未选、多选时日志按钮禁用;单选时进入所选 jobId 的日志页,不再出现无响应。
  • 直接访问日志页时可按 jobId 加载;缺失/非法 ID 有明确提示并可返回列表。
  • 定时任务每次执行恰有一条记录,成功、失败、耗时正确;未知调用目标也记录失败。
  • 服务中断遗留的 running 最终显示为 interrupted,不长期卡住。
  • 日志写入异常不泄露敏感信息;不保存 args、AI 原始响应或业务载荷。
  • 任务删除后历史仍可查看;本单不自动删除历史。
  • API 分页、过滤、权限、任务不存在边界均有自动化测试。
  • HTTP Job、Exec Job、启动恢复及现有调度启停回归测试通过。
  • Web 路由、按钮禁用、正常/空/加载/失败状态测试及生产构建通过。
  • 追加迁移幂等;未获授权不执行本机或线上迁移。
  • #198 及所有原本关闭的任务保持关闭,不触发 AI、采购、订单或付款。

预计影响

  • server/app/jobs/:执行记录模型、统一记录封装、分页服务/API、启动恢复。
  • server/cmd/migrate/migration/version-local/:追加迁移和必要 API/权限事实。
  • web/src/views/schedule/index.vue、web/src/views/schedule/log.vue、相关 API:单选跳转和历史列表。
  • 不影响 Android;不改变 GoAuto Agent API。

验证计划

  • 服务端单元/并发与迁移幂等测试;scripts/verify.ps1 -Component server。
  • Web 单元测试、lint、生产构建;用登录 Admin 验证单选跳转和四种状态。
  • python dev_scripts/harness.py check --strict。
  • 获授权后先备份数据库,再迁移、发布和重启;上线只读查看,不启用 #198。

风险与回退

  • 风险:错误文本泄密、执行记录遗漏/重复、进程中断留下 running、历史表持续增长、权限越界。
  • 控制:集中脱敏、唯一 execution_id、开始/终态事务更新、启动恢复、分页上限、沿用 job:sysJob:log 权限。
  • 回退:前端恢复旧入口隐藏;服务回退后保留新增表和审计记录,不删除生产数据。数据库迁移与权限写入、线上发布均需单独明确授权。

文档影响

  • 需更新 Architecture-and-Code-Map:定时任务执行记录模型和调用链。
  • 需更新 Deployment-and-Operations:日志查询、状态含义和排错方式。
  • Android-Agent-API-Contract 无变化。
  • 默认不创建 Wiki 任务归档或本地原型导出。

依赖与并行

  • 依赖线上 #198 发布基线 aa2ecc6ef791d1ebbd9c4f0ee64c84816de046cc。
  • 数据模型、服务端记录封装和 Web 页面可在设计确认后并行实施;上线顺序必须先备份/迁移,再发布服务端与 Web。
## 阶段 待验收。实现提交 `81c1a7ead226f1c814a7cffdcf29b5770aa21996` 已于 2026-09-02 在线执行追加迁移并发布为 `20260902-81c1a7e-r1`;GoAuto/Nginx 已重启且自动核验通过,所有发布前关闭的定时任务保持关闭,等待登录 Admin 完成人工点击验收。 ## 原始需求摘要 - 来源:用户,2026-09-02。 - 现象:Admin「系统管理 → 定时任务」勾选一条任务后点击「日志」没有反应。 - 用户确认方向:修复无响应,并按所选定时任务提供可查询的持久化执行历史,不继续使用不可用的本机 WebSocket 实时页。 - 关联:问题在 #198 上线后操作定时任务时发现,但属于既有通用定时任务模块缺陷;不改变 #198 的 AI 解析规则。 ## 已确认代码与线上事实 基线:线上提交 `aa2ecc6ef791d1ebbd9c4f0ee64c84816de046cc`,核验时间 2026-09-02。 1. `web/src/views/schedule/index.vue` 的 `handleLog()` 跳转路由名 `job_log`;线上 `sys_menu.menu_name` 与动态路由名实际为 `JobLog`,Vue Router 无法匹配,因此点击无界面反馈。 2. `handleLog()` 未读取 `ids`,勾选任务与日志入口没有关联。 3. `web/src/views/schedule/log.vue` 将 WebSocket 固定为 `ws://127.0.0.1:8000`,线上会错误连接采购员电脑本机;服务端定时任务日志广播代码也已注释。 4. 当前日志页只有瞬时 WebSocket 消息,不保存历史记录,无法回答某次任务何时开始、成功/失败、耗时和脱敏错误。 5. #198 当前 `status=1`,保持关闭;本单不得顺带启用或运行它。 ## 目标范围 1. 日志按钮只在恰好勾选一条任务时启用;跳转到真实 `JobLog` 路由并携带 `jobId`。 2. 将旧日志页改为所选任务的分页执行历史:开始/结束时间、状态、耗时、触发方式和脱敏错误摘要。 3. 新增通用 `sys_job_execution_log` 持久化表;Cron 执行开始写入 `running`,结束收敛为 `succeeded` 或 `failed`。 4. 服务启动时将本实例重启前遗留的 `running` 记录安全收敛为 `interrupted`,避免永久显示执行中。 5. 新增只读分页 API,按 `jobId`、状态和时间范围查询;服务端校验任务存在和访问权限。 6. HTTP Job 与 GoAuto Exec Job 共用同一执行记录封装;日志写入失败不得把原业务任务误报成功,但必须写服务日志供排错。 7. 删除定时任务后保留名称与调用目标快照,历史仍可审计;本单不自动清理历史数据。 ## 非目标与安全边界 - 不保存任务参数、AI Provider 原始响应、API Key、订单/地址/账号、SYB RawJSON 或其他业务载荷。 - 错误摘要统一脱敏并限长;API 不返回堆栈、SQL、凭据或内部配置。 - 不恢复旧 WebSocket 实时日志,不新增“立即执行”能力。 - 不启用 #198 或其他关闭的定时任务,不创建采集任务、采购任务、订单,不执行 Android 动作或付款。 - 不自动删除日志;保留期限另建工单评估。 ## 数据与状态设计 追加迁移建议:`1788357000000_sys_job_execution_log.go`。 `sys_job_execution_log`: - `id`:主键;`execution_id`:唯一、不可猜测执行标识。 - `job_id`、`job_name_snapshot`、`invoke_target_snapshot`。 - `trigger_type`:本期固定 `scheduled`,为后续显式人工执行预留但本单不实现。 - `status`:`running | succeeded | failed | interrupted`。 - `started_at`、`finished_at`、`duration_ms`。 - `error_code`、`error_message`:稳定错误码和限长脱敏摘要,成功时为空。 - 索引:`(job_id, started_at)`、`(status, started_at)`;不设级联外键,以保留已删除任务的历史。 迁移只建表、索引及必要只读 API/权限事实,不回填旧日志,不启用任何任务。迁移和权限写入需用户再次明确授权后才能执行。 ## API 与权限 - `GET /api/v1/sysjob/:id/execution-logs` - 参数:`pageIndex`、`pageSize`(上限 100)、可选 `status`、`startedFrom`、`startedTo`。 - 响应:任务基本信息、分页执行记录;不包含任务参数和原始错误。 - 页面入口继续使用 `job:sysJob:log`;新 API 只授予已有该能力的角色。无权限时按钮隐藏且接口返回 403;任务不存在返回 404。 ## v1 低保真设计证据(已确认) ### 定时任务列表 ```text [新增] [修改(单选)] [删除(有选择)] [日志(单选)] ☑ 5 SYB 异常规格 AI 解析 0 5 * * * * 关闭 ``` - 未选或多选:「日志」禁用。 - 单选:「日志」启用,进入该任务的执行历史。 ### 执行日志页 ```text 定时任务 / 执行日志 ← 返回任务列表 SYB 异常规格 AI 解析(#5) [状态:全部 v] [开始时间:____ 至 ____] [查询] [重置] 执行标识 | 开始时间 | 结束时间 | 状态 | 耗时 | 触发方式 | 错误摘要 ---------|----------|----------|------|------|----------|--------- … | … | … | 成功 | 2.3s | 定时调度 | — < 1 / 3 > ``` 状态覆盖: - 加载:表格 loading。 - 空状态:`该任务尚无执行记录`;关闭任务属于正常空状态。 - 失败:显示稳定错误码和脱敏摘要,不显示原始响应。 - `running`:结束时间/耗时显示“执行中”。 - `interrupted`:显示“服务重启前未完成”。 - 无权限:不进入页面,由现有 401/403 机制处理。 ## 验收标准 - [ ] 未选、多选时日志按钮禁用;单选时进入所选 `jobId` 的日志页,不再出现无响应。 - [ ] 直接访问日志页时可按 `jobId` 加载;缺失/非法 ID 有明确提示并可返回列表。 - [ ] 定时任务每次执行恰有一条记录,成功、失败、耗时正确;未知调用目标也记录失败。 - [ ] 服务中断遗留的 `running` 最终显示为 `interrupted`,不长期卡住。 - [ ] 日志写入异常不泄露敏感信息;不保存 args、AI 原始响应或业务载荷。 - [ ] 任务删除后历史仍可查看;本单不自动删除历史。 - [ ] API 分页、过滤、权限、任务不存在边界均有自动化测试。 - [ ] HTTP Job、Exec Job、启动恢复及现有调度启停回归测试通过。 - [ ] Web 路由、按钮禁用、正常/空/加载/失败状态测试及生产构建通过。 - [ ] 追加迁移幂等;未获授权不执行本机或线上迁移。 - [ ] #198 及所有原本关闭的任务保持关闭,不触发 AI、采购、订单或付款。 ## 预计影响 - `server/app/jobs/`:执行记录模型、统一记录封装、分页服务/API、启动恢复。 - `server/cmd/migrate/migration/version-local/`:追加迁移和必要 API/权限事实。 - `web/src/views/schedule/index.vue`、`web/src/views/schedule/log.vue`、相关 API:单选跳转和历史列表。 - 不影响 Android;不改变 GoAuto Agent API。 ## 验证计划 - 服务端单元/并发与迁移幂等测试;`scripts/verify.ps1 -Component server`。 - Web 单元测试、lint、生产构建;用登录 Admin 验证单选跳转和四种状态。 - `python dev_scripts/harness.py check --strict`。 - 获授权后先备份数据库,再迁移、发布和重启;上线只读查看,不启用 #198。 ## 风险与回退 - 风险:错误文本泄密、执行记录遗漏/重复、进程中断留下 running、历史表持续增长、权限越界。 - 控制:集中脱敏、唯一 execution_id、开始/终态事务更新、启动恢复、分页上限、沿用 `job:sysJob:log` 权限。 - 回退:前端恢复旧入口隐藏;服务回退后保留新增表和审计记录,不删除生产数据。数据库迁移与权限写入、线上发布均需单独明确授权。 ## 文档影响 - 需更新 Architecture-and-Code-Map:定时任务执行记录模型和调用链。 - 需更新 Deployment-and-Operations:日志查询、状态含义和排错方式。 - Android-Agent-API-Contract 无变化。 - 默认不创建 Wiki 任务归档或本地原型导出。 ## 依赖与并行 - 依赖线上 #198 发布基线 `aa2ecc6ef791d1ebbd9c4f0ee64c84816de046cc`。 - 数据模型、服务端记录封装和 Web 页面可在设计确认后并行实施;上线顺序必须先备份/迁移,再发布服务端与 Web。
Author
Owner

当前会话未提供可用的 Gitea MCP 工具,按仓库规则回退 Gitea API 完成工单创建。已附 v1 低保真设计,生产代码、追加迁移和权限写入均停在设计确认及高风险授权门禁前。

当前会话未提供可用的 Gitea MCP 工具,按仓库规则回退 Gitea API 完成工单创建。已附 v1 低保真设计,生产代码、追加迁移和权限写入均停在设计确认及高风险授权门禁前。
Author
Owner

用户已于 2026-09-02 确认 #199 v1 低保真,并明确授权按工单方案实施追加迁移 1788357000000_sys_job_execution_log.go 及权限写入。实施只创建迁移代码并验证,不执行本机或线上迁移;已从线上 #198 基线 aa2ecc6ef791d1ebbd9c4f0ee64c84816de046cc 建立 feat/199-job-execution-logs。

用户已于 2026-09-02 确认 #199 v1 低保真,并明确授权按工单方案实施追加迁移 `1788357000000_sys_job_execution_log.go` 及权限写入。实施只创建迁移代码并验证,不执行本机或线上迁移;已从线上 #198 基线 `aa2ecc6ef791d1ebbd9c4f0ee64c84816de046cc` 建立 `feat/199-job-execution-logs`。
Author
Owner

实施完成,待验收

实现分支:feat/199-job-execution-logs
提交:81c1a7ead226f1c814a7cffdcf29b5770aa21996

已实现

  • 新增 sys_job_execution_log 模型和追加迁移 1788357000000_sys_job_execution_log.go;迁移幂等登记只读 API,并只给原本绑定隐藏菜单 JobLog 的角色补精确 GET 权限,菜单缺失时 fail-closed。
  • Exec Job、HTTP Job 共用执行生命周期记录;覆盖 running / succeeded / failed / interrupted,未知调用目标和 panic 均安全收敛。进程启动按当前单调度器拓扑回收遗留 running。
  • 执行历史只保存稳定错误码与脱敏摘要;不保存 args、Provider 配置/响应、密钥或业务原始载荷,服务运行日志也只输出稳定错误码。
  • 新增 GET /api/v1/sysjob/:id/execution-logs,支持分页、状态与 RFC3339 开始时间范围过滤;删除任务后历史仍可查看。
  • 修复 Admin 日志入口:未选/多选禁用,单选跳转真实 JobLog 并携带 jobId;旧本机 WebSocket 页替换为持久化历史页,覆盖加载、空、失败重试、运行中轮询、已删除提示与返回列表。

验证证据

  • scripts/verify.ps1 -Component server:通过(全量 Go 测试及构建)。
  • go test -race ./app/jobs/...:通过。
  • go vet ./app/jobs/... ./cmd/migrate/migration/version-local:通过。
  • 迁移幂等、仅授权既有菜单角色、菜单缺失 fail-closed:通过自动化测试。
  • Web 变更文件定向 ESLint:通过。
  • Jest:12 个 suite、42 个测试通过。
  • Playwright:单选任务 → JobLog?jobId=5 → 展示脱敏执行历史,1 个场景通过。
  • pnpm run build:prod:通过;仅保留仓库既有 CSS 伪类及大 chunk 警告。
  • 全量 pnpm lint 仍被本工单外 web/src/views/goauto/purchase-tasks/index.vue 的 24 个既有 mixed-tabs 错误阻断;#199 变更文件定向 lint 全部通过,未顺带修改该文件。
  • python dev_scripts/harness.py sync、sync --check、check --strict:通过。

Wiki 与安全边界

  • Architecture-and-Code-Map revision:a8ea0f6ae4c4a05b10ba047516fda23cfb188d13。
  • Deployment-and-Operations revision:16d97e7596dc287786f702c71e25172b75cc4d56。
  • 更新时始终显式提交原页面标题并在线回读,未发生重命名;同时清理了架构页正文遗留的镜像元数据头。
  • Android Agent API 契约无变化;未创建任务、未调用 AI、未创建订单、未执行付款。

尚未执行/需验收

  • 按授权仅实现迁移与权限写入代码;没有在本机或线上执行迁移,没有重启或发布 Admin/API。
  • 尚未验证真实数据库权限写入、线上调度产生执行记录及 Admin 真实账号查看;#198 和其他关闭任务未启用。
  • 标准流程未创建 Wiki 任务归档,也未导出本地原型。
## 实施完成,待验收 实现分支:`feat/199-job-execution-logs` 提交:[`81c1a7ead226f1c814a7cffdcf29b5770aa21996`](https://git.ilapage.cn/OPC/goauto/commit/81c1a7ead226f1c814a7cffdcf29b5770aa21996) ### 已实现 - 新增 `sys_job_execution_log` 模型和追加迁移 `1788357000000_sys_job_execution_log.go`;迁移幂等登记只读 API,并只给原本绑定隐藏菜单 `JobLog` 的角色补精确 GET 权限,菜单缺失时 fail-closed。 - Exec Job、HTTP Job 共用执行生命周期记录;覆盖 `running / succeeded / failed / interrupted`,未知调用目标和 panic 均安全收敛。进程启动按当前单调度器拓扑回收遗留 `running`。 - 执行历史只保存稳定错误码与脱敏摘要;不保存 args、Provider 配置/响应、密钥或业务原始载荷,服务运行日志也只输出稳定错误码。 - 新增 `GET /api/v1/sysjob/:id/execution-logs`,支持分页、状态与 RFC3339 开始时间范围过滤;删除任务后历史仍可查看。 - 修复 Admin 日志入口:未选/多选禁用,单选跳转真实 `JobLog` 并携带 `jobId`;旧本机 WebSocket 页替换为持久化历史页,覆盖加载、空、失败重试、运行中轮询、已删除提示与返回列表。 ### 验证证据 - `scripts/verify.ps1 -Component server`:通过(全量 Go 测试及构建)。 - `go test -race ./app/jobs/...`:通过。 - `go vet ./app/jobs/... ./cmd/migrate/migration/version-local`:通过。 - 迁移幂等、仅授权既有菜单角色、菜单缺失 fail-closed:通过自动化测试。 - Web 变更文件定向 ESLint:通过。 - Jest:12 个 suite、42 个测试通过。 - Playwright:单选任务 → `JobLog?jobId=5` → 展示脱敏执行历史,1 个场景通过。 - `pnpm run build:prod`:通过;仅保留仓库既有 CSS 伪类及大 chunk 警告。 - 全量 `pnpm lint` 仍被本工单外 `web/src/views/goauto/purchase-tasks/index.vue` 的 24 个既有 mixed-tabs 错误阻断;#199 变更文件定向 lint 全部通过,未顺带修改该文件。 - `python dev_scripts/harness.py sync`、`sync --check`、`check --strict`:通过。 ### Wiki 与安全边界 - `Architecture-and-Code-Map` revision:`a8ea0f6ae4c4a05b10ba047516fda23cfb188d13`。 - `Deployment-and-Operations` revision:`16d97e7596dc287786f702c71e25172b75cc4d56`。 - 更新时始终显式提交原页面标题并在线回读,未发生重命名;同时清理了架构页正文遗留的镜像元数据头。 - Android Agent API 契约无变化;未创建任务、未调用 AI、未创建订单、未执行付款。 ### 尚未执行/需验收 - 按授权仅实现迁移与权限写入代码;**没有在本机或线上执行迁移,没有重启或发布 Admin/API**。 - 尚未验证真实数据库权限写入、线上调度产生执行记录及 Admin 真实账号查看;#198 和其他关闭任务未启用。 - 标准流程未创建 Wiki 任务归档,也未导出本地原型。
Author
Owner

2026-09-02 线上点击无响应复核

用户在重启服务后选择“SYB 每小时自动同步”并点击“日志”,仍无反应。只读核验确认这不是单条任务数据问题,而是 #199 尚未发布:

  • 线上 Admin 主包引用 js/schedule.CMMyRkqi.js 与 js/log.BvRPbAYI.js;前者仍包含旧路由名 job_log,后者仍包含 ws://127.0.0.1:8000,且两者均没有 /execution-logs 新接口调用。
  • GET http://185.216.248.75:9527/api/v1/sysjob/1/execution-logs 返回 HTTP 404,证明线上 API 二进制也不包含 #199 路由。
  • #199 提交 81c1a7ead226f1c814a7cffdcf29b5770aa21996 只存在于远端分支 feat/199-job-execution-logs,不在 origin/main;当前 origin/main 为 37dea33。

结论:本次仅重启了既有旧发布目录,重启不能替代构建/迁移/发布。工单继续保持待验收;未执行数据库迁移、权限写入、发布或任务启用。下一步须另获线上高风险授权后,按“备份数据库 → 执行 1788357000000_sys_job_execution_log.go → 发布含 81c1a7e 的 Server/Web → 重启 → 登录账号单选验证”的顺序处理,#198 仍保持关闭。

## 2026-09-02 线上点击无响应复核 用户在重启服务后选择“SYB 每小时自动同步”并点击“日志”,仍无反应。只读核验确认这不是单条任务数据问题,而是 #199 尚未发布: - 线上 Admin 主包引用 `js/schedule.CMMyRkqi.js` 与 `js/log.BvRPbAYI.js`;前者仍包含旧路由名 `job_log`,后者仍包含 `ws://127.0.0.1:8000`,且两者均没有 `/execution-logs` 新接口调用。 - `GET http://185.216.248.75:9527/api/v1/sysjob/1/execution-logs` 返回 HTTP 404,证明线上 API 二进制也不包含 #199 路由。 - #199 提交 `81c1a7ead226f1c814a7cffdcf29b5770aa21996` 只存在于远端分支 `feat/199-job-execution-logs`,不在 `origin/main`;当前 `origin/main` 为 `37dea33`。 结论:本次仅重启了既有旧发布目录,重启不能替代构建/迁移/发布。工单继续保持待验收;未执行数据库迁移、权限写入、发布或任务启用。下一步须另获线上高风险授权后,按“备份数据库 → 执行 `1788357000000_sys_job_execution_log.go` → 发布含 `81c1a7e` 的 Server/Web → 重启 → 登录账号单选验证”的顺序处理,#198 仍保持关闭。
Author
Owner

线上迁移与发布完成(待人工验收)

已按用户明确授权在线执行 #199 追加数据库迁移、发布 Server/Web 并重启;所有发布前关闭的定时任务保持关闭。

数据库备份与迁移

  • 迁移前:1788357000000 版本记录 0、sys_job_execution_log 表 0;JobLog 菜单为 menu_id=471。
  • 备份:/home/goauto/backups/pre-199-20260902-81c1a7e.sql,22,224,274 bytes,SHA-256 a6718c8eef4e8a4f66af63a1514961ac83cdcb35babe409121198b9487b1ef71,已确认 dump 完成标记,权限 600。
  • 迁移:1788357000000_sys_job_execution_log.go,结果“新执行 1 个,跳过已应用 36 个”。
  • 迁移后:版本记录恰有 1 条;目标表存在;唯一执行标识及 job/status 时间索引共 3 个;API id=10280 唯一,并已关联 JobLog(471)。
  • 线上没有角色显式绑定隐藏的 JobLog 菜单,因此按 fail-closed 方案未扩大 Casbin 角色授权(精确策略 0 条);系统管理员由既有 rolekey=admin 中间件规则直接授权。采购员没有该菜单,未新增权限。

发布与重启

  • 提交:81c1a7ead226f1c814a7cffdcf29b5770aa21996。
  • 原 release:/home/goauto/releases/20260902-aa2ecc6-r1(保留用于代码回滚)。
  • 新 release:/home/goauto/releases/20260902-81c1a7e-r1;当前 symlink 已原子切换到该目录。
  • Server SHA-256:2b0ea778efcddb64ff8f05fa6c22ecbb38179401c89d5de8af8fdc9ce3161125。
  • 发布包 SHA-256:16772ec2cd3c41f2661fcea35167303190e6df82feaab2de91cdab64ce5c7f94。
  • goauto.service:active,进程实际指向新 release,2026-09-02 23:37:39 CST 启动,本机健康检查 HTTP 200。
  • Nginx 配置检查通过并重启为 active,2026-09-02 23:37:40 CST 启动。
  • 首次切换脚本末尾使用了该 CentOS systemd 不支持的 systemctl show --value,所以脚本退出码为 1;此前切换、两项重启与健康检查均已成功,随后独立复核全部通过,未发生回滚。

外网与功能证据

  • 外网 / 返回新版主包 index.BLjEc8GV.js,动态资源包含 execution-log.CX0bHb19.js。
  • 新资源包含 JobLog 与 /execution-logs,不含旧 job_log;旧本机 WebSocket 127.0.0.1:8000 已不存在。
  • 未登录访问 GET /api/v1/sysjob/3/execution-logs 返回 HTTP 200 + 业务码 401,而非发布前 HTTP 404,证明新 API 路由及认证边界生效。
  • 当前执行历史 0 条属于正常状态;#199 不回填发布前历史,需等待该任务下一次正常调度后产生记录。

定时任务状态保护

发布前后逐条一致:

  • job 1 http://localhost:8000:status=1(关闭)。
  • job 2 ExamplesOne:status=1(关闭)。
  • job 3 GoAutoSYBHourlySync:status=2(原本开启,保持开启),entry_id=1。
  • job 4 GoAutoShopeeSpecAutoMatch:status=1(关闭)。
  • job 5 GoAutoSYBSpecAIParse:status=1(关闭)。

未手工触发任何定时任务,未调用 AI,未创建采集/采购任务或订单,未执行 Android 动作和付款。发布方式没有改变长期运维事实,因此不重复更新 Wiki。

待人工验收

当前没有可用的已登录浏览器控制会话,未读取 Cookie/localStorage、未伪造管理员 Token。请在现有 Admin 页面强制刷新或重新登录,单选“SYB 每小时自动同步”后点击“日志”:应进入 JobLog?jobId=3,当前显示“该任务尚无执行记录”;下一次正常调度后应出现一条执行历史。

## 线上迁移与发布完成(待人工验收) 已按用户明确授权在线执行 #199 追加数据库迁移、发布 Server/Web 并重启;所有发布前关闭的定时任务保持关闭。 ### 数据库备份与迁移 - 迁移前:`1788357000000` 版本记录 0、`sys_job_execution_log` 表 0;`JobLog` 菜单为 `menu_id=471`。 - 备份:`/home/goauto/backups/pre-199-20260902-81c1a7e.sql`,22,224,274 bytes,SHA-256 `a6718c8eef4e8a4f66af63a1514961ac83cdcb35babe409121198b9487b1ef71`,已确认 dump 完成标记,权限 600。 - 迁移:`1788357000000_sys_job_execution_log.go`,结果“新执行 1 个,跳过已应用 36 个”。 - 迁移后:版本记录恰有 1 条;目标表存在;唯一执行标识及 job/status 时间索引共 3 个;API `id=10280` 唯一,并已关联 `JobLog(471)`。 - 线上没有角色显式绑定隐藏的 `JobLog` 菜单,因此按 fail-closed 方案未扩大 Casbin 角色授权(精确策略 0 条);系统管理员由既有 `rolekey=admin` 中间件规则直接授权。采购员没有该菜单,未新增权限。 ### 发布与重启 - 提交:`81c1a7ead226f1c814a7cffdcf29b5770aa21996`。 - 原 release:`/home/goauto/releases/20260902-aa2ecc6-r1`(保留用于代码回滚)。 - 新 release:`/home/goauto/releases/20260902-81c1a7e-r1`;当前 symlink 已原子切换到该目录。 - Server SHA-256:`2b0ea778efcddb64ff8f05fa6c22ecbb38179401c89d5de8af8fdc9ce3161125`。 - 发布包 SHA-256:`16772ec2cd3c41f2661fcea35167303190e6df82feaab2de91cdab64ce5c7f94`。 - `goauto.service`:active,进程实际指向新 release,2026-09-02 23:37:39 CST 启动,本机健康检查 HTTP 200。 - Nginx 配置检查通过并重启为 active,2026-09-02 23:37:40 CST 启动。 - 首次切换脚本末尾使用了该 CentOS systemd 不支持的 `systemctl show --value`,所以脚本退出码为 1;此前切换、两项重启与健康检查均已成功,随后独立复核全部通过,未发生回滚。 ### 外网与功能证据 - 外网 `/` 返回新版主包 `index.BLjEc8GV.js`,动态资源包含 `execution-log.CX0bHb19.js`。 - 新资源包含 `JobLog` 与 `/execution-logs`,不含旧 `job_log`;旧本机 WebSocket `127.0.0.1:8000` 已不存在。 - 未登录访问 `GET /api/v1/sysjob/3/execution-logs` 返回 HTTP 200 + 业务码 401,而非发布前 HTTP 404,证明新 API 路由及认证边界生效。 - 当前执行历史 0 条属于正常状态;#199 不回填发布前历史,需等待该任务下一次正常调度后产生记录。 ### 定时任务状态保护 发布前后逐条一致: - job 1 `http://localhost:8000`:status=1(关闭)。 - job 2 `ExamplesOne`:status=1(关闭)。 - job 3 `GoAutoSYBHourlySync`:status=2(原本开启,保持开启),entry_id=1。 - job 4 `GoAutoShopeeSpecAutoMatch`:status=1(关闭)。 - job 5 `GoAutoSYBSpecAIParse`:status=1(关闭)。 未手工触发任何定时任务,未调用 AI,未创建采集/采购任务或订单,未执行 Android 动作和付款。发布方式没有改变长期运维事实,因此不重复更新 Wiki。 ### 待人工验收 当前没有可用的已登录浏览器控制会话,未读取 Cookie/localStorage、未伪造管理员 Token。请在现有 Admin 页面强制刷新或重新登录,单选“SYB 每小时自动同步”后点击“日志”:应进入 `JobLog?jobId=3`,当前显示“该任务尚无执行记录”;下一次正常调度后应出现一条执行历史。
Author
Owner

复测补充(2026-09-03 08:49 CST):用户反馈在定时任务页勾选“蝦皮规格自动匹配”后点击日志仍无界面反应。

只读核验与受控重启结果:

  • 线上当前仍为 /home/goauto/releases/20260902-81c1a7e-r1,GoAuto/Nginx 已于 08:49:39 CST 重启并均为 active。
  • 重启前后 sys_job 状态一致:仅“SYB 每小时自动同步”为启用(status=2, entry_id=1);“蝦皮规格自动匹配”等其余任务均保持关闭(status=1, entry_id=0),本次未触发任务。
  • sys_job_execution_log 已有 9 条持久化记录,均为 SYB 定时执行;后端记录链路有效。
  • 管理员菜单接口代码会下发全部 M/C 菜单;线上 JobLog 菜单名、/schedule/log 路径与前端 this.$router.push({name:'JobLog', query:{jobId}}) 一致,未发现路由/权限或部署版本错配。
  • 外部首页仍下发新构建入口 index.BLjEc8GV.js。

当前判断:问题位于浏览器端交互/已加载 SPA 状态,而不是服务未重启或后端日志表缺失。需在浏览器强制刷新(Ctrl+F5)或退出后重新登录,再明确执行“勾选行复选框 → 点击工具栏【日志】”;直接点击任务名称/任务行按现有 v1 设计不会跳转。如强刷后按上述路径仍无反应,需要采集该浏览器控制台/当前路由证据,再决定是否在 #199 内追加路径导航兜底与可见错误提示。

Gitea MCP 当前会话不可用,本评论按仓库规则回退 Gitea API 写入;未记录任何凭据。

复测补充(2026-09-03 08:49 CST):用户反馈在定时任务页勾选“蝦皮规格自动匹配”后点击日志仍无界面反应。 只读核验与受控重启结果: - 线上当前仍为 `/home/goauto/releases/20260902-81c1a7e-r1`,GoAuto/Nginx 已于 08:49:39 CST 重启并均为 active。 - 重启前后 `sys_job` 状态一致:仅“SYB 每小时自动同步”为启用(status=2, entry_id=1);“蝦皮规格自动匹配”等其余任务均保持关闭(status=1, entry_id=0),本次未触发任务。 - `sys_job_execution_log` 已有 9 条持久化记录,均为 SYB 定时执行;后端记录链路有效。 - 管理员菜单接口代码会下发全部 M/C 菜单;线上 `JobLog` 菜单名、`/schedule/log` 路径与前端 `this.$router.push({name:'JobLog', query:{jobId}})` 一致,未发现路由/权限或部署版本错配。 - 外部首页仍下发新构建入口 `index.BLjEc8GV.js`。 当前判断:问题位于浏览器端交互/已加载 SPA 状态,而不是服务未重启或后端日志表缺失。需在浏览器强制刷新(Ctrl+F5)或退出后重新登录,再明确执行“勾选行复选框 → 点击工具栏【日志】”;直接点击任务名称/任务行按现有 v1 设计不会跳转。如强刷后按上述路径仍无反应,需要采集该浏览器控制台/当前路由证据,再决定是否在 #199 内追加路径导航兜底与可见错误提示。 Gitea MCP 当前会话不可用,本评论按仓库规则回退 Gitea API 写入;未记录任何凭据。
Author
Owner

本地复现根因补充(2026-09-03):

  • 本机 8010 API(PID 35088)及 9527 Vite Web(PID 59496)实际均从 D:\OPC\goauto-worktrees\issue-195 启动,基线为 f27ec1630788ac9a6a8287caf65e486ba3e3abce,不是 #199 的 81c1a7e。
  • 绕过本机 HTTP 代理后实测:GET http://127.0.0.1:8010/info 返回 200;GET /api/v1/sysjob/4/execution-logs 返回 HTTP 404,证明本地 API 未包含 #199。
  • 直接读取本地 Vite 实际下发的 /src/views/schedule/index.vue,handleLog() 仍为 this.$router.push({ name: 'job_log' })。数据库迁移后的目标路由名为 JobLog,旧页面无法解析命名路由,且旧实现无失败提示,因此表现为点击无反应。
  • #199 工作树的 schedule-execution-log.spec.js 定向测试通过(3/3),有效单选生成 {name:'JobLog', query:{jobId:'5'}}。
  • 尝试启动 #199 本地 API 时因 8010 已被上述 #195 进程占用而安全退出;未形成第二个调度器,未触发任务,也未修改代码或数据库。

结论:本次本地问题是启动目录/版本错误,不是“蝦皮规格自动匹配”任务数据或 #199 新接口本身异常。后续应先正常停止当前 #195 的 Server/Web,再从 #199 工作树启动两端并做浏览器验收。

Gitea MCP 当前会话不可用,本评论按仓库规则回退 Gitea API写入;未记录任何凭据。

本地复现根因补充(2026-09-03): - 本机 `8010` API(PID 35088)及 `9527` Vite Web(PID 59496)实际均从 `D:\OPC\goauto-worktrees\issue-195` 启动,基线为 `f27ec1630788ac9a6a8287caf65e486ba3e3abce`,不是 #199 的 `81c1a7e`。 - 绕过本机 HTTP 代理后实测:`GET http://127.0.0.1:8010/info` 返回 200;`GET /api/v1/sysjob/4/execution-logs` 返回 HTTP 404,证明本地 API 未包含 #199。 - 直接读取本地 Vite 实际下发的 `/src/views/schedule/index.vue`,`handleLog()` 仍为 `this.$router.push({ name: 'job_log' })`。数据库迁移后的目标路由名为 `JobLog`,旧页面无法解析命名路由,且旧实现无失败提示,因此表现为点击无反应。 - #199 工作树的 `schedule-execution-log.spec.js` 定向测试通过(3/3),有效单选生成 `{name:'JobLog', query:{jobId:'5'}}`。 - 尝试启动 #199 本地 API 时因 8010 已被上述 #195 进程占用而安全退出;未形成第二个调度器,未触发任务,也未修改代码或数据库。 结论:本次本地问题是启动目录/版本错误,不是“蝦皮规格自动匹配”任务数据或 #199 新接口本身异常。后续应先正常停止当前 #195 的 Server/Web,再从 #199 工作树启动两端并做浏览器验收。 Gitea MCP 当前会话不可用,本评论按仓库规则回退 Gitea API写入;未记录任何凭据。
Author
Owner

本地 main/Supervisor 收口完成(2026-09-03 09:05 CST),等待人工验收:

  • 为保护 D:\OPC\goauto 中 #190 分支及未提交文件,新建干净运行工作树 D:\OPC\goauto-worktrees\main-runtime。
  • main 从 37dea33 以 fast-forward 合并 #190/#194/#195/#197/#198/#199 的完整依赖链 11 个提交至 81c1a7e,并已推送 origin/main;本地 main 与远端一致。
  • 推送前验证:Server 受影响包测试全部通过;Web 日志 helper 单测 3/3;生产构建通过(只有既有 CSS/大 chunk 警告);日志页面 Playwright E2E 1/1。
  • 迁移前备份:D:\OPC\goauto-backups\pre-main-199-20260903-090212.sql,22,313,117 bytes,SHA-256 A696972FD23E1E9D3B0EE7749199AD4BA329944279EFCECD3CA89A43C0B89592。
  • Supervisor 运行副本已从 issue-195 改为 main-runtime,GoAuto API/UI 已定向重启;当前均为 Running,启动脚本来源为 main-runtime,GET /info 返回 200。
  • 本地追加迁移 1788354164329、1788357000000 已执行;三项链路迁移均各有记录,sys_job_execution_log 表存在,JobLog 菜单为 /schedule/log。
  • 日志接口实测从旧版本 HTTP 404 变为 HTTP 200 + 业务 401(未登录请求),证明路由已注册并进入认证中间件;Vite 实际下发源码已为 jobLogRoute(this.ids)。
  • 迁移/重启前后既有任务状态保持:SYB 每小时自动同步和蝦皮规格自动匹配仍启用;新增 SYB 异常规格 AI 解析保持关闭。未手工触发任何任务。
  • Supervisor 全量 reload 曾尝试启动原先停止的无关 yovision-sense;已立即执行 stop,当前 PID=0、无进程(Supervisor 状态仍显示其既有 Backoff 失败标记),未修改该实例配置。其他既有服务 PID 未变化。

请在 http://127.0.0.1:9527 强制刷新或重新登录后,勾选“蝦皮规格自动匹配”并点击工具栏“日志”完成真实页面验收。

Gitea MCP 当前会话不可用,本评论按仓库规则回退 Gitea API 写入;未记录任何凭据。

本地 main/Supervisor 收口完成(2026-09-03 09:05 CST),等待人工验收: - 为保护 `D:\OPC\goauto` 中 #190 分支及未提交文件,新建干净运行工作树 `D:\OPC\goauto-worktrees\main-runtime`。 - `main` 从 `37dea33` 以 fast-forward 合并 #190/#194/#195/#197/#198/#199 的完整依赖链 11 个提交至 `81c1a7e`,并已推送 `origin/main`;本地 main 与远端一致。 - 推送前验证:Server 受影响包测试全部通过;Web 日志 helper 单测 3/3;生产构建通过(只有既有 CSS/大 chunk 警告);日志页面 Playwright E2E 1/1。 - 迁移前备份:`D:\OPC\goauto-backups\pre-main-199-20260903-090212.sql`,22,313,117 bytes,SHA-256 `A696972FD23E1E9D3B0EE7749199AD4BA329944279EFCECD3CA89A43C0B89592`。 - Supervisor 运行副本已从 `issue-195` 改为 `main-runtime`,GoAuto API/UI 已定向重启;当前均为 Running,启动脚本来源为 main-runtime,`GET /info` 返回 200。 - 本地追加迁移 `1788354164329`、`1788357000000` 已执行;三项链路迁移均各有记录,`sys_job_execution_log` 表存在,`JobLog` 菜单为 `/schedule/log`。 - 日志接口实测从旧版本 HTTP 404 变为 HTTP 200 + 业务 401(未登录请求),证明路由已注册并进入认证中间件;Vite 实际下发源码已为 `jobLogRoute(this.ids)`。 - 迁移/重启前后既有任务状态保持:SYB 每小时自动同步和蝦皮规格自动匹配仍启用;新增 SYB 异常规格 AI 解析保持关闭。未手工触发任何任务。 - Supervisor 全量 reload 曾尝试启动原先停止的无关 `yovision-sense`;已立即执行 stop,当前 PID=0、无进程(Supervisor 状态仍显示其既有 Backoff 失败标记),未修改该实例配置。其他既有服务 PID 未变化。 请在 `http://127.0.0.1:9527` 强制刷新或重新登录后,勾选“蝦皮规格自动匹配”并点击工具栏“日志”完成真实页面验收。 Gitea MCP 当前会话不可用,本评论按仓库规则回退 Gitea API 写入;未记录任何凭据。
Sign in to join this conversation.
No labels
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: OPC/goauto#199