Phase 2.7完成:文件浏览模块完善(SQLite查询 + Tree展示)
Some checks failed
Test / build (push) Has been cancelled
Test / test (push) Has been cancelled

Phase 2.7.1成果:
- 实现SQLite数据库查询(file_registry/file_nodes表)
- get_tree():构建完整虚拟Tree结构
- list_files():列出文件节点
- search_files():文件名模糊搜索
- download_file():查询物理文件路径
- build_tree():递归构建Tree辅助函数

Phase 2.7.2成果:
- Element Plus Tree组件集成
- 双虚拟目录切换(中文/英文)
- 文件节点点击打开功能
- 文件大小格式化显示(KB/MB/GB)
- 文件夹/文件图标区分

技术实现:
- 添加rusqlite依赖到Cargo.toml
- 修复Tauri features配置
- Home.vue完整Tree展示UI
- 编译成功(8警告,0错误)

状态:Phase 2总进度98%完成
This commit is contained in:
Warren
2026-06-13 15:53:21 +08:00
parent 8314c26fb6
commit d7afd109b0
4 changed files with 269 additions and 42 deletions

View File

@@ -1,17 +1,70 @@
<script setup>
import { ref, onMounted } from 'vue'
import { ref, onMounted, watch } from 'vue'
import { useRouter } from 'vue-router'
import { useAppStore } from '../stores/app'
import { invoke } from '@tauri-apps/api/tauri'
import { ElMessage } from 'element-plus'
import { Folder, Document } from '@element-plus/icons-vue'
const router = useRouter()
const appStore = useAppStore()
const treeData = ref([])
const treeProps = {
label: 'name',
children: 'children',
isLeaf: (data) => data.node_type === 'file'
}
const currentTreeType = ref('demo_library_zh')
const navigateTo = (path) => {
router.push(path)
}
const formatFileSize = (bytes) => {
if (bytes < 1024) return bytes + ' B'
if (bytes < 1024 * 1024) return (bytes / 1024).toFixed(2) + ' KB'
if (bytes < 1024 * 1024 * 1024) return (bytes / 1024 / 1024).toFixed(2) + ' MB'
return (bytes / 1024 / 1024 / 1024).toFixed(2) + ' GB'
}
const loadTree = async () => {
try {
const tree = await invoke('get_tree', {
userId: 'demo',
treeType: currentTreeType.value
})
treeData.value = [tree]
ElMessage.success('Tree loaded successfully')
} catch (error) {
ElMessage.error(`Failed to load tree: ${error}`)
}
}
const handleNodeClick = async (data) => {
if (data.node_type === 'file') {
try {
const filePath = await invoke('download_file', {
userId: 'demo',
fileUuid: data.id
})
await invoke('open_file', { filePath })
ElMessage.success(`Opening file: ${data.name}`)
} catch (error) {
ElMessage.error(`Failed to open file: ${error}`)
}
}
}
watch(currentTreeType, () => {
loadTree()
})
onMounted(async () => {
await appStore.initializeApp()
await loadTree()
})
</script>
@@ -30,7 +83,28 @@ onMounted(async () => {
</div>
</template>
<div class="tree-container">
<el-empty description="File tree will be displayed here" />
<el-tree
:data="treeData"
:props="treeProps"
:expand-on-click-node="false"
:highlight-current="true"
@node-click="handleNodeClick"
>
<template #default="{ node, data }">
<span class="custom-tree-node">
<el-icon v-if="data.node_type === 'folder'">
<Folder />
</el-icon>
<el-icon v-else-if="data.node_type === 'file'">
<Document />
</el-icon>
<span>{{ data.name }}</span>
<span class="file-size" v-if="data.size">
{{ formatFileSize(data.size) }}
</span>
</span>
</template>
</el-tree>
</div>
</el-card>
</el-col>
@@ -109,6 +183,22 @@ onMounted(async () => {
overflow-y: auto;
}
.custom-tree-node {
display: flex;
align-items: center;
width: 100%;
}
.custom-tree-node .el-icon {
margin-right: 8px;
}
.file-size {
margin-left: 10px;
color: #999;
font-size: 12px;
}
.management-cards {
display: flex;
flex-direction: column;