feat(frontend): 搭建桌面端基础界面与 Workspace
- App Shell 壳层:主导航、次导航、Title Bar、状态栏 - Vault 入口页:最近 Vault、打开/创建 Vault、AI Core 状态 - Workspace 与文件树:浏览、打开、创建笔记/文件夹 - Design Token:浅色/深色主题 CSS Variables - Contracts / Service / Store / Router 基础架构 - 统一 ApiClient 与 SseClient,对接后端 API 契约
This commit is contained in:
@@ -0,0 +1,132 @@
|
||||
import { defineStore } from 'pinia'
|
||||
import { ref, computed } from 'vue'
|
||||
import type { FileNode } from '@/contracts'
|
||||
import * as workspaceService from '@/services/workspaceService'
|
||||
|
||||
export const useWorkspaceStore = defineStore('workspace', () => {
|
||||
const vaultPath = ref('')
|
||||
const vaultName = ref('')
|
||||
const fileTree = ref<FileNode[]>([])
|
||||
const openFiles = ref<string[]>([])
|
||||
const activeFilePath = ref<string | null>(null)
|
||||
const isLoading = ref(false)
|
||||
const hasVault = ref(false)
|
||||
const recentVaults = ref<{ path: string; name: string }[]>([])
|
||||
|
||||
const activeFile = computed(() => {
|
||||
if (!activeFilePath.value) return null
|
||||
return findNodeByPath(fileTree.value, activeFilePath.value)
|
||||
})
|
||||
|
||||
function findNodeByPath(nodes: FileNode[], path: string): FileNode | null {
|
||||
for (const node of nodes) {
|
||||
if (node.path === path) return node
|
||||
if (node.children) {
|
||||
const found = findNodeByPath(node.children, path)
|
||||
if (found) return found
|
||||
}
|
||||
}
|
||||
return null
|
||||
}
|
||||
|
||||
function toggleFolder(path: string) {
|
||||
const node = findNodeByPath(fileTree.value, path)
|
||||
if (node && node.type === 'folder') {
|
||||
node.is_open = !node.is_open
|
||||
}
|
||||
}
|
||||
|
||||
function openFile(path: string) {
|
||||
if (!openFiles.value.includes(path)) {
|
||||
openFiles.value.push(path)
|
||||
}
|
||||
activeFilePath.value = path
|
||||
}
|
||||
|
||||
function closeFile(path: string) {
|
||||
const idx = openFiles.value.indexOf(path)
|
||||
if (idx > -1) {
|
||||
openFiles.value.splice(idx, 1)
|
||||
if (activeFilePath.value === path) {
|
||||
activeFilePath.value = openFiles.value[Math.min(idx, openFiles.value.length - 1)] || null
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function setActiveFile(path: string | null) {
|
||||
activeFilePath.value = path
|
||||
}
|
||||
|
||||
async function loadRecentVaults() {
|
||||
recentVaults.value = await workspaceService.getRecentVaults()
|
||||
}
|
||||
|
||||
async function openVault(path: string) {
|
||||
isLoading.value = true
|
||||
try {
|
||||
const info = await workspaceService.openVault(path)
|
||||
vaultPath.value = info.path
|
||||
vaultName.value = info.name
|
||||
fileTree.value = await workspaceService.getFileTree()
|
||||
hasVault.value = true
|
||||
} finally {
|
||||
isLoading.value = false
|
||||
}
|
||||
}
|
||||
|
||||
async function createVault(path: string, name: string) {
|
||||
isLoading.value = true
|
||||
try {
|
||||
const info = await workspaceService.createVault(path, name)
|
||||
vaultPath.value = info.path
|
||||
vaultName.value = info.name
|
||||
fileTree.value = await workspaceService.getFileTree()
|
||||
hasVault.value = true
|
||||
} finally {
|
||||
isLoading.value = false
|
||||
}
|
||||
}
|
||||
|
||||
function addFileToTree(parentPath: string, file: FileNode) {
|
||||
const parent = findNodeByPath(fileTree.value, parentPath)
|
||||
if (parent?.children) {
|
||||
parent.children.push(file)
|
||||
parent.is_open = true
|
||||
}
|
||||
}
|
||||
|
||||
function removeFromTree(path: string) {
|
||||
function remove(nodes: FileNode[]): boolean {
|
||||
for (let i = 0; i < nodes.length; i++) {
|
||||
if (nodes[i].path === path) {
|
||||
nodes.splice(i, 1)
|
||||
return true
|
||||
}
|
||||
if (nodes[i].children && remove(nodes[i].children!)) return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
remove(fileTree.value)
|
||||
}
|
||||
|
||||
return {
|
||||
vaultPath,
|
||||
vaultName,
|
||||
fileTree,
|
||||
openFiles,
|
||||
activeFilePath,
|
||||
activeFile,
|
||||
isLoading,
|
||||
hasVault,
|
||||
recentVaults,
|
||||
toggleFolder,
|
||||
openFile,
|
||||
closeFile,
|
||||
setActiveFile,
|
||||
loadRecentVaults,
|
||||
openVault,
|
||||
createVault,
|
||||
addFileToTree,
|
||||
removeFromTree,
|
||||
}
|
||||
})
|
||||
Reference in New Issue
Block a user