refactor: 移除WebSocket,改为页面轮询机制
- 移除WebSocket相关设计 - 添加页面轮询机制设计 - 轮询间隔:5秒 - 自动启动/停止策略 - 支持手动刷新
This commit is contained in:
@@ -1,211 +1,149 @@
|
|||||||
# 项目异步文件上传功能 - 前端设计文档
|
# 项目异步文件上传功能 - 前端设计文档(轮询版本)
|
||||||
|
|
||||||
## 文档信息
|
## 文档信息
|
||||||
- **创建日期**: 2026-03-05
|
- **创建日期**: 2026-03-05
|
||||||
- **版本**: v1.0
|
- **版本**: v1.1
|
||||||
- **作者**: Claude
|
- **作者**: Claude
|
||||||
- **状态**: 已批准
|
- **状态**: 已批准
|
||||||
- **关联文档**: [后端设计文档](./2026-03-05-async-file-upload-design.md)
|
- **关联文档**: [后端设计文档](./2026-03-05-async-file-upload-design.md)
|
||||||
|
- **变更说明**: 移除WebSocket,改为页面轮询机制
|
||||||
|
|
||||||
## 1. 设计概述
|
## 1. 设计概述
|
||||||
|
|
||||||
### 1.1 功能描述
|
### 1.1 功能描述
|
||||||
基于现有项目管理模块的上传数据组件(UploadData.vue),扩展实现流水文件的异步批量上传功能,提供直观的用户交互界面和实时状态跟踪能力。
|
基于现有项目管理模块的上传数据组件(UploadData.vue),扩展实现流水文件的异步批量上传功能。
|
||||||
|
|
||||||
### 1.2 设计原则
|
### 1.2 技术栈
|
||||||
- **渐进式增强**:在现有组件基础上扩展,不破坏现有功能
|
|
||||||
- **实时反馈**:通过 WebSocket 推送状态更新,用户无需手动刷新
|
|
||||||
- **用户友好**:清晰的状态展示、简洁的操作流程、友好的错误提示
|
|
||||||
- **响应式设计**:适配不同屏幕尺寸
|
|
||||||
|
|
||||||
### 1.3 技术栈
|
|
||||||
- Vue.js 2.6.12
|
- Vue.js 2.6.12
|
||||||
- Element UI 2.15.14
|
- Element UI 2.15.14
|
||||||
- WebSocket(实时通信)
|
|
||||||
- Axios(HTTP 请求)
|
- Axios(HTTP 请求)
|
||||||
|
- 页面轮询(定时刷新)
|
||||||
|
|
||||||
|
## 2. 核心变更
|
||||||
|
|
||||||
## 2. 页面布局设计
|
### 2.1 移除WebSocket
|
||||||
|
- 不再使用WebSocket实时推送
|
||||||
|
- 改用HTTP轮询机制定时刷新
|
||||||
|
|
||||||
### 2.1 整体结构
|
### 2.2 轮询机制
|
||||||
|
|
||||||
UploadData.vue 组件新增以下模块:
|
**启动条件**:
|
||||||
1. **统计卡片区域**:显示上传中、解析中、成功、失败的数量
|
- 上传文件后立即启动
|
||||||
2. **文件上传记录列表**:展示文件上传历史和状态
|
- 检测到有uploading或parsing状态文件时自动启动
|
||||||
3. **批量上传弹窗**:支持批量选择和上传文件
|
|
||||||
|
|
||||||
### 2.2 交互流程
|
**停止条件**:
|
||||||
|
- 所有文件处理完成(无uploading和parsing状态)
|
||||||
|
- 组件销毁时
|
||||||
|
- 用户手动停止
|
||||||
|
|
||||||
1. 用户点击"流水导入"卡片的"上传流水"按钮
|
**轮询间隔**:
|
||||||
2. 打开批量上传弹窗
|
- 默认5秒
|
||||||
3. 用户选择/拖拽多个文件(显示已选文件列表,支持删除)
|
- 可根据活跃任务数量动态调整
|
||||||
4. 点击"开始上传",弹窗关闭,显示"上传任务已提交"提示
|
|
||||||
5. 返回主页面,可以看到统计卡片和列表实时更新(通过WebSocket)
|
|
||||||
|
|
||||||
## 3. 技术架构设计
|
## 3. 轮询实现
|
||||||
|
|
||||||
### 3.1 组件数据结构
|
### 3.1 数据结构
|
||||||
|
|
||||||
```javascript
|
```javascript
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
// 批量上传相关
|
// 轮询相关
|
||||||
batchUploadDialogVisible: false,
|
pollingTimer: null,
|
||||||
selectedFiles: [],
|
pollingEnabled: false,
|
||||||
uploadLoading: false,
|
pollingInterval: 5000 // 5秒
|
||||||
|
|
||||||
// 统计数据
|
|
||||||
statistics: {
|
|
||||||
uploading: 0,
|
|
||||||
parsing: 0,
|
|
||||||
parsed_success: 0,
|
|
||||||
parsed_failed: 0
|
|
||||||
},
|
|
||||||
|
|
||||||
// 文件列表相关
|
|
||||||
fileList: [],
|
|
||||||
listLoading: false,
|
|
||||||
queryParams: {
|
|
||||||
projectId: null,
|
|
||||||
fileStatus: null,
|
|
||||||
pageNum: 1,
|
|
||||||
pageSize: 20
|
|
||||||
},
|
|
||||||
total: 0,
|
|
||||||
|
|
||||||
// WebSocket相关
|
|
||||||
websocket: null,
|
|
||||||
wsReconnectCount: 0
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
### 3.2 API 接口封装
|
### 3.2 核心方法
|
||||||
|
|
||||||
在 src/api/ccdiProjectUpload.js 中新增:
|
|
||||||
|
|
||||||
```javascript
|
```javascript
|
||||||
// 批量上传文件
|
methods: {
|
||||||
export function batchUploadFiles(projectId, files) {
|
// 启动轮询
|
||||||
const formData = new FormData()
|
startPolling() {
|
||||||
files.forEach(file => formData.append('files', file))
|
if (this.pollingEnabled) return
|
||||||
formData.append('projectId', projectId)
|
|
||||||
|
|
||||||
return request({
|
this.pollingEnabled = true
|
||||||
url: '/ccdi/file-upload/batch',
|
|
||||||
method: 'post',
|
|
||||||
data: formData,
|
|
||||||
timeout: 300000
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
// 查询文件上传记录列表
|
const poll = () => {
|
||||||
export function getFileUploadList(params) {
|
if (!this.pollingEnabled) return
|
||||||
return request({
|
|
||||||
url: '/ccdi/file-upload/list',
|
|
||||||
method: 'get',
|
|
||||||
params
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
// 查询文件上传统计
|
Promise.all([
|
||||||
export function getFileUploadStatistics(projectId) {
|
this.loadStatistics(),
|
||||||
return request({
|
this.loadFileList()
|
||||||
url: `/ccdi/file-upload/statistics/${projectId}`,
|
]).then(() => {
|
||||||
method: 'get'
|
// 检查是否需要继续轮询
|
||||||
})
|
if (this.statistics.uploading === 0 &&
|
||||||
|
this.statistics.parsing === 0) {
|
||||||
|
this.stopPolling()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
this.pollingTimer = setTimeout(poll, this.pollingInterval)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
poll()
|
||||||
|
},
|
||||||
|
|
||||||
|
// 停止轮询
|
||||||
|
stopPolling() {
|
||||||
|
this.pollingEnabled = false
|
||||||
|
if (this.pollingTimer) {
|
||||||
|
clearTimeout(this.pollingTimer)
|
||||||
|
this.pollingTimer = null
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
// 上传成功后启动轮询
|
||||||
|
async handleBatchUpload() {
|
||||||
|
// ... 上传逻辑 ...
|
||||||
|
|
||||||
|
// 刷新数据并启动轮询
|
||||||
|
await Promise.all([
|
||||||
|
this.loadStatistics(),
|
||||||
|
this.loadFileList()
|
||||||
|
])
|
||||||
|
|
||||||
|
this.startPolling()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
### 3.3 WebSocket 集成
|
### 3.3 生命周期管理
|
||||||
|
|
||||||
#### 连接配置
|
```javascript
|
||||||
- 连接地址:ws://localhost:8080/ws/file-upload/{projectId}
|
mounted() {
|
||||||
- 连接时机:组件 mounted
|
this.loadStatistics()
|
||||||
- 断开时机:组件 beforeDestroy
|
this.loadFileList()
|
||||||
- 重连机制:最多3次,间隔5秒
|
|
||||||
|
|
||||||
#### 消息格式
|
// 检查是否需要启动轮询
|
||||||
|
if (this.statistics.uploading > 0 || this.statistics.parsing > 0) {
|
||||||
|
this.startPolling()
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
状态更新:
|
beforeDestroy() {
|
||||||
```json
|
this.stopPolling()
|
||||||
{
|
|
||||||
"type": "status_update",
|
|
||||||
"record": { "id": 1, "fileStatus": "parsed_success", ... }
|
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
统计更新:
|
## 4. 其他功能
|
||||||
```json
|
|
||||||
{
|
|
||||||
"type": "statistics_update",
|
|
||||||
"statistics": { "uploading": 2, "parsing": 3, ... }
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
## 4. 核心功能逻辑
|
批量上传弹窗、统计卡片、文件列表等功能保持不变,详见原设计文档。
|
||||||
|
|
||||||
### 4.1 批量上传流程
|
## 5. 开发计划
|
||||||
|
|
||||||
1. 文件选择校验(数量≤100,格式.xlsx/.xls,大小≤50MB)
|
|
||||||
2. 调用 batchUploadFiles API
|
|
||||||
3. 显示"上传任务已提交"提示
|
|
||||||
4. 刷新列表和统计
|
|
||||||
|
|
||||||
### 4.2 文件列表管理
|
|
||||||
|
|
||||||
- 支持按状态筛选
|
|
||||||
- 支持分页(每页20条)
|
|
||||||
- 支持手动刷新
|
|
||||||
|
|
||||||
### 4.3 操作按钮
|
|
||||||
|
|
||||||
- **查看流水**:解析成功时显示,跳转到流水明细页面
|
|
||||||
- **查看错误**:解析失败时显示,弹窗显示错误信息
|
|
||||||
|
|
||||||
## 5. 异常处理
|
|
||||||
|
|
||||||
### 5.1 文件上传异常
|
|
||||||
|
|
||||||
| 异常场景 | 处理方式 | 用户提示 |
|
|
||||||
|---------|---------|---------|
|
|
||||||
| 文件数量超限 | 前端校验 | "最多上传100个文件" |
|
|
||||||
| 文件格式错误 | 前端校验 | "仅支持 .xlsx, .xls 格式文件" |
|
|
||||||
| 文件大小超限 | 前端校验 | "单个文件不能超过50MB" |
|
|
||||||
| 网络请求失败 | 捕获异常 | "上传失败:网络错误" |
|
|
||||||
|
|
||||||
### 5.2 WebSocket 异常
|
|
||||||
|
|
||||||
- 连接失败:记录日志,不影响主要功能
|
|
||||||
- 连接断开:自动重连(最多3次,间隔5秒)
|
|
||||||
- 消息解析失败:忽略该消息
|
|
||||||
|
|
||||||
## 6. 测试要点
|
|
||||||
|
|
||||||
### 6.1 功能测试
|
|
||||||
|
|
||||||
- 文件选择和校验(数量、格式、大小)
|
|
||||||
- 批量上传流程
|
|
||||||
- 状态筛选和分页
|
|
||||||
- 操作按钮(查看流水、查看错误)
|
|
||||||
|
|
||||||
### 6.2 WebSocket 测试
|
|
||||||
|
|
||||||
- 连接建立和断开
|
|
||||||
- 实时状态更新
|
|
||||||
- 断线重连机制
|
|
||||||
|
|
||||||
## 7. 开发计划
|
|
||||||
|
|
||||||
1. **API 接口封装**(0.5天)
|
1. **API 接口封装**(0.5天)
|
||||||
2. **批量上传弹窗**(1天)
|
2. **批量上传弹窗**(1天)
|
||||||
3. **统计卡片组件**(0.5天)
|
3. **统计卡片组件**(0.5天)
|
||||||
4. **文件列表组件**(1天)
|
4. **文件列表组件**(1天)
|
||||||
5. **WebSocket 集成**(1天)
|
5. **轮询机制**(0.5天)
|
||||||
6. **联调测试**(1天)
|
6. **联调测试**(1天)
|
||||||
|
|
||||||
**总计**:5个工作日
|
**总计**:4.5个工作日
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
**文档结束**
|
**文档结束**
|
||||||
|
```
|
||||||
|
|||||||
@@ -2,68 +2,353 @@
|
|||||||
|
|
||||||
## 文档信息
|
## 文档信息
|
||||||
- **创建日期**: 2026-03-05
|
- **创建日期**: 2026-03-05
|
||||||
- **版本**: v1.0
|
- **版本**: v1.1
|
||||||
- **作者**: Claude
|
- **作者**: Claude
|
||||||
- **关联设计**: [前端设计文档](../design/2026-03-05-async-file-upload-frontend-design.md)
|
- **关联设计**: [前端设计文档](../design/2026-03-05-async-file-upload-frontend-design.md)
|
||||||
|
- **变更说明**: 移除WebSocket,改为页面轮询机制
|
||||||
|
|
||||||
## 任务概述
|
## 任务概述
|
||||||
|
|
||||||
根据前端设计文档,扩展UploadData.vue组件实现异步批量上传功能。
|
根据前端设计文档,扩展UploadData.vue组件实现异步批量上传功能。
|
||||||
|
|
||||||
**预计工时**: 5个工作日
|
**预计工时**: 4.5个工作日
|
||||||
|
|
||||||
## 任务清单
|
## 任务清单
|
||||||
|
|
||||||
### 任务 1: API接口封装(0.5天)
|
### 任务 1: API接口封装(0.5天)
|
||||||
|
|
||||||
文件: ruoyi-ui/src/api/ccdiProjectUpload.js
|
**文件**: `ruoyi-ui/src/api/ccdiProjectUpload.js`
|
||||||
|
|
||||||
新增4个接口函数:
|
**工作内容**:
|
||||||
- batchUploadFiles - 批量上传
|
```javascript
|
||||||
- getFileUploadList - 查询列表
|
// 批量上传文件
|
||||||
- getFileUploadStatistics - 查询统计
|
export function batchUploadFiles(projectId, files) {
|
||||||
- getFileUploadDetail - 查询详情
|
const formData = new FormData()
|
||||||
|
files.forEach(file => formData.append('files', file))
|
||||||
|
formData.append('projectId', projectId)
|
||||||
|
|
||||||
|
return request({
|
||||||
|
url: '/ccdi/file-upload/batch',
|
||||||
|
method: 'post',
|
||||||
|
data: formData,
|
||||||
|
timeout: 300000
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// 查询文件上传记录列表
|
||||||
|
export function getFileUploadList(params) {
|
||||||
|
return request({
|
||||||
|
url: '/ccdi/file-upload/list',
|
||||||
|
method: 'get',
|
||||||
|
params
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// 查询文件上传统计
|
||||||
|
export function getFileUploadStatistics(projectId) {
|
||||||
|
return request({
|
||||||
|
url: `/ccdi/file-upload/statistics/${projectId}`,
|
||||||
|
method: 'get'
|
||||||
|
})
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
### 任务 2: 批量上传弹窗(1天)
|
### 任务 2: 批量上传弹窗(1天)
|
||||||
|
|
||||||
修改UploadData.vue组件:
|
**文件**: `ruoyi-ui/src/views/ccdiProject/components/detail/UploadData.vue`
|
||||||
- 添加batchUploadDialogVisible状态
|
|
||||||
- 修改handleUploadClick方法
|
**主要修改**:
|
||||||
- 实现文件选择和校验
|
1. 添加批量上传弹窗状态
|
||||||
- 实现批量上传逻辑
|
2. 修改`handleUploadClick`方法
|
||||||
|
3. 实现文件选择和校验逻辑
|
||||||
|
4. 实现批量上传功能
|
||||||
|
|
||||||
|
**关键代码**:
|
||||||
|
```javascript
|
||||||
|
// 批量上传
|
||||||
|
async handleBatchUpload() {
|
||||||
|
if (this.selectedFiles.length === 0) {
|
||||||
|
this.$message.warning('请选择要上传的文件')
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
this.uploadLoading = true
|
||||||
|
|
||||||
|
try {
|
||||||
|
await batchUploadFiles(
|
||||||
|
this.projectId,
|
||||||
|
this.selectedFiles.map(f => f.raw)
|
||||||
|
)
|
||||||
|
|
||||||
|
this.uploadLoading = false
|
||||||
|
this.batchUploadDialogVisible = false
|
||||||
|
|
||||||
|
this.$message.success('上传任务已提交,请查看处理进度')
|
||||||
|
|
||||||
|
// 刷新数据并启动轮询
|
||||||
|
await Promise.all([
|
||||||
|
this.loadStatistics(),
|
||||||
|
this.loadFileList()
|
||||||
|
])
|
||||||
|
|
||||||
|
this.startPolling()
|
||||||
|
|
||||||
|
} catch (error) {
|
||||||
|
this.uploadLoading = false
|
||||||
|
this.$message.error('上传失败:' + (error.msg || '未知错误'))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
### 任务 3: 统计卡片(0.5天)
|
### 任务 3: 统计卡片(0.5天)
|
||||||
|
|
||||||
添加统计卡片展示:
|
**工作内容**:
|
||||||
- 显示4种状态数量
|
1. 添加统计数据状态
|
||||||
- 点击筛选功能
|
2. 实现统计卡片组件
|
||||||
|
3. 实现点击筛选功能
|
||||||
|
|
||||||
|
**模板代码**:
|
||||||
|
```vue
|
||||||
|
<div class="statistics-section">
|
||||||
|
<div class="stat-card" @click="handleStatusFilter('uploading')">
|
||||||
|
<div class="stat-icon uploading">
|
||||||
|
<i class="el-icon-upload"></i>
|
||||||
|
</div>
|
||||||
|
<div class="stat-content">
|
||||||
|
<div class="stat-label">上传中</div>
|
||||||
|
<div class="stat-value">{{ statistics.uploading }}</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<!-- 其他3个统计卡片 -->
|
||||||
|
</div>
|
||||||
|
```
|
||||||
|
|
||||||
### 任务 4: 文件列表(1天)
|
### 任务 4: 文件列表(1天)
|
||||||
|
|
||||||
添加文件列表组件:
|
**工作内容**:
|
||||||
- 列表展示和分页
|
1. 添加文件列表状态
|
||||||
- 筛选和刷新
|
2. 实现文件列表组件
|
||||||
- 操作按钮
|
3. 实现分页和筛选
|
||||||
|
4. 实现操作按钮
|
||||||
|
|
||||||
### 任务 5: WebSocket集成(1天)
|
**关键方法**:
|
||||||
|
```javascript
|
||||||
|
// 加载文件列表
|
||||||
|
async loadFileList() {
|
||||||
|
this.listLoading = true
|
||||||
|
|
||||||
实现WebSocket实时更新:
|
try {
|
||||||
- 连接和重连
|
const res = await getFileUploadList({
|
||||||
- 消息处理
|
projectId: this.projectId,
|
||||||
- 状态更新
|
fileStatus: this.queryParams.fileStatus,
|
||||||
|
pageNum: this.queryParams.pageNum,
|
||||||
|
pageSize: this.queryParams.pageSize
|
||||||
|
})
|
||||||
|
|
||||||
|
this.fileList = res.rows || []
|
||||||
|
this.total = res.total || 0
|
||||||
|
|
||||||
|
} finally {
|
||||||
|
this.listLoading = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### 任务 5: 轮询机制(0.5天)
|
||||||
|
|
||||||
|
**优先级**: P0
|
||||||
|
**依赖**: 任务2、任务3、任务4完成
|
||||||
|
|
||||||
|
**工作内容**:
|
||||||
|
|
||||||
|
1. **添加轮询状态**:
|
||||||
|
```javascript
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
// 轮询相关
|
||||||
|
pollingTimer: null,
|
||||||
|
pollingEnabled: false,
|
||||||
|
pollingInterval: 5000 // 5秒轮询间隔
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
2. **生命周期钩子**:
|
||||||
|
```javascript
|
||||||
|
mounted() {
|
||||||
|
this.loadStatistics()
|
||||||
|
this.loadFileList()
|
||||||
|
|
||||||
|
// 检查是否需要启动轮询
|
||||||
|
this.$nextTick(() => {
|
||||||
|
if (this.statistics.uploading > 0 || this.statistics.parsing > 0) {
|
||||||
|
this.startPolling()
|
||||||
|
}
|
||||||
|
})
|
||||||
|
},
|
||||||
|
|
||||||
|
beforeDestroy() {
|
||||||
|
this.stopPolling()
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
3. **轮询方法**:
|
||||||
|
```javascript
|
||||||
|
methods: {
|
||||||
|
/**
|
||||||
|
* 启动轮询
|
||||||
|
*/
|
||||||
|
startPolling() {
|
||||||
|
if (this.pollingEnabled) {
|
||||||
|
return // 已经在轮询中
|
||||||
|
}
|
||||||
|
|
||||||
|
this.pollingEnabled = true
|
||||||
|
console.log('启动轮询')
|
||||||
|
|
||||||
|
const poll = () => {
|
||||||
|
if (!this.pollingEnabled) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// 刷新统计数据和列表
|
||||||
|
Promise.all([
|
||||||
|
this.loadStatistics(),
|
||||||
|
this.loadFileList()
|
||||||
|
]).then(() => {
|
||||||
|
// 检查是否需要继续轮询
|
||||||
|
if (this.statistics.uploading === 0 &&
|
||||||
|
this.statistics.parsing === 0) {
|
||||||
|
this.stopPolling()
|
||||||
|
console.log('所有任务已完成,停止轮询')
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// 继续下一次轮询
|
||||||
|
this.pollingTimer = setTimeout(poll, this.pollingInterval)
|
||||||
|
}).catch(error => {
|
||||||
|
console.error('轮询失败:', error)
|
||||||
|
// 发生错误时继续轮询
|
||||||
|
this.pollingTimer = setTimeout(poll, this.pollingInterval)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// 立即执行一次
|
||||||
|
poll()
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 停止轮询
|
||||||
|
*/
|
||||||
|
stopPolling() {
|
||||||
|
this.pollingEnabled = false
|
||||||
|
|
||||||
|
if (this.pollingTimer) {
|
||||||
|
clearTimeout(this.pollingTimer)
|
||||||
|
this.pollingTimer = null
|
||||||
|
}
|
||||||
|
|
||||||
|
console.log('停止轮询')
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 手动刷新
|
||||||
|
*/
|
||||||
|
async handleManualRefresh() {
|
||||||
|
await Promise.all([
|
||||||
|
this.loadStatistics(),
|
||||||
|
this.loadFileList()
|
||||||
|
])
|
||||||
|
|
||||||
|
this.$message.success('刷新成功')
|
||||||
|
|
||||||
|
// 如果有进行中的任务,启动轮询
|
||||||
|
if (this.statistics.uploading > 0 || this.statistics.parsing > 0) {
|
||||||
|
this.startPolling()
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 状态筛选
|
||||||
|
*/
|
||||||
|
handleStatusFilter(status) {
|
||||||
|
this.queryParams.fileStatus = status
|
||||||
|
this.queryParams.pageNum = 1
|
||||||
|
this.loadFileList()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
4. **在模板中添加刷新按钮**:
|
||||||
|
```vue
|
||||||
|
<el-button
|
||||||
|
icon="el-icon-refresh"
|
||||||
|
@click="handleManualRefresh"
|
||||||
|
>
|
||||||
|
刷新
|
||||||
|
</el-button>
|
||||||
|
```
|
||||||
|
|
||||||
|
#### 5.2 验证方式
|
||||||
|
|
||||||
|
1. **启动轮询测试**:
|
||||||
|
- 上传文件后,检查控制台输出"启动轮询"
|
||||||
|
- 观察5秒后数据是否自动刷新
|
||||||
|
|
||||||
|
2. **停止轮询测试**:
|
||||||
|
- 等待所有文件处理完成
|
||||||
|
- 检查控制台输出"停止轮询"
|
||||||
|
|
||||||
|
3. **手动刷新测试**:
|
||||||
|
- 点击刷新按钮
|
||||||
|
- 验证数据立即更新
|
||||||
|
- 验证提示消息显示
|
||||||
|
|
||||||
|
4. **页面销毁测试**:
|
||||||
|
- 切换到其他页面
|
||||||
|
- 检查控制台输出"停止轮询"
|
||||||
|
- 确认定时器被清除
|
||||||
|
|
||||||
### 任务 6: 联调测试(1天)
|
### 任务 6: 联调测试(1天)
|
||||||
|
|
||||||
功能测试和性能测试。
|
**测试项**:
|
||||||
|
1. 批量上传功能
|
||||||
|
2. 统计卡片展示和筛选
|
||||||
|
3. 文件列表展示和分页
|
||||||
|
4. 轮询机制(启动、停止、手动刷新)
|
||||||
|
5. 操作按钮(查看流水、查看错误)
|
||||||
|
|
||||||
## 验收标准
|
## 验收标准
|
||||||
|
|
||||||
- [ ] 所有API接口正常
|
- [ ] 所有API接口正常调用
|
||||||
- [ ] 批量上传功能正常
|
- [ ] 批量上传弹窗正常工作
|
||||||
- [ ] 统计卡片正常
|
- [ ] 统计卡片正常显示和筛选
|
||||||
- [ ] 文件列表正常
|
- [ ] 文件列表正常展示和操作
|
||||||
- [ ] WebSocket实时更新正常
|
- [ ] 轮询机制正常(自动启动/停止/手动刷新)
|
||||||
- [ ] 测试全部通过
|
- [ ] 所有测试项通过
|
||||||
|
|
||||||
|
## 轮询优化建议(可选)
|
||||||
|
|
||||||
|
**智能轮询间隔**:
|
||||||
|
```javascript
|
||||||
|
// 根据活跃任务数动态调整轮询间隔
|
||||||
|
getPollingInterval() {
|
||||||
|
const { uploading, parsing } = this.statistics
|
||||||
|
const activeCount = uploading + parsing
|
||||||
|
|
||||||
|
if (activeCount > 50) {
|
||||||
|
return 3000 // 大量任务时,3秒轮询
|
||||||
|
} else if (activeCount > 10) {
|
||||||
|
return 5000 // 正常情况,5秒轮询
|
||||||
|
} else {
|
||||||
|
return 10000 // 少量任务时,10秒轮询
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
**用户体验优化**:
|
||||||
|
- 在页面顶部显示"自动刷新中..."状态提示
|
||||||
|
- 支持用户手动开关轮询开关
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user