新增: 文件浏览器收尾(滚动条/阶段进度条/空状态/骨架屏/工程下拉)

- 提交之前未提交的滚动条与布局修复
- 移除阶段进度条死代码(模板+CSS+常量)
- 文件预览空状态加图标引导
- 变更视图加载骨架屏
- 工程选择器改为自定义下拉(显示工程路径)
This commit is contained in:
2026-06-30 20:15:05 +08:00
parent 78bd8d4344
commit 6b131f3dc1
4 changed files with 135 additions and 121 deletions

View File

@@ -9,14 +9,24 @@
<div class="explorer-toolbar">
<div class="toolbar-left">
<!-- 多工程下拉(单工程隐藏) -->
<select
v-if="modules.length > 1"
class="module-select"
:value="currentModuleId"
@change="onModuleChange"
>
<option v-for="m in modules" :key="m.id" :value="m.id">{{ m.name }}</option>
</select>
<div v-if="modules.length > 1" class="module-dropdown">
<button class="module-select" @click="moduleDropdownOpen = !moduleDropdownOpen">
<span class="module-select-name">{{ currentModule?.name ?? '...' }}</span>
<span class="module-select-arrow" :class="{ open: moduleDropdownOpen }"></span>
</button>
<div v-if="moduleDropdownOpen" class="module-dropdown-menu" @click.stop>
<div
v-for="m in modules"
:key="m.id"
class="module-dropdown-item"
:class="{ active: m.id === currentModuleId }"
@click="onModuleSelect(m.id)"
>
<span class="module-dropdown-name">{{ m.name }}</span>
<span v-if="m.path" class="module-dropdown-path" :title="m.path">{{ m.path }}</span>
</div>
</div>
</div>
<!-- 路径面包屑 -->
<nav class="breadcrumb">
@@ -160,6 +170,7 @@ const { t } = useI18n()
const modules = ref<ProjectModuleRecord[]>([])
const currentModuleId = ref<string>('')
const refreshing = ref(false)
const moduleDropdownOpen = ref(false)
// 新增工程弹窗
const showAddModule = ref(false)
@@ -216,10 +227,10 @@ function resetTreeState() {
selectedFileGitStatus.value = undefined
}
/** 切换工程(下拉变更)。 */
function onModuleChange(e: Event) {
const target = e.target as HTMLSelectElement
currentModuleId.value = target.value
/** 自定义下拉选择工程。 */
function onModuleSelect(id: string) {
currentModuleId.value = id
moduleDropdownOpen.value = false
resetTreeState()
}
@@ -310,6 +321,9 @@ function onChangeFileSelect(path: string) {
watch(() => props.projectId, loadModules, { immediate: true })
// 点击外部关闭工程下拉
document.addEventListener('click', () => { moduleDropdownOpen.value = false })
/** 提交新增工程。 */
async function onAddModule() {
if (addingModule.value) return
@@ -340,6 +354,7 @@ async function onAddModule() {
display: flex;
flex-direction: column;
height: 100%;
max-height: 100%;
background: var(--df-bg);
border: 0.5px solid var(--df-border);
border-radius: var(--df-radius-lg, 8px);
@@ -367,6 +382,9 @@ async function onAddModule() {
}
.module-select {
display: inline-flex;
align-items: center;
gap: 6px;
padding: 5px 10px;
background: var(--df-bg);
border: 0.5px solid var(--df-border);
@@ -377,9 +395,54 @@ async function onAddModule() {
max-width: 180px;
}
.module-select:focus {
outline: none;
border-color: var(--df-accent);
.module-select:hover { border-color: var(--df-accent); }
.module-select-name { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.module-select-arrow {
font-size: 10px;
color: var(--df-text-dim);
transition: transform 0.15s;
}
.module-select-arrow.open { transform: rotate(180deg); }
.module-dropdown { position: relative; flex-shrink: 0; }
.module-dropdown-menu {
position: absolute;
top: calc(100% + 4px);
left: 0;
min-width: 220px;
max-width: 320px;
background: var(--df-bg-card);
border: 0.5px solid var(--df-border);
border-radius: var(--df-radius-sm, 4px);
box-shadow: 0 6px 16px rgba(0,0,0,0.25);
z-index: 20;
max-height: 280px;
overflow-y: auto;
scrollbar-width: thin;
}
.module-dropdown-item {
display: flex;
flex-direction: column;
gap: 2px;
padding: 8px 12px;
cursor: pointer;
border-bottom: 0.5px solid rgba(255,255,255,0.04);
}
.module-dropdown-item:last-child { border-bottom: none; }
.module-dropdown-item:hover { background: rgba(255,255,255,0.04); }
.module-dropdown-item.active {
background: rgba(255,255,255,0.06);
border-left: 2px solid var(--df-accent);
}
.module-dropdown-name { font-size: 12px; color: var(--df-text); }
.module-dropdown-path {
font-size: 10px;
color: var(--df-text-dim);
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
/* 面包屑 */
@@ -458,6 +521,7 @@ async function onAddModule() {
flex: 1;
display: flex;
overflow: hidden;
min-height: 0;
}
/* 左侧边栏(视图切换 + 内容) */
@@ -564,8 +628,8 @@ async function onAddModule() {
.explorer-preview {
flex: 1;
min-width: 0;
min-height: 0;
overflow: hidden;
scrollbar-width: thin;
}
.preview-placeholder-inline {