-
-
-
-
-
{{ selectedNode.fileName }}
-
-
-
- 打开链接
-
-
- 打开
-
-
- 下载
-
-
- 发送到下载器
-
-
- 复制直链
-
-
-
-
-
-
+
+
+ 详情
+
+
批量下载
+
+ {{ treeExpanding ? '正在展开并收集文件…' : `勾选左侧文件夹将自动展开(最多 ${effectiveBatchMaxDepth} 层)` }}
+
+
+
+
+
+
+
+
{{ selectedNode.fileName }}
+
+
+
+ 打开链接
+
+
+ 打开
+
+
+ 下载
+
+
+ 发送到下载器
+
+
+ 复制直链
+
+
+
+
+
+
请在左侧选择文件查看详情
+
或直接点击「批量下载」勾选多个文件
+
+
+
@@ -353,26 +354,21 @@
请在上方选择文件查看详情
+
或直接点击「批量下载」勾选多个文件
批量下载
-
+
@@ -453,6 +449,7 @@ import { Splitpanes, Pane } from 'splitpanes'
import 'splitpanes/dist/splitpanes.css'
import fileTypeUtils from '@/utils/fileTypeUtils'
import DownloadDialog from '@/components/DownloadDialog.vue'
+import TreeBatchActionBar from '@/components/TreeBatchActionBar.vue'
import { testConnection, autoDetect, addDownload, batchAddDownload, getConfig, saveConfig } from '@/utils/downloaderService'
import batchTreeCollect from '@/utils/batchTreeCollect'
@@ -466,7 +463,7 @@ const {
export default {
name: 'DirectoryTree',
- components: { ElTree, Splitpanes, Pane, DownloadDialog },
+ components: { ElTree, Splitpanes, Pane, DownloadDialog, TreeBatchActionBar },
props: {
fileList: {
type: Array,
@@ -566,6 +563,19 @@ export default {
effectiveBatchMaxDepth() {
const depth = Number(this.batchMaxDepth)
return Number.isFinite(depth) && depth >= 0 ? depth : DEFAULT_BATCH_MAX_DEPTH
+ },
+ treeBatchBarBind() {
+ return {
+ selectedCount: this.selectedFiles.length,
+ batchDownloading: this.batchDownloading,
+ treeExpanding: this.treeExpanding,
+ browserDisabled: this.batchBrowserDownloadDisabled,
+ progressPercent: this.batchProgressPercent,
+ progressStatus: this.batchProgressStatus,
+ progressCurrent: this.batchProgress.current,
+ progressTotal: this.batchProgress.total,
+ progressFailed: this.batchProgress.failed
+ }
}
},
watch: {
@@ -1640,10 +1650,21 @@ html, body, #app, .main-container, .directory-tree, .content-card {
.batch-progress-info {
margin-top: 12px;
}
-.tree-batch-trigger {
- position: absolute;
- bottom: 12px;
- right: 12px;
+.tree-content-footer-hint {
+ font-size: 12px;
+ color: #909399;
+ line-height: 1.4;
+}
+.dark-theme .tree-content-footer-hint {
+ color: #bdc3c7;
+}
+.file-detail-empty-hint {
+ margin-top: 8px;
+ font-size: 13px;
+ color: #909399;
+}
+.dark-theme .file-detail-empty-hint {
+ color: #bdc3c7;
}
.stats {
@@ -1714,8 +1735,7 @@ html, body, #app, .main-container, .directory-tree, .content-card {
}
.tree-content {
flex: 1;
- padding: 16px;
- overflow-y: auto;
+ min-height: 0;
position: relative;
}
@@ -2008,12 +2028,48 @@ html, body, #app, .main-container, .directory-tree, .content-card {
min-height: 0;
display: flex;
flex-direction: column;
- overflow: auto;
- padding: 24px 16px 16px 16px;
- align-items: center;
+ overflow: hidden;
+ padding: 0;
+ align-items: stretch;
position: relative;
}
+.tree-content-toolbar {
+ width: 100%;
+}
+
+.tree-content-body {
+ flex: 1;
+ min-height: 0;
+ overflow: auto;
+ display: flex;
+ flex-direction: column;
+ align-items: center;
+ padding: 24px 16px 16px;
+}
+
+.tree-content-footer {
+ flex-shrink: 0;
+ width: 100%;
+ display: flex;
+ align-items: center;
+ justify-content: space-between;
+ gap: 8px;
+ flex-wrap: wrap;
+ padding: 10px 12px;
+ border-top: 1px solid #eaeaea;
+ background: #f8f9fa;
+}
+
+.tree-content-footer.is-batch {
+ display: block;
+}
+
+.dark-theme .tree-content-footer {
+ border-top-color: #404040;
+ background: #232323;
+}
+
.file-detail-panel {
display: flex;
flex-direction: column;
diff --git a/web-front/src/components/TreeBatchActionBar.vue b/web-front/src/components/TreeBatchActionBar.vue
new file mode 100644
index 0000000..6f23ef2
--- /dev/null
+++ b/web-front/src/components/TreeBatchActionBar.vue
@@ -0,0 +1,51 @@
+