开始完善便签新建、编辑逻辑

This commit is contained in:
2025-10-12 18:32:25 +08:00
parent 3957a7d3b2
commit 1bb9b4a79e
13 changed files with 696 additions and 1039 deletions

View File

@@ -6,41 +6,26 @@
<!-- 悬浮文件夹列表 - 使用绝对定位实现 -->
<div
v-if="isFolderExpanded"
style="position: absolute; top: 50px; left: 10%; right: 10%; z-index: 1000; background-color: var(--background-card); border-radius: 8px; box-shadow: 0 2px 4px var(--shadow); border: 1px solid #f0ece7; overflow: hidden">
class="folder-list">
<FolderManage
:allCount="notes.length"
:allCount="allNotesCount"
:starredCount="starredNotesCount"
:trashCount="0"
:trashCount="trashNotesCount"
:archiveCount="0"
:selectedFolder="currentFolder"
:onAllClick="
() => {
setCurrentFolder('all')
setIsFolderExpanded(false)
}
"
:onStarredClick="
() => {
setCurrentFolder('starred')
setIsFolderExpanded(false)
}
"
:onTrashClick="
() => {
setCurrentFolder('trash')
setIsFolderExpanded(false)
}
" />
:onAllClick="handleAllNotesClick"
:onStarredClick="handleStarredNotesClick"
:onTrashClick="handleTrashNotesClick" />
</div>
<!-- 点击外部区域收起文件夹列表的覆盖层 -->
<div v-if="isFolderExpanded" @click="() => setIsFolderExpanded(false)" style="position: absolute; top: 0; left: 0; right: 0; bottom: 0; background-color: transparent; z-index: 99"></div>
<div v-if="isFolderExpanded" @click="() => setIsFolderExpanded(false)" class="folder-overlay"></div>
<div style="padding: 0.8rem 0.5rem">
<div class="search-container">
<SearchBar v-model="searchQuery" @search="handleSearch" @clear="handleClearSearch" @focus="handleSearchFocus" @blur="handleSearchBlur" />
</div>
<div style="flex: 1">
<div v-for="note in filteredAndSortedNotes" :key="note.id" style="margin: 0.4rem 0">
<div class="notes-container">
<div v-for="note in filteredAndSortedNotes" :key="note.id" class="note-item">
<NoteItem
:title="note.title"
:content="note.content"
@@ -76,7 +61,6 @@
<script setup>
import { ref, computed, onMounted } from 'vue'
import { useAppStore } from '../stores/useAppStore'
import { create, settings } from 'ionicons/icons'
import NoteItem from '../components/NoteItem.vue'
import Header from '../components/Header.vue'
import FolderManage from '../components/FolderManage.vue'
@@ -102,50 +86,67 @@ const currentFolder = ref('all') // 默认文件夹是"全部便签"
const showAlert = ref(false)
const noteToDelete = ref(null)
// 计算加星便签数量
// 计算加星便签数量(未删除的)
const starredNotesCount = computed(() => {
return store.notes.filter(note => note.isStarred).length
return store.notes.filter(note => note.isStarred && !note.isDeleted).length
})
// 计算置顶便签数量
const topNotesCount = computed(() => {
return filteredAndSortedNotes.value.filter(note => note.isTop).length
// 计算回收站便签数量
const trashNotesCount = computed(() => {
return store.notes.filter(note => note.isDeleted).length
})
// 根据当前文件夹过滤便签
const filteredNotes = computed(() => {
// 预处理搜索查询,提高性能
const lowerCaseQuery = searchQuery.value.toLowerCase().trim()
return store.notes.filter(note => {
// 先检查搜索条件
const matchesSearch = !lowerCaseQuery ||
note.title.toLowerCase().includes(lowerCaseQuery) ||
note.content.toLowerCase().includes(lowerCaseQuery)
if (!matchesSearch) return false
// 再检查文件夹条件
switch (currentFolder.value) {
case 'all':
return true
// 全部便签中不显示已删除的便签
return !note.isDeleted
case 'starred':
return note.isStarred
// 加星便签中只显示未删除的加星便签
return note.isStarred && !note.isDeleted
case 'trash':
// 假设我们有一个isDeleted属性来标识已删除的便签
return note.isDeleted || false
// 回收站中只显示已删除的便签
return note.isDeleted
default:
return note.folderId === currentFolder.value
// 自定义文件夹中不显示已删除的便签
return note.folderId === currentFolder.value && !note.isDeleted
}
})
})
// Filter and sort notes
const filteredAndSortedNotes = computed(() => {
return filteredNotes.value
.filter(note => note.title.toLowerCase().includes(searchQuery.value.toLowerCase()) || note.content.toLowerCase().includes(searchQuery.value.toLowerCase()))
.sort((a, b) => {
// 置顶的便签排在前面
if (a.isTop && !b.isTop) return -1
if (!a.isTop && b.isTop) return 1
return [...filteredNotes.value].sort((a, b) => {
// 置顶的便签排在前面
if (a.isTop && !b.isTop) return -1
if (!a.isTop && b.isTop) return 1
if (sortBy.value === 'title') {
// 根据排序方式排序
switch (sortBy.value) {
case 'title':
return a.title.localeCompare(b.title)
} else if (sortBy.value === 'starred') {
case 'starred':
// 加星的便签排在前面
return (b.isStarred ? 1 : 0) - (a.isStarred ? 1 : 0)
} else {
case 'date':
default:
// 按更新时间倒序排列(最新的在前)
return new Date(b.updatedAt).getTime() - new Date(a.updatedAt).getTime()
}
})
}
})
})
// 计算头部标题
@@ -158,10 +159,15 @@ const headerTitle = computed(() => {
case 'trash':
return '回收站'
default:
return '文件夹'
return '全部便签'
}
})
// 计算全部便签数量(未删除的)
const allNotesCount = computed(() => {
return store.notes.filter(note => !note.isDeleted).length
})
const handleNotePress = noteId => {
// 导航到编辑页面的逻辑将在路由中处理
window.location.hash = `#/editor/${noteId}`
@@ -187,21 +193,44 @@ const handleDeleteNote = noteId => {
const handleStarToggle = async noteId => {
const note = store.notes.find(n => n.id === noteId)
if (note) {
await store.updateNote(noteId, { isStarred: !note.isStarred })
try {
await store.updateNote(noteId, { isStarred: !note.isStarred })
console.log(`Note ${noteId} starred status updated`)
} catch (error) {
console.error('Failed to update note star status:', error)
}
}
}
const handleTopToggle = async noteId => {
const note = store.notes.find(n => n.id === noteId)
if (note) {
await store.updateNote(noteId, { isTop: !note.isTop })
try {
await store.updateNote(noteId, { isTop: !note.isTop })
console.log(`Note ${noteId} top status updated`)
} catch (error) {
console.error('Failed to update note top status:', error)
}
}
}
const confirmDeleteNote = () => {
const confirmDeleteNote = async () => {
if (noteToDelete.value) {
store.deleteNote(noteToDelete.value)
noteToDelete.value = null
try {
// 检查当前是否在回收站中
if (currentFolder.value === 'trash') {
// 在回收站中删除便签,彻底删除
await store.permanentlyDeleteNote(noteToDelete.value)
console.log(`Note ${noteToDelete.value} permanently deleted`)
} else {
// 不在回收站中,将便签移至回收站
await store.moveToTrash(noteToDelete.value)
console.log(`Note ${noteToDelete.value} moved to trash`)
}
noteToDelete.value = null
} catch (error) {
console.error('Failed to delete note:', error)
}
}
showAlert.value = false
}
@@ -215,6 +244,21 @@ const handleSort = () => {
console.log('Sort by:', sortOptions[nextIndex])
}
const handleAllNotesClick = () => {
setCurrentFolder('all')
setIsFolderExpanded(false)
}
const handleStarredNotesClick = () => {
setCurrentFolder('starred')
setIsFolderExpanded(false)
}
const handleTrashNotesClick = () => {
setCurrentFolder('trash')
setIsFolderExpanded(false)
}
const handleFolderPress = () => {
// 导航到文件夹页面的逻辑将在路由中处理
window.location.hash = '#/folders'
@@ -228,29 +272,77 @@ const handleSettingsPress = () => {
const handleFolderToggle = () => {
// 在实际应用中,这里会触发文件夹列表的展开/收起
isFolderExpanded.value = !isFolderExpanded.value
console.log('Folder expanded:', !isFolderExpanded.value)
}
const handleSearch = query => {
// 搜索功能已在computed属性filteredAndSortedNotes中实现
console.log('Search for:', query)
// 可以在这里添加搜索统计或其它功能
if (query && query.length > 0) {
console.log(`Found ${filteredAndSortedNotes.value.length} matching notes`)
}
}
const handleClearSearch = () => {
// 清除搜索已在v-model中处理
console.log('Search cleared')
// 清除搜索后可以重置一些状态
setSearchQuery('')
}
const handleSearchFocus = () => {
console.log('Search bar focused')
// 可以在这里添加获得焦点时的特殊处理
}
const handleSearchBlur = () => {
console.log('Search bar blurred')
// 可以在这里添加失去焦点时的特殊处理
}
// 防抖搜索函数,避免频繁触发搜索
const debounceSearch = (func, delay) => {
let timeoutId
return function (...args) {
clearTimeout(timeoutId)
timeoutId = setTimeout(() => func.apply(this, args), delay)
}
}
// 防抖搜索处理
const debouncedHandleSearch = debounceSearch((query) => {
handleSearch(query)
}, 300)
// 改进的日期格式化函数
const formatDate = dateString => {
return new Date(dateString).toLocaleDateString()
const date = new Date(dateString)
const now = new Date()
// 计算日期差
const diffTime = now - date
const diffDays = Math.floor(diffTime / (1000 * 60 * 60 * 24))
// 今天的便签显示时间
if (diffDays === 0) {
return `${date.getHours().toString().padStart(2, '0')}:${date.getMinutes().toString().padStart(2, '0')}`
}
// 昨天的便签显示"昨天"
if (diffDays === 1) {
return '昨天'
}
// 一周内的便签显示星期几
if (diffDays < 7) {
const weekdays = ['周日', '周一', '周二', '周三', '周四', '周五', '周六']
return weekdays[date.getDay()]
}
// 超过一周的便签显示月日
return `${date.getMonth() + 1}/${date.getDate()}`
}
const setCurrentFolder = folder => {
@@ -278,4 +370,39 @@ const notes = computed(() => store.notes)
background: url(/assets/icons/drawable-xxhdpi/note_background.png);
background-size: cover;
}
</style>
.folder-list {
position: absolute;
top: 50px;
left: 10%;
right: 10%;
z-index: 1000;
background-color: var(--background-card);
border-radius: 8px;
box-shadow: 0 2px 4px var(--shadow);
border: 1px solid #f0ece7;
overflow: hidden;
}
.folder-overlay {
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
background-color: transparent;
z-index: 99;
}
.search-container {
padding: 0.8rem 0.5rem;
}
.notes-container {
flex: 1;
}
.note-item {
margin: 0.4rem 0;
}
</style>