perfect comments relates display and optimize some code
This commit is contained in:
parent
8d3197ee98
commit
6044b8eaec
@ -48,8 +48,10 @@
|
|||||||
- 博客页面至多显示数量
|
- 博客页面至多显示数量
|
||||||
- Feed中显示最近数量
|
- Feed中显示最近数量
|
||||||
- 讨论
|
- 讨论
|
||||||
- 其他评论设置-启用评论嵌套,最多嵌套层数
|
- 其他评论设置
|
||||||
- 在每个页面顶部显示 `新旧`评论
|
- `启用|禁止`评论嵌套,最多嵌套层数
|
||||||
|
- 分页显示评论,每页显示评论条数,默认显示`最前/后`页
|
||||||
|
- 在每个页面顶部显示 `新旧`评论
|
||||||
|
|
||||||
#### 主题支持程度
|
#### 主题支持程度
|
||||||
|
|
||||||
|
9
app/pkg/cache/cache.go
vendored
9
app/pkg/cache/cache.go
vendored
@ -47,7 +47,7 @@ func InitActionsCommonCache() {
|
|||||||
return config.GetConfig().CacheTime.RecentPostCacheTime
|
return config.GetConfig().CacheTime.RecentPostCacheTime
|
||||||
})
|
})
|
||||||
|
|
||||||
cachemanager.NewVarMemoryCache(dao.RecentComments, c.CacheTime.RecentCommentsCacheTime, "recentComments", func() time.Duration {
|
cachemanager.NewVarMemoryCache(RecentComment, c.CacheTime.RecentCommentsCacheTime, "recentComments", func() time.Duration {
|
||||||
return config.GetConfig().CacheTime.RecentCommentsCacheTime
|
return config.GetConfig().CacheTime.RecentCommentsCacheTime
|
||||||
})
|
})
|
||||||
|
|
||||||
@ -58,6 +58,9 @@ func InitActionsCommonCache() {
|
|||||||
cachemanager.NewMemoryMapCache(nil, PostTopComments, 30*time.Second, "PostCommentsIds", func() time.Duration {
|
cachemanager.NewMemoryMapCache(nil, PostTopComments, 30*time.Second, "PostCommentsIds", func() time.Duration {
|
||||||
return config.GetConfig().CacheTime.CommentsIncreaseUpdateTime
|
return config.GetConfig().CacheTime.CommentsIncreaseUpdateTime
|
||||||
})
|
})
|
||||||
|
cachemanager.NewMemoryMapCache(nil, dao.PostTopCommentNum, 30*time.Second, "postTopCommentsNum", func() time.Duration {
|
||||||
|
return config.GetConfig().CacheTime.CommentsIncreaseUpdateTime
|
||||||
|
})
|
||||||
|
|
||||||
cachemanager.NewMemoryMapCache(dao.GetCommentByIds, nil, time.Hour, "postCommentData", func() time.Duration {
|
cachemanager.NewMemoryMapCache(dao.GetCommentByIds, nil, time.Hour, "postCommentData", func() time.Duration {
|
||||||
return config.GetConfig().CacheTime.CommentsCacheTime
|
return config.GetConfig().CacheTime.CommentsCacheTime
|
||||||
@ -131,7 +134,7 @@ func CategoriesTags(ctx context.Context, t ...string) []models.TermsMy {
|
|||||||
if len(t) > 0 {
|
if len(t) > 0 {
|
||||||
tt = t[0]
|
tt = t[0]
|
||||||
}
|
}
|
||||||
r, err := cachemanager.Get[[]models.TermsMy]("categoryAndTagsData", ctx, tt, time.Second)
|
r, err := cachemanager.GetBy[[]models.TermsMy]("categoryAndTagsData", ctx, tt, time.Second)
|
||||||
logs.IfError(err, "get category fail")
|
logs.IfError(err, "get category fail")
|
||||||
return r
|
return r
|
||||||
}
|
}
|
||||||
@ -140,7 +143,7 @@ func AllCategoryTagsNames(ctx context.Context, t ...string) map[string]struct{}
|
|||||||
if len(t) > 0 {
|
if len(t) > 0 {
|
||||||
tt = t[0]
|
tt = t[0]
|
||||||
}
|
}
|
||||||
r, err := cachemanager.Get[[]models.TermsMy]("categoryAndTagsData", ctx, tt, time.Second)
|
r, err := cachemanager.GetBy[[]models.TermsMy]("categoryAndTagsData", ctx, tt, time.Second)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logs.Error(err, "get category fail")
|
logs.Error(err, "get category fail")
|
||||||
return nil
|
return nil
|
||||||
|
74
app/pkg/cache/comments.go
vendored
74
app/pkg/cache/comments.go
vendored
@ -2,13 +2,15 @@ package cache
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
"fmt"
|
||||||
"github.com/fthvgb1/wp-go/app/pkg/dao"
|
"github.com/fthvgb1/wp-go/app/pkg/dao"
|
||||||
"github.com/fthvgb1/wp-go/app/pkg/logs"
|
"github.com/fthvgb1/wp-go/app/pkg/logs"
|
||||||
"github.com/fthvgb1/wp-go/app/pkg/models"
|
"github.com/fthvgb1/wp-go/app/pkg/models"
|
||||||
|
"github.com/fthvgb1/wp-go/app/wpconfig"
|
||||||
"github.com/fthvgb1/wp-go/cache"
|
"github.com/fthvgb1/wp-go/cache"
|
||||||
"github.com/fthvgb1/wp-go/cache/cachemanager"
|
"github.com/fthvgb1/wp-go/cache/cachemanager"
|
||||||
"github.com/fthvgb1/wp-go/helper"
|
|
||||||
"github.com/fthvgb1/wp-go/helper/number"
|
"github.com/fthvgb1/wp-go/helper/number"
|
||||||
|
str "github.com/fthvgb1/wp-go/helper/strings"
|
||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -23,7 +25,7 @@ func RecentComments(ctx context.Context, n int) (r []models.Comments) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func PostComments(ctx context.Context, Id uint64) ([]models.Comments, error) {
|
func PostComments(ctx context.Context, Id uint64) ([]models.Comments, error) {
|
||||||
ids, err := cachemanager.Get[[]uint64]("PostCommentsIds", ctx, Id, time.Second)
|
ids, err := cachemanager.GetBy[[]uint64]("PostCommentsIds", ctx, Id, time.Second)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@ -31,11 +33,11 @@ func PostComments(ctx context.Context, Id uint64) ([]models.Comments, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func GetCommentById(ctx context.Context, id uint64) (models.Comments, error) {
|
func GetCommentById(ctx context.Context, id uint64) (models.Comments, error) {
|
||||||
return cachemanager.Get[models.Comments]("postCommentData", ctx, id, time.Second)
|
return cachemanager.GetBy[models.Comments]("postCommentData", ctx, id, time.Second)
|
||||||
}
|
}
|
||||||
|
|
||||||
func GetCommentDataByIds(ctx context.Context, ids []uint64) ([]models.Comments, error) {
|
func GetCommentDataByIds(ctx context.Context, ids []uint64) ([]models.Comments, error) {
|
||||||
return cachemanager.GetMultiple[models.Comments]("postCommentData", ctx, ids, time.Second)
|
return cachemanager.GetBatchBy[models.Comments]("postCommentData", ctx, ids, time.Second)
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewCommentCache() *cache.MapCache[string, string] {
|
func NewCommentCache() *cache.MapCache[string, string] {
|
||||||
@ -43,17 +45,67 @@ func NewCommentCache() *cache.MapCache[string, string] {
|
|||||||
return r
|
return r
|
||||||
}
|
}
|
||||||
|
|
||||||
func PostTopComments(ctx context.Context, _ string, a ...any) (helper.PaginationData[uint64], error) {
|
func PostTopComments(ctx context.Context, _ string, a ...any) ([]uint64, error) {
|
||||||
postId := a[0].(uint64)
|
postId := a[0].(uint64)
|
||||||
page := a[1].(int)
|
page := a[1].(int)
|
||||||
limit := a[2].(int)
|
limit := a[2].(int)
|
||||||
total := a[3].(int)
|
total := a[3].(int)
|
||||||
v, total, err := dao.PostCommentsIds(ctx, postId, page, limit, total)
|
v, _, err := dao.PostCommentsIds(ctx, postId, page, limit, total)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return helper.PaginationData[uint64]{}, err
|
return nil, err
|
||||||
}
|
}
|
||||||
return helper.PaginationData[uint64]{
|
return v, nil
|
||||||
Data: v,
|
}
|
||||||
TotalRaw: total,
|
|
||||||
}, nil
|
func RecentComment(ctx context.Context, a ...any) (r []models.Comments, err error) {
|
||||||
|
r, err = dao.RecentComments(ctx, a...)
|
||||||
|
if err != nil {
|
||||||
|
return r, err
|
||||||
|
}
|
||||||
|
for i, comment := range r {
|
||||||
|
r[i].CommentAuthorUrl, err = GetCommentUrl(ctx, comment.CommentId, comment.CommentPostId)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func GetCommentUrl(ctx context.Context, commentId, postId uint64) (string, error) {
|
||||||
|
if wpconfig.GetOption("page_comments") != "1" {
|
||||||
|
return fmt.Sprintf("/p/%d#comment-%d", postId, commentId), nil
|
||||||
|
}
|
||||||
|
commentsPerPage := str.ToInteger(wpconfig.GetOption("comments_per_page"), 5)
|
||||||
|
topCommentId, err := AncestorCommentId(ctx, commentId)
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
totalNum, err := cachemanager.GetBy[int]("postTopCommentsNum", ctx, postId, time.Second)
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
if totalNum <= commentsPerPage {
|
||||||
|
return fmt.Sprintf("/p/%d#comment-%d", postId, commentId), nil
|
||||||
|
}
|
||||||
|
num, err := dao.PreviousCommentNum(ctx, topCommentId, postId)
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
order := wpconfig.GetOption("comment_order")
|
||||||
|
page := number.DivideCeil(num+1, commentsPerPage)
|
||||||
|
if order == "desc" {
|
||||||
|
page = number.DivideCeil(totalNum-num, commentsPerPage)
|
||||||
|
}
|
||||||
|
return fmt.Sprintf("/p/%d/comment-page-%d/#comment-%d", postId, page, commentId), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func AncestorCommentId(ctx context.Context, commentId uint64) (uint64, error) {
|
||||||
|
comment, err := cachemanager.GetBy[models.Comments]("postCommentData", ctx, commentId, time.Second)
|
||||||
|
if err != nil {
|
||||||
|
return 0, err
|
||||||
|
}
|
||||||
|
if comment.CommentParent == 0 {
|
||||||
|
return comment.CommentId, nil
|
||||||
|
}
|
||||||
|
return AncestorCommentId(ctx, comment.CommentParent)
|
||||||
}
|
}
|
||||||
|
4
app/pkg/cache/feed.go
vendored
4
app/pkg/cache/feed.go
vendored
@ -111,7 +111,7 @@ func postFeed(c context.Context, id string, _ ...any) (x string, err error) {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
comments, err := cachemanager.GetMultiple[models.Comments]("postCommentData", c, ids, time.Second)
|
comments, err := cachemanager.GetBatchBy[models.Comments]("postCommentData", c, ids, time.Second)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@ -182,7 +182,7 @@ func commentsFeed(c context.Context, _ ...any) (r []string, err error) {
|
|||||||
}
|
}
|
||||||
return rss2.Item{
|
return rss2.Item{
|
||||||
Title: fmt.Sprintf("%s对《%s》的评论", t.CommentAuthor, post.PostTitle),
|
Title: fmt.Sprintf("%s对《%s》的评论", t.CommentAuthor, post.PostTitle),
|
||||||
Link: fmt.Sprintf("%s/p/%d#comment-%d", site, post.Id, t.CommentId),
|
Link: t.CommentAuthorUrl,
|
||||||
Creator: t.CommentAuthor,
|
Creator: t.CommentAuthor,
|
||||||
Description: desc,
|
Description: desc,
|
||||||
PubDate: t.CommentDateGmt.Format(timeFormat),
|
PubDate: t.CommentDateGmt.Format(timeFormat),
|
||||||
|
4
app/pkg/cache/postmeta.go
vendored
4
app/pkg/cache/postmeta.go
vendored
@ -7,8 +7,8 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
func GetPostMetaByPostIds(ctx context.Context, ids []uint64) ([]map[string]any, error) {
|
func GetPostMetaByPostIds(ctx context.Context, ids []uint64) ([]map[string]any, error) {
|
||||||
return cachemanager.GetMultiple[map[string]any]("postMetaData", ctx, ids, time.Second)
|
return cachemanager.GetBatchBy[map[string]any]("postMetaData", ctx, ids, time.Second)
|
||||||
}
|
}
|
||||||
func GetPostMetaByPostId(ctx context.Context, id uint64) (map[string]any, error) {
|
func GetPostMetaByPostId(ctx context.Context, id uint64) (map[string]any, error) {
|
||||||
return cachemanager.Get[map[string]any]("postMetaData", ctx, id, time.Second)
|
return cachemanager.GetBy[map[string]any]("postMetaData", ctx, id, time.Second)
|
||||||
}
|
}
|
||||||
|
12
app/pkg/cache/posts.go
vendored
12
app/pkg/cache/posts.go
vendored
@ -15,15 +15,15 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
func GetPostById(ctx context.Context, id uint64) (models.Posts, error) {
|
func GetPostById(ctx context.Context, id uint64) (models.Posts, error) {
|
||||||
return cachemanager.Get[models.Posts]("postData", ctx, id, time.Second)
|
return cachemanager.GetBy[models.Posts]("postData", ctx, id, time.Second)
|
||||||
}
|
}
|
||||||
|
|
||||||
func GetPostsByIds(ctx context.Context, ids []uint64) ([]models.Posts, error) {
|
func GetPostsByIds(ctx context.Context, ids []uint64) ([]models.Posts, error) {
|
||||||
return cachemanager.GetMultiple[models.Posts]("postData", ctx, ids, time.Second)
|
return cachemanager.GetBatchBy[models.Posts]("postData", ctx, ids, time.Second)
|
||||||
}
|
}
|
||||||
|
|
||||||
func SearchPost(ctx context.Context, key string, args ...any) (r []models.Posts, total int, err error) {
|
func SearchPost(ctx context.Context, key string, args ...any) (r []models.Posts, total int, err error) {
|
||||||
ids, err := cachemanager.Get[dao.PostIds]("searchPostIds", ctx, key, time.Second, args...)
|
ids, err := cachemanager.GetBy[dao.PostIds]("searchPostIds", ctx, key, time.Second, args...)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@ -33,7 +33,7 @@ func SearchPost(ctx context.Context, key string, args ...any) (r []models.Posts,
|
|||||||
}
|
}
|
||||||
|
|
||||||
func PostLists(ctx context.Context, key string, args ...any) (r []models.Posts, total int, err error) {
|
func PostLists(ctx context.Context, key string, args ...any) (r []models.Posts, total int, err error) {
|
||||||
ids, err := cachemanager.Get[dao.PostIds]("listPostIds", ctx, key, time.Second, args...)
|
ids, err := cachemanager.GetBy[dao.PostIds]("listPostIds", ctx, key, time.Second, args...)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@ -59,7 +59,7 @@ func RecentPosts(ctx context.Context, n int) (r []models.Posts) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func GetContextPost(ctx context.Context, id uint64, date time.Time) (prev, next models.Posts, err error) {
|
func GetContextPost(ctx context.Context, id uint64, date time.Time) (prev, next models.Posts, err error) {
|
||||||
postCtx, err := cachemanager.Get[dao.PostContext]("postContext", ctx, id, time.Second, date)
|
postCtx, err := cachemanager.GetBy[dao.PostContext]("postContext", ctx, id, time.Second, date)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return models.Posts{}, models.Posts{}, err
|
return models.Posts{}, models.Posts{}, err
|
||||||
}
|
}
|
||||||
@ -69,7 +69,7 @@ func GetContextPost(ctx context.Context, id uint64, date time.Time) (prev, next
|
|||||||
}
|
}
|
||||||
|
|
||||||
func GetMonthPostIds(ctx context.Context, year, month string, page, limit int, order string) (r []models.Posts, total int, err error) {
|
func GetMonthPostIds(ctx context.Context, year, month string, page, limit int, order string) (r []models.Posts, total int, err error) {
|
||||||
res, err := cachemanager.Get[[]uint64]("monthPostIds", ctx, fmt.Sprintf("%s%s", year, month), time.Second, year, month)
|
res, err := cachemanager.GetBy[[]uint64]("monthPostIds", ctx, fmt.Sprintf("%s%s", year, month), time.Second, year, month)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
4
app/pkg/cache/users.go
vendored
4
app/pkg/cache/users.go
vendored
@ -9,7 +9,7 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
func GetUserByName(ctx context.Context, username string) (models.Users, error) {
|
func GetUserByName(ctx context.Context, username string) (models.Users, error) {
|
||||||
return cachemanager.Get[models.Users]("usernameMapToUserData", ctx, username, time.Second)
|
return cachemanager.GetBy[models.Users]("usernameMapToUserData", ctx, username, time.Second)
|
||||||
}
|
}
|
||||||
|
|
||||||
func GetAllUsername(ctx context.Context) (map[string]struct{}, error) {
|
func GetAllUsername(ctx context.Context) (map[string]struct{}, error) {
|
||||||
@ -17,7 +17,7 @@ func GetAllUsername(ctx context.Context) (map[string]struct{}, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func GetUserById(ctx context.Context, uid uint64) models.Users {
|
func GetUserById(ctx context.Context, uid uint64) models.Users {
|
||||||
r, err := cachemanager.Get[models.Users]("userData", ctx, uid, time.Second)
|
r, err := cachemanager.GetBy[models.Users]("userData", ctx, uid, time.Second)
|
||||||
logs.IfError(err, "get user", uid)
|
logs.IfError(err, "get user", uid)
|
||||||
return r
|
return r
|
||||||
}
|
}
|
||||||
|
@ -91,25 +91,51 @@ func CommentNum(ctx context.Context, postId uint64, _ ...any) (int, error) {
|
|||||||
return str.ToInteger(n, 0), err
|
return str.ToInteger(n, 0), err
|
||||||
}
|
}
|
||||||
|
|
||||||
func PostCommentsIds(ctx context.Context, postId uint64, page, limit, totalRaw int, _ ...any) ([]uint64, int, error) {
|
func PostTopCommentNum(ctx context.Context, postId uint64, _ ...any) (int, error) {
|
||||||
order := wpconfig.GetOption("comment_order")
|
v, err := model.GetField[models.Comments](ctx, "count(*) num", model.Conditions(
|
||||||
|
model.Where(postTopCommentNumWhere(postId)),
|
||||||
|
))
|
||||||
|
if err != nil {
|
||||||
|
return 0, err
|
||||||
|
}
|
||||||
|
return str.ToInteger(v, 0), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func postTopCommentNumWhere(postId uint64) model.SqlBuilder {
|
||||||
threadComments := wpconfig.GetOption("thread_comments")
|
threadComments := wpconfig.GetOption("thread_comments")
|
||||||
|
pageComments := wpconfig.GetOption("page_comments")
|
||||||
where := model.SqlBuilder{
|
where := model.SqlBuilder{
|
||||||
{"comment_approved", "1"},
|
{"comment_approved", "1"},
|
||||||
{"comment_post_ID", "=", number.IntToString(postId), "int"},
|
{"comment_post_ID", "=", number.IntToString(postId), "int"},
|
||||||
}
|
}
|
||||||
if threadComments == "1" || "1" == wpconfig.GetOption("thread_comments_depth") {
|
if pageComments != "1" || threadComments == "1" || "1" == wpconfig.GetOption("thread_comments_depth") {
|
||||||
where = append(where, []string{"comment_parent", "0"})
|
where = append(where, []string{"comment_parent", "0"})
|
||||||
}
|
}
|
||||||
r, total, err := model.Pagination[models.Comments](ctx, model.Conditions(
|
return where
|
||||||
model.Where(where),
|
}
|
||||||
|
|
||||||
|
func PostCommentsIds(ctx context.Context, postId uint64, page, limit, totalRaw int, _ ...any) ([]uint64, int, error) {
|
||||||
|
order := wpconfig.GetOption("comment_order")
|
||||||
|
pageComments := wpconfig.GetOption("page_comments")
|
||||||
|
condition := model.Conditions(
|
||||||
|
model.Where(postTopCommentNumWhere(postId)),
|
||||||
model.TotalRaw(totalRaw),
|
model.TotalRaw(totalRaw),
|
||||||
model.Fields("comment_ID"),
|
model.Fields("comment_ID"),
|
||||||
model.Order(model.SqlBuilder{
|
model.Order(model.SqlBuilder{
|
||||||
{"comment_date_gmt", order},
|
{"comment_date_gmt", order},
|
||||||
{"comment_ID", "asc"},
|
{"comment_ID", "asc"},
|
||||||
}),
|
}),
|
||||||
), page, limit)
|
)
|
||||||
|
var r []models.Comments
|
||||||
|
var total int
|
||||||
|
var err error
|
||||||
|
if pageComments != "1" {
|
||||||
|
r, err = model.ChunkFind[models.Comments](ctx, 300, condition)
|
||||||
|
total = len(r)
|
||||||
|
} else {
|
||||||
|
r, total, err = model.Pagination[models.Comments](ctx, condition, page, limit)
|
||||||
|
}
|
||||||
|
|
||||||
if err != nil && errors.Is(err, sql.ErrNoRows) {
|
if err != nil && errors.Is(err, sql.ErrNoRows) {
|
||||||
err = nil
|
err = nil
|
||||||
}
|
}
|
||||||
@ -133,8 +159,27 @@ func CommentChildren(ctx context.Context, commentIds []uint64, _ ...any) (r map[
|
|||||||
}
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
r = slice.GroupBy(rr, func(v models.Comments) (uint64, uint64) {
|
rrr := slice.GroupBy(rr, func(v models.Comments) (uint64, uint64) {
|
||||||
return v.CommentParent, v.CommentId
|
return v.CommentParent, v.CommentId
|
||||||
})
|
})
|
||||||
|
r = make(map[uint64][]uint64)
|
||||||
|
for _, id := range commentIds {
|
||||||
|
r[id] = rrr[id]
|
||||||
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func PreviousCommentNum(ctx context.Context, commentId, postId uint64) (int, error) {
|
||||||
|
v, err := model.GetField[models.Comments](ctx, "count(*)", model.Conditions(
|
||||||
|
model.Where(model.SqlBuilder{
|
||||||
|
{"comment_approved", "1"},
|
||||||
|
{"comment_post_ID", "=", number.IntToString(postId), "int"},
|
||||||
|
{"comment_ID", "<", number.IntToString(commentId), "int"},
|
||||||
|
{"comment_parent", "=", "0", "int"},
|
||||||
|
}),
|
||||||
|
))
|
||||||
|
if err != nil {
|
||||||
|
return 0, err
|
||||||
|
}
|
||||||
|
return str.ToInteger(v, 0), nil
|
||||||
|
}
|
||||||
|
@ -29,7 +29,7 @@ type Comments struct {
|
|||||||
|
|
||||||
type CommentHtml interface {
|
type CommentHtml interface {
|
||||||
FormatLi(c context.Context, m models.Comments, depth, maxDepth, page int, isTls, isThreadComments bool, eo, parent string) string
|
FormatLi(c context.Context, m models.Comments, depth, maxDepth, page int, isTls, isThreadComments bool, eo, parent string) string
|
||||||
FloorOrder(wpOrder string, i, j models.Comments) bool
|
FloorOrder(i, j models.Comments) bool
|
||||||
}
|
}
|
||||||
|
|
||||||
func FormatComments(c *gin.Context, i CommentHtml, comments []models.Comments, maxDepth int) string {
|
func FormatComments(c *gin.Context, i CommentHtml, comments []models.Comments, maxDepth int) string {
|
||||||
@ -146,7 +146,7 @@ func (c CommonCommentFormat) FormatLi(_ context.Context, m models.Comments, curr
|
|||||||
return FormatLi(li, m, respondsFn, currentDepth, maxDepth, page, isTls, isThreadComments, eo, parent)
|
return FormatLi(li, m, respondsFn, currentDepth, maxDepth, page, isTls, isThreadComments, eo, parent)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c CommonCommentFormat) FloorOrder(wpOrder string, i, j models.Comments) bool {
|
func (c CommonCommentFormat) FloorOrder(i, j models.Comments) bool {
|
||||||
return i.CommentId > j.CommentId
|
return i.CommentId > j.CommentId
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -71,7 +71,7 @@ func PostsMore(id uint64, content, closeTag string) string {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func Digest(ctx context.Context, post *models.Posts, limit int) {
|
func Digest(ctx context.Context, post *models.Posts, limit int) {
|
||||||
content, _ := cachemanager.Get[string]("digestPlugin", ctx, post.Id, time.Second, ctx, post.PostContent, post.Id, limit)
|
content, _ := cachemanager.GetBy[string]("digestPlugin", ctx, post.Id, time.Second, ctx, post.PostContent, post.Id, limit)
|
||||||
post.PostContent = content
|
post.PostContent = content
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -41,11 +41,14 @@ type CommentHandle struct {
|
|||||||
threadComments bool
|
threadComments bool
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c CommentHandle) findComments(ctx context.Context, timeout time.Duration, comments []models.Comments) ([]models.Comments, error) {
|
func (c CommentHandle) findGrandchildComments(ctx context.Context, timeout time.Duration, comments []models.Comments) ([]models.Comments, error) {
|
||||||
parentIds := slice.Map(comments, func(t models.Comments) uint64 {
|
parentIds := slice.Map(comments, func(t models.Comments) uint64 {
|
||||||
return t.CommentId
|
return t.CommentId
|
||||||
})
|
})
|
||||||
children, err := c.children.GetCacheBatch(ctx, parentIds, timeout)
|
children, err := c.children.GetCacheBatch(ctx, parentIds, timeout)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
rr := slice.FilterAndMap(children, func(t []uint64) ([]uint64, bool) {
|
rr := slice.FilterAndMap(children, func(t []uint64) ([]uint64, bool) {
|
||||||
return t, len(t) > 0
|
return t, len(t) > 0
|
||||||
})
|
})
|
||||||
@ -57,13 +60,13 @@ func (c CommentHandle) findComments(ctx context.Context, timeout time.Duration,
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
rrr, err := c.findComments(ctx, timeout, r)
|
rrr, err := c.findGrandchildComments(ctx, timeout, r)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
comments = append(comments, rrr...)
|
comments = append(comments, rrr...)
|
||||||
slice.Sort(comments, func(i, j models.Comments) bool {
|
slice.Sort(comments, func(i, j models.Comments) bool {
|
||||||
return c.html.FloorOrder(c.order, i, j)
|
return c.html.FloorOrder(i, j)
|
||||||
})
|
})
|
||||||
return comments, nil
|
return comments, nil
|
||||||
}
|
}
|
||||||
@ -75,12 +78,12 @@ func (c CommentHandle) formatComments(ctx context.Context, ids []uint64, timeout
|
|||||||
}
|
}
|
||||||
if c.depth > 1 && c.depth < c.maxDepth {
|
if c.depth > 1 && c.depth < c.maxDepth {
|
||||||
slice.Sort(comments, func(i, j models.Comments) bool {
|
slice.Sort(comments, func(i, j models.Comments) bool {
|
||||||
return c.html.FloorOrder(c.order, i, j)
|
return c.html.FloorOrder(i, j)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
fixChildren := false
|
fixChildren := false
|
||||||
if c.depth >= c.maxDepth {
|
if c.depth >= c.maxDepth {
|
||||||
comments, err = c.findComments(ctx, timeout, comments)
|
comments, err = c.findGrandchildComments(ctx, timeout, comments)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", err
|
return "", err
|
||||||
}
|
}
|
||||||
@ -97,10 +100,9 @@ func (c CommentHandle) formatComments(ctx context.Context, ids []uint64, timeout
|
|||||||
var children []uint64
|
var children []uint64
|
||||||
if !fixChildren {
|
if !fixChildren {
|
||||||
children, err = c.children.GetCache(ctx, comment.CommentId, timeout)
|
children, err = c.children.GetCache(ctx, comment.CommentId, timeout)
|
||||||
}
|
if err != nil {
|
||||||
|
return "", err
|
||||||
if err != nil {
|
}
|
||||||
return "", err
|
|
||||||
}
|
}
|
||||||
if c.threadComments && len(children) > 0 && c.depth < c.maxDepth+1 {
|
if c.threadComments && len(children) > 0 && c.depth < c.maxDepth+1 {
|
||||||
parent = "parent"
|
parent = "parent"
|
||||||
|
@ -59,9 +59,9 @@ func RecentComments(h *wp.Handle, id string) string {
|
|||||||
comments := slice.Map(cache.RecentComments(h.C, int(conf["number"].(int64))), func(t models.Comments) string {
|
comments := slice.Map(cache.RecentComments(h.C, int(conf["number"].(int64))), func(t models.Comments) string {
|
||||||
return fmt.Sprintf(` <li>
|
return fmt.Sprintf(` <li>
|
||||||
<span class="comment-author-link">%s</span>发表在《
|
<span class="comment-author-link">%s</span>发表在《
|
||||||
<a href="/p/%v#comment-%v">%s</a>
|
<a href="%s">%s</a>
|
||||||
》
|
》
|
||||||
</li>`, t.CommentAuthor, t.CommentPostId, t.CommentId, t.PostTitle)
|
</li>`, t.CommentAuthor, t.CommentAuthorUrl, t.PostTitle)
|
||||||
})
|
})
|
||||||
s := strings.ReplaceAll(recentCommentsTemplate, "{$li}", strings.Join(comments, "\n"))
|
s := strings.ReplaceAll(recentCommentsTemplate, "{$li}", strings.Join(comments, "\n"))
|
||||||
return h.DoActionFilter(widgets.RecentComments, str.Replace(s, args))
|
return h.DoActionFilter(widgets.RecentComments, str.Replace(s, args))
|
||||||
|
@ -11,11 +11,11 @@ import (
|
|||||||
"github.com/fthvgb1/wp-go/app/plugins/wpposts"
|
"github.com/fthvgb1/wp-go/app/plugins/wpposts"
|
||||||
"github.com/fthvgb1/wp-go/app/wpconfig"
|
"github.com/fthvgb1/wp-go/app/wpconfig"
|
||||||
"github.com/fthvgb1/wp-go/cache/cachemanager"
|
"github.com/fthvgb1/wp-go/cache/cachemanager"
|
||||||
"github.com/fthvgb1/wp-go/helper"
|
|
||||||
"github.com/fthvgb1/wp-go/helper/number"
|
"github.com/fthvgb1/wp-go/helper/number"
|
||||||
str "github.com/fthvgb1/wp-go/helper/strings"
|
str "github.com/fthvgb1/wp-go/helper/strings"
|
||||||
"github.com/fthvgb1/wp-go/plugin/pagination"
|
"github.com/fthvgb1/wp-go/plugin/pagination"
|
||||||
"net/http"
|
"net/http"
|
||||||
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -92,27 +92,52 @@ func (d *DetailHandle) Comment() {
|
|||||||
d.ginH["totalCommentNum"] = 0
|
d.ginH["totalCommentNum"] = 0
|
||||||
d.ginH["totalCommentPage"] = 1
|
d.ginH["totalCommentPage"] = 1
|
||||||
d.ginH["commentPageNav"] = ""
|
d.ginH["commentPageNav"] = ""
|
||||||
d.ginH["commentOrder"] = wpconfig.GetOption("comment_order")
|
order := wpconfig.GetOption("comment_order")
|
||||||
|
d.ginH["commentOrder"] = order
|
||||||
|
d.Limit = str.ToInteger(wpconfig.GetOption("comments_per_page"), 5)
|
||||||
|
pageComments := wpconfig.GetOption("page_comments")
|
||||||
|
num, err := cachemanager.GetBy[int]("commentNumber", d.C, d.Post.Id, time.Second)
|
||||||
|
if err != nil {
|
||||||
|
d.SetErr(err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if num < 1 {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
topNum, err := cachemanager.GetBy[int]("postTopCommentsNum", d.C, d.Post.Id, time.Second)
|
||||||
|
if err != nil {
|
||||||
|
d.SetErr(err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
totalPage := number.DivideCeil(topNum, d.Limit)
|
||||||
|
if !strings.Contains(d.C.Request.URL.Path, "comment-page") {
|
||||||
|
defaultCommentsPage := wpconfig.GetOption("default_comments_page")
|
||||||
|
if order == "desc" && defaultCommentsPage == "oldest" || order == "asc" && defaultCommentsPage == "newest" {
|
||||||
|
d.C.AddParam("page", number.IntToString(totalPage))
|
||||||
|
}
|
||||||
|
}
|
||||||
d.Page = str.ToInteger(d.C.Param("page"), 1)
|
d.Page = str.ToInteger(d.C.Param("page"), 1)
|
||||||
d.ginH["currentPage"] = d.Page
|
d.ginH["currentPage"] = d.Page
|
||||||
d.Limit = str.ToInteger(wpconfig.GetOption("comments_per_page"), 5)
|
var key string
|
||||||
key := fmt.Sprintf("%d-%d-%d", d.Post.Id, d.Page, d.Limit)
|
if pageComments != "1" {
|
||||||
data, err := cachemanager.Get[helper.PaginationData[uint64]]("PostCommentsIds", d.C, key, time.Second, d.Post.Id, d.Page, d.Limit, 0)
|
key = number.IntToString(d.Post.Id)
|
||||||
if err != nil {
|
} else {
|
||||||
d.SetErr(err)
|
key = fmt.Sprintf("%d-%d-%d", d.Post.Id, d.Page, d.Limit)
|
||||||
return
|
}
|
||||||
}
|
d.ginH["page_comments"] = pageComments
|
||||||
ids := data.Data
|
d.ginH["totalCommentPage"] = totalPage
|
||||||
totalCommentNum := data.TotalRaw
|
if totalPage < d.Page {
|
||||||
d.TotalRaw = totalCommentNum
|
d.SetErr(errors.New("curren page above total page"))
|
||||||
num, err := cachemanager.Get[int]("commentNumber", d.C, d.Post.Id, time.Second)
|
return
|
||||||
|
}
|
||||||
|
data, err := cachemanager.GetBy[[]uint64]("PostCommentsIds", d.C, key, time.Second, d.Post.Id, d.Page, d.Limit, topNum)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
d.SetErr(err)
|
d.SetErr(err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
d.TotalRaw = topNum
|
||||||
d.ginH["totalCommentNum"] = num
|
d.ginH["totalCommentNum"] = num
|
||||||
d.ginH["totalCommentPage"] = number.DivideCeil(totalCommentNum, d.Limit)
|
d.Comments = data
|
||||||
d.Comments = ids
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d *DetailHandle) RenderComment() {
|
func (d *DetailHandle) RenderComment() {
|
||||||
@ -138,8 +163,9 @@ func (d *DetailHandle) RenderComment() {
|
|||||||
if d.CommentPageEle == nil {
|
if d.CommentPageEle == nil {
|
||||||
d.CommentPageEle = plugins.TwentyFifteenCommentPagination()
|
d.CommentPageEle = plugins.TwentyFifteenCommentPagination()
|
||||||
}
|
}
|
||||||
d.ginH["commentPageNav"] = pagination.Paginate(d.CommentPageEle, d.TotalRaw, d.Limit, d.Page, 1, *d.C.Request.URL, d.IsHttps())
|
if wpconfig.GetOption("page_comments") == "1" {
|
||||||
|
d.ginH["commentPageNav"] = pagination.Paginate(d.CommentPageEle, d.TotalRaw, d.Limit, d.Page, 1, *d.C.Request.URL, d.IsHttps())
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d *DetailHandle) ContextPost() {
|
func (d *DetailHandle) ContextPost() {
|
||||||
|
6
cache/cachemanager/manger.go
vendored
6
cache/cachemanager/manger.go
vendored
@ -100,7 +100,7 @@ func PushMangerMap[K comparable, V any](name string, m *cache.MapCache[K, V]) {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
func Get[T any, K comparable](name string, ct context.Context, key K, timeout time.Duration, params ...any) (r T, err error) {
|
func GetBy[T any, K comparable](name string, ct context.Context, key K, timeout time.Duration, params ...any) (r T, err error) {
|
||||||
ct = context.WithValue(ct, "getCache", name)
|
ct = context.WithValue(ct, "getCache", name)
|
||||||
ca, err := getMap[K, T](name)
|
ca, err := getMap[K, T](name)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -125,7 +125,7 @@ func getMap[K comparable, T any](name string) (*cache.MapCache[K, T], error) {
|
|||||||
}
|
}
|
||||||
return vk, nil
|
return vk, nil
|
||||||
}
|
}
|
||||||
func GetMultiple[T any, K comparable](name string, ct context.Context, key []K, timeout time.Duration, params ...any) (r []T, err error) {
|
func GetBatchBy[T any, K comparable](name string, ct context.Context, key []K, timeout time.Duration, params ...any) (r []T, err error) {
|
||||||
ct = context.WithValue(ct, "getCache", name)
|
ct = context.WithValue(ct, "getCache", name)
|
||||||
ca, err := getMap[K, T](name)
|
ca, err := getMap[K, T](name)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -138,7 +138,7 @@ func GetMultiple[T any, K comparable](name string, ct context.Context, key []K,
|
|||||||
r = vv
|
r = vv
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
func GetMultipleToMap[T any, K comparable](name string, ct context.Context, key []K, timeout time.Duration, params ...any) (r map[K]T, err error) {
|
func GetBatchByToMap[T any, K comparable](name string, ct context.Context, key []K, timeout time.Duration, params ...any) (r map[K]T, err error) {
|
||||||
ct = context.WithValue(ct, "getCache", name)
|
ct = context.WithValue(ct, "getCache", name)
|
||||||
ca, err := getMap[K, T](name)
|
ca, err := getMap[K, T](name)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
10
cache/cachemanager/manger_test.go
vendored
10
cache/cachemanager/manger_test.go
vendored
@ -28,7 +28,7 @@ func TestFlushMapVal(t *testing.T) {
|
|||||||
return r, nil
|
return r, nil
|
||||||
}, nil, time.Second, "test")
|
}, nil, time.Second, "test")
|
||||||
|
|
||||||
gets, err := GetMultiple[int]("test", ctx, number.Range(1, 10), time.Second)
|
gets, err := GetBatchBy[int]("test", ctx, number.Range(1, 10), time.Second)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(t, "err:", err)
|
t.Fatal(t, "err:", err)
|
||||||
}
|
}
|
||||||
@ -48,7 +48,7 @@ func TestFlushMapVal(t *testing.T) {
|
|||||||
FlushMapVal("test", 3, 4)
|
FlushMapVal("test", 3, 4)
|
||||||
fmt.Println(vv.Get(ctx, 3))
|
fmt.Println(vv.Get(ctx, 3))
|
||||||
fmt.Println(vv.Get(ctx, 4))
|
fmt.Println(vv.Get(ctx, 4))
|
||||||
get, err := Get[int]("test", ctx, 3, time.Second)
|
get, err := GetBy[int]("test", ctx, 3, time.Second)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(t, "err", err)
|
t.Fatal(t, "err", err)
|
||||||
}
|
}
|
||||||
@ -85,7 +85,7 @@ func TestSetExpireTime(t *testing.T) {
|
|||||||
cc.Set(ctx, "ww", "vv")
|
cc.Set(ctx, "ww", "vv")
|
||||||
m, err := cc.GetBatchToMap(ctx, []string{"fff", "ffx", "ww", "kkkk"}, time.Second)
|
m, err := cc.GetBatchToMap(ctx, []string{"fff", "ffx", "ww", "kkkk"}, time.Second)
|
||||||
fmt.Println(m, err)
|
fmt.Println(m, err)
|
||||||
fmt.Println(GetMultipleToMap[string]("xx", ctx, []string{"fff", "ffx", "ww", "kkkk"}, time.Second))
|
fmt.Println(GetBatchByToMap[string]("xx", ctx, []string{"fff", "ffx", "ww", "kkkk"}, time.Second))
|
||||||
v := NewVarMemoryCache(func(ct context.Context, a ...any) (string, error) {
|
v := NewVarMemoryCache(func(ct context.Context, a ...any) (string, error) {
|
||||||
return "ssss", nil
|
return "ssss", nil
|
||||||
}, 3*time.Second, "ff")
|
}, 3*time.Second, "ff")
|
||||||
@ -100,7 +100,7 @@ func TestSetMapCache(t *testing.T) {
|
|||||||
fmt.Println("memory cache")
|
fmt.Println("memory cache")
|
||||||
return strings.Repeat(k, 2), nil
|
return strings.Repeat(k, 2), nil
|
||||||
}, time.Hour, "test")
|
}, time.Hour, "test")
|
||||||
fmt.Println(Get[string]("test", ctx, "test", time.Second))
|
fmt.Println(GetBy[string]("test", ctx, "test", time.Second))
|
||||||
|
|
||||||
NewMapCache[string, string](xx[string, string]{m: map[string]string{}}, nil, func(ctx2 context.Context, k string, a ...any) (string, error) {
|
NewMapCache[string, string](xx[string, string]{m: map[string]string{}}, nil, func(ctx2 context.Context, k string, a ...any) (string, error) {
|
||||||
fmt.Println("other cache drives. eg: redis,file.....")
|
fmt.Println("other cache drives. eg: redis,file.....")
|
||||||
@ -110,7 +110,7 @@ func TestSetMapCache(t *testing.T) {
|
|||||||
if err := SetMapCache("kkk", x); err != nil {
|
if err := SetMapCache("kkk", x); err != nil {
|
||||||
t.Errorf("SetMapCache() error = %v, wantErr %v", err, nil)
|
t.Errorf("SetMapCache() error = %v, wantErr %v", err, nil)
|
||||||
}
|
}
|
||||||
fmt.Println(Get[string]("test", ctx, "test", time.Second))
|
fmt.Println(GetBy[string]("test", ctx, "test", time.Second))
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,26 +1,6 @@
|
|||||||
package helper
|
package helper
|
||||||
|
|
||||||
import "context"
|
|
||||||
|
|
||||||
type Pagination[T any] interface {
|
|
||||||
SetData(ctx context.Context, data []T)
|
|
||||||
GetData(ctx context.Context) []T
|
|
||||||
TotalRaws(ctx context.Context) int
|
|
||||||
}
|
|
||||||
|
|
||||||
type PaginationData[T any] struct {
|
type PaginationData[T any] struct {
|
||||||
Data []T
|
Data []T
|
||||||
TotalRaw int
|
TotalRaw int
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *PaginationData[T]) SetData(ctx context.Context, data []T) {
|
|
||||||
p.Data = data
|
|
||||||
}
|
|
||||||
|
|
||||||
func (p *PaginationData[T]) GetData(ctx context.Context) []T {
|
|
||||||
return p.Data
|
|
||||||
}
|
|
||||||
|
|
||||||
func (p *PaginationData[T]) TotalRaws(ctx context.Context) int {
|
|
||||||
return p.TotalRaw
|
|
||||||
}
|
|
||||||
|
@ -79,7 +79,7 @@ func Limit(limit int) Condition {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// TotalRaw only effect on Pagination,when TotalRaw>0 ,will not query count
|
// TotalRaw only effect on Pagination, ChunkFind,when TotalRaw>0 ,will not query count
|
||||||
func TotalRaw(total int) Condition {
|
func TotalRaw(total int) Condition {
|
||||||
return func(c *QueryCondition) {
|
return func(c *QueryCondition) {
|
||||||
c.TotalRow = total
|
c.TotalRow = total
|
||||||
|
@ -48,7 +48,8 @@ A WordPress front-end written in Go, with relatively simple functions, only the
|
|||||||
- Syndication feeds show the most recent
|
- Syndication feeds show the most recent
|
||||||
- discussion
|
- discussion
|
||||||
- Other comment settings
|
- Other comment settings
|
||||||
- Enable threaded (nested) comments levels deep
|
- `enable|disable` threaded (nested) comments levels deep
|
||||||
|
- Break comments into pages with top level comments per page number and the `last|first` page displayed by default
|
||||||
- Comments should be displayed with the `newer|older`comments
|
- Comments should be displayed with the `newer|older`comments
|
||||||
|
|
||||||
#### Theme support
|
#### Theme support
|
||||||
|
Loading…
Reference in New Issue
Block a user