新增 文件夹管理功能:实现文件夹选择模式、添加、编辑和删除功能

This commit is contained in:
yuantao
2025-10-23 18:35:23 +08:00
parent ff4adcd949
commit 2eb7eb8618
6 changed files with 1880 additions and 1024 deletions

View File

@@ -1,336 +1,383 @@
import { defineStore } from 'pinia'
import * as storage from '../utils/indexedDBStorage'
import { getCurrentDateTime, getPastDate } from '../utils/dateUtils'
/**
* 应用状态管理Store
* 使用Pinia进行状态管理包含便签、文件夹和设置数据
*/
export const useAppStore = defineStore('app', {
/**
* 状态定义
* 包含应用的核心数据:便签列表、文件夹列表和设置
*/
state: () => ({
notes: [], // 便签列表
folders: [], // 文件夹列表
settings: { cloudSync: false, darkMode: false }, // 应用设置
}),
/**
* 计算属性
* 基于状态派生的计算值
*/
getters: {
/**
* 计算加星便签数量
* @param {Object} state - 当前状态对象
* @returns {number} 加星便签的数量
*/
starredNotesCount: state => {
return state.notes.filter(note => note.isStarred).length
},
/**
* 计算所有便签数量
* @param {Object} state - 当前状态对象
* @returns {number} 所有便签的数量
*/
allNotesCount: state => {
return state.notes.length
},
},
/**
* 状态变更操作
* 包含所有修改状态的方法
*/
actions: {
/**
* 初始化数据
* 从Storage加载便签、文件夹和设置数据
* 如果没有数据则加载预设的mock数据
* @returns {Promise<void>}
*/
async loadData() {
try {
// 从Storage加载数据
const loadedNotes = await storage.getNotes()
const loadedFolders = await storage.getFolders()
const loadedSettings = await storage.getSettings()
// 如果没有数据则加载mock数据
if (loadedNotes.length === 0 && loadedFolders.length === 0) {
this.loadMockData()
} else {
// 否则使用加载的数据
this.notes = loadedNotes
this.folders = loadedFolders
this.settings = loadedSettings
}
} catch (error) {
console.error('Error loading data:', error)
}
},
/**
* 加载预设的mock数据
* 用于开发和演示目的,提供示例便签、文件夹和设置
* @returns {Promise<void>}
*/
async loadMockData() {
// Mock notes - 使用固定的日期值以避免每次运行时变化
const fixedCurrentDate = '2025-10-12T10:00:00.000Z';
// 预设的便签示例数据 - 仅保留一条关于应用功能介绍和示例的便签
const mockNotes = [
{
id: '1',
title: '欢迎使用锤子便签',
content: '<p>这是一个功能强大的便签应用,您可以在这里记录您的想法、待办事项等。</p><br><h2>功能介绍</h2><p>1. 创建和编辑便签<br>2. 为便签加星和置顶<br>3. 将便签分类到文件夹<br>4. 搜索便签内容<br>5. 回收站功能</p><br><h2>编辑器功能演示</h2><br><h2>标题格式</h2><p>点击标题按钮可创建居中的标题</p><br><h2>待办事项</h2><div class="todo-container"><div class="todo-icon"></div><div contenteditable="true" class="todo-content">这是一个待办事项</div></div><div class="todo-container"><div class="todo-icon completed"></div><div contenteditable="true" class="todo-content" style="color: var(--text-tertiary); text-decoration: line-through;">这是一个已完成的待办事项</div></div><br><h2>列表格式</h2><ul><li>无序列表项1</li><li>无序列表项2</li></ul><br><h2>文本格式</h2><p><strong>加粗文本</strong></p><br><h2>引用格式</h2><div class="quote-container"><div class="quote-icon"></div><div class="quote-content">这是一段引用文本<br>可以用来引用他人的话语</div></div><br><h2>图片</h2><p>点击图片按钮可以插入图片,长按图片可以拖拽排序</p>',
createdAt: fixedCurrentDate,
updatedAt: fixedCurrentDate,
folderId: null,
isStarred: true, // 加星便签
isTop: true, // 置顶便签
hasImage: true, // 包含图片
isDeleted: false, // 未删除
deletedAt: null,
}
]
// Mock folders - 使用固定的日期值
// 预设的文件夹示例数据
const mockFolders = [
{
id: 'folder1',
name: '工作',
createdAt: '2025-10-12T10:00:00.000Z',
},
{
id: 'folder2',
name: '个人',
createdAt: '2025-10-12T10:00:00.000Z',
},
{
id: 'folder3',
name: '学习',
createdAt: '2025-10-12T10:00:00.000Z',
},
]
// Mock settings
// 预设的设置示例数据
const mockSettings = {
cloudSync: false, // 云同步关闭
darkMode: false, // 深色模式关闭
}
// 更新store状态
this.notes = mockNotes
this.folders = mockFolders
this.settings = mockSettings
// 保存到Storage
await storage.saveNotes(mockNotes)
await storage.saveFolders(mockFolders)
await storage.saveSettings(mockSettings)
},
/**
* 保存便签数据到Storage
* @returns {Promise<void>}
*/
async saveNotes() {
try {
await storage.saveNotes(this.notes)
} catch (error) {
console.error('Error saving notes:', error)
}
},
/**
* 保存文件夹数据到Storage
* @returns {Promise<void>}
*/
async saveFolders() {
try {
await storage.saveFolders(this.folders)
} catch (error) {
console.error('Error saving folders:', error)
}
},
/**
* 保存设置数据到Storage
* @returns {Promise<void>}
*/
async saveSettings() {
try {
await storage.saveSettings(this.settings)
} catch (error) {
console.error('Error saving settings:', error)
}
},
/**
* 便签操作函数
*/
/**
* 添加新便签
* @param {Object} note - 便签对象
* @returns {Promise<Object>} 新创建的便签对象
*/
async addNote(note) {
try {
const newNote = await storage.addNote(note)
this.notes.push(newNote)
return newNote
} catch (error) {
console.error('Error adding note:', error)
throw error
}
},
/**
* 更新便签
* @param {string} id - 便签ID
* @param {Object} updates - 要更新的属性对象
* @returns {Promise<Object>} 更新后的便签对象
*/
async updateNote(id, updates) {
try {
const updatedNote = await storage.updateNote(id, updates)
if (updatedNote) {
const index = this.notes.findIndex(note => note.id === id)
if (index !== -1) {
this.notes[index] = updatedNote
}
}
return updatedNote
} catch (error) {
console.error('Error updating note:', error)
throw error
}
},
/**
* 删除便签
* @param {string} id - 要删除的便签ID
* @returns {Promise<boolean>} 删除成功返回true失败返回false
*/
async deleteNote(id) {
try {
const result = await storage.deleteNote(id)
if (result) {
this.notes = this.notes.filter(note => note.id !== id)
}
return result
} catch (error) {
console.error('Error deleting note:', error)
throw error
}
},
/**
* 将便签移至回收站
* 将便签标记为已删除状态,并记录删除时间
* @param {string} id - 便签ID
* @returns {Promise<Object>} 更新后的便签对象
*/
async moveToTrash(id) {
try {
const updatedNote = await storage.updateNote(id, { isDeleted: true, deletedAt: getCurrentDateTime() })
if (updatedNote) {
const index = this.notes.findIndex(note => note.id === id)
if (index !== -1) {
this.notes[index] = updatedNote
}
}
return updatedNote
} catch (error) {
console.error('Error moving note to trash:', error)
throw error
}
},
/**
* 永久删除便签
* 从便签列表中彻底移除便签
* @param {string} id - 便签ID
* @returns {Promise<boolean>} 删除成功返回true失败返回false
*/
async permanentlyDeleteNote(id) {
try {
const result = await storage.deleteNote(id)
if (result) {
this.notes = this.notes.filter(note => note.id !== id)
}
return result
} catch (error) {
console.error('Error permanently deleting note:', error)
throw error
}
},
/**
* 文件夹操作函数
*/
/**
* 添加新文件夹
* @param {Object} folder - 文件夹对象
* @returns {Promise<Object>} 新创建的文件夹对象
*/
async addFolder(folder) {
try {
const newFolder = await storage.addFolder(folder)
this.folders.push(newFolder)
return newFolder
} catch (error) {
console.error('Error adding folder:', error)
throw error
}
},
/**
* 设置操作函数
*/
/**
* 更新设置
* @param {Object} newSettings - 新的设置对象
* @returns {Promise<void>}
*/
async updateSettings(newSettings) {
try {
const updatedSettings = { ...this.settings, ...newSettings }
this.settings = updatedSettings
await storage.saveSettings(updatedSettings)
} catch (error) {
console.error('Error updating settings:', error)
throw error
}
},
/**
* 切换云同步设置
* 开启或关闭云同步功能
* @returns {Promise<void>}
*/
async toggleCloudSync() {
await this.updateSettings({ cloudSync: !this.settings.cloudSync })
},
/**
* 切换深色模式设置
* 开启或关闭深色模式
* @returns {Promise<void>}
*/
async toggleDarkMode() {
await this.updateSettings({ darkMode: !this.settings.darkMode })
},
},
})
import { defineStore } from 'pinia'
import * as storage from '../utils/indexedDBStorage'
import { getCurrentDateTime, getPastDate } from '../utils/dateUtils'
/**
* 应用状态管理Store
* 使用Pinia进行状态管理包含便签、文件夹和设置数据
*/
export const useAppStore = defineStore('app', {
/**
* 状态定义
* 包含应用的核心数据:便签列表、文件夹列表和设置
*/
state: () => ({
notes: [], // 便签列表
folders: [], // 文件夹列表
settings: { cloudSync: false, darkMode: false }, // 应用设置
}),
/**
* 计算属性
* 基于状态派生的计算值
*/
getters: {
/**
* 计算加星便签数量
* @param {Object} state - 当前状态对象
* @returns {number} 加星便签的数量
*/
starredNotesCount: state => {
return state.notes.filter(note => note.isStarred).length
},
/**
* 计算所有便签数量
* @param {Object} state - 当前状态对象
* @returns {number} 所有便签的数量
*/
allNotesCount: state => {
return state.notes.length
},
},
/**
* 状态变更操作
* 包含所有修改状态的方法
*/
actions: {
/**
* 初始化数据
* 从Storage加载便签、文件夹和设置数据
* 如果没有数据则加载预设的mock数据
* @returns {Promise<void>}
*/
async loadData() {
try {
// 从Storage加载数据
const loadedNotes = await storage.getNotes()
const loadedFolders = await storage.getFolders()
const loadedSettings = await storage.getSettings()
// 如果没有数据则加载mock数据
if (loadedNotes.length === 0 && loadedFolders.length === 0) {
this.loadMockData()
} else {
// 否则使用加载的数据
this.notes = loadedNotes
this.folders = loadedFolders
this.settings = loadedSettings
}
} catch (error) {
console.error('Error loading data:', error)
}
},
/**
* 加载预设的mock数据
* 用于开发和演示目的,提供示例便签、文件夹和设置
* @returns {Promise<void>}
*/
async loadMockData() {
// Mock notes - 使用固定的日期值以避免每次运行时变化
const fixedCurrentDate = '2025-10-12T10:00:00.000Z';
// 预设的便签示例数据 - 仅保留一条关于应用功能介绍和示例的便签
const mockNotes = [
{
id: '1',
title: '欢迎使用锤子便签',
content: '<p>这是一个功能强大的便签应用,您可以在这里记录您的想法、待办事项等。</p><br><h2>功能介绍</h2><p>1. 创建和编辑便签<br>2. 为便签加星和置顶<br>3. 将便签分类到文件夹<br>4. 搜索便签内容<br>5. 回收站功能</p><br><h2>编辑器功能演示</h2><br><h2>标题格式</h2><p>点击标题按钮可创建居中的标题</p><br><h2>待办事项</h2><div class="todo-container"><div class="todo-icon"></div><div contenteditable="true" class="todo-content">这是一个待办事项</div></div><div class="todo-container"><div class="todo-icon completed"></div><div contenteditable="true" class="todo-content" style="color: var(--text-tertiary); text-decoration: line-through;">这是一个已完成的待办事项</div></div><br><h2>列表格式</h2><ul><li>无序列表项1</li><li>无序列表项2</li></ul><br><h2>文本格式</h2><p><strong>加粗文本</strong></p><br><h2>引用格式</h2><div class="quote-container"><div class="quote-icon"></div><div class="quote-content">这是一段引用文本<br>可以用来引用他人的话语</div></div><br><h2>图片</h2><p>点击图片按钮可以插入图片,长按图片可以拖拽排序</p>',
createdAt: fixedCurrentDate,
updatedAt: fixedCurrentDate,
folderId: null,
isStarred: true, // 加星便签
isTop: true, // 置顶便签
hasImage: true, // 包含图片
isDeleted: false, // 未删除
deletedAt: null,
}
]
// Mock folders - 使用固定的日期值
// 预设的文件夹示例数据
const mockFolders = [
{
id: 'folder1',
name: '工作',
createdAt: '2025-10-12T10:00:00.000Z',
},
{
id: 'folder2',
name: '个人',
createdAt: '2025-10-12T10:00:00.000Z',
},
{
id: 'folder3',
name: '学习',
createdAt: '2025-10-12T10:00:00.000Z',
},
]
// Mock settings
// 预设的设置示例数据
const mockSettings = {
cloudSync: false, // 云同步关闭
darkMode: false, // 深色模式关闭
}
// 更新store状态
this.notes = mockNotes
this.folders = mockFolders
this.settings = mockSettings
// 保存到Storage
await storage.saveNotes(mockNotes)
await storage.saveFolders(mockFolders)
await storage.saveSettings(mockSettings)
},
/**
* 保存便签数据到Storage
* @returns {Promise<void>}
*/
async saveNotes() {
try {
await storage.saveNotes(this.notes)
} catch (error) {
console.error('Error saving notes:', error)
}
},
/**
* 保存文件夹数据到Storage
* @returns {Promise<void>}
*/
async saveFolders() {
try {
await storage.saveFolders(this.folders)
} catch (error) {
console.error('Error saving folders:', error)
}
},
/**
* 保存设置数据到Storage
* @returns {Promise<void>}
*/
async saveSettings() {
try {
await storage.saveSettings(this.settings)
} catch (error) {
console.error('Error saving settings:', error)
}
},
/**
* 便签操作函数
*/
/**
* 添加新便签
* @param {Object} note - 便签对象
* @returns {Promise<Object>} 新创建的便签对象
*/
async addNote(note) {
try {
const newNote = await storage.addNote(note)
this.notes.push(newNote)
return newNote
} catch (error) {
console.error('Error adding note:', error)
throw error
}
},
/**
* 更新便签
* @param {string} id - 便签ID
* @param {Object} updates - 要更新的属性对象
* @returns {Promise<Object>} 更新后的便签对象
*/
async updateNote(id, updates) {
try {
const updatedNote = await storage.updateNote(id, updates)
if (updatedNote) {
const index = this.notes.findIndex(note => note.id === id)
if (index !== -1) {
this.notes[index] = updatedNote
}
}
return updatedNote
} catch (error) {
console.error('Error updating note:', error)
throw error
}
},
/**
* 删除便签
* @param {string} id - 要删除的便签ID
* @returns {Promise<boolean>} 删除成功返回true失败返回false
*/
async deleteNote(id) {
try {
const result = await storage.deleteNote(id)
if (result) {
this.notes = this.notes.filter(note => note.id !== id)
}
return result
} catch (error) {
console.error('Error deleting note:', error)
throw error
}
},
/**
* 将便签移至回收站
* 将便签标记为已删除状态,并记录删除时间
* @param {string} id - 便签ID
* @returns {Promise<Object>} 更新后的便签对象
*/
async moveToTrash(id) {
try {
const updatedNote = await storage.updateNote(id, { isDeleted: true, deletedAt: getCurrentDateTime() })
if (updatedNote) {
const index = this.notes.findIndex(note => note.id === id)
if (index !== -1) {
this.notes[index] = updatedNote
}
}
return updatedNote
} catch (error) {
console.error('Error moving note to trash:', error)
throw error
}
},
/**
* 永久删除便签
* 从便签列表中彻底移除便签
* @param {string} id - 便签ID
* @returns {Promise<boolean>} 删除成功返回true失败返回false
*/
async permanentlyDeleteNote(id) {
try {
const result = await storage.deleteNote(id)
if (result) {
this.notes = this.notes.filter(note => note.id !== id)
}
return result
} catch (error) {
console.error('Error permanently deleting note:', error)
throw error
}
},
/**
* 文件夹操作函数
*/
/**
* 添加新文件夹
* @param {Object} folder - 文件夹对象
* @returns {Promise<Object>} 新创建的文件夹对象
*/
async addFolder(folder) {
try {
const newFolder = await storage.addFolder(folder)
this.folders.push(newFolder)
return newFolder
} catch (error) {
console.error('Error adding folder:', error)
throw error
}
},
/**
* 更新文件夹
* @param {string} id - 文件夹ID
* @param {Object} updates - 要更新的属性对象
* @returns {Promise<Object>} 更新后的文件夹对象
*/
async updateFolder(id, updates) {
try {
const updatedFolder = await storage.updateFolder(id, updates)
if (updatedFolder) {
const index = this.folders.findIndex(folder => folder.id === id)
if (index !== -1) {
this.folders[index] = updatedFolder
}
}
return updatedFolder
} catch (error) {
console.error('Error updating folder:', error)
throw error
}
},
/**
* 删除文件夹
* @param {string} id - 要删除的文件夹ID
* @returns {Promise<boolean>} 删除成功返回true失败返回false
*/
async deleteFolder(id) {
try {
const result = await storage.deleteFolder(id)
if (result) {
// 将文件夹中的便签移回"全部便签"
const notesInFolder = this.notes.filter(note => note.folderId === id)
for (const note of notesInFolder) {
await this.updateNote(note.id, { folderId: null })
}
// 从文件夹列表中移除文件夹
this.folders = this.folders.filter(folder => folder.id !== id)
}
return result
} catch (error) {
console.error('Error deleting folder:', error)
throw error
}
},
/**
* 设置操作函数
*/
/**
* 更新设置
* @param {Object} newSettings - 新的设置对象
* @returns {Promise<void>}
*/
async updateSettings(newSettings) {
try {
const updatedSettings = { ...this.settings, ...newSettings }
this.settings = updatedSettings
await storage.saveSettings(updatedSettings)
} catch (error) {
console.error('Error updating settings:', error)
throw error
}
},
/**
* 切换云同步设置
* 开启或关闭云同步功能
* @returns {Promise<void>}
*/
async toggleCloudSync() {
await this.updateSettings({ cloudSync: !this.settings.cloudSync })
},
/**
* 切换深色模式设置
* 开启或关闭深色模式
* @returns {Promise<void>}
*/
async toggleDarkMode() {
await this.updateSettings({ darkMode: !this.settings.darkMode })
},
},
})