commit
1267d45ffb
|
@ -4,16 +4,13 @@ import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/fthvgb1/wp-go/internal/pkg/cache"
|
"github.com/fthvgb1/wp-go/internal/pkg/cache"
|
||||||
"github.com/fthvgb1/wp-go/internal/pkg/logs"
|
"github.com/fthvgb1/wp-go/internal/pkg/logs"
|
||||||
"github.com/fthvgb1/wp-go/internal/pkg/models"
|
|
||||||
"github.com/fthvgb1/wp-go/internal/plugins"
|
"github.com/fthvgb1/wp-go/internal/plugins"
|
||||||
"github.com/fthvgb1/wp-go/internal/theme"
|
"github.com/fthvgb1/wp-go/internal/theme"
|
||||||
"github.com/fthvgb1/wp-go/internal/wpconfig"
|
"github.com/fthvgb1/wp-go/internal/wpconfig"
|
||||||
"github.com/gin-contrib/sessions"
|
"github.com/gin-contrib/sessions"
|
||||||
"github.com/gin-gonic/gin"
|
"github.com/gin-gonic/gin"
|
||||||
"net/http"
|
"net/http"
|
||||||
"sort"
|
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
type detailHandler struct {
|
type detailHandler struct {
|
||||||
|
@ -22,9 +19,6 @@ type detailHandler struct {
|
||||||
|
|
||||||
func Detail(c *gin.Context) {
|
func Detail(c *gin.Context) {
|
||||||
var err error
|
var err error
|
||||||
hh := detailHandler{
|
|
||||||
c,
|
|
||||||
}
|
|
||||||
recent := cache.RecentPosts(c, 5)
|
recent := cache.RecentPosts(c, 5)
|
||||||
archive := cache.Archives(c)
|
archive := cache.Archives(c)
|
||||||
categoryItems := cache.Categories(c)
|
categoryItems := cache.Categories(c)
|
||||||
|
@ -92,7 +86,7 @@ func Detail(c *gin.Context) {
|
||||||
plugins.ApplyPlugin(plugins.NewPostPlugin(c, plugins.Detail), &post)
|
plugins.ApplyPlugin(plugins.NewPostPlugin(c, plugins.Detail), &post)
|
||||||
comments, err := cache.PostComments(c, post.Id)
|
comments, err := cache.PostComments(c, post.Id)
|
||||||
logs.ErrPrintln(err, "get post comment", post.Id)
|
logs.ErrPrintln(err, "get post comment", post.Id)
|
||||||
commentss := treeComments(comments)
|
ginH["comments"] = comments
|
||||||
prev, next, err := cache.GetContextPost(c, post.Id, post.PostDate)
|
prev, next, err := cache.GetContextPost(c, post.Id, post.PostDate)
|
||||||
logs.ErrPrintln(err, "get pre and next post", post.Id, post.PostDate)
|
logs.ErrPrintln(err, "get pre and next post", post.Id, post.PostDate)
|
||||||
ginH["title"] = fmt.Sprintf("%s-%s", post.PostTitle, wpconfig.Options.Value("blogname"))
|
ginH["title"] = fmt.Sprintf("%s-%s", post.PostTitle, wpconfig.Options.Value("blogname"))
|
||||||
|
@ -105,158 +99,8 @@ func Detail(c *gin.Context) {
|
||||||
logs.ErrPrintln(err, "get comment depth ", depth)
|
logs.ErrPrintln(err, "get comment depth ", depth)
|
||||||
d = 5
|
d = 5
|
||||||
}
|
}
|
||||||
ginH["comments"] = hh.formatComment(commentss, 1, d)
|
ginH["maxDep"] = d
|
||||||
ginH["next"] = next
|
ginH["next"] = next
|
||||||
ginH["user"] = user
|
ginH["user"] = user
|
||||||
ginH["scene"] = plugins.Detail
|
ginH["scene"] = plugins.Detail
|
||||||
}
|
}
|
||||||
|
|
||||||
type Comment struct {
|
|
||||||
models.Comments
|
|
||||||
Children []*Comment
|
|
||||||
}
|
|
||||||
|
|
||||||
type Comments []*Comment
|
|
||||||
|
|
||||||
func (c Comments) Len() int {
|
|
||||||
return len(c)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c Comments) Less(i, j int) bool {
|
|
||||||
return c[i].CommentId < c[j].CommentId
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c Comments) Swap(i, j int) {
|
|
||||||
c[i], c[j] = c[j], c[i]
|
|
||||||
}
|
|
||||||
|
|
||||||
func (d detailHandler) formatComment(comments Comments, depth, maxDepth int) (html string) {
|
|
||||||
s := strings.Builder{}
|
|
||||||
if depth > maxDepth {
|
|
||||||
comments = findComments(comments)
|
|
||||||
}
|
|
||||||
sort.Sort(comments)
|
|
||||||
for i, comment := range comments {
|
|
||||||
eo := "even"
|
|
||||||
if (i+1)%2 == 0 {
|
|
||||||
eo = "odd"
|
|
||||||
}
|
|
||||||
p := ""
|
|
||||||
fl := false
|
|
||||||
if len(comment.Children) > 0 && depth < maxDepth+1 {
|
|
||||||
p = "parent"
|
|
||||||
fl = true
|
|
||||||
}
|
|
||||||
s.WriteString(d.formatLi(comment.Comments, depth, eo, p))
|
|
||||||
if fl {
|
|
||||||
depth++
|
|
||||||
s.WriteString(`<ol class="children">`)
|
|
||||||
s.WriteString(d.formatComment(comment.Children, depth, maxDepth))
|
|
||||||
s.WriteString(`</ol>`)
|
|
||||||
}
|
|
||||||
s.WriteString("</li><!-- #comment-## -->")
|
|
||||||
i++
|
|
||||||
if i >= len(comments) {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
html = s.String()
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
func findComments(comments Comments) Comments {
|
|
||||||
var r Comments
|
|
||||||
for _, comment := range comments {
|
|
||||||
tmp := *comment
|
|
||||||
tmp.Children = nil
|
|
||||||
r = append(r, &tmp)
|
|
||||||
if len(comment.Children) > 0 {
|
|
||||||
t := findComments(comment.Children)
|
|
||||||
r = append(r, t...)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return r
|
|
||||||
}
|
|
||||||
|
|
||||||
func treeComments(comments []models.Comments) Comments {
|
|
||||||
var r = map[uint64]*Comment{
|
|
||||||
0: {
|
|
||||||
Comments: models.Comments{},
|
|
||||||
},
|
|
||||||
}
|
|
||||||
var top []*Comment
|
|
||||||
for _, comment := range comments {
|
|
||||||
c := Comment{
|
|
||||||
Comments: comment,
|
|
||||||
Children: []*Comment{},
|
|
||||||
}
|
|
||||||
r[comment.CommentId] = &c
|
|
||||||
if comment.CommentParent == 0 {
|
|
||||||
top = append(top, &c)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
for id, son := range r {
|
|
||||||
if id == son.CommentParent {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
parent := r[son.CommentParent]
|
|
||||||
parent.Children = append(parent.Children, son)
|
|
||||||
}
|
|
||||||
return top
|
|
||||||
}
|
|
||||||
|
|
||||||
func (d detailHandler) formatLi(comments models.Comments, depth int, eo, parent string) string {
|
|
||||||
li := `
|
|
||||||
<li id="comment-{{CommentId}}" class="comment {{eo}} thread-even depth-{{Depth}} {{parent}}">
|
|
||||||
<article id="div-comment-{{CommentId}}" class="comment-body">
|
|
||||||
<footer class="comment-meta">
|
|
||||||
<div class="comment-author vcard">
|
|
||||||
<img alt=""
|
|
||||||
src="{{Gravatar}}"
|
|
||||||
srcset="{{Gravatar}} 2x"
|
|
||||||
class="avatar avatar-56 photo" height="56" width="56" loading="lazy">
|
|
||||||
<b class="fn">
|
|
||||||
<a href="{{CommentAuthorUrl}}" rel="external nofollow ugc"
|
|
||||||
class="url">{{CommentAuthor}}</a>
|
|
||||||
</b>
|
|
||||||
<span class="says">说道:</span></div><!-- .comment-author -->
|
|
||||||
|
|
||||||
<div class="comment-metadata">
|
|
||||||
<a href="/p/{{PostId}}#comment-{{CommentId}}">
|
|
||||||
<time datetime="{{CommentDateGmt}}">{{CommentDate}}</time>
|
|
||||||
</a></div><!-- .comment-metadata -->
|
|
||||||
|
|
||||||
</footer><!-- .comment-meta -->
|
|
||||||
|
|
||||||
<div class="comment-content">
|
|
||||||
<p>{{CommentContent}}</p>
|
|
||||||
</div><!-- .comment-content -->
|
|
||||||
|
|
||||||
<div class="reply">
|
|
||||||
<a rel="nofollow" class="comment-reply-link"
|
|
||||||
href="/p/{{PostId}}?replytocom={{CommentId}}#respond" data-commentid="{{CommentId}}" data-postid="{{PostId}}"
|
|
||||||
data-belowelement="div-comment-{{CommentId}}" data-respondelement="respond"
|
|
||||||
data-replyto="回复给{{CommentAuthor}}"
|
|
||||||
aria-label="回复给{{CommentAuthor}}">回复</a>
|
|
||||||
</div>
|
|
||||||
</article><!-- .comment-body -->
|
|
||||||
|
|
||||||
`
|
|
||||||
for k, v := range map[string]string{
|
|
||||||
"{{CommentId}}": strconv.FormatUint(comments.CommentId, 10),
|
|
||||||
"{{Depth}}": strconv.Itoa(depth),
|
|
||||||
"{{Gravatar}}": plugins.Gravatar(comments.CommentAuthorEmail, d.Context.Request.TLS != nil),
|
|
||||||
"{{CommentAuthorUrl}}": comments.CommentAuthorUrl,
|
|
||||||
"{{CommentAuthor}}": comments.CommentAuthor,
|
|
||||||
"{{PostId}}": strconv.FormatUint(comments.CommentPostId, 10),
|
|
||||||
"{{CommentDateGmt}}": comments.CommentDateGmt.String(),
|
|
||||||
"{{CommentDate}}": comments.CommentDate.Format("2006-01-02 15:04"),
|
|
||||||
"{{CommentContent}}": comments.CommentContent,
|
|
||||||
"{{eo}}": eo,
|
|
||||||
"{{parent}}": parent,
|
|
||||||
} {
|
|
||||||
li = strings.Replace(li, k, v, -1)
|
|
||||||
}
|
|
||||||
return li
|
|
||||||
}
|
|
||||||
|
|
|
@ -1 +1,191 @@
|
||||||
package plugins
|
package plugins
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/fthvgb1/wp-go/helper/slice"
|
||||||
|
"github.com/fthvgb1/wp-go/internal/pkg/models"
|
||||||
|
"github.com/gin-gonic/gin"
|
||||||
|
"strconv"
|
||||||
|
"strings"
|
||||||
|
)
|
||||||
|
|
||||||
|
type CommentHandler struct {
|
||||||
|
*gin.Context
|
||||||
|
comments []*Comments
|
||||||
|
maxDepth int
|
||||||
|
depth int
|
||||||
|
i CommentHtml
|
||||||
|
}
|
||||||
|
|
||||||
|
type Comments struct {
|
||||||
|
models.Comments
|
||||||
|
Children []*Comments
|
||||||
|
}
|
||||||
|
|
||||||
|
type CommentHtml interface {
|
||||||
|
Sort(i, j *Comments) bool
|
||||||
|
FormatLi(c *gin.Context, m models.Comments, depth int, eo, parent string) string
|
||||||
|
}
|
||||||
|
|
||||||
|
func FormatComments(c *gin.Context, i CommentHtml, comments []models.Comments, maxDepth int) string {
|
||||||
|
tree := treeComments(comments)
|
||||||
|
h := CommentHandler{
|
||||||
|
Context: c,
|
||||||
|
comments: tree,
|
||||||
|
maxDepth: maxDepth,
|
||||||
|
depth: 1,
|
||||||
|
i: i,
|
||||||
|
}
|
||||||
|
return h.formatComment(h.comments, true)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d CommentHandler) formatComment(comments []*Comments, isTop bool) (html string) {
|
||||||
|
s := strings.Builder{}
|
||||||
|
if d.depth > d.maxDepth {
|
||||||
|
comments = d.findComments(comments)
|
||||||
|
}
|
||||||
|
slice.SortSelf(comments, d.i.Sort)
|
||||||
|
for i, comment := range comments {
|
||||||
|
eo := "even"
|
||||||
|
if (i+1)%2 == 0 {
|
||||||
|
eo = "odd"
|
||||||
|
}
|
||||||
|
parent := ""
|
||||||
|
fl := false
|
||||||
|
if len(comment.Children) > 0 && d.depth < d.maxDepth+1 {
|
||||||
|
parent = "parent"
|
||||||
|
fl = true
|
||||||
|
}
|
||||||
|
s.WriteString(d.i.FormatLi(d.Context, comment.Comments, d.depth, eo, parent))
|
||||||
|
if fl {
|
||||||
|
d.depth++
|
||||||
|
s.WriteString(`<ol class="children">`)
|
||||||
|
s.WriteString(d.formatComment(comment.Children, false))
|
||||||
|
s.WriteString(`</ol>`)
|
||||||
|
if isTop {
|
||||||
|
d.depth = 1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
s.WriteString("</li><!-- #comment-## -->")
|
||||||
|
}
|
||||||
|
|
||||||
|
html = s.String()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d CommentHandler) findComments(comments []*Comments) []*Comments {
|
||||||
|
var r []*Comments
|
||||||
|
for _, comment := range comments {
|
||||||
|
tmp := *comment
|
||||||
|
comment.Children = nil
|
||||||
|
r = append(r, &tmp)
|
||||||
|
if len(comment.Children) > 0 {
|
||||||
|
t := d.findComments(comment.Children)
|
||||||
|
r = append(r, t...)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return r
|
||||||
|
}
|
||||||
|
|
||||||
|
func treeComments(comments []models.Comments) []*Comments {
|
||||||
|
var r = map[uint64]*Comments{
|
||||||
|
0: {
|
||||||
|
Comments: models.Comments{},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
var top []*Comments
|
||||||
|
for _, comment := range comments {
|
||||||
|
c := Comments{
|
||||||
|
Comments: comment,
|
||||||
|
Children: []*Comments{},
|
||||||
|
}
|
||||||
|
r[comment.CommentId] = &c
|
||||||
|
if comment.CommentParent == 0 {
|
||||||
|
top = append(top, &c)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for id, son := range r {
|
||||||
|
if id == son.CommentParent {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
parent := r[son.CommentParent]
|
||||||
|
parent.Children = append(parent.Children, son)
|
||||||
|
}
|
||||||
|
return top
|
||||||
|
}
|
||||||
|
|
||||||
|
func CommonLi() string {
|
||||||
|
return li
|
||||||
|
}
|
||||||
|
|
||||||
|
var commonCommentFormat = CommonCommentFormat{}
|
||||||
|
|
||||||
|
func CommentRender() CommonCommentFormat {
|
||||||
|
return commonCommentFormat
|
||||||
|
}
|
||||||
|
|
||||||
|
type CommonCommentFormat struct {
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c CommonCommentFormat) Sort(i, j *Comments) bool {
|
||||||
|
return i.CommentDate.UnixNano() < j.CommentDate.UnixNano()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c CommonCommentFormat) FormatLi(ctx *gin.Context, m models.Comments, depth int, eo, parent string) string {
|
||||||
|
return FormatLi(CommonLi(), ctx, m, depth, eo, parent)
|
||||||
|
}
|
||||||
|
|
||||||
|
var li = `
|
||||||
|
<li id="comment-{{CommentId}}" class="comment {{eo}} thread-even depth-{{Depth}} {{parent}}">
|
||||||
|
<article id="div-comment-{{CommentId}}" class="comment-body">
|
||||||
|
<footer class="comment-meta">
|
||||||
|
<div class="comment-author vcard">
|
||||||
|
<img alt=""
|
||||||
|
src="{{Gravatar}}"
|
||||||
|
srcset="{{Gravatar}} 2x"
|
||||||
|
class="avatar avatar-56 photo" height="56" width="56" loading="lazy">
|
||||||
|
<b class="fn">
|
||||||
|
<a href="{{CommentAuthorUrl}}" rel="external nofollow ugc"
|
||||||
|
class="url">{{CommentAuthor}}</a>
|
||||||
|
</b>
|
||||||
|
<span class="says">说道:</span></div><!-- .comment-author -->
|
||||||
|
|
||||||
|
<div class="comment-metadata">
|
||||||
|
<a href="/p/{{PostId}}#comment-{{CommentId}}">
|
||||||
|
<time datetime="{{CommentDateGmt}}">{{CommentDate}}</time>
|
||||||
|
</a></div><!-- .comment-metadata -->
|
||||||
|
|
||||||
|
</footer><!-- .comment-meta -->
|
||||||
|
|
||||||
|
<div class="comment-content">
|
||||||
|
<p>{{CommentContent}}</p>
|
||||||
|
</div><!-- .comment-content -->
|
||||||
|
|
||||||
|
<div class="reply">
|
||||||
|
<a rel="nofollow" class="comment-reply-link"
|
||||||
|
href="/p/{{PostId}}?replytocom={{CommentId}}#respond" data-commentid="{{CommentId}}" data-postid="{{PostId}}"
|
||||||
|
data-belowelement="div-comment-{{CommentId}}" data-respondelement="respond"
|
||||||
|
data-replyto="回复给{{CommentAuthor}}"
|
||||||
|
aria-label="回复给{{CommentAuthor}}">回复</a>
|
||||||
|
</div>
|
||||||
|
</article><!-- .comment-body -->
|
||||||
|
|
||||||
|
`
|
||||||
|
|
||||||
|
func FormatLi(li string, c *gin.Context, comments models.Comments, depth int, eo, parent string) string {
|
||||||
|
for k, v := range map[string]string{
|
||||||
|
"{{CommentId}}": strconv.FormatUint(comments.CommentId, 10),
|
||||||
|
"{{Depth}}": strconv.Itoa(depth),
|
||||||
|
"{{Gravatar}}": Gravatar(comments.CommentAuthorEmail, c.Request.TLS != nil),
|
||||||
|
"{{CommentAuthorUrl}}": comments.CommentAuthorUrl,
|
||||||
|
"{{CommentAuthor}}": comments.CommentAuthor,
|
||||||
|
"{{PostId}}": strconv.FormatUint(comments.CommentPostId, 10),
|
||||||
|
"{{CommentDateGmt}}": comments.CommentDateGmt.String(),
|
||||||
|
"{{CommentDate}}": comments.CommentDate.Format("2006-01-02 15:04"),
|
||||||
|
"{{CommentContent}}": comments.CommentContent,
|
||||||
|
"{{eo}}": eo,
|
||||||
|
"{{parent}}": parent,
|
||||||
|
} {
|
||||||
|
li = strings.Replace(li, k, v, -1)
|
||||||
|
}
|
||||||
|
return li
|
||||||
|
}
|
||||||
|
|
|
@ -26,7 +26,7 @@ func GetTemplate() *multipTemplate.MultipleFsTemplate {
|
||||||
|
|
||||||
// 所有主题模板通用设置
|
// 所有主题模板通用设置
|
||||||
func commonTemplate(t *multipTemplate.MultipleFsTemplate) {
|
func commonTemplate(t *multipTemplate.MultipleFsTemplate) {
|
||||||
m, err := fs.Glob(t.Fs, "*/*[^layout]/*.gohtml")
|
m, err := fs.Glob(t.Fs, "*/posts/*.gohtml")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,6 +3,7 @@ package theme
|
||||||
import (
|
import (
|
||||||
"errors"
|
"errors"
|
||||||
"github.com/fthvgb1/wp-go/internal/pkg/logs"
|
"github.com/fthvgb1/wp-go/internal/pkg/logs"
|
||||||
|
"github.com/fthvgb1/wp-go/internal/pkg/models"
|
||||||
"github.com/fthvgb1/wp-go/internal/plugins"
|
"github.com/fthvgb1/wp-go/internal/plugins"
|
||||||
"github.com/fthvgb1/wp-go/plugin/pagination"
|
"github.com/fthvgb1/wp-go/plugin/pagination"
|
||||||
"github.com/gin-gonic/gin"
|
"github.com/gin-gonic/gin"
|
||||||
|
@ -34,6 +35,7 @@ func Hook(themeName string, code int, c *gin.Context, h gin.H, scene, status int
|
||||||
c.HTML(code, "twentyfifteen/posts/index.gohtml", h)
|
c.HTML(code, "twentyfifteen/posts/index.gohtml", h)
|
||||||
return
|
return
|
||||||
} else if scene == plugins.Detail {
|
} else if scene == plugins.Detail {
|
||||||
|
h["comments"] = plugins.FormatComments(c, plugins.CommentRender(), h["comments"].([]models.Comments), h["maxDep"].(int))
|
||||||
c.HTML(code, "twentyfifteen/posts/detail.gohtml", h)
|
c.HTML(code, "twentyfifteen/posts/detail.gohtml", h)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
38
internal/theme/twentyseventeen/layout/comment.gohtml
Normal file
38
internal/theme/twentyseventeen/layout/comment.gohtml
Normal file
|
@ -0,0 +1,38 @@
|
||||||
|
{{define "respond"}}
|
||||||
|
<div id="respond" class="comment-respond">
|
||||||
|
<h3 id="reply-title" class="comment-reply-title">发表回复
|
||||||
|
<small>
|
||||||
|
<a rel="nofollow" id="cancel-comment-reply-link" href="/p/{{.post.Id}}#respond" style="display:none;">取消回复</a>
|
||||||
|
</small>
|
||||||
|
</h3>
|
||||||
|
<form action="/comment" method="post" id="commentform" class="comment-form"
|
||||||
|
novalidate="">
|
||||||
|
<p class="comment-notes">
|
||||||
|
<span id="email-notes">您的电子邮箱地址不会被公开。</span>
|
||||||
|
<span class="required-field-message" aria-hidden="true">必填项已用<span class="required" aria-hidden="true">*</span>标注</span>
|
||||||
|
</p>
|
||||||
|
<p class="comment-form-comment">
|
||||||
|
<label for="comment">评论 <span class="required" aria-hidden="true">*</span></label>
|
||||||
|
<textarea id="comment" name="comment" cols="45" rows="8" maxlength="65525" required=""></textarea></p>
|
||||||
|
<p class="comment-form-author">
|
||||||
|
<label for="author">显示名称 <span class="required" aria-hidden="true">*</span></label>
|
||||||
|
<input id="author" name="author" type="text" value="" size="30" maxlength="245"
|
||||||
|
required=""></p>
|
||||||
|
<p class="comment-form-email">
|
||||||
|
<label for="email">电子邮箱地址 <span class="required" aria-hidden="true">*</span></label>
|
||||||
|
<input id="email" name="email" type="email" value="" size="30" maxlength="100"
|
||||||
|
aria-describedby="email-notes" required="">
|
||||||
|
</p>
|
||||||
|
<p class="comment-form-url">
|
||||||
|
<label for="url">网站地址</label>
|
||||||
|
<input id="url" name="url" type="url" value="" size="30" maxlength="200">
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<p class="form-submit">
|
||||||
|
<input name="submit" type="submit" id="submit" class="submit" value="发表评论">
|
||||||
|
<input type="hidden" name="comment_post_ID" value="{{.post.Id}}" id="comment_post_ID">
|
||||||
|
<input type="hidden" name="comment_parent" id="comment_parent" value="0">
|
||||||
|
</p>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
{{end}}
|
|
@ -65,50 +65,15 @@
|
||||||
{{ if .showComment}}
|
{{ if .showComment}}
|
||||||
<div id="comments" class="comments-area">
|
<div id="comments" class="comments-area">
|
||||||
{{ if gt .post.CommentCount 0}}
|
{{ if gt .post.CommentCount 0}}
|
||||||
<h2 class="comments-title">《{{.post.PostTitle}}》上有{{.post.CommentCount}}条评论 </h2>
|
<h2 class="comments-title">“{{.post.PostTitle}}”的{{.post.CommentCount}}个回复 </h2>
|
||||||
<ol class="comment-list">
|
<ol class="comment-list">
|
||||||
{{.comments|unescaped}}
|
{{.comments|unescaped}}
|
||||||
</ol>
|
</ol>
|
||||||
|
|
||||||
{{end}}
|
{{end}}
|
||||||
{{if eq .post.CommentStatus "open"}}
|
{{if eq .post.CommentStatus "open"}}
|
||||||
<div id="respond" class="comment-respond">
|
{{template "respond" .}}
|
||||||
<h3 id="reply-title" class="comment-reply-title">发表回复
|
<!-- #respond -->
|
||||||
<small>
|
|
||||||
<a rel="nofollow" id="cancel-comment-reply-link" href="/p/{{.post.Id}}#respond" style="display:none;">取消回复</a>
|
|
||||||
</small>
|
|
||||||
</h3>
|
|
||||||
<form action="/comment" method="post" id="commentform" class="comment-form"
|
|
||||||
novalidate="">
|
|
||||||
<p class="comment-notes">
|
|
||||||
<span id="email-notes">您的电子邮箱地址不会被公开。</span>
|
|
||||||
<span class="required-field-message" aria-hidden="true">必填项已用<span class="required" aria-hidden="true">*</span>标注</span>
|
|
||||||
</p>
|
|
||||||
<p class="comment-form-comment">
|
|
||||||
<label for="comment">评论 <span class="required" aria-hidden="true">*</span></label>
|
|
||||||
<textarea id="comment" name="comment" cols="45" rows="8" maxlength="65525" required=""></textarea></p>
|
|
||||||
<p class="comment-form-author">
|
|
||||||
<label for="author">显示名称 <span class="required" aria-hidden="true">*</span></label>
|
|
||||||
<input id="author" name="author" type="text" value="" size="30" maxlength="245"
|
|
||||||
required=""></p>
|
|
||||||
<p class="comment-form-email">
|
|
||||||
<label for="email">电子邮箱地址 <span class="required" aria-hidden="true">*</span></label>
|
|
||||||
<input id="email" name="email" type="email" value="" size="30" maxlength="100"
|
|
||||||
aria-describedby="email-notes" required="">
|
|
||||||
</p>
|
|
||||||
<p class="comment-form-url"><label for="url">网站地址</label>
|
|
||||||
<input id="url" name="url" type="url" value="" size="30" maxlength="200"></p>
|
|
||||||
<p class="comment-form-cookies-consent">
|
|
||||||
<input id="wp-comment-cookies-consent" name="wp-comment-cookies-consent" type="checkbox" value="yes">
|
|
||||||
<label for="wp-comment-cookies-consent">在此浏览器中保存我的显示名称、邮箱地址和网站地址,以便下次评论时使用。</label>
|
|
||||||
</p>
|
|
||||||
<p class="form-submit">
|
|
||||||
<input name="submit" type="submit" id="submit" class="submit" value="发表评论">
|
|
||||||
<input type="hidden" name="comment_post_ID" value="{{.post.Id}}" id="comment_post_ID">
|
|
||||||
<input type="hidden" name="comment_parent" id="comment_parent" value="0">
|
|
||||||
</p>
|
|
||||||
</form>
|
|
||||||
</div><!-- #respond -->
|
|
||||||
{{else}}
|
{{else}}
|
||||||
<p class="no-comments">评论已关闭。</p>
|
<p class="no-comments">评论已关闭。</p>
|
||||||
{{end}}
|
{{end}}
|
||||||
|
@ -118,22 +83,32 @@
|
||||||
|
|
||||||
<nav class="navigation post-navigation" aria-label="文章">
|
<nav class="navigation post-navigation" aria-label="文章">
|
||||||
<h2 class="screen-reader-text">文章导航</h2>
|
<h2 class="screen-reader-text">文章导航</h2>
|
||||||
|
|
||||||
<div class="nav-links">
|
<div class="nav-links">
|
||||||
{{if gt .prev.Id 0}}
|
{{if gt .prev.Id 0}}
|
||||||
<div class="nav-previous">
|
<div class="nav-previous">
|
||||||
<a href="/p/{{.prev.Id}}" rel="prev">
|
<a href="/p/{{.prev.Id}}" rel="prev">
|
||||||
<span class="meta-nav" aria-hidden="true">上一篇</span>
|
<span class="screen-reader-text">上一篇文章</span>
|
||||||
<span class="screen-reader-text">上篇文章:</span>
|
<span aria-hidden="true" class="nav-subtitle">上一篇</span>
|
||||||
<span class="post-title">{{.prev.PostTitle}}</span></a>
|
<span class="nav-title">
|
||||||
|
<span class="nav-title-icon-wrapper">
|
||||||
|
<svg class="icon icon-arrow-left" aria-hidden="true" role="img"> <use href="#icon-arrow-left" xlink:href="#icon-arrow-left"></use>
|
||||||
|
</svg>
|
||||||
|
</span> {{.prev.PostTitle}}
|
||||||
|
</span>
|
||||||
|
</a>
|
||||||
</div>
|
</div>
|
||||||
{{end}}
|
{{end}}
|
||||||
{{if gt .next.Id 0}}
|
{{if gt .next.Id 0}}
|
||||||
<div class="nav-next">
|
<div class="nav-next">
|
||||||
<a href="/p/{{.next.Id}}" rel="next">
|
<a href="/p/{{.next.Id}}" rel="next">
|
||||||
<span class="meta-nav" aria-hidden="true">下一篇</span>
|
<span class="screen-reader-text" aria-hidden="true">下一篇文章</span>
|
||||||
<span class="screen-reader-text">下篇文章:</span>
|
<span aria-hidden="true" class="nav-subtitle">下一篇</span>
|
||||||
<span class="post-title">{{.next.PostTitle}}</span></a>
|
<span class="nav-title">{{.next.PostTitle}}
|
||||||
|
<span class="nav-title-icon-wrapper">
|
||||||
|
<svg class="icon icon-arrow-right" aria-hidden="true" role="img"> <use href="#icon-arrow-right" xlink:href="#icon-arrow-right"></use> </svg>
|
||||||
|
</span>
|
||||||
|
</span>
|
||||||
|
</a>
|
||||||
</div>
|
</div>
|
||||||
{{end}}
|
{{end}}
|
||||||
|
|
||||||
|
|
|
@ -86,12 +86,33 @@ func Hook(status int, c *gin.Context, h gin.H, scene, stats int) {
|
||||||
img.Srcset = fmt.Sprintf("%s %dw, %s", img.Path, img.Width, img.Srcset)
|
img.Srcset = fmt.Sprintf("%s %dw, %s", img.Path, img.Width, img.Srcset)
|
||||||
post.Thumbnail = img
|
post.Thumbnail = img
|
||||||
h["post"] = post
|
h["post"] = post
|
||||||
|
comments := h["comments"].([]models.Comments)
|
||||||
|
dep := h["maxDep"].(int)
|
||||||
|
h["comments"] = plugins.FormatComments(c, comment{}, comments, dep)
|
||||||
templ = "twentyseventeen/posts/detail.gohtml"
|
templ = "twentyseventeen/posts/detail.gohtml"
|
||||||
}
|
}
|
||||||
c.HTML(status, templ, h)
|
c.HTML(status, templ, h)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type comment struct {
|
||||||
|
plugins.CommonCommentFormat
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c comment) FormatLi(ctx *gin.Context, m models.Comments, depth int, eo, parent string) string {
|
||||||
|
templ := plugins.CommonLi()
|
||||||
|
templ = strings.ReplaceAll(templ, `<a rel="nofollow" class="comment-reply-link"
|
||||||
|
href="/p/{{PostId}}?replytocom={{CommentId}}#respond" data-commentid="{{CommentId}}" data-postid="{{PostId}}"
|
||||||
|
data-belowelement="div-comment-{{CommentId}}" data-respondelement="respond"
|
||||||
|
data-replyto="回复给{{CommentAuthor}}"
|
||||||
|
aria-label="回复给{{CommentAuthor}}">回复</a>`, `<a rel="nofollow" class="comment-reply-link"
|
||||||
|
href="/p/{{PostId}}?replytocom={{CommentId}}#respond" data-commentid="{{CommentId}}" data-postid="{{PostId}}"
|
||||||
|
data-belowelement="div-comment-{{CommentId}}" data-respondelement="respond"
|
||||||
|
data-replyto="回复给{{CommentAuthor}}"
|
||||||
|
aria-label="回复给{{CommentAuthor}}"><svg class="icon icon-mail-reply" aria-hidden="true" role="img"> <use href="#icon-mail-reply" xlink:href="#icon-mail-reply"></use> </svg>回复</a>`)
|
||||||
|
return plugins.FormatLi(templ, ctx, m, depth, eo, parent)
|
||||||
|
}
|
||||||
|
|
||||||
func postThumbnail(posts []models.Posts, scene int) []models.Posts {
|
func postThumbnail(posts []models.Posts, scene int) []models.Posts {
|
||||||
return slice.Map(posts, func(t models.Posts) models.Posts {
|
return slice.Map(posts, func(t models.Posts) models.Posts {
|
||||||
if t.Thumbnail.Path != "" {
|
if t.Thumbnail.Path != "" {
|
||||||
|
|
Loading…
Reference in New Issue
Block a user