7.6 KiB
7.6 KiB
异步文件上传功能实施计划 - Part 4: 前端开发
文档信息
- 创建日期: 2026-03-05
- 版本: v1.1
- 作者: Claude
- 关联设计: 前端设计文档
- 变更说明: 移除WebSocket,改为页面轮询机制
任务概述
根据前端设计文档,扩展UploadData.vue组件实现异步批量上传功能。
预计工时: 4.5个工作日
任务清单
任务 1: API接口封装(0.5天)
文件: ruoyi-ui/src/api/ccdiProjectUpload.js
工作内容:
// 批量上传文件
export function batchUploadFiles(projectId, files) {
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天)
文件: ruoyi-ui/src/views/ccdiProject/components/detail/UploadData.vue
主要修改:
- 添加批量上传弹窗状态
- 修改
handleUploadClick方法 - 实现文件选择和校验逻辑
- 实现批量上传功能
关键代码:
// 批量上传
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天)
工作内容:
- 添加统计数据状态
- 实现统计卡片组件
- 实现点击筛选功能
模板代码:
<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天)
工作内容:
- 添加文件列表状态
- 实现文件列表组件
- 实现分页和筛选
- 实现操作按钮
关键方法:
// 加载文件列表
async loadFileList() {
this.listLoading = true
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完成
工作内容:
- 添加轮询状态:
data() {
return {
// 轮询相关
pollingTimer: null,
pollingEnabled: false,
pollingInterval: 5000 // 5秒轮询间隔
}
}
- 生命周期钩子:
mounted() {
this.loadStatistics()
this.loadFileList()
// 检查是否需要启动轮询
this.$nextTick(() => {
if (this.statistics.uploading > 0 || this.statistics.parsing > 0) {
this.startPolling()
}
})
},
beforeDestroy() {
this.stopPolling()
}
- 轮询方法:
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()
}
}
- 在模板中添加刷新按钮:
<el-button
icon="el-icon-refresh"
@click="handleManualRefresh"
>
刷新
</el-button>
5.2 验证方式
-
启动轮询测试:
- 上传文件后,检查控制台输出"启动轮询"
- 观察5秒后数据是否自动刷新
-
停止轮询测试:
- 等待所有文件处理完成
- 检查控制台输出"停止轮询"
-
手动刷新测试:
- 点击刷新按钮
- 验证数据立即更新
- 验证提示消息显示
-
页面销毁测试:
- 切换到其他页面
- 检查控制台输出"停止轮询"
- 确认定时器被清除
任务 6: 联调测试(1天)
测试项:
- 批量上传功能
- 统计卡片展示和筛选
- 文件列表展示和分页
- 轮询机制(启动、停止、手动刷新)
- 操作按钮(查看流水、查看错误)
验收标准
- 所有API接口正常调用
- 批量上传弹窗正常工作
- 统计卡片正常显示和筛选
- 文件列表正常展示和操作
- 轮询机制正常(自动启动/停止/手动刷新)
- 所有测试项通过
轮询优化建议(可选)
智能轮询间隔:
// 根据活跃任务数动态调整轮询间隔
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秒轮询
}
}
用户体验优化:
- 在页面顶部显示"自动刷新中..."状态提示
- 支持用户手动开关轮询开关
文档结束