From 9f563f0ae997ce22f92c3f2ed392087279e2bca9 Mon Sep 17 00:00:00 2001 From: deepzz0 Date: Wed, 28 Apr 2021 11:57:37 +0800 Subject: [PATCH] chore: complete api --- cmd/blog/main.go | 4 +- pkg/cache/cache.go | 403 +++++++++++++++++++---------------- pkg/cache/store/mongodb.go | 115 ++++------ pkg/cache/store/store.go | 27 ++- pkg/core/blog/admin/admin.go | 117 +++++++++- pkg/core/blog/file/timer.go | 2 +- pkg/core/blog/page/be.go | 23 +- pkg/core/blog/page/fe.go | 2 +- 8 files changed, 409 insertions(+), 284 deletions(-) diff --git a/cmd/blog/main.go b/cmd/blog/main.go index 99757d0..5975163 100644 --- a/cmd/blog/main.go +++ b/cmd/blog/main.go @@ -49,10 +49,10 @@ func runHTTPServer(endRun chan bool) { root := filepath.Join(config.WorkDir, "assets") e.Static("/static", root) - // frontend pages - page.RegisterRoutes(e) // static files file.RegisterRoutes(e) + // frontend pages + page.RegisterRoutes(e) // unauthz api admin.RegisterRoutes(e) diff --git a/pkg/cache/cache.go b/pkg/cache/cache.go index f622c9c..6733059 100644 --- a/pkg/cache/cache.go +++ b/pkg/cache/cache.go @@ -71,8 +71,64 @@ type Cache struct { ArticlesMap map[string]*model.Article // slug:article } -// PageArticles 文章翻页 -func (c *Cache) PageArticles(page int, pageSize int) (prev, +// AddArticle 添加文章 +func (c *Cache) AddArticle(article *model.Article) error { + c.lock.Lock() + defer c.lock.Unlock() + + // store + err := c.InsertArticle(context.Background(), article) + if err != nil { + return err + } + // 是否是草稿 + if article.IsDraft { + return nil + } + // 正式发布文章 + c.refreshCache(article, false) + return nil +} + +// RepArticle 替换文章 +func (c *Cache) RepArticle(oldArticle, newArticle *model.Article) { + c.lock.Lock() + defer c.lock.Unlock() + + c.ArticlesMap[newArticle.Slug] = newArticle + render.GenerateExcerptMarkdown(newArticle) + if newArticle.ID < config.Conf.BlogApp.General.StartID { + return + } + if oldArticle != nil { // 移除旧文章 + c.refreshCache(oldArticle, true) + } + c.refreshCache(newArticle, false) +} + +// DelArticles 删除文章 +func (c *Cache) DelArticles(ids []int) error { + c.lock.Lock() + defer c.lock.Unlock() + + for _, id := range ids { + article, _ := c.FindArticleByID(id) + + // set delete + err := c.UpdateArticle(context.Background(), id, map[string]interface{}{ + "deleted_at": time.Now(), + }) + if err != nil { + return err + } + // drop from tags,series,archives + c.refreshCache(article, true) + } + return nil +} + +// PageArticleFE 文章翻页 +func (c *Cache) PageArticleFE(page int, pageSize int) (prev, next int, articles []*model.Article) { var l int @@ -106,114 +162,37 @@ func (c *Cache) PageArticles(page int, pageSize int) (prev, return } -// PageArticlesBE 后台文章分页 -// func (c *Cache) PageArticleBE(se int, kw string, draft, del bool, p, n int)(max int, artcs []*model.Article){ -// -// } +// PageArticleBE 后台文章分页 +func (c *Cache) PageArticleBE(se int, kw string, draft, del bool, p, + n int) ([]*model.Article, int) { -// DeleteArticles 删除文章 -func (c *Cache) DeleteArticles(ids []int) error { - c.lock.Lock() - defer c.lock.Unlock() - - for _, id := range ids { - article, idx := c.FindArticleByID(id) - // drop from linkedList - if article.Prev == nil && article.Next != nil { - article.Next.Prev = nil - } else if article.Prev != nil && article.Next == nil { - article.Prev.Next = nil - } else if article.Prev != nil && article.Next != nil { - article.Prev.Next = article.Next - article.Next.Prev = article.Prev - } - // drop from articles - c.Articles = append(c.Articles[:idx], c.Articles[idx+1:]...) - delete(c.ArticlesMap, article.Slug) - // set delete - err := c.UpdateArticle(context.Background(), id, map[string]interface{}{ - "deletetime": time.Now(), - }) - if err != nil { - return err - } - // drop from tags,series,archives - c.redelArticle(article) + search := store.SearchArticles{ + Page: p, + Limit: n, + Fields: make(map[string]interface{}), } - return nil -} - -// AddArticle 添加文章 -func (c *Cache) AddArticle(article *model.Article) error { - err := c.InsertArticle(context.Background(), article) + if draft { + search.Fields[store.SearchArticleDraft] = true + } else if del { + search.Fields[store.SearchArticleTrash] = true + } else { + search.Fields[store.SearchArticleDraft] = false + if se > 0 { + search.Fields[store.SearchArticleSerieID] = se + } + if kw != "" { + search.Fields[store.SearchArticleTitle] = kw + } + } + articles, count, err := c.LoadArticleList(context.Background(), search) if err != nil { - return err + return nil, 0 } - // 正式发布文章 - if !article.IsDraft { - defer render.GenerateExcerptMarkdown(article) - - c.ArticlesMap[article.Slug] = article - c.Articles = append([]*model.Article{article}, c.Articles...) - sort.Sort(c.Articles) - - article, idx := c.FindArticleByID(article.ID) - if idx == 0 && c.Articles[idx+1].ID >= - config.Conf.BlogApp.General.StartID { - article.Next = c.Articles[idx+1] - c.Articles[idx+1].Prev = article - } else if idx > 0 && c.Articles[idx-1].ID >= - config.Conf.BlogApp.General.StartID { - article.Prev = c.Articles[idx-1] - if c.Articles[idx-1].Next != nil { - article.Next = c.Articles[idx-1].Next - c.Articles[idx-1].Next.Prev = article - } - c.Articles[idx-1].Next = article - } - c.readdArticle(article, true) + max := count / n + if max%n > 0 { + max++ } - return nil -} - -// ReplaceArticle 替换文章 -func (c *Cache) ReplaceArticle(oldArticle, newArticle *model.Article) { - c.ArticlesMap[newArticle.Slug] = newArticle - render.GenerateExcerptMarkdown(newArticle) - if newArticle.ID < config.Conf.BlogApp.General.StartID { - return - } - if oldArticle != nil { - article, idx := c.FindArticleByID(oldArticle.ID) - if article.Prev == nil && article.Next != nil { - article.Next.Prev = nil - } else if article.Prev != nil && article.Next == nil { - article.Prev.Next = nil - } else if article.Prev != nil && article.Next != nil { - article.Prev.Next = article.Next - article.Next.Prev = article.Prev - } - c.Articles = append(Ei.Articles[:idx], Ei.Articles[idx+1:]...) - - c.redelArticle(article) - } - - c.Articles = append(c.Articles, newArticle) - sort.Sort(c.Articles) - _, idx := c.FindArticleByID(newArticle.ID) - if idx == 0 && c.Articles[idx+1].ID >= config.Conf.BlogApp.General.StartID { - newArticle.Next = c.Articles[idx+1] - c.Articles[idx+1].Prev = newArticle - } else if idx > 0 && c.Articles[idx-1].ID >= - config.Conf.BlogApp.General.StartID { - newArticle.Prev = Ei.Articles[idx-1] - if c.Articles[idx-1].Next != nil { - newArticle.Next = Ei.Articles[idx-1].Next - c.Articles[idx-1].Next.Prev = newArticle - } - c.Articles[idx-1].Next = newArticle - } - c.readdArticle(newArticle, true) + return articles, max } // FindArticleByID 通过ID查找文章 @@ -226,86 +205,59 @@ func (c *Cache) FindArticleByID(id int) (*model.Article, int) { return nil, -1 } -// loadOrInit 读取数据或初始化 -func (c *Cache) loadOrInit() error { - blogapp := config.Conf.BlogApp - // blogger - blogger := &model.Blogger{ - BlogName: strings.Title(blogapp.Account.Username), - SubTitle: "Rome was not built in one day.", - BeiAn: "蜀ICP备xxxxxxxx号-1", - BTitle: fmt.Sprintf("%s's Blog", strings.Title(blogapp.Account.Username)), - Copyright: `本站使用「署名 4.0 国际」创作共享协议,转载请注明作者及原网址。`, - } - created, err := c.LoadInsertBlogger(context.Background(), blogger) - if err != nil { - return err - } - c.Blogger = blogger - if created { // init articles: about blogroll - about := &model.Article{ - ID: 1, // 固定ID - Author: blogapp.Account.Username, - Title: "关于", - Slug: "about", - } - err = c.InsertArticle(context.Background(), about) - if err != nil { - return err - } - // 推送到 disqus - go internal.ThreadCreate(about, blogger.BTitle) - blogroll := &model.Article{ - ID: 2, // 固定ID - Author: blogapp.Account.Username, - Title: "友情链接", - Slug: "blogroll", - } - err = c.InsertArticle(context.Background(), blogroll) - if err != nil { - return err - } - } - // account - pwd := tools.EncryptPasswd(blogapp.Account.Password, - blogapp.Account.Password) +// refreshCache 刷新缓存 +func (c *Cache) refreshCache(article *model.Article, del bool) { + if del { + _, idx := c.FindArticleByID(article.ID) - account := &model.Account{ - Username: blogapp.Account.Username, - Password: pwd, + delete(c.ArticlesMap, article.Slug) + c.Articles = append(Ei.Articles[:idx], Ei.Articles[idx+1:]...) + // 从链表移除 + c.recalcLinkedList(article, true) + // 从tag、serie、archive移除 + c.redelArticle(article) } - _, err = c.LoadInsertAccount(context.Background(), account) - if err != nil { - return err - } - c.Account = account - // all articles - articles, err := c.LoadAllArticle(context.Background()) - if err != nil { - return err - } - for i, v := range articles { - // 渲染页面 - render.GenerateExcerptMarkdown(v) + // 添加文章 + defer render.GenerateExcerptMarkdown(article) - c.ArticlesMap[v.Slug] = v - // 分析文章 - if v.ID < blogapp.General.StartID { - continue + c.ArticlesMap[article.Slug] = article + c.Articles = append([]*model.Article{article}, c.Articles...) + sort.Sort(c.Articles) + // 从链表添加 + c.recalcLinkedList(article, false) + // 从tag、serie、archive添加 + c.readdArticle(article, true) +} + +// recalcLinkedList 重算文章链表 +func (c *Cache) recalcLinkedList(article *model.Article, del bool) { + // 删除操作 + if del { + if article.Prev == nil && article.Next != nil { + article.Next.Prev = nil + } else if article.Prev != nil && article.Next == nil { + article.Prev.Next = nil + } else if article.Prev != nil && article.Next != nil { + article.Prev.Next = article.Next + article.Next.Prev = article.Prev } - if i > 0 { - v.Prev = Ei.Articles[i-1] - } - if Ei.Articles[i+1].ID >= blogapp.General.StartID { - v.Next = Ei.Articles[i+1] - } - c.readdArticle(v, false) + return + } + // 添加操作 + _, idx := c.FindArticleByID(article.ID) + if idx == 0 && c.Articles[idx+1].ID >= + config.Conf.BlogApp.General.StartID { + article.Next = c.Articles[idx+1] + c.Articles[idx+1].Prev = article + } else if idx > 0 && c.Articles[idx-1].ID >= + config.Conf.BlogApp.General.StartID { + article.Prev = c.Articles[idx-1] + if c.Articles[idx-1].Next != nil { + article.Next = c.Articles[idx-1].Next + c.Articles[idx-1].Next.Prev = article + } + c.Articles[idx-1].Next = article } - Ei.Articles = articles - // 重建专题与归档 - PagesCh <- PageSeries - PagesCh <- PageArchive - return nil } // readdArticle 添加文章到tag、series、archive @@ -396,6 +348,97 @@ func (c *Cache) redelArticle(article *model.Article) { } } +// loadOrInit 读取数据或初始化 +func (c *Cache) loadOrInit() error { + blogapp := config.Conf.BlogApp + // blogger + blogger := &model.Blogger{ + BlogName: strings.Title(blogapp.Account.Username), + SubTitle: "Rome was not built in one day.", + BeiAn: "蜀ICP备xxxxxxxx号-1", + BTitle: fmt.Sprintf("%s's Blog", strings.Title(blogapp.Account.Username)), + Copyright: `本站使用「署名 4.0 国际」创作共享协议,转载请注明作者及原网址。`, + } + created, err := c.LoadInsertBlogger(context.Background(), blogger) + if err != nil { + return err + } + c.Blogger = blogger + if created { // init articles: about blogroll + about := &model.Article{ + ID: 1, // 固定ID + Author: blogapp.Account.Username, + Title: "关于", + Slug: "about", + UpdatedAt: time.Now(), + CreatedAt: time.Now(), + } + err = c.InsertArticle(context.Background(), about) + if err != nil { + return err + } + // 推送到 disqus + go internal.ThreadCreate(about, blogger.BTitle) + blogroll := &model.Article{ + ID: 2, // 固定ID + Author: blogapp.Account.Username, + Title: "友情链接", + Slug: "blogroll", + UpdatedAt: time.Now(), + CreatedAt: time.Now(), + } + err = c.InsertArticle(context.Background(), blogroll) + if err != nil { + return err + } + } + // account + pwd := tools.EncryptPasswd(blogapp.Account.Password, + blogapp.Account.Password) + + account := &model.Account{ + Username: blogapp.Account.Username, + Password: pwd, + } + _, err = c.LoadInsertAccount(context.Background(), account) + if err != nil { + return err + } + c.Account = account + // all articles + search := store.SearchArticles{ + Page: 1, + Limit: 9999, + Fields: map[string]interface{}{store.SearchArticleDraft: false}, + } + articles, _, err := c.LoadArticleList(context.Background(), search) + if err != nil { + return err + } + for i, v := range articles { + // 渲染页面 + render.GenerateExcerptMarkdown(v) + + c.ArticlesMap[v.Slug] = v + // 分析文章 + if v.ID < blogapp.General.StartID { + continue + } + if i > 0 { + v.Prev = Ei.Articles[i-1] + } + if Ei.Articles[i+1].ID >= blogapp.General.StartID { + v.Next = Ei.Articles[i+1] + } + c.readdArticle(v, false) + } + Ei.Articles = articles + // 重建专题与归档 + PagesCh <- PageSeries + PagesCh <- PageArchive + return nil +} + // regeneratePages 重新生成series,archive页面 func (c *Cache) regeneratePages() { for { diff --git a/pkg/cache/store/mongodb.go b/pkg/cache/store/mongodb.go index 4c7a6e3..d5a9999 100644 --- a/pkg/cache/store/mongodb.go +++ b/pkg/cache/store/mongodb.go @@ -233,16 +233,6 @@ func (db *mongodb) RemoveArticle(ctx context.Context, id int) error { return err } -// DeleteArticle 软删除文章,放入回收箱 -func (db *mongodb) DeleteArticle(ctx context.Context, id int) error { - collection := db.Database(mongoDBName).Collection(collectionArticle) - - filter := bson.M{"id": id} - update := bson.M{"$set": bson.M{"deletetime": time.Now()}} - _, err := collection.UpdateOne(ctx, filter, update) - return err -} - // CleanArticles 清理回收站文章 func (db *mongodb) CleanArticles(ctx context.Context) error { collection := db.Database(mongoDBName).Collection(collectionArticle) @@ -270,16 +260,6 @@ func (db *mongodb) UpdateArticle(ctx context.Context, id int, return err } -// RecoverArticle 恢复文章到草稿 -func (db *mongodb) RecoverArticle(ctx context.Context, id int) error { - collection := db.Database(mongoDBName).Collection(collectionArticle) - - filter := bson.M{"id": id} - update := bson.M{"$set": bson.M{"deletetime": time.Time{}, "isdraft": true}} - _, err := collection.UpdateOne(ctx, filter, update) - return err -} - // LoadArticle 查找文章 func (db *mongodb) LoadArticle(ctx context.Context, id int) (*model.Article, error) { collection := db.Database(mongoDBName).Collection(collectionArticle) @@ -295,76 +275,55 @@ func (db *mongodb) LoadArticle(ctx context.Context, id int) (*model.Article, err return article, err } -// LoadAllArticle 读取所有文章 -func (db *mongodb) LoadAllArticle(ctx context.Context) (model.SortedArticles, error) { +// LoadArticleList 获取文章列表 +func (db *mongodb) LoadArticleList(ctx context.Context, search SearchArticles) ( + model.SortedArticles, int, error) { collection := db.Database(mongoDBName).Collection(collectionArticle) - filter := bson.M{"isdraft": false, "deletetime": bson.M{"$eq": time.Time{}}} - cur, err := collection.Find(ctx, filter) - if err != nil { - return nil, err + filter := bson.M{} + for k, v := range search.Fields { + switch k { + case SearchArticleDraft: + if ok := v.(bool); ok { + filter["is_draft"] = true + } else { + filter["is_draft"] = false + filter["deleted_at"] = bson.M{"$eq": time.Time{}} + } + case SearchArticleTitle: + filter["title"] = bson.M{ + "$regex": v.(string), + "$options": "$i", + } + case SearchArticleSerieID: + filter["serie_id"] = v.(int) + case SearchArticleTrash: + filter["deleted_at"] = bson.M{"$nq": time.Time{}} + } + } + // search count + count, err := collection.CountDocuments(ctx, filter) + if err != nil { + return nil, 0, err + } + opts := options.Find().SetLimit(int64(search.Limit)). + SetSkip(int64((search.Page - 1) * search.Limit)). + SetSort(bson.M{"created_at": -1}) + cur, err := collection.Find(ctx, filter, opts) + if err != nil { + return nil, 0, err } - defer cur.Close(ctx) - var articles model.SortedArticles for cur.Next(ctx) { obj := model.Article{} err = cur.Decode(&obj) if err != nil { - return nil, err + return nil, 0, err } articles = append(articles, &obj) } sort.Sort(articles) - return articles, nil -} - -// LoadTrashArticles 读取回收箱 -func (db *mongodb) LoadTrashArticles(ctx context.Context) (model.SortedArticles, error) { - collection := db.Database(mongoDBName).Collection(collectionArticle) - - filter := bson.M{"deletetime": bson.M{"$ne": time.Time{}}} - cur, err := collection.Find(ctx, filter) - if err != nil { - return nil, err - } - defer cur.Close(ctx) - - var articles model.SortedArticles - for cur.Next(ctx) { - obj := model.Article{} - err = cur.Decode(&obj) - if err != nil { - return nil, err - } - articles = append(articles, &obj) - } - sort.Sort(articles) - return articles, nil -} - -// LoadDraftArticles 读取草稿箱 -func (db *mongodb) LoadDraftArticles(ctx context.Context) (model.SortedArticles, error) { - collection := db.Database(mongoDBName).Collection(collectionArticle) - - filter := bson.M{"isdraft": true} - cur, err := collection.Find(ctx, filter) - if err != nil { - return nil, err - } - defer cur.Close(ctx) - - var articles model.SortedArticles - for cur.Next(ctx) { - obj := model.Article{} - err = cur.Decode(&obj) - if err != nil { - return nil, err - } - articles = append(articles, &obj) - } - sort.Sort(articles) - return articles, nil + return articles, int(count), nil } // counter counter diff --git a/pkg/cache/store/store.go b/pkg/cache/store/store.go index c5f0b1e..2cf5746 100644 --- a/pkg/cache/store/store.go +++ b/pkg/cache/store/store.go @@ -15,6 +15,21 @@ var ( stores = make(map[string]Driver) ) +// search field +const ( + SearchArticleDraft = "draft" + SearchArticleTrash = "trash" + SearchArticleTitle = "title" + SearchArticleSerieID = "serieid" +) + +// SearchArticles 搜索字段 +type SearchArticles struct { + Page int // 第几页/1 + Limit int // 每页大小 + Fields map[string]interface{} // 字段:值 +} + // Store 存储后端 type Store interface { // LoadInsertBlogger 读取或创建博客 @@ -40,22 +55,14 @@ type Store interface { InsertArticle(ctx context.Context, article *model.Article) error // RemoveArticle 硬删除文章 RemoveArticle(ctx context.Context, id int) error - // DeleteArticle 软删除文章,放入回收箱 - DeleteArticle(ctx context.Context, id int) error // CleanArticles 清理回收站文章 CleanArticles(ctx context.Context) error // UpdateArticle 更新文章 UpdateArticle(ctx context.Context, id int, fields map[string]interface{}) error - // RecoverArticle 恢复文章到草稿 - RecoverArticle(ctx context.Context, id int) error // LoadArticle 查找文章 LoadArticle(ctx context.Context, id int) (*model.Article, error) - // LoadAllArticle 读取所有文章 - LoadAllArticle(ctx context.Context) (model.SortedArticles, error) - // LoadTrashArticles 读取回收箱 - LoadTrashArticles(ctx context.Context) (model.SortedArticles, error) - // LoadDraftArticles 读取草稿箱 - LoadDraftArticles(ctx context.Context) (model.SortedArticles, error) + // LoadArticleList 查找文章列表 + LoadArticleList(ctx context.Context, search SearchArticles) (model.SortedArticles, int, error) } // Driver 存储驱动 diff --git a/pkg/core/blog/admin/admin.go b/pkg/core/blog/admin/admin.go index d0588c8..c9586a8 100644 --- a/pkg/core/blog/admin/admin.go +++ b/pkg/core/blog/admin/admin.go @@ -7,6 +7,7 @@ import ( "fmt" "net/http" "strconv" + "strings" "time" "github.com/eiblog/eiblog/pkg/cache" @@ -37,6 +38,18 @@ func RegisterRoutesAuthz(group gin.IRoutes) { group.GET("/draft-delete", handleDraftDelete) group.POST("/api/account", handleAPIAccount) + group.POST("/api/blog", handleAPIBlogger) + group.POST("/api/password", handleAPIPassword) + group.POST("/api/post-delete", handleAPIPostDelete) + group.POST("/api/post-add", handleAPIPostCreate) + group.POST("/api/serie-delete", handleAPISerieDelete) + group.POST("/api/serie-add", handleAPISerieCreate) + group.POST("/api/serie-sort", handleAPISerieSort) + group.POST("/api/draft-delete", handleDraftDelete) + group.POST("/api/trash-delete", handleAPITrashDelete) + group.POST("/api/trash-recover", handleAPITrashRecover) + group.POST("/api/file-upload", handleAPIQiniuUpload) + group.POST("/api/file-delete", handleAPIQiniuDelete) } // handleAcctLogin 登录接口 @@ -67,7 +80,7 @@ func handleAcctLogin(c *gin.Context) { c.Redirect(http.StatusFound, "/admin/profile") } -// handleDraftDelete 删除草稿 +// handleDraftDelete 删除草稿, 物理删除 func handleDraftDelete(c *gin.Context) { id, err := strconv.Atoi(c.Query("cid")) if err != nil || id < 1 { @@ -189,7 +202,7 @@ func handleAPIPostDelete(c *gin.Context) { } ids = append(ids, id) } - err := cache.Ei.DeleteArticles(ids) + err := cache.Ei.DelArticles(ids) if err != nil { logrus.Error("handleAPIPostDelete.DeleteArticles: ", err) @@ -261,7 +274,7 @@ func handleAPIPostCreate(c *gin.Context) { if err != nil || cid < 1 { err = cache.Ei.AddArticle(article) if err != nil { - logrus.Error("handleAPIPostCreate.InsertArticle: ", err) + logrus.Error("handleAPIPostCreate.AddArticle: ", err) return } if !article.IsDraft { @@ -289,12 +302,12 @@ func handleAPIPostCreate(c *gin.Context) { artc.UpdatedAt = time.Now() } // 数据库更新 - err = cache.Ei.UpdateArticle(context.Background(), artc.ID, map[string]interface{}{ + err = cache.Ei.UpdateArticle(context.Background(), article.ID, map[string]interface{}{ "title": article.Title, "content": article.Content, "serie_id": article.SerieID, - "tags": article.Tags, "is_draft": article.IsDraft, + "tags": article.Tags, "updated_at": article.UpdatedAt, "created_at": article.CreatedAt, }) @@ -303,7 +316,7 @@ func handleAPIPostCreate(c *gin.Context) { return } if !artc.IsDraft { - cache.Ei.ReplaceArticle(artc, article) + cache.Ei.RepArticle(artc, article) // 异步执行,快 go func() { // elastic @@ -349,6 +362,12 @@ func handleAPISerieDelete(c *gin.Context) { responseNotice(c, NoticeSuccess, "删除成功", "") } +// handleAPISerieSort 专题排序 +func handleAPISerieSort(c *gin.Context) { + v := c.PostFormArray("mid[]") + logrus.Debug(v) +} + // handleAPISerieCreate 添加专题,如果专题有提交 mid 即更新专题 func handleAPISerieCreate(c *gin.Context) { name := c.PostForm("name") @@ -396,6 +415,92 @@ func handleAPISerieCreate(c *gin.Context) { responseNotice(c, NoticeSuccess, "操作成功", "") } +// handleAPITrashDelete 删除回收箱, 物理删除 +func handleAPITrashDelete(c *gin.Context) { + for _, v := range c.PostFormArray("mid[]") { + id, err := strconv.Atoi(v) + if err != nil || id < 1 { + responseNotice(c, NoticeNotice, "参数错误", "") + return + } + err = cache.Ei.RemoveArticle(context.Background(), id) + if err != nil { + responseNotice(c, NoticeNotice, err.Error(), "") + return + } + } + responseNotice(c, NoticeSuccess, "删除成功", "") +} + +// handleAPITrashRecover 恢复到草稿 +func handleAPITrashRecover(c *gin.Context) { + for _, v := range c.PostFormArray("mid[]") { + id, err := strconv.Atoi(v) + if err != nil || id < 1 { + responseNotice(c, NoticeNotice, "参数错误", "") + return + + } + err = cache.Ei.UpdateArticle(context.Background(), id, map[string]interface{}{ + "deleted_at": time.Time{}, + "is_draft": true, + }) + if err != nil { + responseNotice(c, NoticeNotice, err.Error(), "") + return + } + } + responseNotice(c, NoticeSuccess, "恢复成功", "") +} + +// handleAPIQiniuUpload 上传文件 +func handleAPIQiniuUpload(c *gin.Context) { + type Size interface { + Size() int64 + } + file, header, err := c.Request.FormFile("file") + if err != nil { + logrus.Error("handleAPIQiniuUpload.FormFile: ", err) + c.String(http.StatusBadRequest, err.Error()) + return + } + s, ok := file.(Size) + if !ok { + logrus.Error("assert failed") + c.String(http.StatusBadRequest, "false") + return + } + filename := strings.ToLower(header.Filename) + url, err := internal.QiniuUpload(filename, s.Size(), file) + if err != nil { + logrus.Error("handleAPIQiniuUpload.QiniuUpload: ", err) + c.String(http.StatusBadRequest, err.Error()) + return + } + typ := header.Header.Get("Content-Type") + c.JSON(http.StatusOK, gin.H{ + "title": filename, + "isImage": typ[:5] == "image", + "url": url, + "bytes": fmt.Sprintf("%dkb", s.Size()/1000), + }) +} + +// handleAPIQiniuDelete 删除文件 +func handleAPIQiniuDelete(c *gin.Context) { + defer c.String(http.StatusOK, "删掉了吗?鬼知道。。。") + + name := c.PostForm("title") + if name == "" { + logrus.Error("handleAPIQiniuDelete.PostForm: 参数错误") + return + } + err := internal.QiniuDelete(name) + if err != nil { + logrus.Error("handleAPIQiniuDelete.QiniuDelete: ", err) + } +} + // parseLocationDate 解析日期 func parseLocationDate(date string) time.Time { t, err := time.ParseInLocation("2006-01-02 15:04", date, time.Local) diff --git a/pkg/core/blog/file/timer.go b/pkg/core/blog/file/timer.go index 0dc0721..295ed6e 100644 --- a/pkg/core/blog/file/timer.go +++ b/pkg/core/blog/file/timer.go @@ -42,7 +42,7 @@ func timerFeed() { } now := time.Now() - _, _, articles := cache.Ei.PageArticles(1, 20) + _, _, articles := cache.Ei.PageArticleFE(1, 20) params := map[string]interface{}{ "Titile": cache.Ei.Blogger.BTitle, "SubTitle": cache.Ei.Blogger.SubTitle, diff --git a/pkg/core/blog/page/be.go b/pkg/core/blog/page/be.go index d627c5b..5d5f1fa 100644 --- a/pkg/core/blog/page/be.go +++ b/pkg/core/blog/page/be.go @@ -11,6 +11,7 @@ import ( "strconv" "github.com/eiblog/eiblog/pkg/cache" + "github.com/eiblog/eiblog/pkg/cache/store" "github.com/eiblog/eiblog/pkg/config" "github.com/eiblog/eiblog/pkg/core/blog" "github.com/eiblog/eiblog/pkg/model" @@ -23,7 +24,7 @@ import ( func baseBEParams(c *gin.Context) gin.H { return gin.H{ "Author": cache.Ei.Account.Username, - "Qiniu": config.Conf.BlogApp.Qiniu.Domain, + "Qiniu": config.Conf.BlogApp.Qiniu, } } @@ -103,8 +104,8 @@ func handleAdminPosts(c *gin.Context) { params["Serie"] = se params["KW"] = kw var max int - // TODO - // max, params["List"] = cache.Ei.PageListBack(se, kw, false, false, pg, setting.Conf.General.PageSize) + params["List"], max = cache.Ei.PageArticleBE(se, kw, false, false, + pg, config.Conf.BlogApp.General.PageSize) if pg < max { vals.Set("page", fmt.Sprint(pg+1)) params["Next"] = vals.Encode() @@ -171,7 +172,12 @@ func handleAdminDraft(c *gin.Context) { params["Manage"] = true params["Path"] = c.Request.URL.Path var err error - params["List"], err = cache.Ei.LoadDraftArticles(context.Background()) + search := store.SearchArticles{ + Page: 1, + Limit: 9999, + Fields: map[string]interface{}{store.SearchArticleDraft: true}, + } + params["List"], _, err = cache.Ei.LoadArticleList(context.Background(), search) if err != nil { logrus.Error("handleDraft.LoadDraftArticles: ", err) c.Status(http.StatusBadRequest) @@ -188,9 +194,14 @@ func handleAdminTrash(c *gin.Context) { params["Manage"] = true params["Path"] = c.Request.URL.Path var err error - params["List"], err = cache.Ei.LoadTrashArticles(context.Background()) + search := store.SearchArticles{ + Page: 1, + Limit: 9999, + Fields: map[string]interface{}{store.SearchArticleTrash: true}, + } + params["List"], _, err = cache.Ei.LoadArticleList(context.Background(), search) if err != nil { - logrus.Error("handleTrash.LoadTrashArticles: ", err) + logrus.Error("handleTrash.LoadArticleList: ", err) c.HTML(http.StatusBadRequest, "backLayout.html", params) return } diff --git a/pkg/core/blog/page/fe.go b/pkg/core/blog/page/fe.go index 7ef478a..3f0e27b 100644 --- a/pkg/core/blog/page/fe.go +++ b/pkg/core/blog/page/fe.go @@ -64,7 +64,7 @@ func handleHomePage(c *gin.Context) { if err != nil || pn < 1 { pn = 1 } - params["Prev"], params["Next"], params["List"] = cache.Ei.PageArticles(pn, + params["Prev"], params["Next"], params["List"] = cache.Ei.PageArticleFE(pn, config.Conf.BlogApp.General.PageNum) renderHTMLHomeLayout(c, "home", params)