From 6fcfb090de776f2f35f612d640483b7878966d84 Mon Sep 17 00:00:00 2001 From: Wenjie Zhang Date: Thu, 30 Apr 2026 22:40:55 +0800 Subject: [PATCH] =?UTF-8?q?feat(workspace):=20=E9=87=8D=E6=9E=84=E5=B7=A5?= =?UTF-8?q?=E4=BD=9C=E5=8C=BA=E7=BB=84=E4=BB=B6=EF=BC=8C=E4=BC=98=E5=8C=96?= =?UTF-8?q?=E8=B7=AF=E5=BE=84=E9=80=89=E6=8B=A9=E5=92=8C=E9=9D=A2=E5=8C=85?= =?UTF-8?q?=E5=B1=91=E5=AF=BC=E8=88=AA=E5=8A=9F=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Copilot --- .../workspace/WorkspaceFileList.vue | 108 +++++++++++------- .../workspace/WorkspacePreviewPane.vue | 4 + .../components/workspace/WorkspaceSidebar.vue | 7 +- web/src/views/WorkspaceView.vue | 12 +- 4 files changed, 77 insertions(+), 54 deletions(-) diff --git a/web/src/components/workspace/WorkspaceFileList.vue b/web/src/components/workspace/WorkspaceFileList.vue index 0373c8c1..8902ec55 100644 --- a/web/src/components/workspace/WorkspaceFileList.vue +++ b/web/src/components/workspace/WorkspaceFileList.vue @@ -2,22 +2,34 @@
- - {{ currentPath }} + + + + +
{{ entries.length }} 项 - - 多选 - + + + + + import { computed } from 'vue' -import { ChevronLeft, Download, Folder, MoreHorizontal, Trash2 } from 'lucide-vue-next' +import { Download, Folder, ListChecks, MoreHorizontal, Trash2 } from 'lucide-vue-next' import { formatFileSize, formatRelativeTime, getFileIcon, getFileIconColor } from '@/utils/file_utils' const props = defineProps({ @@ -137,7 +149,7 @@ const props = defineProps({ const emit = defineEmits([ 'select-entry', - 'go-parent', + 'select-path', 'update:selectedPaths', 'update:selectionMode', 'delete-selected', @@ -148,6 +160,23 @@ const emit = defineEmits([ const selectedPathSet = computed(() => new Set(props.selectedPaths)) const deletingPathSet = computed(() => new Set(props.deletingPaths)) const entryPaths = computed(() => props.entries.map((entry) => entry.path)) +const breadcrumbItems = computed(() => { + const normalizedPath = props.currentPath || '/' + if (normalizedPath === '/') { + return [{ name: '工作区', path: '/' }] + } + + const segments = normalizedPath.split('/').filter(Boolean) + return segments.reduce( + (items, segment) => { + const parentPath = items[items.length - 1].path + const path = parentPath === '/' ? `/${segment}` : `${parentPath}/${segment}` + items.push({ name: segment, path }) + return items + }, + [{ name: '工作区', path: '/' }] + ) +}) const allSelected = computed(() => { return entryPaths.value.length > 0 && entryPaths.value.every((path) => selectedPathSet.value.has(path)) @@ -213,37 +242,34 @@ const toggleEntrySelection = (path, checked) => { flex: 0 0 auto; } -.path-action { - display: inline-flex; - align-items: center; - justify-content: center; - width: 30px; - height: 30px; - border: 1px solid var(--gray-150); - border-radius: 8px; - background: var(--gray-0); - color: var(--gray-600); - cursor: pointer; - - &:disabled { - color: var(--gray-300); - cursor: not-allowed; - } - - &:hover:not(:disabled) { - background: var(--main-20); - color: var(--main-color); - } -} - -.path-text { +.path-breadcrumb { min-width: 0; overflow: hidden; - color: var(--gray-900); font-size: 14px; - font-weight: 600; +} + +.breadcrumb-action { + max-width: 180px; + padding: 0; + overflow: hidden; + border: 0; + background: transparent; + color: var(--main-800); + cursor: pointer; + font: inherit; text-overflow: ellipsis; white-space: nowrap; + font-weight: 400; + + &:hover:not(:disabled) { + color: var(--main-600); + } + + &.current, + &:disabled { + color: var(--gray-900); + cursor: default; + } } .entry-count { diff --git a/web/src/components/workspace/WorkspacePreviewPane.vue b/web/src/components/workspace/WorkspacePreviewPane.vue index 3c0b172f..2935a3f6 100644 --- a/web/src/components/workspace/WorkspacePreviewPane.vue +++ b/web/src/components/workspace/WorkspacePreviewPane.vue @@ -5,10 +5,12 @@ :file="file" :file-path="filePath" :show-download="false" + :show-close="true" :show-fullscreen="true" :full-height="true" container-class="workspace-preview-container" content-class="workspace-preview-content" + @close="$emit('close')" />
@@ -31,6 +33,8 @@ defineProps({ filePath: { type: String, default: '' }, loading: { type: Boolean, default: false } }) + +defineEmits(['close'])