Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
D
download-web
Overview
Overview
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
downloader
download-web
Commits
a224ea9d
Commit
a224ea9d
authored
Sep 02, 2025
by
焦子成
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
1
parent
01ebec5a
Show whitespace changes
Inline
Side-by-side
Showing
3 changed files
with
104 additions
and
130 deletions
+104
-130
src/stores/download.js
+5
-0
src/views/Downloader.vue
+93
-117
src/views/History.vue
+6
-13
No files found.
src/stores/download.js
View file @
a224ea9d
...
...
@@ -533,6 +533,11 @@ export const useDownloadStore = defineStore('download', () => {
download.status = '
paused
'
activeDownloadCount.value--
saveToStorage()
http.post(config.downLoadStatus,{
detailId: download.id,
fileStatus: 2, //下载状态 0:等待中 1:下载中 2:已暂停 3:已完成 4:失败
}).then(res=>{
})
// 只有在非批量下载且非单个下载模式下才自动启动下一个等待中的下载
if (!isBatchDownloading.value && !isSingleDownloading.value) {
startNextPendingDownload()
...
...
src/views/Downloader.vue
View file @
a224ea9d
...
...
@@ -14,7 +14,6 @@
<el-icon>
<User
/>
</el-icon>
<!--
{{
authStore
.
user
?.
userName
}}
-->
{{
userName
}}
<el-icon>
<ArrowDown
/>
...
...
@@ -235,7 +234,7 @@
<
div
class
=
"download-actions"
>
<!--
状态筛选
-->
<
!--
<
el
-
select
v
-
model
=
"statusFilter"
placeholder
=
"按状态筛选"
clearable
style
=
"width: 150px; margin-right: 10px;"
<
el
-
select
v
-
model
=
"statusFilter"
placeholder
=
"按状态筛选"
clearable
style
=
"width: 150px; margin-right: 10px;"
@
change
=
"handleStatusFilterChange"
>
<
el
-
option
label
=
"全部"
value
=
""
/>
<
el
-
option
label
=
"等待中"
value
=
"pending"
/>
...
...
@@ -243,15 +242,6 @@
<
el
-
option
label
=
"已暂停"
value
=
"paused"
/>
<
el
-
option
label
=
"已完成"
value
=
"completed"
/>
<
el
-
option
label
=
"失败"
value
=
"error"
/>
<
/el-select> --
>
<
el
-
select
v
-
model
=
"fileStatus"
placeholder
=
"按状态筛选"
clearable
style
=
"width: 150px; margin-right: 10px;"
@
change
=
"handleStatusFilterChange"
>
<
el
-
option
label
=
"全部"
value
=
""
/>
<
el
-
option
label
=
"等待中"
:
value
=
"0"
/>
<
el
-
option
label
=
"下载中"
:
value
=
"1"
/>
<
el
-
option
label
=
"已暂停"
:
value
=
"2"
/>
<
el
-
option
label
=
"已完成"
:
value
=
"3"
/>
<
el
-
option
label
=
"失败"
:
value
=
"4"
/>
<
/el-select
>
<!--
页面级别操作
-->
...
...
@@ -262,15 +252,9 @@
暂停当前页
<
/el-button
>
<
el
-
divider
direction
=
"vertical"
/>
<!--
<
el
-
button
@
click
=
"downloadStore.clearCompleted"
size
=
"small"
>
清除已完成
<
/el-button> --
>
<
el
-
button
@
click
=
"clearCompleted"
size
=
"small"
>
清除已完成
<
/el-button
>
<!--
<
el
-
button
@
click
=
"downloadStore.clearAll"
type
=
"danger"
size
=
"small"
>
清除所有
<
/el-button> --
>
<
el
-
button
@
click
=
"clearAll"
type
=
"danger"
size
=
"small"
>
清除所有
<
/el-button
>
...
...
@@ -381,19 +365,15 @@
暂停
<
/el-button> --
>
<
!--
<
el
-
button
v
-
if
=
"row.status === 'paused'"
@
click
=
"resumeSingleDownload(row.id)"
type
=
"success"
<
el
-
button
v
-
if
=
"row.status === 'paused'"
@
click
=
"resumeSingleDownload(row.id)"
type
=
"success"
size
=
"small"
>
继续
<
/el-button>
--
>
<
/el-button
>
<
el
-
button
v
-
if
=
"row.status === 'error'"
@
click
=
"startSingleDownload(row.id)"
type
=
"warning"
size
=
"small"
>
重试
<
/el-button
>
<!--
<
el
-
button
@
click
=
"downloadStore.cancelDownload(row.id)"
type
=
"danger"
size
=
"small"
>
删除
<
/el-button> --
>
<
el
-
button
@
click
=
"deleteRow(row)"
type
=
"danger"
size
=
"small"
>
删除
<
/el-button
>
...
...
@@ -427,7 +407,22 @@ import config from '@/api/api.js';
import
axios
from
"axios"
;
import
{
el
,
ro
}
from
'element-plus/es/locales.mjs'
const
statusMap
=
{
0
:
'pending'
,
1
:
'downloading'
,
2
:
'paused'
,
3
:
'completed'
,
4
:
'error'
}
const
statusMap1
=
{
'pending'
:
0
,
'downloading'
:
1
,
'paused'
:
2
,
'completed'
:
3
,
'error'
:
4
}
const
userName
=
ref
(
''
)
const
router
=
useRouter
()
const
authStore
=
useAuthStore
()
const
downloadStore
=
useDownloadStore
()
...
...
@@ -446,7 +441,6 @@ const activeCollapse = ref(['upload']) // 默认展开配置区域
// 分页相关
const
currentPage
=
ref
(
1
)
const
pageSize
=
ref
(
10
)
const
fileStatus
=
ref
(
''
)
// 已上传文件列表
let
upQuery
=
ref
({
current
:
1
,
...
...
@@ -455,12 +449,6 @@ let upQuery = ref({
let
upTableData
=
reactive
([])
let
upTotal
=
ref
(
0
)
// 下载任务管理列表
// let deQuery = ref(
{
// current: 1,
// pageSize: 10,
// fileStatus: ''
//
}
)
let
deTableData
=
reactive
([])
let
deTotal
=
ref
(
0
)
let
columnMapping
=
ref
({
...
...
@@ -479,25 +467,10 @@ const canParse = computed(() => {
previewData
.
value
.
length
>
0
}
)
// 已上传 Excel 文件列表数据加载
const
loadUpTableData
=
()
=>
{
http
.
post
(
config
.
uploadBatchList
,
upQuery
.
value
).
then
(
res
=>
{
if
(
res
.
code
===
200
)
{
for
(
let
element
of
res
.
data
.
rows
)
{
element
.
createTime
=
element
.
createTime
?
element
.
createTime
.
substring
(
0
,
10
)
:
''
}
upTableData
=
res
.
data
.
rows
upTotal
.
value
=
res
.
data
.
total
}
else
{
ElMessage
.
error
(
res
.
message
)
}
}
)
}
// 计算分页后的下载列表
const
paginatedDownloads
=
computed
(()
=>
{
const
start
=
(
currentPage
.
value
-
1
)
*
pageSize
.
value
const
end
=
start
+
pageSize
.
value
//
const start = (currentPage.value - 1) * pageSize.value
//
const end = start + pageSize.value
// return filteredDownloads.value.slice(start, end)
return
filteredDownloads
.
value
.
slice
(
0
)
}
)
...
...
@@ -549,6 +522,7 @@ const selectExcelFile = async (fileId) => {
ElMessage.error('文件信息不存在')
return
}
downloadStore.setCurrentExcelFile(fileId)
selectedFile.value = {
name: res.data.uploadName,
}
...
...
@@ -562,7 +536,9 @@ const selectExcelFile = async (fileId) => {
url: element.fileUrl
}
)
}
// 总数据
rawExcelData.value = list || []
// 生成预览数据
if (list.length > 5) {
previewData.value = list.slice(0, 5)
}
else {
...
...
@@ -583,21 +559,22 @@ const deleteExcelFile = async (fileId) => {
return
}
// try {
// await downloadStore.deleteExcelFile(fileId)
// ElMessage.success('Excel文件已删除')
//
}
catch (error) {
// console.error('删除Excel文件失败:', error)
// ElMessage.error('删除Excel文件失败: ' + (error.message || '未知错误'))
//
}
try {
await downloadStore.deleteExcelFile(fileId)
ElMessage.success('Excel文件已删除')
http.post(config.uploadBatchDelete, { batchId: fileId
}
).then(res => {
if (res.code === 200) {
ElMessage.success('Excel文件已删除')
loadUpTableData()
}
else {
ElMessage.error(res.message)
}
}
)
}
catch (error) {
console.error('删除Excel文件失败:', error)
ElMessage.error('删除Excel文件失败: ' + (error.message || '未知错误'))
}
}
// 处理文件选择
...
...
@@ -785,7 +762,6 @@ const getFileExtensionFromUrl = (url) => {
return extension
}
}
// 如果没有找到有效的扩展名,返回.tmp
return '.tmp'
}
catch (error) {
...
...
@@ -795,20 +771,20 @@ const getFileExtensionFromUrl = (url) => {
}
// 选择下载路径
//
const selectDownloadPath = () => {
//
ElMessageBox.prompt('请输入自定义子文件夹名称', '设置下载子文件夹', {
//
confirmButtonText: '确定',
//
cancelButtonText: '取消',
//
inputValue: customSubFolder.value,
//
inputPlaceholder: '例如: vue-downloader-files (留空则直接下载到默认路径)'
//
}
).then(({ value
}
) => {
//
customSubFolder.value = value
//
updateDownloadPath()
//
ElMessage.success('下载路径已设置')
//
}
).catch(() => {
//
// 用户取消
//
}
)
//
}
const selectDownloadPath = () => {
ElMessageBox.prompt('请输入自定义子文件夹名称', '设置下载子文件夹', {
confirmButtonText: '确定',
cancelButtonText: '取消',
inputValue: customSubFolder.value,
inputPlaceholder: '例如: vue-downloader-files (留空则直接下载到默认路径)'
}
).then(({ value
}
) => {
customSubFolder.value = value
updateDownloadPath()
ElMessage.success('下载路径已设置')
}
).catch(() => {
// 用户取消
}
)
}
// 清空文件名前缀
const clearFileNamePrefix = () => {
...
...
@@ -828,7 +804,7 @@ const updateDownloadPath = () => {
// 更新store中的文件名前缀
downloadStore.setCustomSubFolder(customSubFolder.value)
}
const userName = ref('')
// 组件挂载时初始化
onMounted(() => {
// 先初始化下载store
...
...
@@ -841,20 +817,28 @@ onMounted(() => {
detectBrowserDownloadPath()
loadUpTableData()
loadDetailTableData()
}
)
const statusMap = {
0: 'pending',
1: 'downloading',
2: 'paused',
3: 'completed',
4: 'error'
// 已上传 Excel 文件列表数据加载
const loadUpTableData = () => {
http.post(config.uploadBatchList, upQuery.value).then(res => {
if (res.code === 200) {
for (let element of res.data.rows) {
element.createTime = element.createTime ? element.createTime.substring(0, 10) : ''
}
upTableData = res.data.rows
upTotal.value = res.data.total
}
else {
ElMessage.error(res.message)
}
}
)
}
function loadDetailTableData() {
http.post(config.uploadDetailList, {
current: currentPage.value,
size: pageSize.value,
fileStatus:
fileStatus.value
fileStatus:
statusMap1[statusFilter.value]
}
).then(res => {
if (res.code === 200) {
var list = []
...
...
@@ -882,16 +866,16 @@ function loadDetailTableData() {
}
)
}
// console.log('--lsit:',list)
// deTableData = res.data.rows
downloadStore.downloads = list
downloadStore.setCustomSubFolder(filePrefix)
deTotal.value = res.data.total
customSubFolder.value = filePrefix
loadUploadDetailTotalNum()
}
else {
ElMessage.error(res.message)
}
}
)
}
let totalNumObj = ref({
countNum: 0,
fileLength: '',
...
...
@@ -916,12 +900,12 @@ function loadUploadDetailTotalNum() {
// 清除已完成
function clearCompleted() {
downloadStore.clearCompleted()
http.post(config.uploadDetailDeleteAll, {
type: 0
}
).then(res => {
if (res.code === 200) {
ElMessage.success(res.message)
// deQuery.value.current = 1
currentPage.value = 1
// loadUploadDetailList()
loadDetailTableData()
...
...
@@ -932,6 +916,7 @@ function clearCompleted() {
}
// 清除所有
function clearAll() {
downloadStore.clearAll()
http.post(config.uploadDetailDeleteAll, {
type: 1
}
).then(res => {
...
...
@@ -947,14 +932,13 @@ function clearAll() {
}
// 删除单行
function deleteRow(row) {
downloadStore.cancelDownload(row.id)
http.post(config.uploadDetailDelete, {
detailId: row.detailId
}
).then(res => {
if (res.code === 200) {
ElMessage.success(res.message)
// deQuery.value.current = 1
currentPage.value = 1
// loadUploadDetailList()
loadDetailTableData()
}
else {
ElMessage.error(res.message)
...
...
@@ -972,6 +956,7 @@ const parseExcelFile = async () => {
ElMessage.warning('请先选择Excel文件并配置列映射')
return
}
// 数据预览列表 URL 列必须是有效的 HTTP/HTTPS URL
const url = previewData.value[0]?.url
if (!url || !/^https?:\/\//i.test(url)) {
ElMessage.warning('预览数据中的URL格式不正确,请检查列映射')
...
...
@@ -1030,7 +1015,8 @@ const parseExcelFile = async () => {
ElMessage.warning('Excel文件中没有找到有效数据')
return
}
// 保存文件到本地之前先删除本地所有文件
downloadStore.clearAll()
// 保存Excel文件到本地存储
processingProgress.value = 30
processingMessage.value = '正在保存Excel文件到本地...'
...
...
@@ -1147,8 +1133,10 @@ function getDetailList() {
return preview
}
var upDetailId = ''
let detailList = reactive([])
function uploadDetails() {
detailList = getDetailList()
http.post(config.uploadBatchFileUpload, {
...
...
@@ -1163,7 +1151,6 @@ function uploadDetails() {
// details: detailList
}
).then(res => {
if (res.code === 200) {
// loadDetailTableData()
upDetailId = res.data
uploadDetailsFile()
}
else {
...
...
@@ -1181,7 +1168,6 @@ function uploadDetailsFile() {
uplist = detailList
detailList = []
}
// console.log('list-->', detailList.length)
http.post(config.fileUploadDetail, {
batchId: upDetailId,
details: uplist
...
...
@@ -1201,7 +1187,6 @@ function uploadDetailsFile() {
// 下载当前页所有任务
const downloadCurrentPage = async () => {
const currentPageItems = paginatedDownloads.value
// const currentPageItems = deTableData
if (currentPageItems.length === 0) {
ElMessage.warning('当前页没有下载任务')
return
...
...
@@ -1211,16 +1196,12 @@ const downloadCurrentPage = async () => {
const startableItems = currentPageItems.filter(item =>
['pending', 'paused', 'error'].includes(item.status)
)
// const startableItems = currentPageItems.filter(item =>
// [0, 2, 4].includes(item.fileStatus)
// )
if (startableItems.length === 0) {
ElMessage.warning('当前页没有可以开始下载的任务')
return
}
// console.log('currentPageItems-->',currentPageItems)
// console.log('startableItems-->',startableItems)
try {
await ElMessageBox.confirm(`
确定要下载当前页的
$
{
startableItems
.
length
}
个任务吗?
`, '下载当前页', {
confirmButtonText: '确定',
...
...
@@ -1239,21 +1220,20 @@ const downloadCurrentPage = async () => {
// 用户取消
}
}
//
async function getFileSize(url) {
//
try {
//
const response = await axios.head(url);
//
const size = response.headers["content-length"];
//
return size ? parseInt(size, 10) : null;
//
}
catch (err) {
//
console.error("获取文件大小失败:", err);
//
return null;
//
}
//
}
async function getFileSize(url) {
try {
const response = await axios.head(url);
const size = response.headers["content-length"];
return size ? parseInt(size, 10) : null;
}
catch (err) {
console.error("获取文件大小失败:", err);
return null;
}
}
// 暂停当前页所有任务
const pauseCurrentPage = async () => {
const currentPageItems = paginatedDownloads.value
// const currentPageItems = deTableData
if (currentPageItems.length === 0) {
ElMessage.warning('当前页没有下载任务')
return
...
...
@@ -1288,29 +1268,25 @@ const pauseCurrentPage = async () => {
}
}
// 处理分页大小变化
// 处理下载任务管理 列表分页条数变化
const handleSizeChange = (size) => {
// deQuery.value.pageSize = size
// deQuery.value.current = 1
pageSize.value = size
currentPage.value = 1
loadDetailTableData()
}
// 处理
当前页
变化
// 处理
下载任务管理 列表页码
变化
const handleCurrentChange = (page) => {
// deQuery.value.current = page
currentPage.value = page
loadDetailTableData()
}
// 处理已上传Excel文件 列表分页条数变化
const handleUpSizeChange = (size) => {
upQuery.value.pageSize = size
upQuery.value.current = 1
loadUpTableData()
}
// 处理
当前页
变化
// 处理
已上传Excel文件 列表页码
变化
const handleUpCurrentChange = (page) => {
upQuery.value.current = page
loadUpTableData()
...
...
@@ -1318,9 +1294,7 @@ const handleUpCurrentChange = (page) => {
// 处理状态筛选变化
const handleStatusFilterChange = () => {
// currentPage.value = 1 // 重置当前页为1,以便重新加载数据
// deQuery.value.current = 1
currentPage.value = 1
currentPage.value = 1 // 重置当前页为1,以便重新加载数据
loadDetailTableData()
}
...
...
@@ -1330,6 +1304,7 @@ const startSingleDownload = async (downloadId) => {
try {
await downloadStore.startDownload(downloadId)
loadDetailTableData()
loadUploadDetailTotalNum()
}
finally {
downloadStore.isSingleDownloading = false
}
...
...
@@ -1340,6 +1315,8 @@ const resumeSingleDownload = async (downloadId) => {
downloadStore.isSingleDownloading = true
try {
await downloadStore.resumeDownload(downloadId)
loadDetailTableData()
loadUploadDetailTotalNum()
}
finally {
downloadStore.isSingleDownloading = false
}
...
...
@@ -1582,4 +1559,3 @@ const handleUserCommand = (command) => {
background-color: #f5f5f5;
}
</style>
\ No newline at end of file
uo
\ No newline at end of file
src/views/History.vue
View file @
a224ea9d
...
...
@@ -130,15 +130,13 @@
<el-table-column
prop=
"fileSize"
label=
"文件大小"
width=
"120"
>
<
template
#
default=
"scope"
>
<!--
{{
formatFileSize
(
scope
.
row
.
fileSize
)
}}
-->
{{
scope
.
row
.
fileSize
}}
{{
scope
.
row
.
status
==
'completed'
?
scope
.
row
.
fileSize
:
'-'
}}
</
template
>
</el-table-column>
<el-table-column
prop=
"downloadedBytes"
label=
"已下载"
width=
"120"
>
<
template
#
default=
"scope"
>
<!--
{{
formatFileSize
(
scope
.
row
.
downloadedBytes
)
}}
-->
{{
scope
.
row
.
fileSize
}}
{{
scope
.
row
.
status
==
'completed'
?
scope
.
row
.
fileSize
:
'-'
}}
</
template
>
</el-table-column>
...
...
@@ -436,7 +434,6 @@ const getStatusText = (status) => {
// 查看详情
const
viewDetails
=
(
record
)
=>
{
// selectedRecord.value = record
http
.
post
(
config
.
detailInfo
,{
detailId
:
record
.
id
}).
then
(
res
=>
{
if
(
res
.
code
===
200
){
selectedRecord
.
value
=
{
...
...
@@ -448,7 +445,7 @@ const viewDetails = (record) => {
"status"
:
statusMap
[
res
.
data
.
fileStatus
],
"progress"
:
res
.
data
.
fileStatus
==
3
?
100
:
0
,
"fileSize"
:
res
.
data
.
fileLength
,
"downloadedBytes"
:
res
.
data
.
fileStatus
==
3
?
res
.
data
.
fileLength
:
'
0 KB
'
,
"downloadedBytes"
:
res
.
data
.
fileStatus
==
3
?
res
.
data
.
fileLength
:
'
-
'
,
"startTime"
:
res
.
data
.
createTime
,
"endTime"
:
''
,
"error"
:
res
.
data
.
errorMsg
...
...
@@ -492,16 +489,15 @@ const clearAllHistory = async () => {
type
:
'warning'
}
)
authStore
.
clearDownloadHistory
()
// loadHistory()
// ElMessage.success('历史记录已清空')
http
.
post
(
config
.
uploadDetailDeleteAll
,
{
type
:
1
}).
then
(
res
=>
{
if
(
res
.
code
===
200
)
{
loadHistory
()
ElMessage
.
success
(
'历史记录已清空'
)
loadHistory
()
loadUploadDetailTotalNum
()
}
else
{
ElMessage
.
error
(
res
.
message
)
}
...
...
@@ -515,14 +511,11 @@ const clearAllHistory = async () => {
const
handleSizeChange
=
(
size
)
=>
{
pageSize
.
value
=
size
currentPage
.
value
=
1
// deQuery.value.pageSize = size
// deQuery.value.current = 1
loadHistory
()
}
const
handleCurrentChange
=
(
page
)
=>
{
currentPage
.
value
=
page
// deQuery.value.current = page
loadHistory
()
}
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment