This commit is contained in:
2026-07-07 00:21:53 +08:00
parent 8ad8af7e6b
commit b1d318ae52
7 changed files with 55 additions and 20 deletions

View File

@@ -149,6 +149,7 @@ const showSettings = ref(false);
v-if="rootEntry"
:entry="rootEntry"
:depth="0"
:currentFilePath="currentFilePath"
@toggle-folder="(path: string) => emit('toggleFolder', path)"
@open-file="(path: string) => emit('openFile', path)"
/>

View File

@@ -4,7 +4,7 @@ export default { name: "TreeEntry" };
</script>
<script setup lang="ts">
import { ref, watch } from "vue";
import { computed, ref, watch } from "vue";
interface DirEntry {
name: string;
@@ -16,6 +16,7 @@ interface DirEntry {
const props = defineProps<{
entry: DirEntry;
depth: number;
currentFilePath?: string | null;
}>();
const emit = defineEmits<{
@@ -35,13 +36,15 @@ watch(
},
);
const isActive = computed(() => {
return props.currentFilePath != null && props.currentFilePath === props.entry.path;
});
function onClick() {
if (props.entry.is_dir) {
if (props.entry.children === undefined) {
// Not loaded yet — ask parent to load
emit("toggleFolder", props.entry.path);
} else {
// Already loaded — toggle visibility
expanded.value = !expanded.value;
}
} else {
@@ -51,10 +54,9 @@ function onClick() {
</script>
<template>
<div>
<!-- Folder -->
<template v-if="entry.is_dir">
<!-- Folder label -->
<div
v-if="entry.is_dir"
class="flex items-center gap-1 px-2 py-1 rounded-md text-sm text-[#5c574e] hover:bg-[#ede8de] cursor-pointer select-none"
:style="{ paddingLeft: `${depth * 16 + 8}px` }"
@click="onClick"
@@ -68,26 +70,32 @@ function onClick() {
</div>
<!-- Children (recursive) -->
<template v-if="entry.is_dir && expanded && entry.children">
<template v-if="expanded && entry.children">
<TreeEntry
v-for="child in entry.children"
:key="child.path"
:entry="child"
:depth="depth + 1"
:currentFilePath="currentFilePath"
@toggle-folder="(path: string) => emit('toggleFolder', path)"
@open-file="(path: string) => emit('openFile', path)"
/>
</template>
</template>
<!-- File -->
<div
v-else-if="!entry.is_dir"
class="flex items-center gap-1.5 px-2 py-1 rounded-md text-sm text-[#8c877d] hover:bg-[#ede8de] hover:text-[#38342e] cursor-pointer"
:style="{ paddingLeft: `${depth * 16 + 8}px` }"
@click="onClick"
>
<i class="ri-file-line text-sm text-[#bf6a3b]/60 shrink-0"></i>
<span class="truncate">{{ entry.name }}</span>
</div>
<!-- File -->
<div
v-else
:class="[
'flex items-center gap-1.5 px-2 py-1 rounded-md text-sm cursor-pointer transition-colors',
isActive
? 'bg-[#ede8de] text-[#bf6a3b] font-medium'
: 'text-[#8c877d] hover:bg-[#ede8de] hover:text-[#38342e]',
]"
:style="{ paddingLeft: `${depth * 16 + 8}px` }"
@click="onClick"
>
<i class="ri-file-line text-sm text-[#bf6a3b]/60 shrink-0"></i>
<span class="truncate">{{ entry.name }}</span>
</div>
</template>