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

212 lines
6.9 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 前端 Bug 修复 + 代码质量提升设计文档
日期: 2026-05-12
状态: 待审核
## 背景
通过全面审计 Web 前端(Vue 3 + Element Plus),发现了 50+ 个问题。本文档聚焦于前端高优先级 Bug 修复和代码质量改进,分 3 个阶段执行。
## 阶段 1:关键 Bug 修复
### 1.1 修复 fetchUser 未调用
**问题**: `Layout.vue``onMounted` 时未调用 `authStore.fetchUser()`。页面刷新后 `authStore.username` 为空,头像显示 "U" 而非用户名首字母。
**修复**: 在 `Layout.vue``onMounted` 中添加 `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.vue``Tables.vue``Orders.vue``loadData()``loading.value = false` 不在 `finally` 块中。异常发生时 loading 转圈卡住。
**修复**: 统一改为 `try { ... } finally { loading.value = false }` 模式。
**影响文件**: `files/Images.vue``files/Tables.vue``files/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` 注册全局错误处理器:
```typescript
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`
```typescript
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.vue``Barcodes.vue``Tasks.vue``Logs.vue`
### 2.2 提取文件视图共享逻辑
**问题**: `Images.vue``Tables.vue``Orders.vue` 有大量重复代码:
- `statusType()``statusText()``fmtTime()` 函数完全相同
- 预览对话框模板 + 逻辑 + CSS 完全相同
- 详情对话框模板 + 逻辑完全相同
- 分页、多选、排序模式完全相同
- 批量删除模式完全相同
**修复**: 创建 3 个共享 composable
#### `composables/useFileUtils.ts`
```typescript
export function statusType(status: string): string { ... }
export function statusText(status: string): string { ... }
export function fmtTime(t: string): string { ... }
```
#### `composables/useFilePreview.ts`
```typescript
export function useFilePreview() {
// previewVisible, previewContent, previewTitle, previewLoading
// openPreview(), closePreview()
return { ... }
}
```
#### `composables/useFileSelection.ts`
```typescript
export function useFileSelection(fetchFn: Function) {
// selectedFiles, currentPage, pageSize, total, sortProp, sortOrder
// handleSelectionChange(), handlePageChange(), handleSortChange(), toggleSelectAll()
return { ... }
}
```
3 个文件视图改为使用这些 composable,每个文件预计减少 100-150 行重复代码。
**影响文件**:
- 新建: `composables/useFileUtils.ts``composables/useFilePreview.ts``composables/useFileSelection.ts`
- 修改: `files/Images.vue``files/Tables.vue``files/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.vue``files/Tables.vue``files/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 调用