blog, tags, archives

This commit is contained in:
life
2014-11-10 23:56:15 +08:00
parent 6555384e5c
commit d979a0c3e2
11 changed files with 233 additions and 125 deletions

View File

@ -8,18 +8,20 @@ import (
. "github.com/leanote/leanote/app/lea"
"github.com/leanote/leanote/app/lea/blog"
"gopkg.in/mgo.v2/bson"
"fmt"
// "github.com/leanote/leanote/app/types"
// "io/ioutil"
// "math"
// "os"
// "path"
// "fmt"
)
type Blog struct {
BaseController
}
//-----------------------------
// 前台
/*
公共
// 分类 [ok]
@ -114,7 +116,7 @@ func (c Blog) setPreviewUrl() {
postUrl = blogUrl + "/post" // /xxxxx
searchUrl = blogUrl + "/search/" + userIdOrEmail // blog.leanote.com/search/userId
singleUrl = blogUrl + "/single" // blog.leanote.com/single/singleId
archiveUrl = blogUrl + "/archive/" + userIdOrEmail // blog.leanote.com/archive/userId
archiveUrl = blogUrl + "/archives/" + userIdOrEmail // blog.leanote.com/archive/userId
tagsUrl = blogUrl + "/tags/" + userIdOrEmail // blog.leanote.com/archive/userId
c.RenderArgs["indexUrl"] = indexUrl
@ -123,8 +125,10 @@ func (c Blog) setPreviewUrl() {
c.RenderArgs["searchUrl"] = searchUrl
c.RenderArgs["singleUrl"] = singleUrl // 单页
c.RenderArgs["archiveUrl"] = archiveUrl
c.RenderArgs["archivesUrl"] = archiveUrl // 别名
c.RenderArgs["tagsUrl"] = tagsUrl
c.RenderArgs["tagPostsUrl"] = blogUrl + "/tag/" + userIdOrEmail
c.RenderArgs["tagUrl"] = c.RenderArgs["tagPostsUrl"]
// themeBaseUrl 本theme的路径url, 可以加载js, css, images之类的
c.RenderArgs["themeBaseUrl"] = "/" + theme.Path
@ -146,7 +150,7 @@ func (c Blog) setUrl(userBlog info.UserBlog, userInfo info.User) {
postUrl = indexUrl + "/post" // /xxxxx
searchUrl = indexUrl + "/search" // /xxxxx
singleUrl = indexUrl + "/single"
archiveUrl = indexUrl + "/archive"
archiveUrl = indexUrl + "/archives"
tagsUrl = indexUrl + "/tags"
tagPostsUrl = indexUrl + "/tag"
} else if userBlog.SubDomain != "" {
@ -155,7 +159,7 @@ func (c Blog) setUrl(userBlog info.UserBlog, userInfo info.User) {
postUrl = indexUrl + "/post" // /xxxxx
searchUrl = indexUrl + "/search" // /xxxxx
singleUrl = indexUrl + "/single"
archiveUrl = indexUrl + "/archive"
archiveUrl = indexUrl + "/archives"
tagsUrl = indexUrl + "/tags"
tagPostsUrl = indexUrl + "/tag"
} else {
@ -174,7 +178,7 @@ func (c Blog) setUrl(userBlog info.UserBlog, userInfo info.User) {
postUrl = blogUrl + "/post" // /xxxxx
searchUrl = blogUrl + "/search/" + userIdOrEmail // blog.leanote.com/search/userId
singleUrl = blogUrl + "/single" // blog.leanote.com/single/singleId
archiveUrl = blogUrl + "/archive/" + userIdOrEmail // blog.leanote.com/archive/userId
archiveUrl = blogUrl + "/archives/" + userIdOrEmail // blog.leanote.com/archive/userId
tagsUrl = blogUrl + "/tags/" + userIdOrEmail
tagPostsUrl = blogUrl + "/tag/" + userIdOrEmail // blog.leanote.com/archive/userId
}
@ -189,8 +193,10 @@ func (c Blog) setUrl(userBlog info.UserBlog, userInfo info.User) {
c.RenderArgs["searchUrl"] = searchUrl
c.RenderArgs["singleUrl"] = singleUrl // 单页
c.RenderArgs["archiveUrl"] = archiveUrl
c.RenderArgs["archivesUrl"] = archiveUrl // 别名
c.RenderArgs["tagsUrl"] = tagsUrl
c.RenderArgs["tagPostsUrl"] = tagPostsUrl
c.RenderArgs["tagUrl"] = c.RenderArgs["tagPostsUrl"] // 别名
// themeBaseUrl 本theme的路径url, 可以加载js, css, images之类的
c.RenderArgs["themeBaseUrl"] = "/" + userBlog.ThemePath
@ -323,6 +329,7 @@ func (c Blog) blogCommon(userId string, userBlog info.UserBlog, userInfo info.Us
_, recentBlogs := blogService.ListBlogs(userId, "", 1, 5, userBlog.SortField, userBlog.IsAsc)
c.RenderArgs["recentPosts"] = c.fixBlogs(recentBlogs)
c.RenderArgs["latestPosts"] = c.RenderArgs["recentPosts"]
c.RenderArgs["tags"] = blogService.GetBlogTags(userId)
// 语言, url地址
c.SetLocale()
@ -355,26 +362,26 @@ func (c Blog) blogCommon(userId string, userBlog info.UserBlog, userInfo info.Us
}
// 修复博客, index, cate用到
func (c Blog) fixBlog(blog info.BlogItem) map[string]interface{} {
blog2 := map[string]interface{}{
"NoteId": blog.NoteId.Hex(),
"Title": blog.Title,
"CreatedTime": blog.CreatedTime,
"UpdatedTime": blog.UpdatedTime,
"PublicTime": blog.PublicTime,
"Desc": blog.Desc,
"Abstract": blog.Abstract,
"Content": blog.Content,
"Tags": blog.Tags,
"CommentNum": blog.CommentNum,
"ReadNum": blog.ReadNum,
"LikeNum": blog.LikeNum,
"IsMarkdown": blog.IsMarkdown,
func (c Blog) fixBlog(blog info.BlogItem) info.Post {
blog2 := info.Post{
NoteId: blog.NoteId.Hex(),
Title: blog.Title,
CreatedTime: blog.CreatedTime,
UpdatedTime: blog.UpdatedTime,
PublicTime: blog.PublicTime,
Desc: blog.Desc,
Abstract: blog.Abstract,
Content: blog.Content,
Tags: blog.Tags,
CommentNum: blog.CommentNum,
ReadNum: blog.ReadNum,
LikeNum: blog.LikeNum,
IsMarkdown: blog.IsMarkdown,
}
return blog2
}
func (c Blog) fixBlogs(blogs []info.BlogItem) []map[string]interface{} {
blogs2 := make([]map[string]interface{}, len(blogs))
func (c Blog) fixBlogs(blogs []info.BlogItem) []info.Post {
blogs2 := make([]info.Post, len(blogs))
for i, blog := range blogs {
blogs2[i] = c.fixBlog(blog)
}
@ -430,7 +437,7 @@ func (c Blog) Tags(userIdOrEmail string) (re revel.Result) {
}
c.RenderArgs["curIsTags"] = true
tags := blogService.ListBlogsTag(userId)
tags := blogService.GetBlogTags(userId)
c.RenderArgs["tags"] = tags
return c.render("tags.html", userBlog.ThemePath)
}
@ -482,12 +489,13 @@ func (c Blog) Tag(userIdOrEmail, tag string) (re revel.Result) {
}
// 归档
func (c Blog) Archive(userIdOrEmail string, cateId string) (re revel.Result) {
func (c Blog) Archives(userIdOrEmail string, cateId string, year, month int) (re revel.Result) {
notebookId := cateId
// 自定义域名
hasDomain, userBlog := c.domain()
defer func() {
if err := recover(); err != nil {
fmt.Println(err)
re = c.e404(userBlog.ThemePath);
}
}()
@ -513,7 +521,7 @@ func (c Blog) Archive(userIdOrEmail string, cateId string) (re revel.Result) {
return c.e404(userBlog.ThemePath) // 404 TODO 使用用户的404
}
arcs := blogService.ListBlogsArchive(userId, notebookId, "PublicTime", false)
arcs := blogService.ListBlogsArchive(userId, notebookId, year, month, "PublicTime", false)
c.RenderArgs["archives"] = arcs
c.RenderArgs["curIsArchive"] = true
@ -522,6 +530,9 @@ func (c Blog) Archive(userIdOrEmail string, cateId string) (re revel.Result) {
c.RenderArgs["curCateTitle"] = notebook.Title
c.RenderArgs["curCateId"] = notebookId
}
c.RenderArgs["curYear"] = year
c.RenderArgs["curMonth"] = month
return c.render("archive.html", userBlog.ThemePath)
}
@ -622,7 +633,6 @@ func (c Blog) Index(userIdOrEmail string) (re revel.Result) {
c.RenderArgs["curIsIndex"] = true
Log("----")
return c.render("index.html", userBlog.ThemePath)
}

View File

@ -7,7 +7,7 @@ import (
. "github.com/leanote/leanote/app/lea"
"github.com/leanote/leanote/app/info"
"os/exec"
"time"
// "time"
// "github.com/leanote/leanote/app/types"
// "io/ioutil"
// "fmt"
@ -358,19 +358,6 @@ func (c Note) Html2Image(noteId string) revel.Result {
// 设置/取消Blog; 置顶
func (c Note) SetNote2Blog(noteId string, isBlog, isTop bool) revel.Result {
noteUpdate := bson.M{}
if isTop {
isBlog = true
}
if !isBlog {
isTop = false
}
noteUpdate["IsBlog"] = isBlog
noteUpdate["IsTop"] = isTop
if isBlog {
noteUpdate["PublicTime"] = time.Now()
}
re := noteService.UpdateNote(c.GetUserId(), c.GetUserId(),
noteId, noteUpdate)
re := noteService.ToBlog(c.GetUserId(), noteId, isBlog, isTop)
return c.RenderJson(re)
}

View File

@ -72,8 +72,6 @@ func (c Notebook) DragNotebooks(data string) revel.Result {
// 设置notebook <-> blog
func (c Notebook) SetNotebook2Blog(notebookId string, isBlog bool) revel.Result {
noteUpdate := bson.M{"IsBlog": isBlog}
re := notebookService.UpdateNotebook(c.GetUserId(),
notebookId, noteUpdate)
re := notebookService.ToBlog(c.GetUserId(), notebookId, isBlog)
return c.RenderJson(re)
}

View File

@ -64,11 +64,11 @@ func (c Preview) Tags(userIdOrEmail string) revel.Result {
// }
// return blog.RenderTemplate("tag_posts.html", c.RenderArgs, c.getPreviewThemeAbsolutePath(""))
}
func (c Preview) Archive(userIdOrEmail string, notebookId string) revel.Result {
func (c Preview) Archives(userIdOrEmail string, notebookId string, year, month int) revel.Result {
if !c.getPreviewThemeAbsolutePath("") {
return c.E404()
}
return c.Blog.Archive(c.GetUserId(), notebookId)
return c.Blog.Archives(c.GetUserId(), notebookId, year, month)
// return blog.RenderTemplate("archive.html", c.RenderArgs, c.getPreviewThemeAbsolutePath(""))
}
func (c Preview) Cate(notebookId string) revel.Result {

View File

@ -27,7 +27,8 @@ var Groups *mgo.Collection
var GroupUsers *mgo.Collection
var Tags *mgo.Collection
var TagNotes *mgo.Collection
//var TagNotes *mgo.Collection
var TagCounts *mgo.Collection
var UserBlogs *mgo.Collection
@ -110,7 +111,8 @@ func Init() {
// tag
Tags = Session.DB(dbname).C("tags")
TagNotes = Session.DB(dbname).C("tag_notes")
// TagNotes = Session.DB(dbname).C("tag_notes")
TagCounts = Session.DB(dbname).C("tag_count")
// blog
UserBlogs = Session.DB(dbname).C("user_blogs")

View File

@ -1,7 +1,7 @@
package info
import (
// "time"
"time"
)
// 仅仅为了博客的主题
@ -22,24 +22,26 @@ type BlogInfoCustom struct {
type Post struct {
NoteId string
Title string
CreatedTime time.Time
UpdatedTime time.Time
PublicTime time.Time
Desc string
Abstract string
Content string
Tags []string
CommentNum int
ReadNum int
LikeNum int
IsMarkdown bool
}
// 归档
type ArchiveMonth struct {
Month int
Posts []*Post
}
type Archive struct {
Year int
Posts []map[string]interface{}
}
type TagsCounts []TagCount
type TagCount struct {
Tag string
Count int
}
func (this TagsCounts) Len() int {
return len(this)
}
func (this TagsCounts) Less(i, j int) bool {
return this[i].Count > this[j].Count
}
func (this TagsCounts) Swap(i, j int) {
this[i], this[j] = this[j], this[i]
MonthAchives []ArchiveMonth
Posts []*Post
}

View File

@ -5,15 +5,38 @@ import (
)
// 这里主要是为了统计每个tag的note数目
// 暂时没用
/*
type TagNote struct {
TagId bson.ObjectId `bson:"_id,omitempty"` // 必须要设置bson:"_id" 不然mgo不会认为是主键
UserId bson.ObjectId `bson:"UserId"`
Tag string `Title` // 标题
NoteNum int `NoteNum` // note数目
}
*/
// 每个用户一条记录, 存储用户的所有tags
type Tag struct {
UserId bson.ObjectId `bson:"_id"`
Tags []string `Tags`
}
type TagCount struct {
TagCountId bson.ObjectId `bson:"_id,omitempty"`
UserId bson.ObjectId `UserId` // 谁的
Tag string `Tag`
IsBlog bool `IsBlog` // 是否是博客的tag统计
Count int `Count` // 统计数量
}
/*
type TagsCounts []TagCount
func (this TagsCounts) Len() int {
return len(this)
}
func (this TagsCounts) Less(i, j int) bool {
return this[i].Count > this[j].Count
}
func (this TagsCounts) Swap(i, j int) {
this[i], this[j] = this[j], this[i]
}
*/

View File

@ -7,7 +7,7 @@ import (
// "github.com/leanote/leanote/app/lea/netutil"
"gopkg.in/mgo.v2/bson"
// "time"
"sort"
// "sort"
"strings"
"time"
"strconv"
@ -111,13 +111,25 @@ func (this *BlogService) ListBlogs(userId, notebookId string, page, pageSize int
{Tag:xxx, Count: 32}
]
*/
func (this *BlogService) ListBlogsTag(userId string) (info.TagsCounts) {
func (this *BlogService) GetBlogTags(userId string) ([]info.TagCount) {
// 得到所有博客
tagCounts := []info.TagCount{}
query := bson.M{"UserId": bson.ObjectIdHex(userId), "IsBlog": true}
db.TagCounts.Find(query).Sort("-Count").All(&tagCounts)
return tagCounts
}
// 重新计算博客的标签
// 在设置设置/取消为博客时调用
func (this *BlogService) ReCountBlogTags(userId string) (bool) {
// 得到所有博客
notes := []info.Note{}
query := bson.M{"UserId": bson.ObjectIdHex(userId), "IsTrash": false, "IsBlog": true}
userIdO := bson.ObjectIdHex(userId)
query := bson.M{"UserId": userIdO, "IsTrash": false, "IsBlog": true}
db.ListByQWithFields(db.Notes, query, []string{"Tags"}, &notes)
db.DeleteAll(db.TagCounts, bson.M{"UserId": userIdO, "IsBlog": true});
if(notes == nil || len(notes) == 0) {
return nil
return true
}
// 统计所有的Tags和数目
tagsCount := map[string]int{}
@ -131,16 +143,12 @@ func (this *BlogService) ListBlogsTag(userId string) (info.TagsCounts) {
}
}
}
// 排序, 从大到小
var tagsCounts info.TagsCounts
tagsCounts = make(info.TagsCounts, len(tagsCount))
i := 0
// 一个个插入
for tag, count := range tagsCount {
tagsCounts[i] = info.TagCount{tag, count}
i++
db.Insert(db.TagCounts,
info.TagCount{UserId: userIdO, IsBlog: true, Tag: tag, Count: count})
}
sort.Sort(&tagsCounts)
return tagsCounts
return true
}
// 归档博客
/*
@ -155,8 +163,42 @@ Year: 2014
Posts: []
}
*/
func (this *BlogService) ListBlogsArchive(userId, notebookId string, sortField string, isAsc bool) ([]info.Archive) {
_, notes := noteService.ListNotes(userId, notebookId, false, 1, 99999, sortField, isAsc, true);
func (this *BlogService) ListBlogsArchive(userId, notebookId string, year, month int, sortField string, isAsc bool) ([]info.Archive) {
// _, notes := noteService.ListNotes(userId, notebookId, false, 1, 99999, sortField, isAsc, true);
q := bson.M{"UserId": bson.ObjectIdHex(userId), "IsBlog": true, "IsTrash": false}
if notebookId != "" {
q["NotebookId"] = bson.ObjectIdHex(notebookId)
}
if year > 0 {
now := time.Now()
nextYear := year
nextMonth := month
if month == 0 {
month = 1
nextYear = year + 1
nextMonth = month
} else if month >= 12 {
month = 12
nextYear = year + 1
nextMonth = 1
} else { // month 在1-12之间
nextMonth = month + 1
}
leftT := time.Date(year, time.Month(month), 1, 0, 0, 0, 0, now.Location())
rightT := time.Date(nextYear, time.Month(nextMonth), 1, 0, 0, 0, 0, now.Location())
if sortField == "CreatedTime" || sortField == "UpdatedTime" {
q[sortField] = bson.M{"$gte": leftT, "$lt": rightT}
} else {
q["PublicTime"] = bson.M{"$gte": leftT, "$lt": rightT}
}
}
sorter := sortField
if !isAsc {
sorter = "-" + sortField
}
notes := []info.Note{}
db.Notes.Find(q).Sort(sorter).All(&notes)
if(notes == nil || len(notes) == 0) {
return nil
@ -164,9 +206,11 @@ func (this *BlogService) ListBlogsArchive(userId, notebookId string, sortField s
arcs := []info.Archive{}
// 按年汇总
arcsMap := map[int]*info.Archive{}
arcsMap := map[int]info.Archive{}
// 按月汇总
arcsMonth := []info.ArchiveMonth{}
var t time.Time
var arc *info.Archive
var arc info.Archive
everYear := 0
for _, note := range notes {
if sortField == "PublicTime" {
@ -177,37 +221,56 @@ func (this *BlogService) ListBlogsArchive(userId, notebookId string, sortField s
t = note.UpdatedTime
}
year := t.Year()
month := int(t.Month())
if everYear == 0 {
everYear = year
}
if everYear != year {
arcs = append(arcs, *arcsMap[everYear])
yearArc := arcsMap[everYear]
yearArc.MonthAchives = arcsMonth
arcs = append(arcs, yearArc)
everYear = year
// 新的一年
arcsMonth = []info.ArchiveMonth{}
}
if arcT, ok := arcsMap[year]; ok {
arc = arcT
} else {
arc = &info.Archive{Year: year, Posts: []map[string]interface{}{}}
arc = info.Archive{Year: year, Posts: []*info.Post{}}
}
arc.Posts = append(arc.Posts, map[string]interface{}{
"NoteId": note.NoteId.Hex(),
"Title": note.Title,
"CreatedTime": note.CreatedTime,
"UpdatedTime": note.UpdatedTime,
"PublicTime": note.PublicTime,
"Desc": note.Desc,
"Tags": note.Tags,
"CommentNum": note.CommentNum,
"ReadNum": note.ReadNum,
"LikeNum": note.LikeNum,
"IsMarkdown": note.IsMarkdown,
});
p := &info.Post{
NoteId: note.NoteId.Hex(),
Title: note.Title,
CreatedTime: note.CreatedTime,
UpdatedTime: note.UpdatedTime,
PublicTime: note.PublicTime,
Desc: note.Desc,
Tags: note.Tags,
CommentNum: note.CommentNum,
ReadNum: note.ReadNum,
LikeNum: note.LikeNum,
IsMarkdown: note.IsMarkdown,
}
arc.Posts = append(arc.Posts, p);
arcsMap[year] = arc
// month
lm := len(arcsMonth)
if(lm == 0 || arcsMonth[lm-1].Month != month) {
arcsMonth = append(arcsMonth, info.ArchiveMonth{month, []*info.Post{p}})
} else {
arcsMonth[lm-1].Posts = append(arcsMonth[lm-1].Posts, p)
}
}
// 最后一个
arcs = append(arcs, *arcsMap[everYear])
if everYear > 0 {
yearArc := arcsMap[everYear]
yearArc.MonthAchives = arcsMonth
arcs = append(arcs, yearArc)
}
return arcs
}

View File

@ -472,7 +472,6 @@ func init() {
})
}
func (this *ConfigService) GetSchema() string {
return schema;
}

View File

@ -294,6 +294,27 @@ func (this *NoteService) UpdateTags(noteId string, userId string, tags []string)
return db.UpdateByIdAndUserIdField(db.Notes, noteId, userId, "Tags", tags)
}
func (this *NoteService) ToBlog(userId, noteId string, isBlog, isTop bool) bool {
noteUpdate := bson.M{}
if isTop {
isBlog = true
}
if !isBlog {
isTop = false
}
noteUpdate["IsBlog"] = isBlog
noteUpdate["IsTop"] = isTop
if isBlog {
noteUpdate["PublicTime"] = time.Now()
}
ok := db.UpdateByIdAndUserIdMap(db.Notes, noteId, userId, noteUpdate)
// 重新计算tags
go (func() {
blogService.ReCountBlogTags(userId)
})()
return ok
}
// 移动note
// trash, 正常的都可以用
// 1. 要检查下notebookId是否是自己的

View File

@ -170,15 +170,15 @@ func (this *NotebookService) UpdateNotebookTitle(notebookId, userId, title strin
// 更新notebook
func (this *NotebookService) UpdateNotebook(userId, notebookId string, needUpdate bson.M) bool {
needUpdate["UpdatedTime"] = time.Now();
return db.UpdateByIdAndUserIdMap(db.Notebooks, notebookId, userId, needUpdate)
}
// 如果有IsBlog之类的, 需要特殊处理
if isBlog, ok := needUpdate["IsBlog"]; ok {
// 设为blog/取消, 把它下面所有的note都设为isBlog
if is, ok2 := isBlog.(bool); ok2 {
// ToBlog or Not
func (this *NotebookService) ToBlog(userId, notebookId string, isBlog bool) (bool) {
q := bson.M{"UserId": bson.ObjectIdHex(userId),
"NotebookId": bson.ObjectIdHex(notebookId)}
data := bson.M{"IsBlog": is}
if is {
data := bson.M{"IsBlog": isBlog}
if isBlog {
data["PublicTime"] = time.Now()
}
db.UpdateByQMap(db.Notes, q, data)
@ -194,10 +194,13 @@ func (this *NotebookService) UpdateNotebook(userId, notebookId string, needUpdat
}
db.UpdateByQMap(db.NoteContents, bson.M{"_id": bson.M{"$in": noteIds}}, bson.M{"IsBlog": isBlog})
}
}
}
return db.UpdateByIdAndUserIdMap(db.Notebooks, notebookId, userId, needUpdate)
// 重新计算tags
go (func() {
blogService.ReCountBlogTags(userId)
})()
return true
}
// 查看是否有子notebook