Files
orc-order-v2/docs/superpowers/specs/2026-05-12-frontend-bugfix-quality-design.md
T
houhuan 7c3616ff98 docs: add frontend bug fix and code quality design spec
Addresses 11 issues across 3 phases: critical bug fixes (fetchUser,
silent errors, loading states, stats fallback, global error handler),
code quality (extract composables, remove dead code), and minor
improvements (password validation, batch delete endpoint).

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-12 21:06:05 +08:00

6.9 KiB
Raw Blame History

前端 Bug 修复 + 代码质量提升设计文档

日期: 2026-05-12 状态: 待审核

背景

通过全面审计 Web 前端(Vue 3 + Element Plus),发现了 50+ 个问题。本文档聚焦于前端高优先级 Bug 修复和代码质量改进,分 3 个阶段执行。

阶段 1:关键 Bug 修复

1.1 修复 fetchUser 未调用

问题: Layout.vueonMounted 时未调用 authStore.fetchUser()。页面刷新后 authStore.username 为空,头像显示 "U" 而非用户名首字母。

修复: 在 Layout.vueonMounted 中添加 await authStore.fetchUser()

影响文件: web/frontend/src/views/Layout.vue

1.2 修复静默吞错

问题: 以下文件的 catch 块完全为空,API 失败时用户无任何反馈:

文件 函数 行号
files/Images.vue loadData() 165
files/Tables.vue loadData() 161
files/Orders.vue loadData() 168
Sync.vue checkStatus() 127
Tasks.vue loadStats() 207
Logs.vue loadStats() 164
files/Images.vue deleteFile() 272
files/Tables.vue deleteFile() 250
files/Orders.vue deleteFile() 242

修复: 所有 catch 块添加 ElMessage.error() 提示,使用中文错误消息。

影响文件: 上述 6 个 Vue 文件

1.3 修复 loading 状态管理

问题: Images.vueTables.vueOrders.vueloadData()loading.value = false 不在 finally 块中。异常发生时 loading 转圈卡住。

修复: 统一改为 try { ... } finally { loading.value = false } 模式。

影响文件: files/Images.vuefiles/Tables.vuefiles/Orders.vue

1.4 修复内存统计回退逻辑

问题: Memory.vue 当 API 不返回 stats 时,从 items.value(当前页 50 条)计算置信度统计,显示为全局数据,严重误导用户。

修复: 移除误导性回退逻辑,当 stats 不可用时显示 "暂无统计数据" 占位。

影响文件: web/frontend/src/views/Memory.vue

1.5 添加全局错误处理

问题: main.ts 没有 app.config.errorHandler,未捕获的 Vue 错误只输出到 console.warn,用户无感知。

修复: 在 main.ts 注册全局错误处理器:

app.config.errorHandler = (err, instance, info) => {
  console.error('Vue error:', err, info)
  ElMessage.error('操作失败,请稍后重试')
}

影响文件: web/frontend/src/main.ts


阶段 2:代码质量 — 提取共享逻辑

2.1 提取 useDebounce composable

问题: useDebounce 函数在 4 个文件中完全重复(Memory.vue:166-174, Barcodes.vue:190-198, Tasks.vue:144-152, Logs.vue:107-115)。

修复: 创建 web/frontend/src/composables/useDebounce.ts

import { ref } from 'vue'

export function useDebounce(fn: Function, delay = 300) {
  const timer = ref<ReturnType<typeof setTimeout> | null>(null)
  return (...args: any[]) => {
    if (timer.value) clearTimeout(timer.value)
    timer.value = setTimeout(() => fn(...args), delay)
  }
}

4 个文件改为 import { useDebounce } from '@/composables/useDebounce'

影响文件:

  • 新建: web/frontend/src/composables/useDebounce.ts
  • 修改: Memory.vueBarcodes.vueTasks.vueLogs.vue

2.2 提取文件视图共享逻辑

问题: Images.vueTables.vueOrders.vue 有大量重复代码:

  • statusType()statusText()fmtTime() 函数完全相同
  • 预览对话框模板 + 逻辑 + CSS 完全相同
  • 详情对话框模板 + 逻辑完全相同
  • 分页、多选、排序模式完全相同
  • 批量删除模式完全相同

修复: 创建 3 个共享 composable

composables/useFileUtils.ts

export function statusType(status: string): string { ... }
export function statusText(status: string): string { ... }
export function fmtTime(t: string): string { ... }

composables/useFilePreview.ts

export function useFilePreview() {
  // previewVisible, previewContent, previewTitle, previewLoading
  // openPreview(), closePreview()
  return { ... }
}

composables/useFileSelection.ts

export function useFileSelection(fetchFn: Function) {
  // selectedFiles, currentPage, pageSize, total, sortProp, sortOrder
  // handleSelectionChange(), handlePageChange(), handleSortChange(), toggleSelectAll()
  return { ... }
}

3 个文件视图改为使用这些 composable,每个文件预计减少 100-150 行重复代码。

影响文件:

  • 新建: composables/useFileUtils.tscomposables/useFilePreview.tscomposables/useFileSelection.ts
  • 修改: files/Images.vuefiles/Tables.vuefiles/Orders.vue

2.3 清理死代码

文件 死代码 行号
Layout.vue navItems 数组(未被引用) 175-183
stores/processing.ts pollTaskStatus 函数(未被调用) 124-129
router/index.ts routeLoadingTimer 逻辑(无消费者) 87-94
Barcodes.vue Plus 图标导入(未使用) 186

影响文件: 上述 4 个文件


阶段 3:小改进

3.1 修改密码表单验证

问题: Layout.vue 的修改密码对话框无任何验证:无最小长度要求、无确认密码字段。

修复:

  • 添加 el-form 验证规则:密码最少 6 位
  • 添加确认密码字段,验证两次输入一致
  • 提交前调用 formRef.validate()

影响文件: web/frontend/src/views/Layout.vue

3.2 修复 Layout.vue 冗余代码

问题: navigator.onLine !== false 冗余(navigator.onLine 已经是 boolean)。

修复: 改为 navigator.onLine

影响文件: web/frontend/src/views/Layout.vue

3.3 后端批量删除端点

问题: 前端批量删除是 N+1 API 调用(每个文件 2 次请求),50 个文件 = 100 次 HTTP 请求。

修复:

  • 后端添加 POST /api/files/batch-delete 端点,接受 files: [{directory, filename}] 数组
  • 前端批量删除改为单次 API 调用

影响文件:

  • 新建/修改: web/backend/routers/files.py
  • 修改: files/Images.vuefiles/Tables.vuefiles/Orders.vue

不在范围内

以下问题记录但不在本次修复范围内:

  • 响应式布局(仅 Dashboard 有 @media 查询)
  • 键盘快捷键
  • 类型感知配置编辑器
  • 后端安全问题(路径遍历、登录限流等)
  • WebSocket 认证 token 刷新
  • 产品记忆批量操作/导出
  • 任务取消支持

验证标准

  1. 页面刷新后头像正确显示用户名首字母
  2. API 失败时用户看到错误提示 toast
  3. loading 状态不会卡住
  4. 统计数据准确或显示占位
  5. 未捕获的 Vue 错误有用户提示
  6. useDebounce 在 4 个文件中通过 import 使用,无重复定义
  7. 3 个文件视图使用共享 composable,每个文件减少 100+ 行
  8. 4 处死代码已清理
  9. 修改密码表单有验证规则和确认字段
  10. 批量删除为单次 API 调用