Files
tunji2/src/views/NotesListView.vue
2026-06-01 17:28:00 +08:00

109 lines
3.9 KiB
Vue

<script setup>
import { onMounted } from 'vue'
import { useRouter } from 'vue-router'
import { useNotesStore } from '@/stores/notes'
import { useWorkspaceStore } from '@/stores/workspace'
import { FileText, LayoutGrid, List } from 'lucide-vue-next'
const router = useRouter()
const notesStore = useNotesStore()
const workspaceStore = useWorkspaceStore()
onMounted(async () => {
if (workspaceStore.path) {
await notesStore.fetchNotes()
}
})
function openNote(note) {
router.push({ name: 'note-detail', params: { id: note.id } })
}
function toggleView() {
notesStore.viewMode = notesStore.viewMode === 'list' ? 'grid' : 'list'
}
</script>
<template>
<div class="h-full flex flex-col">
<!-- 头部 -->
<div
class="flex items-center justify-between px-6 py-4 border-b"
:style="{ borderColor: 'var(--p-surface-200)' }"
>
<h1 class="text-lg font-semibold" :style="{ color: 'var(--p-surface-800)' }">全部笔记</h1>
<button
class="p-1.5 rounded-md transition-colors"
:style="{ color: 'var(--p-surface-500)' }"
@click="toggleView"
:title="notesStore.viewMode === 'list' ? '卡片视图' : '列表视图'"
>
<component :is="notesStore.viewMode === 'list' ? LayoutGrid : List" :size="18" />
</button>
</div>
<!-- 内容区 -->
<div class="flex-1 overflow-y-auto p-6">
<!-- 无笔记提示 -->
<div
v-if="notesStore.filteredNotes.length === 0"
class="flex flex-col items-center justify-center h-full"
>
<div
class="w-16 h-16 rounded-xl flex items-center justify-center mb-4"
:style="{ backgroundColor: 'var(--p-surface-100)', color: 'var(--p-surface-400)' }"
>
<FileText :size="32" />
</div>
<p class="text-sm" :style="{ color: 'var(--p-surface-500)' }">
{{ workspaceStore.path ? '暂无笔记,点击左侧 + 创建' : '请先选择工作目录' }}
</p>
</div>
<!-- 列表视图 -->
<div v-else-if="notesStore.viewMode === 'list'" class="space-y-1">
<div
v-for="note in notesStore.filteredNotes"
:key="note.id"
class="flex items-center gap-3 px-4 py-3 rounded-lg cursor-pointer transition-colors"
:style="{ color: 'var(--p-surface-700)' }"
@click="openNote(note)"
@mouseenter="$event.currentTarget.style.backgroundColor = 'var(--p-surface-50)'"
@mouseleave="$event.currentTarget.style.backgroundColor = 'transparent'"
>
<FileText :size="18" :style="{ color: 'var(--p-surface-400)' }" />
<div class="flex-1 min-w-0">
<div class="text-sm font-medium truncate">{{ note.title }}</div>
<div class="text-xs mt-0.5" :style="{ color: 'var(--p-surface-400)' }">
{{ note.filePath }}
</div>
</div>
</div>
</div>
<!-- 卡片视图 -->
<div v-else class="grid grid-cols-2 lg:grid-cols-3 gap-4">
<div
v-for="note in notesStore.filteredNotes"
:key="note.id"
class="p-4 rounded-xl border cursor-pointer transition-colors"
:style="{ borderColor: 'var(--p-surface-200)', backgroundColor: 'var(--p-surface-50)' }"
@click="openNote(note)"
@mouseenter="$event.currentTarget.style.borderColor = 'var(--p-primary-300)'"
@mouseleave="$event.currentTarget.style.borderColor = 'var(--p-surface-200)'"
>
<div class="flex items-center gap-2 mb-2">
<FileText :size="16" :style="{ color: 'var(--p-primary-500)' }" />
<span class="text-sm font-medium truncate" :style="{ color: 'var(--p-surface-700)' }">
{{ note.title }}
</span>
</div>
<p class="text-xs truncate" :style="{ color: 'var(--p-surface-400)' }">
{{ note.filePath }}
</p>
</div>
</div>
</div>
</div>
</template>