Files
estel_docs/app/components/content/FileTreeItem.vue

108 lines
3.1 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<template>
<div class="file-tree-item">
<div
class="flex items-center py-1 px-2 rounded hover:bg-gray-100 dark:hover:bg-gray-700 cursor-pointer transition-colors"
:class="{
'bg-blue-50 dark:bg-blue-900/20': item.highlighted,
'text-green-600 dark:text-green-400': item.diff === 'addition',
'text-red-600 dark:text-red-400': item.diff === 'deletion'
}"
@click="toggleFolder"
>
<!-- 缩进 -->
<div class="flex items-center" :style="{ marginLeft: level * 16 + 'px' }">
<!-- 箭头仅文件夹且有子项时显示 -->
<Icon
v-if="showArrow && item.isFolder && item.children && item.children.length > 0"
:name="isExpanded ? 'lucide-chevron-down' : 'lucide-chevron-right'"
class="mr-1 text-gray-400 w-4 h-4 transition-transform"
:class="{ 'rotate-90': isExpanded }"
/>
<div v-else-if="showArrow" class="w-4 mr-1"></div>
<!-- 图标 -->
<Icon
v-if="showIcon"
:name="item.icon || 'lucide-file'"
class="mr-2 text-gray-500 w-4 h-4"
:class="{
'text-green-500': item.icon?.includes('vue'),
'text-blue-500': item.icon?.includes('typescript') || item.icon?.includes('javascript'),
'text-orange-500': item.icon?.includes('markdown'),
'text-yellow-500': item.icon?.includes('json')
}"
/>
<!-- 标题 -->
<span
class="text-sm font-mono"
:class="{
'font-semibold': item.isFolder,
'underline': item.highlighted
}"
>
{{ item.title }}
</span>
</div>
</div>
<!-- 子项 -->
<div v-if="item.children && item.children.length > 0 && isExpanded" class="ml-4">
<FileTreeItem
v-for="child in item.children"
:key="child.title"
:item="child"
:level="level + 1"
:show-arrow="showArrow"
:show-icon="showIcon"
/>
</div>
</div>
</template>
<script setup lang="ts">
type FileTreeItemDiff = 'none' | 'addition' | 'deletion';
interface FileTreeItem {
title: string;
icon?: string;
children?: FileTreeItem[];
highlighted?: boolean;
diff?: FileTreeItemDiff;
isFolder?: boolean;
}
const props = defineProps<{
item: FileTreeItem;
level: number;
showArrow: boolean;
showIcon: boolean;
}>();
const expandedState = inject('expandedState', ref(new Set<string>()));
const itemKey = computed(() => `${props.item.title}-${props.level}`);
const isExpanded = computed({
get: () => expandedState.value.has(itemKey.value),
set: (value: boolean) => {
if (value) {
expandedState.value.add(itemKey.value);
} else {
expandedState.value.delete(itemKey.value);
}
}
});
// 初始化时展开所有文件夹
onMounted(() => {
if (props.item.isFolder && props.item.children && props.item.children.length > 0) {
isExpanded.value = true;
}
});
function toggleFolder() {
if (props.item.isFolder && props.item.children && props.item.children.length > 0) {
isExpanded.value = !isExpanded.value;
}
}
</script>