新增工作区下载列表
This commit is contained in:
@@ -380,3 +380,164 @@
|
||||
.workspace-footer .iconfont {
|
||||
font-size: 40rpx !important;
|
||||
}
|
||||
|
||||
/* ===== 标签切换 ===== */
|
||||
.workspace-tabs {
|
||||
display: flex;
|
||||
width: 100%;
|
||||
padding: 0 24rpx;
|
||||
box-sizing: border-box;
|
||||
gap: 20rpx;
|
||||
}
|
||||
|
||||
.tab-item {
|
||||
flex: 1;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
padding: 18rpx 0;
|
||||
font-size: 28rpx;
|
||||
font-weight: 500;
|
||||
color: #999;
|
||||
border-bottom: 4rpx solid transparent;
|
||||
transition: all 0.2s ease;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.tab-item.active {
|
||||
color: #6c63ff;
|
||||
border-bottom-color: #6c63ff;
|
||||
}
|
||||
|
||||
.tab-badge {
|
||||
margin-left: 8rpx;
|
||||
background: #ff5e57;
|
||||
color: #fff;
|
||||
font-size: 20rpx;
|
||||
padding: 2rpx 10rpx;
|
||||
border-radius: 20rpx;
|
||||
line-height: 1.4;
|
||||
}
|
||||
|
||||
/* ===== 下载列表 ===== */
|
||||
.download-content {
|
||||
flex: 1;
|
||||
overflow: auto;
|
||||
}
|
||||
|
||||
.download-empty {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
padding-top: 200rpx;
|
||||
color: #bbb;
|
||||
font-size: 28rpx;
|
||||
}
|
||||
|
||||
.download-empty .iconfont {
|
||||
font-size: 140rpx;
|
||||
color: #ddd;
|
||||
margin-bottom: 20rpx;
|
||||
}
|
||||
|
||||
.download-list {
|
||||
padding: 20rpx 24rpx;
|
||||
}
|
||||
|
||||
.download-header {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
padding: 12rpx 8rpx 20rpx;
|
||||
font-size: 24rpx;
|
||||
color: #999;
|
||||
}
|
||||
|
||||
.clear-btn {
|
||||
color: #ff5e57;
|
||||
font-size: 24rpx;
|
||||
font-weight: 500;
|
||||
padding: 4rpx 12rpx;
|
||||
}
|
||||
|
||||
.download-item {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
padding: 24rpx 20rpx;
|
||||
background: rgba(255, 255, 255, 0.85);
|
||||
border-radius: 20rpx;
|
||||
margin-bottom: 16rpx;
|
||||
transition: all 0.15s ease;
|
||||
}
|
||||
|
||||
.download-item:active {
|
||||
transform: scale(0.98);
|
||||
background: rgba(255, 255, 255, 0.95);
|
||||
}
|
||||
|
||||
.di-icon {
|
||||
width: 80rpx;
|
||||
height: 80rpx;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
background: rgba(108, 99, 255, 0.08);
|
||||
border-radius: 18rpx;
|
||||
margin-right: 20rpx;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.di-icon .iconfont {
|
||||
font-size: 40rpx;
|
||||
color: #6c63ff;
|
||||
}
|
||||
|
||||
.di-info {
|
||||
flex: 1;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 6rpx;
|
||||
min-width: 0;
|
||||
}
|
||||
|
||||
.di-name {
|
||||
font-size: 28rpx;
|
||||
font-weight: 500;
|
||||
color: #333;
|
||||
white-space: nowrap;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
|
||||
.di-meta {
|
||||
font-size: 22rpx;
|
||||
color: #999;
|
||||
}
|
||||
|
||||
.di-path {
|
||||
font-size: 20rpx;
|
||||
color: #bbb;
|
||||
white-space: nowrap;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
|
||||
.di-delete {
|
||||
width: 56rpx;
|
||||
height: 56rpx;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.di-delete .iconfont {
|
||||
font-size: 36rpx;
|
||||
color: #ccc;
|
||||
transition: color 0.15s ease;
|
||||
}
|
||||
|
||||
.di-delete:active .iconfont {
|
||||
color: #ff5e57;
|
||||
}
|
||||
|
||||
@@ -66,8 +66,20 @@
|
||||
<view v-if="isSearchFocus" class="cancel-search" @click="handleSearchFocus">取消</view>
|
||||
</view>
|
||||
|
||||
<!-- 标签切换 -->
|
||||
<view class="workspace-tabs">
|
||||
<view class="tab-item" :class="{ active: activeTab === 'workspace' }" @click="switchTab('workspace')">
|
||||
工作区
|
||||
</view>
|
||||
<view class="tab-item" :class="{ active: activeTab === 'downloads' }" @click="switchTab('downloads')">
|
||||
下载列表
|
||||
<text v-if="downloadList.length > 0" class="tab-badge">{{ downloadList.length }}</text>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
<view class="workspace-content">
|
||||
|
||||
<!-- ===== 工作区文件 ===== -->
|
||||
<view class="workspace-content" v-if="activeTab === 'workspace'">
|
||||
<view class="folder-null" v-if="currentFolderList.length===0">
|
||||
<view class="iconfont icon-wenjianjia"></view>
|
||||
文件夹为空
|
||||
@@ -89,6 +101,34 @@
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- ===== 下载列表 ===== -->
|
||||
<view class="download-content" v-if="activeTab === 'downloads'">
|
||||
<view v-if="downloadList.length === 0" class="download-empty">
|
||||
<text class="iconfont icon-xiazai"></text>
|
||||
<text>暂无下载文件</text>
|
||||
</view>
|
||||
<view v-else class="download-list">
|
||||
<view class="download-header">
|
||||
<text>已下载 {{ downloadList.length }} 个文件</text>
|
||||
<text class="clear-btn" @click="handleClearDownloads">清空</text>
|
||||
</view>
|
||||
<view class="download-item" v-for="item in downloadList" :key="item.id" @click="openDownloadFile(item)">
|
||||
<view class="di-icon">
|
||||
<text class="iconfont" :class="getFileIcon(item.name)"></text>
|
||||
</view>
|
||||
<view class="di-info">
|
||||
<text class="di-name">{{ item.name }}</text>
|
||||
<text class="di-meta">{{ formatDownloadTime(item.time) }} · {{ formatDownloadSize(item.size) }}</text>
|
||||
<text class="di-path">{{ item.displayPath || item.path }}</text>
|
||||
</view>
|
||||
<view class="di-delete" @click.stop="handleDeleteDownload(item.id)">
|
||||
<text class="iconfont icon-del"></text>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<view v-if="isSelectFolder" class="workspace-footer" :class="{'folder-actions':selectFileList.length>0}">
|
||||
<view class="iconfont icon-shangchuan" @click="handleUploadFile"></view>
|
||||
<!-- <view class="iconfont icon-fuzhi"></view> -->
|
||||
@@ -122,11 +162,21 @@
|
||||
updateWorkspaceFileName
|
||||
} from '@/utils/cloud-api.js'
|
||||
import { openFile as openFileNative } from '@/utils/fileOpener.js'
|
||||
import {
|
||||
getDownloadList,
|
||||
saveDownload,
|
||||
deleteDownload,
|
||||
clearAllDownloads,
|
||||
formatFileSize,
|
||||
formatTime
|
||||
} from '@/utils/downloadManager.js'
|
||||
|
||||
const UserToken = ref('')
|
||||
const workspaceId = ref('')
|
||||
const navbarBeforeTitle = ref('');
|
||||
const navbarTitle = ref('工作区');
|
||||
const activeTab = ref('workspace')
|
||||
const downloadList = ref([])
|
||||
|
||||
// 选择文件模式
|
||||
const isSelectFolder = ref(false);
|
||||
@@ -395,6 +445,7 @@ import { openFile as openFileNative } from '@/utils/fileOpener.js'
|
||||
|
||||
const downloadUrl = fileInfo.url;
|
||||
const fileName = folder.name;
|
||||
const fileSize = fileInfo.size || 0;
|
||||
|
||||
uni.showLoading({
|
||||
title: '下载中...'
|
||||
@@ -407,8 +458,14 @@ import { openFile as openFileNative } from '@/utils/fileOpener.js'
|
||||
uni.hideLoading();
|
||||
if (downloadRes.statusCode === 200) {
|
||||
const tempPath = downloadRes.tempFilePath;
|
||||
// 下载成功,直接打开文件
|
||||
console.log("// 下载成功,文件下载路径为:",tempPath);
|
||||
// 持久化保存到本地
|
||||
saveDownload(tempPath, fileName, fileSize).then((record) => {
|
||||
downloadList.value.unshift(record);
|
||||
uni.showToast({ title: '下载成功', icon: 'success' });
|
||||
}).catch(() => {
|
||||
// 保存失败不影响打开
|
||||
});
|
||||
// 下载成功后打开文件
|
||||
openFile(tempPath);
|
||||
} else {
|
||||
uni.showToast({
|
||||
@@ -443,6 +500,102 @@ import { openFile as openFileNative } from '@/utils/fileOpener.js'
|
||||
});
|
||||
};
|
||||
|
||||
// ===== 下载列表相关 =====
|
||||
const switchTab = (tab) => {
|
||||
activeTab.value = tab
|
||||
if (tab === 'downloads') {
|
||||
loadDownloads()
|
||||
}
|
||||
}
|
||||
|
||||
const loadDownloads = () => {
|
||||
downloadList.value = getDownloadList()
|
||||
}
|
||||
|
||||
const openDownloadFile = (item) => {
|
||||
// #ifdef APP-PLUS
|
||||
// 检查公共目录下文件是否存在
|
||||
plus.io.resolveLocalFileSystemURL(
|
||||
item.path,
|
||||
() => {
|
||||
// 文件存在,直接打开
|
||||
openFile(item.path)
|
||||
},
|
||||
() => {
|
||||
// 文件已被手动删除
|
||||
uni.showToast({ title: '文件已失效,将移除记录', icon: 'none' })
|
||||
handleDeleteDownload(item.id)
|
||||
}
|
||||
)
|
||||
// #endif
|
||||
// #ifndef APP-PLUS
|
||||
uni.getSavedFileList({
|
||||
success: (res) => {
|
||||
const found = res.fileList.find(f => f.filePath === item.path)
|
||||
if (found) {
|
||||
openFile(item.path)
|
||||
} else {
|
||||
uni.showToast({ title: '文件已失效,将移除记录', icon: 'none' })
|
||||
handleDeleteDownload(item.id)
|
||||
}
|
||||
},
|
||||
fail: () => openFile(item.path)
|
||||
})
|
||||
// #endif
|
||||
}
|
||||
|
||||
const handleDeleteDownload = (id) => {
|
||||
uni.showModal({
|
||||
title: '删除文件',
|
||||
content: '确定要删除此下载文件吗?',
|
||||
success: (res) => {
|
||||
if (res.confirm) {
|
||||
deleteDownload(id).then(() => {
|
||||
downloadList.value = getDownloadList()
|
||||
uni.showToast({ title: '已删除', icon: 'success' })
|
||||
}).catch(() => {
|
||||
uni.showToast({ title: '删除失败', icon: 'error' })
|
||||
})
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
const handleClearDownloads = () => {
|
||||
if (downloadList.value.length === 0) return
|
||||
uni.showModal({
|
||||
title: '清空下载',
|
||||
content: '确定要清空所有下载文件吗?此操作不可撤销。',
|
||||
success: (res) => {
|
||||
if (res.confirm) {
|
||||
clearAllDownloads().then(() => {
|
||||
downloadList.value = []
|
||||
uni.showToast({ title: '已清空', icon: 'success' })
|
||||
})
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
const formatDownloadSize = formatFileSize
|
||||
const formatDownloadTime = formatTime
|
||||
|
||||
// const getFileIcon = (fileName) => {
|
||||
// const ext = fileName.split('.').pop().toLowerCase()
|
||||
// const iconMap = {
|
||||
// pdf: 'icon-PDF',
|
||||
// doc: 'icon-word', docx: 'icon-word',
|
||||
// xls: 'icon-excel', xlsx: 'icon-excel',
|
||||
// ppt: 'icon-PPD', pptx: 'icon-PPD',
|
||||
// zip: 'icon-yasuobao', rar: 'icon-yasuobao', '7z': 'icon-yasuobao',
|
||||
// jpg: 'icon-tupian', jpeg: 'icon-tupian', png: 'icon-tupian', gif: 'icon-tupian',
|
||||
// mp3: 'icon-yinle', wav: 'icon-yinle', flac: 'icon-yinle',
|
||||
// mp4: 'icon-shipin', avi: 'icon-shipin', mov: 'icon-shipin',
|
||||
// txt: 'icon-txt', md: 'icon-txt',
|
||||
// }
|
||||
// return iconMap[ext] || 'icon-weizhiwenjian'
|
||||
// }
|
||||
|
||||
// WYXD 查看器入口
|
||||
const openWyxdViewer = (folder) => {
|
||||
const filePath = folder.path.startsWith('./') ? folder.path.slice(2) : folder.path;
|
||||
@@ -666,6 +819,7 @@ import { openFile as openFileNative } from '@/utils/fileOpener.js'
|
||||
|
||||
onMounted(() => {
|
||||
initCurrentFolderList();
|
||||
loadDownloads();
|
||||
})
|
||||
</script>
|
||||
|
||||
|
||||
Reference in New Issue
Block a user