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:
2026-08-29 10:36:16 +08:00
parent 694c1b27c1
commit f9efc4f4a2
42 changed files with 8044 additions and 167 deletions
@@ -0,0 +1,72 @@
<script setup lang="ts">
import { onMounted } from 'vue'
import { useWorkspaceStore } from '@/stores/workspace'
import { useEditorStore } from '@/stores/editor'
import EditorHeader from '@/features/editor/EditorHeader.vue'
import EditorPane from '@/features/editor/EditorPane.vue'
const workspaceStore = useWorkspaceStore()
const editorStore = useEditorStore()
onMounted(() => {
if (!workspaceStore.fileTree.length && workspaceStore.hasVault) {
// Already loaded
}
if (!workspaceStore.activeFilePath && workspaceStore.fileTree.length === 0) {
workspaceStore.openFile('/欢迎使用知笔知己.md')
editorStore.loadFile('/欢迎使用知笔知己.md')
}
})
</script>
<template>
<div class="workspace-view">
<template v-if="workspaceStore.activeFilePath">
<EditorHeader />
<EditorPane />
</template>
<div v-else class="empty-workspace">
<div class="empty-content">
<div class="empty-icon">📝</div>
<h2>开始写作</h2>
<p>从左侧文件树选择笔记或创建新的笔记</p>
</div>
</div>
</div>
</template>
<style scoped>
.workspace-view {
display: flex;
flex-direction: column;
height: 100%;
overflow: hidden;
}
.empty-workspace {
flex: 1;
display: flex;
align-items: center;
justify-content: center;
color: var(--color-text-tertiary);
}
.empty-content {
text-align: center;
h2 {
font-size: 18px;
color: var(--color-text-secondary);
margin: 12px 0 8px;
}
p {
font-size: 14px;
}
}
.empty-icon {
font-size: 48px;
opacity: 0.5;
}
</style>