feat(web): add Vue workspace with file tree, tabs, autosave and live sync

- Login and first-run setup screens
- File tree with inline create/rename, context menu, drag-and-drop
  move and trash with undo; all operations update the UI first and roll
  back on failure
- Tabs keep a CodeMirror state each; edits autosave after 500 ms with
  If-Match revisions, unsent edits persist in IndexedDB, and conflicts
  or remote deletions surface as banners with explicit choices
- WebSocket events sync external edits, moves and deletions into open
  tabs; reconnects trigger a full resync
- Pasted or dropped images show instantly and upload to note.assets/
- Responsive layout with a swipe-in sidebar drawer on phones
- Switch to TypeScript 6: vue-tsc does not support TypeScript 7 yet
This commit is contained in:
eezd committed 2026-10-16 18:37:14 +08:00
1 parent c4d2bd4636
commit 02d904056c
28 files changed
+2231 -398

No files matched your search

+22
View File
@@ -0,0 +1,22 @@
<script setup lang="ts">
import { computed } from 'vue'
import { activeTab, keepLocalVersion, retrySave, useServerVersion } from './workspace'
const tab = computed(activeTab)
</script>
<template>
<div v-if="tab?.status === 'conflict'" class="rm-banner warn">
<span>这篇笔记已在其他地方被修改,与你的修改冲突。</span>
<button class="rm-btn" @click="useServerVersion(tab.path)">载入服务器版本</button>
<button class="rm-btn" @click="keepLocalVersion(tab.path)">保留我的修改</button>
</div>
<div v-else-if="tab?.status === 'deleted'" class="rm-banner warn">
<span>这篇笔记已在其他地方被删除或移动。</span>
<button class="rm-btn" @click="keepLocalVersion(tab.path)">重新保存</button>
</div>
<div v-else-if="tab?.saveError" class="rm-banner error">
<span>{{ tab.saveError }}</span>
<button class="rm-btn" @click="retrySave(tab.path)">立即重试</button>
</div>
</template>