<template>
|
<div class="transmissionBox">
|
<div class="subMenuBox">
|
<div
|
:class="['menuItem', selectMenuIndex == index ? 'active' : '']"
|
v-for="(item, index) in menuData"
|
@click="selectMenu(index)"
|
>
|
<div class="iconBox">
|
<el-icon v-if="item.icon == 'download'" :size="20"><Download /></el-icon>
|
<el-icon v-if="item.icon == 'success'" :size="20"><CircleCheck /></el-icon>
|
</div>
|
<p>{{ item.name }}</p>
|
<span>{{ item.num }}</span>
|
</div>
|
</div>
|
<div class="pageBox">
|
<div class="herderBox">
|
<p>{{ menuData[selectMenuIndex].name }}</p>
|
</div>
|
<div class="toolBox" v-if="selectMenuIndex == 0">
|
<p>
|
下载列表 · <span>已下载 {{ totalProgress }}%{{ allPause ? ',已全部暂停' : '' }}</span>
|
</p>
|
<div class="toolBtnBox">
|
<el-button
|
:icon="Download"
|
size="small"
|
type="primary"
|
:disabled="allStart"
|
@click="newTask"
|
>新增下载</el-button
|
>
|
<el-button :icon="CaretRight" size="small" :disabled="allStart" @click="startAll"
|
>全部开始</el-button
|
>
|
<el-button :icon="VideoPause" size="small" :disabled="allPause" @click="pauseAll"
|
>全部暂停</el-button
|
>
|
<el-button :icon="CloseBold" size="small" @click="cleanAll">全部取消</el-button>
|
</div>
|
</div>
|
<div class="fileList">
|
<el-table
|
:data="tableData"
|
style="width: 100%"
|
:height="'100%'"
|
empty-text="暂无数据"
|
@cell-mouse-enter="mouseEnter"
|
@cell-mouse-leave="mouseLeave"
|
>
|
<el-table-column prop="name" label="名称">
|
<template #default="scope">
|
<p class="title">
|
<span>{{ scope.row.name }}</span>
|
<span class="tableItemBtnBox" v-show="showId == scope.row.id">
|
<el-tooltip
|
v-if="scope.row.state == 'pause'"
|
effect="dark"
|
content="开始"
|
placement="top"
|
>
|
<el-button :icon="CaretRight" circle @click="start(scope.row.id)" />
|
</el-tooltip>
|
<el-tooltip
|
v-if="scope.row.state == 'download'"
|
effect="dark"
|
content="暂停"
|
placement="top"
|
>
|
<el-button :icon="VideoPause" circle @click="pause(scope.row.id)" />
|
</el-tooltip>
|
<el-tooltip
|
effect="dark"
|
:content="scope.row.state == 'success' ? '删除记录' : '取消'"
|
placement="top"
|
>
|
<el-button :icon="CloseBold" circle @click="clean(scope.row.id)" />
|
</el-tooltip>
|
<el-tooltip effect="dark" content="在本地目录查看" placement="top">
|
<el-button :icon="Search" circle @click="openFile(scope.row.id)" />
|
</el-tooltip>
|
</span>
|
</p>
|
</template>
|
</el-table-column>
|
<el-table-column prop="size" label="大小" width="180">
|
<template #default="scope">
|
<span v-if="selectMenuIndex == 0"
|
>{{ getFileSize(scope.row.offset) }} / {{ getFileSize(scope.row.size) }}</span
|
>
|
<span v-if="selectMenuIndex == 1">{{ getFileSize(scope.row.size) }}</span>
|
</template>
|
</el-table-column>
|
<el-table-column prop="createDate" label="创建时间" width="180" sortable>
|
</el-table-column>
|
<el-table-column
|
v-if="selectMenuIndex == 1"
|
prop="completeDate"
|
label="完成时间"
|
width="180"
|
sortable
|
>
|
</el-table-column>
|
<el-table-column v-if="selectMenuIndex == 0" prop="createDate" label="状态" width="300">
|
<template #default="scope">
|
<p class="itemState" v-if="scope.row.state == 'download'" style="color: #409eff">
|
正在下载
|
</p>
|
<p class="itemState" v-if="scope.row.state == 'pause'" style="color: #e6a23c">
|
已暂停
|
</p>
|
<p class="itemState" v-if="scope.row.state == 'getFileInfo'" style="color: #409eff">
|
获取文件信息
|
</p>
|
<p class="itemState" v-if="scope.row.state == 'error'" style="color: #f56c6c">
|
下载错误
|
</p>
|
<p class="itemState" v-if="scope.row.state == 'success'" style="color: #67c23a">
|
已完成
|
</p>
|
<el-progress
|
:show-text="false"
|
:striped="scope.row.state == 'download'"
|
:duration="10"
|
:striped-flow="scope.row.state == 'download'"
|
:percentage="scope.row.progress"
|
:color="
|
() => {
|
if (scope.row.state == 'download') {
|
return '#409EFF'
|
} else if (scope.row.state == 'success') {
|
return '#67C23A'
|
} else {
|
return '#E6A23C'
|
}
|
}
|
"
|
/>
|
</template>
|
</el-table-column>
|
</el-table>
|
</div>
|
<div class="stateInfoBox" v-if="stateInfo">
|
{{ stateInfo }}
|
</div>
|
</div>
|
<el-dialog
|
v-model="newTaskDialogVisible"
|
title="新增下载任务"
|
width="400"
|
align-center
|
:modal="false"
|
>
|
<el-input
|
v-model="newTaskInfo"
|
:autosize="{ minRows: 4, maxRows: 8 }"
|
type="textarea"
|
placeholder="请填写任务字符"
|
/>
|
<template #footer>
|
<span class="dialog-footer">
|
<el-button type="primary" @click="submitTask">确定</el-button>
|
</span>
|
</template>
|
</el-dialog>
|
</div>
|
</template>
|
|
<script setup lang="ts">
|
import { ref, reactive, inject, onMounted, watch } from 'vue'
|
import { Check } from '@element-plus/icons-vue'
|
import { useRouter, RouterView } from 'vue-router'
|
import { Download, CaretRight, CloseBold, VideoPause, Search } from '@element-plus/icons-vue'
|
import { ElMessage } from 'element-plus'
|
import { useDownloadTask } from '@/store'
|
const router = useRouter()
|
const { getFileSize } = inject('toolClass')
|
const downloadTask = useDownloadTask()
|
|
// 菜单
|
const menuData = ref([
|
{
|
name: '下载',
|
num: 0,
|
icon: 'download'
|
},
|
{
|
name: '已完成',
|
num: 0,
|
icon: 'success'
|
}
|
])
|
const selectMenuIndex = ref(0)
|
const selectMenu = (index) => {
|
selectMenuIndex.value = index
|
updateListData()
|
}
|
|
// 总进度
|
const totalProgress = ref(0)
|
// 全部暂停
|
const allPause = ref(false)
|
// 全部开始
|
const allStart = ref(false)
|
|
// 文件列表
|
const tableData = ref([])
|
|
const stateInfo = ref()
|
|
onMounted(() => {
|
updateListData()
|
|
// 绑定消息提醒
|
// window.electronAPI.onShowMessage((data) => {
|
// console.log(data)
|
// if (data.type == 'showState') {
|
// stateInfo.value = data.msg
|
// } else if (data.type == 'notDownloadFolder') {
|
// console.log('notDownloadFolder')
|
// // 下载目录检测不存在,设置下载目录
|
// const path = window.electronAPI.openSelectFileOrFolderDialog({
|
// title: '选择下载目录',
|
// properties: ['openDirectory']
|
// })
|
// if (path && path.length > 0) {
|
// console.log('setDownloadPath')
|
// debugger
|
// const returnData = window.electronAPI.setDownloadPath(path[0], data.msg)
|
// }
|
// } else {
|
// ElMessage({
|
// message: data.msg,
|
// type: data.type
|
// })
|
// }
|
// })
|
})
|
|
watch(
|
() => downloadTask.updateList,
|
(newValue, oldValue) => {
|
updateListData()
|
}
|
)
|
|
watch(
|
() => downloadTask.msgData,
|
(newValue, oldValue) => {
|
if (newValue.type == 'showState') {
|
stateInfo.value = newValue.msg
|
} else if (newValue.type == 'notDownloadFolder') {
|
console.log('notDownloadFolder')
|
// 下载目录检测不存在,设置下载目录
|
const path = window.electronAPI.openSelectFileOrFolderDialog({
|
title: '选择下载目录',
|
properties: ['openDirectory']
|
})
|
if (path && path.length > 0) {
|
const returnData = window.electronAPI.setDownloadPath(path[0], newValue.msg)
|
}
|
} else {
|
ElMessage({
|
message: newValue.msg,
|
type: newValue.type
|
})
|
}
|
}
|
)
|
|
const updateListData = () => {
|
// 获取下载任务列表
|
const taskListData = window.electronAPI.getDownloadTasks()
|
if (selectMenuIndex.value == 0) {
|
tableData.value = taskListData
|
.filter((item) => item.state != 'success')
|
.map((item) => {
|
// if(item.state == "download") alert(JSON.stringify(item))
|
return {
|
...item,
|
progress: (item.offset / item.size) * 100
|
}
|
})
|
} else if (selectMenuIndex.value == 1) {
|
tableData.value = taskListData.filter((item) => item.state == 'success')
|
}
|
|
menuData.value[0].num = taskListData.filter((item) => item.state != 'success').length
|
menuData.value[1].num = taskListData.filter((item) => item.state == 'success').length
|
|
let totalOffset = 0
|
let totalSize = 0
|
taskListData.forEach((item) => {
|
if (item.state != 'success') {
|
totalOffset += item.offset
|
totalSize += item.size
|
}
|
})
|
|
totalProgress.value = totalSize ? ((totalOffset / totalSize) * 100).toFixed(2) : 0
|
}
|
|
const newTaskDialogVisible = ref(false)
|
const newTaskInfo = ref('')
|
const newTask = () => {
|
newTaskInfo.value = ''
|
newTaskDialogVisible.value = true
|
}
|
|
const submitTask = () => {
|
console.log(newTaskInfo.value)
|
if (newTaskInfo.value) {
|
let infoData = null
|
try {
|
infoData = JSON.parse(newTaskInfo.value)
|
} catch (error) {
|
infoData = null
|
}
|
if (infoData) {
|
// 新建任务
|
window.electronAPI.newDownloadTask(infoData)
|
newTaskDialogVisible.value = false
|
} else {
|
ElMessage({
|
message: '无法识别您输入的内容,请确认后重新填写',
|
type: 'warning'
|
})
|
}
|
} else {
|
ElMessage({
|
message: '请填写新建数据',
|
type: 'warning'
|
})
|
}
|
}
|
|
const clean = (id) => {
|
window.electronAPI.cleanTask(id)
|
}
|
|
const cleanAll = () => {
|
tableData.value = []
|
window.electronAPI.cleanAll()
|
}
|
|
const start = (id) => {
|
window.electronAPI.startTask(id)
|
}
|
|
const startAll = () => {
|
window.electronAPI.startAllTask()
|
}
|
|
const pause = (id) => {
|
window.electronAPI.pauseTask(id)
|
}
|
|
const pauseAll = () => {
|
window.electronAPI.pauseAllTask()
|
}
|
|
const openFile = (id) => {
|
window.electronAPI.openPathByTaskId(id)
|
}
|
|
const showId = ref()
|
const mouseEnter = (row) => {
|
showId.value = row.id //赋值行id,便于页面判断
|
}
|
//鼠标移出单元格事件
|
const mouseLeave = (row) => {
|
showId.value = ''
|
}
|
</script>
|
|
<style lang="less">
|
.transmissionBox {
|
width: 100%;
|
height: 100%;
|
display: flex;
|
.subMenuBox {
|
width: 180px;
|
height: 100%;
|
overflow: auto;
|
border-right: 1px solid #e6e7e8;
|
padding: 40px 20px;
|
.menuItem {
|
display: flex;
|
width: 100%;
|
padding: 10px;
|
border-radius: 10px;
|
cursor: pointer;
|
margin-bottom: 10px;
|
position: relative;
|
&.active {
|
background-color: #ebebed;
|
span {
|
background-color: #409eff;
|
color: #fff;
|
border-color: #409eff;
|
}
|
}
|
&:hover {
|
background-color: #ebebed;
|
}
|
.iconBox {
|
display: inline-block;
|
width: 20px;
|
height: 20px;
|
vertical-align: middle;
|
margin-right: 16px;
|
}
|
p {
|
vertical-align: middle;
|
line-height: 20px;
|
}
|
span {
|
position: absolute;
|
right: 10px;
|
top: 11px;
|
font-size: 12px;
|
background-color: #f6f6f7;
|
display: inline-block;
|
width: 30px;
|
padding: 1px 0;
|
border-radius: 50px;
|
text-align: center;
|
color: #999;
|
border: 1px solid #ccc;
|
}
|
}
|
}
|
.pageBox {
|
flex: 1;
|
height: 100%;
|
padding: 50px;
|
box-sizing: border-box;
|
display: flex;
|
flex-direction: column;
|
overflow: auto;
|
position: relative;
|
.herderBox {
|
overflow: hidden;
|
margin-bottom: 20px;
|
p {
|
float: left;
|
font-size: 20px;
|
font-weight: bold;
|
line-height: 32px;
|
}
|
}
|
.toolBox {
|
border-bottom: 1px solid #e6e7e8;
|
padding: 16px 0;
|
margin-bottom: 10px;
|
overflow: hidden;
|
p {
|
float: left;
|
font-size: 14px;
|
color: #333;
|
line-height: 24px;
|
span {
|
font-size: 12px;
|
color: #666;
|
}
|
}
|
.toolBtnBox {
|
float: right;
|
}
|
}
|
.fileList {
|
flex: 1;
|
overflow: hidden;
|
.title {
|
line-height: 34px;
|
.tableItemBtnBox {
|
float: right;
|
padding: 0 10px;
|
}
|
}
|
}
|
.stateInfoBox {
|
position: absolute;
|
bottom: 18px;
|
left: 60px;
|
font-size: 12px;
|
color: #409eff;
|
}
|
.itemState {
|
font-size: 12px;
|
}
|
}
|
}
|
</style>
|