note_repository.go 6.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212
  1. package repository
  2. import (
  3. "fmt"
  4. "os"
  5. "path/filepath"
  6. "gorm.io/driver/sqlite"
  7. "gorm.io/gorm"
  8. "note-manager/model"
  9. )
  10. // NoteRepository 笔记数据访问层
  11. type NoteRepository struct {
  12. db *gorm.DB
  13. }
  14. // NewNoteRepository 创建数据仓库实例,初始化数据库
  15. func NewNoteRepository(dbPath string) (*NoteRepository, error) {
  16. // 确保数据库目录存在
  17. dir := filepath.Dir(dbPath)
  18. if err := os.MkdirAll(dir, 0755); err != nil {
  19. return nil, fmt.Errorf("创建数据库目录失败: %w", err)
  20. }
  21. db, err := gorm.Open(sqlite.Open(dbPath), &gorm.Config{})
  22. if err != nil {
  23. return nil, fmt.Errorf("连接数据库失败: %w", err)
  24. }
  25. // 自动迁移表结构
  26. if err := db.AutoMigrate(&model.Note{}); err != nil {
  27. return nil, fmt.Errorf("数据库迁移失败: %w", err)
  28. }
  29. return &NoteRepository{db: db}, nil
  30. }
  31. // Create 创建笔记
  32. func (r *NoteRepository) Create(note *model.Note) error {
  33. return r.db.Select("Title", "Content", "Category", "Tags", "Password", "IsPinned", "IsFavorite", "IsPublic", "ParentID", "IsFolder", "SortOrder").Create(note).Error
  34. }
  35. // GetByID 根据 ID 获取笔记
  36. func (r *NoteRepository) GetByID(id uint) (*model.Note, error) {
  37. var note model.Note
  38. err := r.db.First(&note, id).Error
  39. if err != nil {
  40. return nil, err
  41. }
  42. return &note, nil
  43. }
  44. // Update 更新笔记
  45. func (r *NoteRepository) Update(note *model.Note) error {
  46. return r.db.Save(note).Error
  47. }
  48. // Delete 删除笔记
  49. func (r *NoteRepository) Delete(id uint) error {
  50. return r.db.Delete(&model.Note{}, id).Error
  51. }
  52. // ListQuery 列表查询参数
  53. type ListQuery struct {
  54. Page int
  55. PageSize int
  56. Category string
  57. Tag string
  58. Pinned *bool
  59. Favorite *bool
  60. ParentID *uint // 父目录 ID,nil 表示所有
  61. }
  62. // List 获取笔记列表(分页)
  63. func (r *NoteRepository) List(q ListQuery) ([]model.NoteListItem, int64, error) {
  64. var items []model.NoteListItem
  65. var total int64
  66. query := r.db.Model(&model.Note{})
  67. if q.Category != "" {
  68. query = query.Where("category = ?", q.Category)
  69. }
  70. if q.Tag != "" {
  71. query = query.Where("tags LIKE ?", fmt.Sprintf("%%\"%s\"%%", q.Tag))
  72. }
  73. if q.Pinned != nil {
  74. query = query.Where("is_pinned = ?", *q.Pinned)
  75. }
  76. if q.Favorite != nil {
  77. query = query.Where("is_favorite = ?", *q.Favorite)
  78. }
  79. if q.ParentID != nil {
  80. query = query.Where("parent_id = ?", *q.ParentID)
  81. }
  82. if err := query.Count(&total).Error; err != nil {
  83. return nil, 0, err
  84. }
  85. offset := (q.Page - 1) * q.PageSize
  86. err := query.Select("id, title, category, tags, is_pinned, is_favorite, parent_id, is_folder, sort_order, created_at, updated_at").
  87. Order("is_folder DESC, sort_order ASC, updated_at DESC").
  88. Offset(offset).
  89. Limit(q.PageSize).
  90. Find(&items).Error
  91. return items, total, err
  92. }
  93. // GetAllTree 获取所有笔记的树形结构
  94. func (r *NoteRepository) GetAllTree() ([]model.NoteListItem, error) {
  95. var items []model.NoteListItem
  96. err := r.db.Model(&model.Note{}).
  97. Select("id, title, category, tags, CASE WHEN password != '' THEN 1 ELSE 0 END as has_password, is_pinned, is_favorite, is_public, parent_id, is_folder, sort_order, created_at, updated_at").
  98. Order("is_folder DESC, sort_order ASC, title ASC").
  99. Find(&items).Error
  100. return items, err
  101. }
  102. // GetPublicTree 获取公开可见的树形结构(显示所有目录和笔记,访问时再验证密码)
  103. func (r *NoteRepository) GetPublicTree() ([]model.NoteListItem, error) {
  104. var items []model.NoteListItem
  105. err := r.db.Model(&model.Note{}).
  106. Select("id, title, category, tags, CASE WHEN password != '' THEN 1 ELSE 0 END as has_password, is_pinned, is_favorite, is_public, parent_id, is_folder, sort_order, created_at, updated_at").
  107. Order("is_folder DESC, sort_order ASC, title ASC").
  108. Find(&items).Error
  109. return items, err
  110. }
  111. // GetByParentID 获取指定父目录下的所有项目
  112. func (r *NoteRepository) GetByParentID(parentID uint) ([]model.NoteListItem, error) {
  113. var items []model.NoteListItem
  114. err := r.db.Model(&model.Note{}).
  115. Where("parent_id = ?", parentID).
  116. Select("id, title, category, tags, is_pinned, is_favorite, is_public, parent_id, is_folder, sort_order, created_at, updated_at").
  117. Order("is_folder DESC, sort_order ASC, title ASC").
  118. Find(&items).Error
  119. return items, err
  120. }
  121. // GetChildrenCount 获取子项数量
  122. func (r *NoteRepository) GetChildrenCount(parentID uint) (int64, error) {
  123. var count int64
  124. err := r.db.Model(&model.Note{}).Where("parent_id = ?", parentID).Count(&count).Error
  125. return count, err
  126. }
  127. // DeleteWithChildren 删除目录及其下所有内容
  128. func (r *NoteRepository) DeleteWithChildren(id uint) error {
  129. // 先删除所有子项
  130. if err := r.db.Where("parent_id = ?", id).Delete(&model.Note{}).Error; err != nil {
  131. return err
  132. }
  133. // 再删除自己
  134. return r.db.Delete(&model.Note{}, id).Error
  135. }
  136. // Search 搜索笔记(按标题和内容)
  137. func (r *NoteRepository) Search(keyword string, page, pageSize int) ([]model.NoteListItem, int64, error) {
  138. var items []model.NoteListItem
  139. var total int64
  140. like := "%" + keyword + "%"
  141. query := r.db.Model(&model.Note{}).Where("(title LIKE ? OR content LIKE ?) AND is_folder = ?", like, like, false)
  142. if err := query.Count(&total).Error; err != nil {
  143. return nil, 0, err
  144. }
  145. offset := (page - 1) * pageSize
  146. err := query.Select("id, title, category, tags, is_pinned, is_favorite, parent_id, is_folder, sort_order, created_at, updated_at").
  147. Order("is_pinned DESC, updated_at DESC").
  148. Offset(offset).
  149. Limit(pageSize).
  150. Find(&items).Error
  151. return items, total, err
  152. }
  153. // GetCategories 获取所有分类
  154. func (r *NoteRepository) GetCategories() ([]string, error) {
  155. var categories []string
  156. err := r.db.Model(&model.Note{}).
  157. Distinct("category").
  158. Where("category != '' AND is_folder = ?", false).
  159. Pluck("category", &categories).Error
  160. return categories, err
  161. }
  162. // GetTags 获取所有标签
  163. func (r *NoteRepository) GetTags() ([]string, error) {
  164. var tagsJSON []string
  165. err := r.db.Model(&model.Note{}).
  166. Where("tags != '' AND tags IS NOT NULL AND is_folder = ?", false).
  167. Pluck("tags", &tagsJSON).Error
  168. if err != nil {
  169. return nil, err
  170. }
  171. // 去重
  172. seen := make(map[string]bool)
  173. var result []string
  174. for _, t := range tagsJSON {
  175. if !seen[t] {
  176. seen[t] = true
  177. result = append(result, t)
  178. }
  179. }
  180. return result, nil
  181. }