diff --git a/.gitignore b/.gitignore
index ec6ad68..ca75a72 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,9 +1,11 @@
-*.exe
-*.exe~
-static/dist/*
-dist/*
-logs/*
-docs/*
-blog
-blog.*
-publish*
\ No newline at end of file
+*.exe
+*.exe~
+static/dist/*
+dist/*
+logs/*
+docs/*
+blog
+blog.*
+publish*
+package-lock.json
+.idea
diff --git a/control/post.go b/control/post.go
index a8d7bcd..c6bd135 100644
--- a/control/post.go
+++ b/control/post.go
@@ -1,174 +1,178 @@
-package control
-
-import (
- "blog/model"
- "strconv"
- "strings"
- "time"
-
- "github.com/labstack/echo/v4"
- "github.com/zxysilent/utils"
-)
-
-// PostGet 一个
-// id int
-func PostGet(ctx echo.Context) error {
- id, err := strconv.Atoi(ctx.Param("id"))
- if err != nil {
- return ctx.JSON(utils.ErrIpt(`数据输入错误,请重试`, err.Error()))
- }
- mod, has := model.PostGet(id)
- if !has {
- return ctx.JSON(utils.ErrOpt(`未查询信息`))
- }
- return ctx.JSON(utils.Succ(`信息`, mod))
-}
-
-// PostPageAll 页面列表
-func PostPageAll(ctx echo.Context) error {
- mods, err := model.PostPageAll()
- if err != nil {
- return ctx.JSON(utils.ErrOpt(`未查询到页面信息`, err.Error()))
- }
- if len(mods) < 1 {
- return ctx.JSON(utils.ErrOpt(`未查询到页面信息`, "len"))
- }
- return ctx.JSON(utils.Succ(`页面信息`, mods))
-}
-
-// PostTagGet 通过文章id 获取 标签ids
-func PostTagGet(ctx echo.Context) error {
- id, err := strconv.Atoi(ctx.Param("id"))
- if err != nil {
- return ctx.JSON(utils.ErrIpt(`数据输入错误,请重试`, err.Error()))
- }
- mods := model.PostTagGet(id)
- if mods == nil {
- return ctx.JSON(utils.ErrOpt(`未查询到标签信息`))
- }
- return ctx.JSON(utils.Succ(`标签ids`, mods))
-}
-
-// PostOpts 文章操作
-func PostOpts(ctx echo.Context) error {
- ipt := &struct {
- Post model.Post `json:"post" form:"post"` // 文章信息
- Type int `json:"type" form:"type"` // 0 文章 1 页面
- Tags []int `json:"tags" form:"tags"` // 标签
- Edit bool `json:"edit" form:"edit"` // 是否编辑
- }{}
- err := ctx.Bind(ipt)
- if err != nil {
- return ctx.JSON(utils.ErrIpt(`数据输入错误,请重试`, err.Error()))
- }
- if !ipt.Edit && model.PostExist(ipt.Post.Path) {
- return ctx.JSON(utils.ErrIpt(`当前访问路径已经存在,请重新输入`))
- }
- // 同步类型
- ipt.Post.Type = ipt.Type
- if strings.Contains(ipt.Post.Content, "") {
- ipt.Post.Summary = strings.Split(ipt.Post.Content, "")[0]
- }
- // 生成目录
- if ipt.Type == 0 {
- ipt.Post.Content = getTocHTML(ipt.Post.Content)
- }
- // 编辑 文章/页面
- if ipt.Edit {
- // 修改日期在发布日期之前
- if ipt.Post.UpdateTime.Before(ipt.Post.CreateTime) {
- // 修改时间再发布时间后1分钟
- ipt.Post.UpdateTime = ipt.Post.CreateTime.Add(time.Minute * 2)
- }
- if model.PostEdit(&ipt.Post) {
- if ipt.Type == 0 {
- // 处理变动标签
- old := model.PostTagGet(ipt.Post.Id)
- new := ipt.Tags
- add := make([]int, 0)
- del := make([]int, 0)
- for _, itm := range old {
- if !inOf(itm, new) {
- del = append(del, itm)
- }
- }
- for _, itm := range new {
- if !inOf(itm, old) {
- add = append(add, itm)
- }
- }
- tagAdds := make([]model.PostTag, 0, len(add))
- for _, itm := range add {
- tagAdds = append(tagAdds, model.PostTag{
- TagId: itm,
- PostId: ipt.Post.Id,
- })
- }
- // 删除标签
- model.PostTagDrops(ipt.Post.Id, del)
- // 添加标签
- model.TagPostAdds(&tagAdds)
- return ctx.JSON(utils.Succ(`文章修改成功`))
- }
- return ctx.JSON(utils.Succ(`页面修改成功`))
- }
- if ipt.Type == 0 {
- return ctx.JSON(utils.Fail(`文章修改失败,请重试`))
- }
- return ctx.JSON(utils.Fail(`页面修改失败,请重试`))
- }
- // 添加 文章/页面
- ipt.Post.UpdateTime = time.Now()
- if model.PostAdd(&ipt.Post) {
- // 添加标签
- // 文章
- if ipt.Type == 0 {
- //添加标签
- tagPosts := make([]model.PostTag, 0, len(ipt.Tags))
- for _, itm := range ipt.Tags {
- tagPosts = append(tagPosts, model.PostTag{
- TagId: itm,
- PostId: ipt.Post.Id,
- })
- }
- model.TagPostAdds(&tagPosts)
- return ctx.JSON(utils.Succ(`文章添加成功`))
- }
- return ctx.JSON(utils.Succ(`页面添加成功`))
- }
- if ipt.Type == 0 {
- return ctx.JSON(utils.Fail(`文章添加失败,请重试`))
- }
- return ctx.JSON(utils.Fail(`页面添加失败,请重试`))
-}
-func similar(a, b string) int {
- if a[:4] == b[:4] {
- return 0
- }
- if a[:4] < b[:4] {
- return 1
- }
- return -1
-}
-
-// PostDrop 删除
-func PostDrop(ctx echo.Context) error {
- id, err := strconv.Atoi(ctx.Param("id"))
- if err != nil {
- return ctx.JSON(utils.ErrIpt(`数据输入错误,请重试`, err.Error()))
- }
- if !model.PostDrop(id) {
- return ctx.JSON(utils.Fail(`删除失败,请重试`))
- }
- // 删除 文章对应的标签信息
- model.PostTagDrop(id)
- return ctx.JSON(utils.Succ(`删除成功`))
-}
-func inOf(goal int, arr []int) bool {
- for idx := range arr {
- if goal == arr[idx] {
- return true
- }
- }
- return false
-}
+package control
+
+import (
+ "blog/model"
+ "strconv"
+ "strings"
+ "time"
+
+ "github.com/labstack/echo/v4"
+ "github.com/zxysilent/utils"
+)
+
+// PostGet 一个
+// id int
+func PostGet(ctx echo.Context) error {
+ id, err := strconv.Atoi(ctx.Param("id"))
+ if err != nil {
+ return ctx.JSON(utils.ErrIpt(`数据输入错误,请重试`, err.Error()))
+ }
+ mod, has := model.PostGet(id)
+ if !has {
+ return ctx.JSON(utils.ErrOpt(`未查询信息`))
+ }
+ return ctx.JSON(utils.Succ(`信息`, mod))
+}
+
+// PostPageAll 页面列表
+func PostPageAll(ctx echo.Context) error {
+ mods, err := model.PostPageAll()
+ if err != nil {
+ return ctx.JSON(utils.ErrOpt(`未查询到页面信息`, err.Error()))
+ }
+ if len(mods) < 1 {
+ return ctx.JSON(utils.ErrOpt(`未查询到页面信息`, "len"))
+ }
+ return ctx.JSON(utils.Succ(`页面信息`, mods))
+}
+
+// PostTagGet 通过文章id 获取 标签ids
+func PostTagGet(ctx echo.Context) error {
+ id, err := strconv.Atoi(ctx.Param("id"))
+ if err != nil {
+ return ctx.JSON(utils.ErrIpt(`数据输入错误,请重试`, err.Error()))
+ }
+ mods := model.PostTagGet(id)
+ if mods == nil {
+ return ctx.JSON(utils.ErrOpt(`未查询到标签信息`))
+ }
+ return ctx.JSON(utils.Succ(`标签ids`, mods))
+}
+
+// PostOpts 文章操作
+func PostOpts(ctx echo.Context) error {
+ ipt := &struct {
+ Post model.Post `json:"post" form:"post"` // 文章信息
+ Type int `json:"type" form:"type"` // 0 文章 1 页面
+ Tags []int `json:"tags" form:"tags"` // 标签
+ Edit bool `json:"edit" form:"edit"` // 是否编辑
+ }{}
+
+ err := ctx.Bind(ipt)
+ if err != nil {
+ return ctx.JSON(utils.ErrIpt(`数据输入错误,请重试`, err.Error()))
+ }
+ if !ipt.Edit && model.PostExist(ipt.Post.Path) {
+ return ctx.JSON(utils.ErrIpt(`当前访问路径已经存在,请重新输入`))
+ }
+ // 同步类型
+ ipt.Post.Type = ipt.Type
+ if strings.Contains(ipt.Post.Content, "") {
+ ipt.Post.Summary = strings.Split(ipt.Post.Content, "")[0]
+ }
+ // 生成目录
+ if ipt.Type == 0 {
+ ipt.Post.Content = getTocHTML(ipt.Post.Content)
+ }
+
+ ipt.Post.UserId = ctx.Get("uid").(int)
+
+ // 编辑 文章/页面
+ if ipt.Edit {
+ // 修改日期在发布日期之前
+ if ipt.Post.UpdateTime.Before(ipt.Post.CreateTime) {
+ // 修改时间再发布时间后1分钟
+ ipt.Post.UpdateTime = ipt.Post.CreateTime.Add(time.Minute * 2)
+ }
+ if model.PostEdit(&ipt.Post) {
+ if ipt.Type == 0 {
+ // 处理变动标签
+ old := model.PostTagGet(ipt.Post.Id)
+ new := ipt.Tags
+ add := make([]int, 0)
+ del := make([]int, 0)
+ for _, itm := range old {
+ if !inOf(itm, new) {
+ del = append(del, itm)
+ }
+ }
+ for _, itm := range new {
+ if !inOf(itm, old) {
+ add = append(add, itm)
+ }
+ }
+ tagAdds := make([]model.PostTag, 0, len(add))
+ for _, itm := range add {
+ tagAdds = append(tagAdds, model.PostTag{
+ TagId: itm,
+ PostId: ipt.Post.Id,
+ })
+ }
+ // 删除标签
+ model.PostTagDrops(ipt.Post.Id, del)
+ // 添加标签
+ model.TagPostAdds(&tagAdds)
+ return ctx.JSON(utils.Succ(`文章修改成功`))
+ }
+ return ctx.JSON(utils.Succ(`页面修改成功`))
+ }
+ if ipt.Type == 0 {
+ return ctx.JSON(utils.Fail(`文章修改失败,请重试`))
+ }
+ return ctx.JSON(utils.Fail(`页面修改失败,请重试`))
+ }
+ // 添加 文章/页面
+ ipt.Post.UpdateTime = time.Now()
+ if model.PostAdd(&ipt.Post) {
+ // 添加标签
+ // 文章
+ if ipt.Type == 0 {
+ //添加标签
+ tagPosts := make([]model.PostTag, 0, len(ipt.Tags))
+ for _, itm := range ipt.Tags {
+ tagPosts = append(tagPosts, model.PostTag{
+ TagId: itm,
+ PostId: ipt.Post.Id,
+ })
+ }
+ model.TagPostAdds(&tagPosts)
+ return ctx.JSON(utils.Succ(`文章添加成功`))
+ }
+ return ctx.JSON(utils.Succ(`页面添加成功`))
+ }
+ if ipt.Type == 0 {
+ return ctx.JSON(utils.Fail(`文章添加失败,请重试`))
+ }
+ return ctx.JSON(utils.Fail(`页面添加失败,请重试`))
+}
+func similar(a, b string) int {
+ if a[:4] == b[:4] {
+ return 0
+ }
+ if a[:4] < b[:4] {
+ return 1
+ }
+ return -1
+}
+
+// PostDrop 删除
+func PostDrop(ctx echo.Context) error {
+ id, err := strconv.Atoi(ctx.Param("id"))
+ if err != nil {
+ return ctx.JSON(utils.ErrIpt(`数据输入错误,请重试`, err.Error()))
+ }
+ if !model.PostDrop(id) {
+ return ctx.JSON(utils.Fail(`删除失败,请重试`))
+ }
+ // 删除 文章对应的标签信息
+ model.PostTagDrop(id)
+ return ctx.JSON(utils.Succ(`删除成功`))
+}
+func inOf(goal int, arr []int) bool {
+ for idx := range arr {
+ if goal == arr[idx] {
+ return true
+ }
+ }
+ return false
+}
diff --git a/control/views.go b/control/views.go
index db9d146..ee844a1 100644
--- a/control/views.go
+++ b/control/views.go
@@ -1,222 +1,284 @@
-package control
-
-import (
- "blog/model"
- "net/http"
- "regexp"
- "strconv"
- "strings"
-
- "github.com/labstack/echo/v4"
- "github.com/zxysilent/utils"
-)
-
-// IndexView 主页面
-func IndexView(ctx echo.Context) error {
- //return ctx.HTML(200, `
文档 doc `)
- pi, _ := strconv.Atoi(ctx.FormValue("page"))
- if pi == 0 {
- pi = 1
- }
- ps, _ := atoi(model.MapOpts.MustGet("page_size"), 6)
- mods, _ := model.PostPage(pi, ps)
- total := model.PostCount()
- naver := model.Naver{}
- if pi > 1 {
- naver.Prev = "/?page=" + strconv.Itoa(pi-1)
- }
- if total > (pi * ps) {
- naver.Next = "/?page=" + strconv.Itoa(pi+1)
- }
- return ctx.Render(http.StatusOK, "index.html", map[string]interface{}{
- "Posts": mods,
- "Naver": naver,
- })
-}
-
-// ArchivesView 归档
-func ArchivesView(ctx echo.Context) error {
- mods, err := model.PostArchive()
- if err != nil {
- return ctx.Redirect(302, "/")
- }
- return ctx.Render(http.StatusOK, "archive.html", map[string]interface{}{
- "Posts": mods,
- })
-}
-func ArchivesJson(ctx echo.Context) error {
- mods, err := model.PostArchive()
- if err != nil {
- return ctx.JSON(utils.Fail("未查询到数据", err))
- }
- return ctx.JSON(utils.Succ("归档", mods))
-}
-
-// CatePostView 分类文章列表
-func CatePostView(ctx echo.Context) error {
- cate := ctx.Param("cate")
- if cate == "" {
- return ctx.Redirect(302, "/")
- }
- mod, has := model.CateName(cate)
- if !has {
- return ctx.Redirect(302, "/")
- }
- pi, _ := strconv.Atoi(ctx.FormValue("page"))
- if pi == 0 {
- pi = 1
- }
- ps, _ := atoi(model.MapOpts.MustGet("page_size"), 6)
- mods, err := model.CatePostList(mod.Id, pi, ps, true)
- if err != nil || len(mods) < 1 {
- return ctx.Redirect(302, "/")
- }
- total := model.CatePostCount(mod.Id, true)
- naver := model.Naver{}
- if pi > 1 {
- naver.Prev = "/cate/" + mod.Name + "?page=1"
- }
- if total > (pi * ps) {
- naver.Next = "/cate/" + mod.Name + "?page=" + strconv.Itoa(pi+1)
- }
- return ctx.Render(http.StatusOK, "cate-post.html", map[string]interface{}{
- "Cate": mod,
- "CatePosts": mods,
- "Naver": naver,
- })
-}
-
-// TagsView 标签列表
-func TagsView(ctx echo.Context) error {
- mods, err := model.TagStateAll()
- if err != nil {
- return ctx.Redirect(302, "/")
- }
- return ctx.Render(http.StatusOK, "tags.html", map[string]interface{}{
- "Tags": mods,
- })
-}
-func TagsJson(ctx echo.Context) error {
- mods, err := model.TagStateAll()
- if err != nil {
- return ctx.JSON(utils.Fail("未查询到标签", err))
- }
- return ctx.JSON(utils.Succ("标签", mods))
-}
-
-// TagPostView 标签文章列表
-func TagPostView(ctx echo.Context) error {
- tag := ctx.Param("tag")
- if tag == "" {
- return ctx.Redirect(302, "/tags")
- }
- mod, has := model.TagName(tag)
- if !has {
- return ctx.Redirect(302, "/tags")
- }
- pi, _ := strconv.Atoi(ctx.FormValue("page"))
- if pi == 0 {
- pi = 1
- }
- ps, _ := atoi(model.MapOpts.MustGet("page_size"), 6)
- mods, err := model.TagPostList(mod.Id, pi, ps)
- if err != nil || len(mods) < 1 {
- return ctx.Redirect(302, "/tags")
- }
- total := model.TagPostCount(mod.Id)
- naver := model.Naver{}
- if pi > 1 {
- naver.Prev = "/tag/" + mod.Name + "?page=1"
- }
- if total > (pi * ps) {
- naver.Next = "/tag/" + mod.Name + "?page=" + strconv.Itoa(pi+1)
- }
- return ctx.Render(http.StatusOK, "tag-post.html", map[string]interface{}{
- "Tag": mod,
- "TagPosts": mods,
- "Naver": naver,
- })
-}
-
-// PostView 文章页面
-func PostView(ctx echo.Context) error {
- //return ctx.HTML(200, `文档 doc `)
- paths := strings.Split(ctx.Param("*"), ".")
- if len(paths) == 2 {
- mod, naver, has := model.PostPath(paths[0])
- if !has {
- return ctx.Redirect(302, "/")
- }
- if paths[1] == "html" {
- mod.Content = reg.ReplaceAllString(mod.Content, ` `)
- tags, _ := model.PostTags(mod.Id)
- return ctx.Render(http.StatusOK, "post.html", map[string]interface{}{
- "Post": mod,
- "Naver": naver,
- "Tags": tags,
- "HasTag": len(tags) > 0,
- "HasCate": mod.Cate != nil,
- })
- }
- return ctx.JSON(utils.Succ("", mod))
- }
- return ctx.Redirect(302, "/404")
-}
-
-var reg = regexp.MustCompile(` `)
-
-// 生成目录并替换内容
-func getTocHTML(html string) string {
- html = strings.Replace(html, `id="`, `id="toc_`, -1)
- regToc := regexp.MustCompile(".*? ")
- regH := regexp.MustCompile(` (.*?) `)
- hs := regToc.FindAllString(html, -1)
- if len(hs) > 1 {
- sb := strings.Builder{}
- sb.WriteString(``)
- level := 0
- for i := 0; i < len(hs)-1; i++ {
- fg := similar(hs[i], hs[i+1])
- if fg == 0 {
- sb.WriteString(regH.ReplaceAllString(hs[i], `$2 `))
- } else if fg == 1 {
- level++
- sb.WriteString(regH.ReplaceAllString(hs[i], `$2 `))
- } else {
- level--
- sb.WriteString(regH.ReplaceAllString(hs[i], `$2 `))
- }
- }
- fg := similar(hs[len(hs)-2], hs[len(hs)-1])
- if fg == 0 {
- sb.WriteString(regH.ReplaceAllString(hs[len(hs)-1], `$2 `))
- } else if fg == 1 {
- level++
- sb.WriteString(regH.ReplaceAllString(hs[len(hs)-1], `$2 `))
- } else {
- level--
- sb.WriteString(regH.ReplaceAllString(hs[len(hs)-1], `$2 `))
- }
- for level > 0 {
- sb.WriteString(` `)
- level--
- }
- sb.WriteString(`
`)
- return sb.String() + html
- }
- if len(hs) == 1 {
- sb := strings.Builder{}
- sb.WriteString(``)
- sb.WriteString(regH.ReplaceAllString(hs[0], `$2 `))
- sb.WriteString(` `)
- return sb.String() + html
- }
- return html
-}
-func atoi(raw string, def int) (int, error) {
- out, err := strconv.Atoi(raw)
- if err != nil {
- return def, err
- }
- return out, nil
-}
+package control
+
+import (
+ "blog/model"
+ "net/http"
+ "regexp"
+ "strconv"
+ "strings"
+
+ "github.com/labstack/echo/v4"
+ "github.com/zxysilent/utils"
+ "github.com/grokify/html-strip-tags-go"
+ "time"
+ "fmt"
+)
+
+// IndexView 主页面
+func IndexView(ctx echo.Context) error {
+ //return ctx.HTML(200, `文档 doc `)
+ pi, _ := strconv.Atoi(ctx.FormValue("page"))
+ if pi == 0 {
+ pi = 1
+ }
+ ps, _ := atoi(model.MapOpts.MustGet("page_size"), 6)
+ mods, _ := model.PostPage(pi, ps)
+ total := model.PostCount()
+ naver := model.Naver{}
+ if pi > 1 {
+ naver.Prev = "/?page=" + strconv.Itoa(pi-1)
+ }
+ if total > (pi * ps) {
+ naver.Next = "/?page=" + strconv.Itoa(pi+1)
+ }
+ return ctx.Render(http.StatusOK, "index.html", map[string]interface{}{
+ "Posts": mods,
+ "Naver": naver,
+ })
+}
+
+// ArchivesView 归档
+func ArchivesView(ctx echo.Context) error {
+ mods, err := model.PostArchive()
+ if err != nil {
+ return ctx.Redirect(302, "/")
+ }
+ return ctx.Render(http.StatusOK, "archive.html", map[string]interface{}{
+ "Posts": mods,
+ })
+}
+func ArchivesJson(ctx echo.Context) error {
+ mods, err := model.PostArchive()
+ if err != nil {
+ return ctx.JSON(utils.Fail("未查询到数据", err))
+ }
+ return ctx.JSON(utils.Succ("归档", mods))
+}
+
+// CatePostView 分类文章列表
+func CatePostView(ctx echo.Context) error {
+ cate := ctx.Param("cate")
+ if cate == "" {
+ return ctx.Redirect(302, "/")
+ }
+ mod, has := model.CateName(cate)
+ if !has {
+ return ctx.Redirect(302, "/")
+ }
+ pi, _ := strconv.Atoi(ctx.FormValue("page"))
+ if pi == 0 {
+ pi = 1
+ }
+ ps, _ := atoi(model.MapOpts.MustGet("page_size"), 6)
+ mods, err := model.CatePostList(mod.Id, pi, ps, true)
+ if err != nil || len(mods) < 1 {
+ return ctx.Redirect(302, "/")
+ }
+ total := model.CatePostCount(mod.Id, true)
+ naver := model.Naver{}
+ if pi > 1 {
+ naver.Prev = "/cate/" + mod.Name + "?page=1"
+ }
+ if total > (pi * ps) {
+ naver.Next = "/cate/" + mod.Name + "?page=" + strconv.Itoa(pi+1)
+ }
+ return ctx.Render(http.StatusOK, "cate-post.html", map[string]interface{}{
+ "Cate": mod,
+ "CatePosts": mods,
+ "Naver": naver,
+ })
+}
+
+// TagsView 标签列表
+func TagsView(ctx echo.Context) error {
+ mods, err := model.TagStateAll()
+ if err != nil {
+ return ctx.Redirect(302, "/")
+ }
+ return ctx.Render(http.StatusOK, "tags.html", map[string]interface{}{
+ "Tags": mods,
+ })
+}
+func TagsJson(ctx echo.Context) error {
+ mods, err := model.TagStateAll()
+ if err != nil {
+ return ctx.JSON(utils.Fail("未查询到标签", err))
+ }
+ return ctx.JSON(utils.Succ("标签", mods))
+}
+
+// TagPostView 标签文章列表
+func TagPostView(ctx echo.Context) error {
+ tag := ctx.Param("tag")
+ if tag == "" {
+ return ctx.Redirect(302, "/tags")
+ }
+ mod, has := model.TagName(tag)
+ if !has {
+ return ctx.Redirect(302, "/tags")
+ }
+ pi, _ := strconv.Atoi(ctx.FormValue("page"))
+ if pi == 0 {
+ pi = 1
+ }
+ ps, _ := atoi(model.MapOpts.MustGet("page_size"), 6)
+ mods, err := model.TagPostList(mod.Id, pi, ps)
+ if err != nil || len(mods) < 1 {
+ return ctx.Redirect(302, "/tags")
+ }
+ total := model.TagPostCount(mod.Id)
+ naver := model.Naver{}
+ if pi > 1 {
+ naver.Prev = "/tag/" + mod.Name + "?page=1"
+ }
+ if total > (pi * ps) {
+ naver.Next = "/tag/" + mod.Name + "?page=" + strconv.Itoa(pi+1)
+ }
+ return ctx.Render(http.StatusOK, "tag-post.html", map[string]interface{}{
+ "Tag": mod,
+ "TagPosts": mods,
+ "Naver": naver,
+ })
+}
+
+// PostView 文章页面
+func PostView(ctx echo.Context) error {
+ //return ctx.HTML(200, `文档 doc `)
+ paths := strings.Split(ctx.Param("*"), ".")
+ if len(paths) == 2 {
+ mod, naver, has := model.PostPath(paths[0])
+ if !has {
+ return ctx.Redirect(302, "/")
+ }
+ if paths[1] == "html" {
+ mod.Content = reg.ReplaceAllString(mod.Content, ` `)
+ tags, _ := model.PostTags(mod.Id)
+ return ctx.Render(http.StatusOK, "post.html", map[string]interface{}{
+ "Post": mod,
+ "Naver": naver,
+ "Tags": tags,
+ "HasTag": len(tags) > 0,
+ "HasCate": mod.Cate != nil,
+ })
+ }
+ return ctx.JSON(utils.Succ("", mod))
+ }
+ return ctx.Redirect(302, "/404")
+}
+
+// TagsView 标签列表
+func SearchView(ctx echo.Context) error {
+ t1 := time.Now()
+ q := ctx.QueryParam("q")
+
+ pi, _ := strconv.Atoi(ctx.FormValue("page"))
+ if pi == 0 {
+ pi = 1
+ }
+ ps, _ := atoi(model.MapOpts.MustGet("page_size"), 6)
+
+ mods, err := model.PostPageSearch(pi, ps, q)
+ if err != nil {
+ //return ctx.Redirect(302, "/")
+ }
+
+ total := model.PostCountSearch(q)
+ naver := model.Naver{}
+ if pi > 1 {
+ naver.Prev = "/search?q="+q+"&page=" + strconv.Itoa(pi-1)
+ }
+ if total > (pi * ps) {
+ naver.Next = "/search?q="+q+"&page=" + strconv.Itoa(pi+1)
+ }
+
+ re := regexp.MustCompile(`(?i)`+q)
+ for i:=0; i< len(mods); i++ {
+ mods[i].Title = re.ReplaceAllString(mods[i].Title, ""+"$0"+" ")
+ mods[i].Summary = re.ReplaceAllString(strip.StripTags(mods[i].Summary), ""+"$0"+" ")
+ }
+
+ t2 := time.Now()
+ delta := t2.Sub(t1)
+ duration := fmt.Sprintf("%.3f", delta.Seconds())
+
+ return ctx.Render(http.StatusOK, "search.html", map[string]interface{}{
+ "Q":q,
+ "NotSearch": q == "",
+ "Posts": mods,
+ "Naver":naver,
+ "Total":total,
+ "Duration":duration,
+ })
+}
+
+func Series(ctx echo.Context) error {
+ cates, err := model.CateAll()
+ if err != nil {
+ return err
+ }
+ for i:=0; i`)
+
+// 生成目录并替换内容
+func getTocHTML(html string) string {
+ html = strings.Replace(html, `id="`, `id="toc_`, -1)
+ regToc := regexp.MustCompile(".*? ")
+ regH := regexp.MustCompile(` (.*?) `)
+ hs := regToc.FindAllString(html, -1)
+ if len(hs) > 1 {
+ sb := strings.Builder{}
+ sb.WriteString(`预览目录
`)
+ level := 0
+ for i := 0; i < len(hs)-1; i++ {
+ fg := similar(hs[i], hs[i+1])
+ if fg == 0 {
+ sb.WriteString(regH.ReplaceAllString(hs[i], `$2 `))
+ } else if fg == 1 {
+ level++
+ sb.WriteString(regH.ReplaceAllString(hs[i], `$2 `))
+ } else {
+ level--
+ sb.WriteString(regH.ReplaceAllString(hs[i], `$2 `))
+ }
+ }
+ fg := similar(hs[len(hs)-2], hs[len(hs)-1])
+ if fg == 0 {
+ sb.WriteString(regH.ReplaceAllString(hs[len(hs)-1], `$2 `))
+ } else if fg == 1 {
+ level++
+ sb.WriteString(regH.ReplaceAllString(hs[len(hs)-1], `$2 `))
+ } else {
+ level--
+ sb.WriteString(regH.ReplaceAllString(hs[len(hs)-1], `$2 `))
+ }
+ for level > 0 {
+ sb.WriteString(` `)
+ level--
+ }
+ sb.WriteString(`
`)
+ return sb.String() + html
+ }
+ if len(hs) == 1 {
+ sb := strings.Builder{}
+ sb.WriteString(`预览目录
`)
+ sb.WriteString(regH.ReplaceAllString(hs[0], `$2 `))
+ sb.WriteString(` `)
+ return sb.String() + html
+ }
+ return html
+}
+func atoi(raw string, def int) (int, error) {
+ out, err := strconv.Atoi(raw)
+ if err != nil {
+ return def, err
+ }
+ return out, nil
+}
diff --git a/go.mod b/go.mod
index 5c2df98..680a959 100644
--- a/go.mod
+++ b/go.mod
@@ -6,11 +6,19 @@ go 1.15
require (
github.com/BurntSushi/toml v0.3.1
github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751
+ github.com/cpuguy83/go-md2man/v2 v2.0.0 // indirect
+ github.com/gin-gonic/gin v1.6.3 // indirect
+ github.com/go-openapi/spec v0.20.0 // indirect
github.com/go-sql-driver/mysql v1.5.0
+ github.com/gofrs/uuid v3.3.0+incompatible // indirect
+ github.com/grokify/html-strip-tags-go v0.0.1
github.com/labstack/echo/v4 v4.1.17
+ github.com/russross/blackfriday/v2 v2.1.0 // indirect
github.com/swaggo/echo-swagger v1.0.0
- github.com/swaggo/swag v1.6.9
+ github.com/swaggo/swag v1.7.0
github.com/zxysilent/logs v0.1.4
github.com/zxysilent/utils v0.2.1
+ golang.org/x/net v0.0.0-20201224014010-6772e930b67b // indirect
+ golang.org/x/tools v0.0.0-20210106214847-113979e3529a // indirect
xorm.io/xorm v1.0.5
)
diff --git a/go.sum b/go.sum
index 0fe0dc8..5edb40a 100644
--- a/go.sum
+++ b/go.sum
@@ -13,7 +13,11 @@ github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578/go.mod h1:uGdko
github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751 h1:JYp7IbQjafoB+tBA3gMyHYHrpOtNuDiK/uB5uXxq5wM=
github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
github.com/andybalholm/cascadia v1.1.0/go.mod h1:GsXiBklL0woXo1j/WYWtSYYC4ouU9PqHO0sqidkEA4Y=
+github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d h1:U+s90UTSYgptZMwQh2aRr3LuazLJIa+Pg3Kc1ylSYVY=
github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU=
+github.com/cpuguy83/go-md2man/v2 v2.0.0 h1:EoUDS0afbrsXAZ9YQ9jdu/mZ2sXgT1/2yyNng4PGlyM=
+github.com/cpuguy83/go-md2man/v2 v2.0.0/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU=
+github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
@@ -22,6 +26,7 @@ github.com/dgrijalva/jwt-go v3.2.0+incompatible h1:7qlOGliEKZXTDg6OTjfoBKDXWrumC
github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ=
github.com/fsnotify/fsnotify v1.4.7 h1:IXs+QLmnXW2CcXuY+8Mzv/fWEsPGWxqefPtCP5CnV9I=
github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
+github.com/ghodss/yaml v1.0.0 h1:wQHKEahhL6wmXdzwWG11gIVCkOv05bNOh+Rxn0yngAk=
github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04=
github.com/gin-contrib/gzip v0.0.1/go.mod h1:fGBJBCdt6qCZuCAOwWuFhBB4OOq9EFqlo5dEaFhhu5w=
github.com/gin-contrib/sse v0.0.0-20170109093832-22d885f9ecc7/go.mod h1:VJ0WA2NBN22VlZ2dKZQPAPnyWw5XTlK1KymzLKsr59s=
@@ -34,6 +39,8 @@ github.com/go-openapi/jsonpointer v0.17.0/go.mod h1:cOnomiV+CVVwFLk0A/MExoFMjwds
github.com/go-openapi/jsonpointer v0.19.2/go.mod h1:3akKfEdA7DF1sugOqz1dVQHBcuDBPKZGEoHC/NkiQRg=
github.com/go-openapi/jsonpointer v0.19.3 h1:gihV7YNZK1iK6Tgwwsxo2rJbD1GTbdm72325Bq8FI3w=
github.com/go-openapi/jsonpointer v0.19.3/go.mod h1:Pl9vOtqEWErmShwVjC8pYs9cog34VGT37dQOVbmoatg=
+github.com/go-openapi/jsonpointer v0.19.5 h1:gZr+CIYByUqjcgeLXnQu2gHYQC9o73G2XUeOFYEICuY=
+github.com/go-openapi/jsonpointer v0.19.5/go.mod h1:Pl9vOtqEWErmShwVjC8pYs9cog34VGT37dQOVbmoatg=
github.com/go-openapi/jsonreference v0.17.0/go.mod h1:g4xxGn04lDIRh0GJb5QlpE3HfopLOL6uZrK/VgnsK9I=
github.com/go-openapi/jsonreference v0.19.0/go.mod h1:g4xxGn04lDIRh0GJb5QlpE3HfopLOL6uZrK/VgnsK9I=
github.com/go-openapi/jsonreference v0.19.2/go.mod h1:jMjeRr2HHw6nAVajTXJ4eiUwohSTlpa0o73RUL1owJc=
@@ -41,15 +48,23 @@ github.com/go-openapi/jsonreference v0.19.3 h1:5cxNfTy0UVC3X8JL5ymxzyoUZmo8iZb+j
github.com/go-openapi/jsonreference v0.19.3/go.mod h1:rjx6GuL8TTa9VaixXglHmQmIL98+wF9xc8zWvFonSJ8=
github.com/go-openapi/jsonreference v0.19.4 h1:3Vw+rh13uq2JFNxgnMTGE1rnoieU9FmyE1gvnyylsYg=
github.com/go-openapi/jsonreference v0.19.4/go.mod h1:RdybgQwPxbL4UEjuAruzK1x3nE69AqPYEJeo/TWfEeg=
+github.com/go-openapi/jsonreference v0.19.5 h1:1WJP/wi4OjB4iV8KVbH73rQaoialJrqv8gitZLxGLtM=
+github.com/go-openapi/jsonreference v0.19.5/go.mod h1:RdybgQwPxbL4UEjuAruzK1x3nE69AqPYEJeo/TWfEeg=
github.com/go-openapi/spec v0.19.0/go.mod h1:XkF/MOi14NmjsfZ8VtAKf8pIlbZzyoTvZsdfssdxcBI=
github.com/go-openapi/spec v0.19.4 h1:ixzUSnHTd6hCemgtAJgluaTSGYpLNpJY4mA2DIkdOAo=
github.com/go-openapi/spec v0.19.4/go.mod h1:FpwSN1ksY1eteniUU7X0N/BgJ7a4WvBFVA8Lj9mJglo=
github.com/go-openapi/spec v0.19.9 h1:9z9cbFuZJ7AcvOHKIY+f6Aevb4vObNDkTEyoMfO7rAc=
github.com/go-openapi/spec v0.19.9/go.mod h1:vqK/dIdLGCosfvYsQV3WfC7N3TiZSnGY2RZKoFK7X28=
+github.com/go-openapi/spec v0.19.14/go.mod h1:gwrgJS15eCUgjLpMjBJmbZezCsw88LmgeEip0M63doA=
+github.com/go-openapi/spec v0.20.0 h1:HGLc8AJ7ynOxwv0Lq4TsnwLsWMawHAYiJIFzbcML86I=
+github.com/go-openapi/spec v0.20.0/go.mod h1:+81FIL1JwC5P3/Iuuozq3pPE9dXdIEGxFutcFKaVbmU=
github.com/go-openapi/swag v0.17.0/go.mod h1:AByQ+nYG6gQg71GINrmuDXCPWdL640yX49/kXLo40Tg=
github.com/go-openapi/swag v0.19.2/go.mod h1:POnQmlKehdgb5mhVOsnJFsivZCEZ/vjK9gh66Z9tfKk=
github.com/go-openapi/swag v0.19.5 h1:lTz6Ys4CmqqCQmZPBlbQENR1/GucA2bzYTE12Pw4tFY=
github.com/go-openapi/swag v0.19.5/go.mod h1:POnQmlKehdgb5mhVOsnJFsivZCEZ/vjK9gh66Z9tfKk=
+github.com/go-openapi/swag v0.19.11/go.mod h1:Uc0gKkdR+ojzsEpjh39QChyu92vPgIr72POcgHMAgSY=
+github.com/go-openapi/swag v0.19.12 h1:Bc0bnY2c3AoF7Gc+IMIAQQsD8fLHjHpc19wXvYuayQI=
+github.com/go-openapi/swag v0.19.12/go.mod h1:eFdyEBkTdoAf/9RXBvj4cr1nH7GD8Kzo5HTt47gr72M=
github.com/go-playground/assert/v2 v2.0.1/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvScMdVu0Titje2rxJ4=
github.com/go-playground/locales v0.13.0/go.mod h1:taPMhCMXrRLJO55olJkUXHZBHCxTMfnGwq/HNwmWNS8=
github.com/go-playground/universal-translator v0.17.0/go.mod h1:UkSxE5sNxxRwHyU+Scu5vgOQjsIJAF8j9muTVoKLVtA=
@@ -66,8 +81,12 @@ github.com/golang/protobuf v1.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaW
github.com/golang/snappy v0.0.0-20180518054509-2e65f85255db h1:woRePGFeVFfLKN/pOkfl+p/TAqKOfFu+7KPlMVpok/w=
github.com/golang/snappy v0.0.0-20180518054509-2e65f85255db/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
+github.com/grokify/html-strip-tags-go v0.0.1 h1:0fThFwLbW7P/kOiTBs03FsJSV9RM2M/Q/MOnCQxKMo0=
+github.com/grokify/html-strip-tags-go v0.0.1/go.mod h1:2Su6romC5/1VXOQMaWL2yb618ARB8iVo6/DR99A6d78=
github.com/hpcloud/tail v1.0.0 h1:nfCOvKYfkgYP8hkirhJocXT2+zOD8yUNjXaWfTlyFKI=
github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU=
+github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8HmY=
+github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y=
github.com/json-iterator/go v1.1.5/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU=
github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU=
github.com/json-iterator/go v1.1.9/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
@@ -77,6 +96,7 @@ github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
github.com/kr/pty v1.1.5/go.mod h1:9r2w37qlBe7rQ6e1fg1S/9xpWHSnaqNdHD3WcMdbPDA=
github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE=
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
+github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
github.com/labstack/echo/v4 v4.0.0/go.mod h1:tZv7nai5buKSg5h/8E6zz4LsD/Dqh9/91Mvs7Z5Zyno=
github.com/labstack/echo/v4 v4.1.17 h1:PQIBaRplyRy3OjwILGkPg89JRtH2x5bssi59G2EL3fo=
github.com/labstack/echo/v4 v4.1.17/go.mod h1:Tn2yRQL/UclUalpb5rPdXDevbkJ+lp/2svdyFBg6CHQ=
@@ -90,6 +110,8 @@ github.com/mailru/easyjson v0.0.0-20190614124828-94de47d64c63/go.mod h1:C1wdFJiN
github.com/mailru/easyjson v0.0.0-20190626092158-b2ccc519800e/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc=
github.com/mailru/easyjson v0.7.0 h1:aizVhC/NAAcKWb+5QsU1iNOZb4Yws5UO2I+aIprQITM=
github.com/mailru/easyjson v0.7.0/go.mod h1:KAzv3t3aY1NaHWoQz1+4F1ccyAH66Jk7yos7ldAVICs=
+github.com/mailru/easyjson v0.7.6 h1:8yTIVnZgCoiM1TgqoeTl+LfU5Jg6/xL3QhGQnimLYnA=
+github.com/mailru/easyjson v0.7.6/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc=
github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU=
github.com/mattn/go-colorable v0.1.0/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU=
github.com/mattn/go-colorable v0.1.2/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE=
@@ -107,6 +129,7 @@ github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJ
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
+github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno=
github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
github.com/onsi/ginkgo v1.7.0 h1:WSHQ+IS43OoUrWtD1/bbclrwK8TTH5hzp+umCiuxHgs=
github.com/onsi/ginkgo v1.7.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
@@ -115,7 +138,11 @@ github.com/onsi/gomega v1.4.3/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1Cpa
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
+github.com/russross/blackfriday/v2 v2.0.1 h1:lPqVAte+HuHNfhJ/0LC98ESWRz8afy9tM/0RK8m9o+Q=
github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
+github.com/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf35Ld67mk=
+github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
+github.com/shurcooL/sanitized_anchor_name v1.0.0 h1:PdmoCO6wvbs+7yrJyMORt4/BmY5IYyJwS/kOiWx8mHo=
github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/objx v0.2.0/go.mod h1:qt09Ya8vawLte6SNmTgCsAVtYtaKzEcn8ATUoHMkEqE=
@@ -135,6 +162,8 @@ github.com/swaggo/swag v1.5.1/go.mod h1:1Bl9F/ZBpVWh22nY0zmYyASPO1lI/zIwRDrpZU+t
github.com/swaggo/swag v1.6.3/go.mod h1:wcc83tB4Mb2aNiL/HP4MFeQdpHUrca+Rp/DRNgWAUio=
github.com/swaggo/swag v1.6.9 h1:BukKRwZjnEcUxQt7Xgfrt9fpav0hiWw9YimdNO9wssw=
github.com/swaggo/swag v1.6.9/go.mod h1:a0IpNeMfGidNOcm2TsqODUh9JHdHu3kxDA0UlGbBKjI=
+github.com/swaggo/swag v1.7.0 h1:5bCA/MTLQoIqDXXyHfOpMeDvL9j68OY/udlK4pQoo4E=
+github.com/swaggo/swag v1.7.0/go.mod h1:BdPIL73gvS9NBsdi7M1JOxLvlbfvNRaBP8m6WT6Aajo=
github.com/syndtr/goleveldb v1.0.0 h1:fBdIW9lB4Iz0n9khmH8w27SJ3QEJ7+IgjPEwGSZiFdE=
github.com/syndtr/goleveldb v1.0.0/go.mod h1:ZVVdQEZoIme9iO1Ch2Jdy24qqXrMMOU6lpPAyBWyWuQ=
github.com/ugorji/go v1.1.4/go.mod h1:uQMGLiO92mf5W77hV/PUCpI3pbzQx3CRekS0kk+RGrc=
@@ -143,8 +172,12 @@ github.com/ugorji/go v1.1.7/go.mod h1:kZn38zHttfInRq0xu/PH0az30d+z6vm202qpg1oXVM
github.com/ugorji/go/codec v0.0.0-20181022190402-e5e69e061d4f/go.mod h1:VFNgLljTbGfSG7qAOspJ7OScBnGdDN/yBr0sguwnwf0=
github.com/ugorji/go/codec v1.1.5-pre/go.mod h1:tULtS6Gy1AE1yCENaw4Vb//HLH5njI2tfCQDUqRd8fI=
github.com/ugorji/go/codec v1.1.7/go.mod h1:Ax+UKWsSmolVDwsd+7N3ZtXu+yMGCf907BLYF3GoBXY=
+github.com/urfave/cli v1.20.0 h1:fDqGv3UG/4jbVl/QkFwEdddtEDjh/5Ov6X+0B/3bPaw=
github.com/urfave/cli v1.20.0/go.mod h1:70zkFmudgCuE/ngEzBv17Jvp/497gISqfk5gWijbERA=
+github.com/urfave/cli/v2 v2.2.0 h1:JTTnM6wKzdA0Jqodd966MVj4vWbbquZykeX1sKbe2C4=
github.com/urfave/cli/v2 v2.2.0/go.mod h1:SE9GqnLQmjVa0iPEY0f1w3ygNIYcIJ0OKPMoW2caLfQ=
+github.com/urfave/cli/v2 v2.3.0 h1:qph92Y649prgesehzOrQjdWyxFOp/QVM+6imKHad91M=
+github.com/urfave/cli/v2 v2.3.0/go.mod h1:LJmUH05zAU44vOAcrfzZQKsZbVcdbOG8rtL3/XcUArI=
github.com/valyala/bytebufferpool v1.0.0 h1:GqA5TC/0021Y/b9FG4Oi9Mr3q7XYx6KllzawFIhcdPw=
github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc=
github.com/valyala/fasttemplate v0.0.0-20170224212429-dcecefd839c4/go.mod h1:50wTf68f99/Zt14pr046Tgt3Lp2vLyFZKzbFXTOabXw=
@@ -152,6 +185,7 @@ github.com/valyala/fasttemplate v1.0.1/go.mod h1:UQGH1tvbgY+Nz5t2n7tXsz52dQxojPU
github.com/valyala/fasttemplate v1.2.1 h1:TVEnxayobAdVkhQfrfes2IzOB6o+z4roRkPF52WA1u4=
github.com/valyala/fasttemplate v1.2.1/go.mod h1:KHLXt3tVN2HBp8eijSv/kGJopbvo7S+qRAEEKiv+SiQ=
github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
+github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
github.com/ziutek/mymysql v1.5.4/go.mod h1:LMSpPZ6DbqWFxNCHW77HeMg9I646SAhApZ/wKdgO/C0=
github.com/zxysilent/logs v0.1.4 h1:iZPA00egVI/ndzyrQbrWJqvEM8PjXrf6qfsTScDyRhc=
github.com/zxysilent/logs v0.1.4/go.mod h1:n2QCxPdkVW4haduEpXBg72/sX/bH8y532JVxI0bxXIU=
@@ -185,10 +219,15 @@ golang.org/x/net v0.0.0-20200324143707-d3edc9973b7e/go.mod h1:qpuaurCH72eLCgpAm/
golang.org/x/net v0.0.0-20200625001655-4c5254603344/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
golang.org/x/net v0.0.0-20200822124328-c89045814202 h1:VvcQYSHwXgi7W+TpUR6A9g6Up98WAHf3f/ulnJ62IyA=
golang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
+golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
+golang.org/x/net v0.0.0-20201110031124-69a78807bb2b/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
+golang.org/x/net v0.0.0-20201224014010-6772e930b67b h1:iFwSg7t5GZmB/Q5TjiEAsdoLDrdJRC1RiF2WhuV29Qw=
+golang.org/x/net v0.0.0-20201224014010-6772e930b67b/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
+golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20181228144115-9a3f9b0469bb/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190129075346-302c3dd5f1cc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
@@ -204,11 +243,17 @@ golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd h1:xhmwyvizuTgC2qz7ZlMluP20u
golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200826173525-f9321e4c35a6 h1:DvY3Zkh7KabQE/kfzMvYvKirSiguP9Q/veMtkYyf0o8=
golang.org/x/sys v0.0.0-20200826173525-f9321e4c35a6/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20201119102817-f84b799fce68 h1:nxC68pudNYkKU6jWhgrqdreuFiOQWj1Fs7T3VrH4Pjw=
+golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.2 h1:tW2bmiBqwgJj/UpqtC8EpXEZVYOwU0yG4iWbprSVAcs=
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
golang.org/x/text v0.3.3 h1:cokOdA+Jmi5PJGXLlLllQSgYigAEfHXJAERHVMaCc2k=
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
+golang.org/x/text v0.3.4 h1:0YWbFKbhXG/wIiuHDSKpS0Iy7FSA+u45VtBMfQcFTTc=
+golang.org/x/text v0.3.4/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20190606050223-4d9ae51c2468/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
golang.org/x/tools v0.0.0-20190611222205-d73e1c7e250b/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
@@ -218,13 +263,18 @@ golang.org/x/tools v0.0.0-20191205060818-73c7173a9f7d h1:HjXQhd1u/svlhQb0V71w0I7
golang.org/x/tools v0.0.0-20191205060818-73c7173a9f7d/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20200820010801-b793a1359eac h1:DugppSxw0LSF8lcjaODPJZoDzq0ElTGskTst3ZaBkHI=
golang.org/x/tools v0.0.0-20200820010801-b793a1359eac/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA=
+golang.org/x/tools v0.0.0-20201120155355-20be4ac4bd6e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
+golang.org/x/tools v0.0.0-20210106214847-113979e3529a h1:CB3a9Nez8M13wwlr/E2YtwoU+qYHKfC+JrDa45RXXoQ=
+golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
+golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 h1:qIbj1fsPNlZgppZ+VLlY7N33q108Sa+fhmuc+sWQYwY=
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
+gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/fsnotify.v1 v1.4.7 h1:xOHLXZwVvI9hhs+cLKq5+I5onOuwQLhQwiu63xxlHs4=
gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys=
gopkg.in/go-playground/assert.v1 v1.2.1/go.mod h1:9RXL0bg/zibRAgZUYszZSwO/z8Y/a8bDuhia5mkpMnE=
@@ -233,13 +283,18 @@ gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkep
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw=
gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
+gopkg.in/yaml.v2 v2.2.3/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.2.7 h1:VUgggvou5XRW9mHwD/yXxIYSMtY0zoKQf/v226p2nyo=
gopkg.in/yaml.v2 v2.2.7/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.2.8 h1:obN1ZagJSUGI0Ek/LBmuj4SNLPfIny3KsKFopxRdj10=
gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
+gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
+gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY=
+gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c h1:dUUwHk2QECo/6vqA44rthZ8ie2QXMNeKRTHCNY2nXvo=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
+gopkg.in/yaml.v3 v3.0.0-20200615113413-eeeca48fe776/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
xorm.io/builder v0.3.7 h1:2pETdKRK+2QG4mLX4oODHEhn5Z8j1m8sXa7jfu+/SZI=
xorm.io/builder v0.3.7/go.mod h1:aUW0S9eb9VCaPohFCH3j7czOx1PMW3i1HrSzbLYGBSE=
xorm.io/xorm v1.0.5 h1:LRr5PfOUb4ODPR63YwbowkNDwcolT2LnkwP/TUaMaB0=
diff --git a/init.sh b/init.sh
new file mode 100755
index 0000000..c13e294
--- /dev/null
+++ b/init.sh
@@ -0,0 +1,16 @@
+#!/usr/bin/env bash
+
+rm -rf logs
+mkdir logs
+
+cd vue
+npm install
+cd ..
+
+go get -u github.com/swaggo/swag/cmd/swag
+swag init
+
+go run main.go
+
+#导入sql数据
+
diff --git a/model/cate.go b/model/cate.go
index eb8b006..4641e2a 100644
--- a/model/cate.go
+++ b/model/cate.go
@@ -1,6 +1,8 @@
package model
-import "strconv"
+import (
+ "strconv"
+)
// Cate 分类
type Cate struct {
@@ -8,6 +10,8 @@ type Cate struct {
Name string `xorm:"not null unique VARCHAR(255)" json:"name"`
Pid int `xorm:"not null default 0 INT(11)" json:"pid"`
Intro string `xorm:"not null VARCHAR(255)" json:"intro"`
+ Sort int `xorm:"not null default 0 INT(11)" json:"sort"`
+ Posts []Post `xorm:"-"`
}
// CateIds 通过id返回新闻类别信息集合
@@ -46,7 +50,7 @@ func CateName(nam string) (*Cate, bool) {
// CateAll 所有分类
func CateAll() ([]Cate, error) {
mods := make([]Cate, 0, 4)
- err := Db.Asc("id").Find(&mods)
+ err := Db.Asc("sort", "id").Find(&mods)
return mods, err
}
@@ -69,7 +73,7 @@ func CateEdit(mod *Cate) bool {
sess := Db.NewSession()
defer sess.Close()
sess.Begin()
- affect, err := sess.ID(mod.Id).Cols("Name", "Intro").Update(mod)
+ affect, err := sess.ID(mod.Id).Cols("Name", "Intro", "Sort").Update(mod)
if affect >= 0 && err == nil {
sess.Commit()
return true
@@ -135,3 +139,11 @@ func CatePostList(cid, pi, ps int, lmt bool) ([]Post, error) {
}
return mods, err
}
+
+func CatePostAll(cid int) ([]Post, error){
+ mods := make([]Post, 0)
+ sess := Db.NewSession()
+ defer sess.Close()
+ err := sess.Cols("id", "title", "path", "create_time").Where("cate_id = ?", cid).Desc("sort", "create_time").Find(&mods)
+ return mods, err
+}
diff --git a/model/post.go b/model/post.go
index 23309ba..a565997 100644
--- a/model/post.go
+++ b/model/post.go
@@ -1,228 +1,278 @@
-package model
-
-import (
- "strconv"
- "time"
-
- "github.com/zxysilent/utils"
-)
-
-// // Post 文章
-// type Post struct {
-// Id int `xorm:"pk autoincr INT(11)" json:"id" form:"id"`
-// UserId int `xorm:"INT(11)" json:"user_id" form:"user_id"`
-// CateId int `xorm:"INT(11)" json:"cate_id" form:"cate_id"`
-// Cate *Cate `xorm:"- <- ->" json:"cate,omitempty" form:"cate"`
-// Type int `xorm:"TINYINT(11)" json:"type" form:"type"` //0 为文章,1 为页面
-// Status int `xorm:"TINYINT(11)" json:"status" form:"status"` //'0 为草稿,1 为待审核,2 为已拒绝,3 为已经发布
-// Title string `xorm:"VARCHAR(255)" json:"title" form:"title"`
-// Path string `xorm:"unique VARCHAR(255)" json:"path" form:"path"`
-// Summary string `xorm:"LONGTEXT" json:"summary,omitempty" form:"summary"`
-// MarkdownContent string `xorm:"LONGTEXT" json:"markdown_content,omitempty" form:"markdown_content"`
-// Content string `xorm:"LONGTEXT" json:"content,omitempty" form:"content"`
-// AllowComment bool `xorm:"TINYINT(4)" json:"allow_comment" form:"allow_comment"`
-// CreateTime time.Time `xorm:"index DATETIME" json:"create_time" form:"create_time"`
-// UpdateTime time.Time `xorm:"DATETIME" json:"update_time" form:"update_time"`
-// IsPublic bool `xorm:"TINYINT(4)" json:"is_public" form:"is_public"`
-// CommentNum int `xorm:"INT(11)" json:"comment_num" form:"comment_num"`
-// Options string `xorm:"TEXT" json:"options,omitempty" form:"options"`
-// }
-
-// Post 文章
-type Post struct {
- Id int `xorm:"not null pk autoincr INT(11)" json:"id"`
- CateId int `xorm:"not null default 0 INT(11)" json:"cate_id"`
- Cate *Cate `xorm:"-" json:"cate,omitempty" form:"cate"`
- UserId int `xorm:"not null INT(11)" json:"user_id"`
- Type int `xorm:"not null default 0 comment('0 为文章,1 为页面') TINYINT(4)" json:"type"`
- Status int `xorm:"not null default 0 comment('0 为草稿,1 为待审核,2 为已拒绝,3 为已经发布') TINYINT(4)" json:"status"`
- Title string `xorm:"not null VARCHAR(255)" json:"title"`
- Path string `xorm:"not null comment('URL 的 path') VARCHAR(255)" json:"path"`
- Summary string `xorm:"not null comment('摘要') LONGTEXT" json:"summary"`
- MarkdownContent string `xorm:"not null LONGTEXT" json:"markdown_content"`
- Content string `xorm:"not null LONGTEXT" json:"content"`
- AllowComment bool `xorm:"not null default 1 comment('1 为允许, 0 为不允许') TINYINT(4)" json:"allow_comment"`
- CreateTime time.Time `xorm:"default 'NULL' index DATETIME" json:"create_time"`
- UpdateTime time.Time `xorm:"not null DATETIME" json:"update_time"`
- IsPublic bool `xorm:"not null default 1 comment('1 为公开,0 为不公开') TINYINT(4)" json:"is_public"`
- CommentNum int `xorm:"not null default 0 INT(11)" json:"comment_num"`
- Options string `xorm:"not null comment('一些选项,JSON 结构') VARCHAR(4096)" json:"options"`
-}
-
-// Archive 归档
-type Archive struct {
- Time time.Time // 日期
- Posts []Post //文章
-}
-
-// PostPage 分页
-func PostPage(pi, ps int) ([]Post, error) {
- mods := make([]Post, 0, ps)
- err := Db.Cols("id", "title", "path", "create_time", "summary", "comment_num", "options").Where("Type = 0 and Is_Public = 1 and Status = 3 ").Desc("create_time").Limit(ps, (pi-1)*ps).Find(&mods)
- return mods, err
-}
-
-// PostCount 返回总数
-func PostCount() int {
- mod := &Post{
- Type: 0,
- IsPublic: true,
- }
- count, _ := Db.UseBool("is_public").Count(mod)
- return int(count)
-}
-
-// PostArchive 归档
-func PostArchive() ([]Archive, error) {
- posts := make([]Post, 0, 8)
- err := Db.Cols("id", "title", "path", "create_time").Where("Type = 0 and Is_Public = 1 and Status = 3 ").Desc("create_time").Find(&posts)
- if err != nil {
- return nil, err
- }
- mods := make([]Archive, 0, 8)
- for _, v := range posts {
- v.MarkdownContent = ""
- v.Content = ""
- v.Summary = ""
- v.Options = ""
- if idx := archInOf(v.CreateTime, mods); idx == -1 { //没有
- mods = append(mods, Archive{
- Time: v.CreateTime,
- Posts: []Post{v},
- })
- } else { //有
- mods[idx].Posts = append(mods[idx].Posts, v)
- }
- }
- return mods, nil
-}
-
-func archInOf(time time.Time, mods []Archive) int {
- for idx := 0; idx < len(mods); idx++ {
- if time.Year() == mods[idx].Time.Year() && time.Month() == mods[idx].Time.Month() {
- return idx
- }
- }
- return -1
-}
-
-// PostPath 一条post
-func PostPath(path string) (*Post, *Naver, bool) {
- mod := &Post{
- Path: path,
- Type: 0,
- IsPublic: true,
- }
- has, _ := Db.UseBool("is_public").Get(mod)
- if has {
- mod.Cate, _ = CateGet(mod.CateId)
- naver := &Naver{}
- p := Post{}
- b, _ := Db.Where("Type = 0 and Is_Public = 1 and Status = 3 and Create_Time ", mod.CreateTime.Format(utils.FormatDateTime)).Desc("Create_Time").Get(&p)
- if b {
- // « 上一页
- naver.Prev = `« ` + p.Title + ` `
- }
- n := Post{}
- b1, _ := Db.Where("Type = 0 and Is_Public = 1 and Status = 3 and Create_Time >?", mod.CreateTime.Format(utils.FormatDateTime)).Asc("Create_Time").Get(&n)
- if b1 {
- //下一页 »
- naver.Next = ` ` + n.Title + ` » `
- }
- return mod, naver, true
- }
- return nil, nil, has
-}
-
-//PostSingle 单页面 page
-func PostSingle(path string) (*Post, bool) {
- mod := &Post{
- Path: path,
- Type: 1,
- }
- has, _ := Db.Get(mod)
- return mod, has
-}
-
-// PostPageAll 所有页面
-func PostPageAll() ([]Post, error) {
- mods := make([]Post, 0, 4)
- err := Db.Cols("id", "title", "path", "create_time", "summary", "comment_num", "options", "update_time", "is_public", "status").Where("Type = 1").Desc("create_time").Find(&mods)
- return mods, err
-}
-
-//PostGet 一个
-func PostGet(id int) (*Post, bool) {
- mod := &Post{
- Id: id,
- }
- has, _ := Db.Get(mod)
- if has {
- mod.Summary = ""
- }
- return mod, has
-}
-
-// postIds 通过id返回文章集合
-func postIds(ids []int) map[int]*Post {
- mods := make([]Post, 0, 6)
- Db.Cols("id", "title", "path", "cate_id", "create_time", "summary", "comment_num", "options").In("id", ids).Find(&mods)
- if len(mods) > 0 {
- mapSet := make(map[int]*Post, len(mods))
- for idx := range mods {
- mapSet[mods[idx].Id] = &mods[idx]
- }
- return mapSet
- }
- return nil
-}
-
-//PostExist 判断是否存在
-func PostExist(ptah string) bool {
- has, _ := Db.Exist(&Post{
- Path: ptah,
- })
- return has
-}
-
-// PostEdit 修改文章/页面
-func PostEdit(mod *Post) bool {
- sess := Db.NewSession()
- defer sess.Close()
- sess.Begin()
- affect, err := sess.ID(mod.Id).Cols("Cate_id", "Status", "Title", "Summary", "Markdown_Content", "Content", "allow_comment", "Create_Time", "Comment_Num", "update_time", "is_public").Update(mod)
- if affect >= 0 && err == nil {
- sess.Commit()
- return true
- }
- sess.Rollback()
- return false
-}
-
-// PostAdd 添加文章/页面
-func PostAdd(mod *Post) bool {
- sess := Db.NewSession()
- defer sess.Close()
- sess.Begin()
- affect, _ := sess.InsertOne(mod)
- if affect != 1 {
- sess.Rollback()
- return false
- }
- sess.Commit()
- return true
-}
-
-// PostDrop 删除
-func PostDrop(id int) bool {
- sess := Db.NewSession()
- defer sess.Close()
- sess.Begin()
- if affect, err := sess.ID(id).Delete(&Post{}); affect > 0 && err == nil {
- sess.Commit()
- Db.ClearCacheBean(&Post{}, strconv.Itoa(id))
- return true
- }
- sess.Rollback()
- return false
-}
+package model
+
+import (
+ "strconv"
+ "time"
+
+ "github.com/zxysilent/utils"
+)
+
+// // Post 文章
+// type Post struct {
+// Id int `xorm:"pk autoincr INT(11)" json:"id" form:"id"`
+// UserId int `xorm:"INT(11)" json:"user_id" form:"user_id"`
+// CateId int `xorm:"INT(11)" json:"cate_id" form:"cate_id"`
+// Cate *Cate `xorm:"- <- ->" json:"cate,omitempty" form:"cate"`
+// Type int `xorm:"TINYINT(11)" json:"type" form:"type"` //0 为文章,1 为页面
+// Status int `xorm:"TINYINT(11)" json:"status" form:"status"` //'0 为草稿,1 为待审核,2 为已拒绝,3 为已经发布
+// Title string `xorm:"VARCHAR(255)" json:"title" form:"title"`
+// Path string `xorm:"unique VARCHAR(255)" json:"path" form:"path"`
+// Summary string `xorm:"LONGTEXT" json:"summary,omitempty" form:"summary"`
+// MarkdownContent string `xorm:"LONGTEXT" json:"markdown_content,omitempty" form:"markdown_content"`
+// Content string `xorm:"LONGTEXT" json:"content,omitempty" form:"content"`
+// AllowComment bool `xorm:"TINYINT(4)" json:"allow_comment" form:"allow_comment"`
+// CreateTime time.Time `xorm:"index DATETIME" json:"create_time" form:"create_time"`
+// UpdateTime time.Time `xorm:"DATETIME" json:"update_time" form:"update_time"`
+// IsPublic bool `xorm:"TINYINT(4)" json:"is_public" form:"is_public"`
+// CommentNum int `xorm:"INT(11)" json:"comment_num" form:"comment_num"`
+// Options string `xorm:"TEXT" json:"options,omitempty" form:"options"`
+// }
+
+// Post 文章
+type Post struct {
+ Id int `xorm:"not null pk autoincr INT(11)" json:"id"`
+ CateId int `xorm:"not null default 0 INT(11)" json:"cate_id"`
+ Cate *Cate `xorm:"-" json:"cate,omitempty" form:"cate"`
+ UserId int `xorm:"not null INT(11)" json:"user_id"`
+ Type int `xorm:"not null default 0 comment('0 为文章,1 为页面') TINYINT(4)" json:"type"`
+ Status int `xorm:"not null default 0 comment('0 为草稿,1 为待审核,2 为已拒绝,3 为已经发布') TINYINT(4)" json:"status"`
+ Title string `xorm:"not null VARCHAR(255)" json:"title"`
+ Path string `xorm:"not null comment('URL 的 path') VARCHAR(255)" json:"path"`
+ Summary string `xorm:"not null comment('摘要') LONGTEXT" json:"summary"`
+ MarkdownContent string `xorm:"not null LONGTEXT" json:"markdown_content"`
+ Content string `xorm:"not null LONGTEXT" json:"content"`
+ AllowComment bool `xorm:"not null default 1 comment('1 为允许, 0 为不允许') TINYINT(4)" json:"allow_comment"`
+ CreateTime time.Time `xorm:"default 'NULL' index DATETIME" json:"create_time"`
+ UpdateTime time.Time `xorm:"not null DATETIME" json:"update_time"`
+ IsPublic bool `xorm:"not null default 1 comment('1 为公开,0 为不公开') TINYINT(4)" json:"is_public"`
+ CommentNum int `xorm:"not null default 0 INT(11)" json:"comment_num"`
+ Options string `xorm:"not null comment('一些选项,JSON 结构') VARCHAR(4096)" json:"options"`
+ Sort int `xorm:"not null default 0 INT(11)" json:"sort"`
+ User *User `xorm:"-"`
+}
+
+// Archive 归档
+type Archive struct {
+ Time time.Time // 日期
+ Posts []Post //文章
+}
+
+// PostPage 分页 搜索
+func PostPageSearch(pi, ps int, k string) ([]Post, error) {
+ mods := make([]Post, 0, ps)
+ err := Db.Cols("id", "user_id", "title", "path", "create_time", "summary", "comment_num", "options").Where("Type = 0 and Is_Public = 1 and Status = 3"+" and (title like '%"+k+"%' or content like '%"+k+"%')").Desc("create_time").Limit(ps, (pi-1)*ps).Find(&mods)
+ mp := make(map[int]*User)
+ for i:=0; i« 上一页
+ naver.Prev = `« ` + p.Title + ` `
+ }
+ n := Post{}
+ b1, _ := Db.Where("Type = 0 and Is_Public = 1 and Status = 3 and Create_Time >?", mod.CreateTime.Format(utils.FormatDateTime)).Asc("Create_Time").Get(&n)
+ if b1 {
+ //下一页 »
+ naver.Next = ` ` + n.Title + ` » `
+ }
+ return mod, naver, true
+ }
+ return nil, nil, has
+}
+
+//PostSingle 单页面 page
+func PostSingle(path string) (*Post, bool) {
+ mod := &Post{
+ Path: path,
+ Type: 1,
+ }
+ has, _ := Db.Get(mod)
+ return mod, has
+}
+
+// PostPageAll 所有页面
+func PostPageAll() ([]Post, error) {
+ mods := make([]Post, 0, 4)
+ err := Db.Cols("id", "title", "path", "create_time", "summary", "comment_num", "options", "update_time", "is_public", "status").Where("Type = 1").Desc("create_time").Find(&mods)
+ return mods, err
+}
+
+//PostGet 一个
+func PostGet(id int) (*Post, bool) {
+ mod := &Post{
+ Id: id,
+ }
+ has, _ := Db.Get(mod)
+ if has {
+ mod.Summary = ""
+ }
+ return mod, has
+}
+
+// postIds 通过id返回文章集合
+func postIds(ids []int) map[int]*Post {
+ mods := make([]Post, 0, 6)
+ Db.Cols("id", "title", "path", "cate_id", "create_time", "summary", "comment_num", "options").In("id", ids).Find(&mods)
+ if len(mods) > 0 {
+ mapSet := make(map[int]*Post, len(mods))
+ for idx := range mods {
+ mapSet[mods[idx].Id] = &mods[idx]
+ }
+ return mapSet
+ }
+ return nil
+}
+
+//PostExist 判断是否存在
+func PostExist(ptah string) bool {
+ has, _ := Db.Exist(&Post{
+ Path: ptah,
+ })
+ return has
+}
+
+// PostEdit 修改文章/页面
+func PostEdit(mod *Post) bool {
+ sess := Db.NewSession()
+ defer sess.Close()
+ sess.Begin()
+ affect, err := sess.ID(mod.Id).Cols("Cate_id", "Status", "Title", "Summary", "Markdown_Content", "Content", "allow_comment", "Create_Time", "Comment_Num", "update_time", "is_public", "user_id", "sort").Update(mod)
+ if affect >= 0 && err == nil {
+ sess.Commit()
+ return true
+ }
+ sess.Rollback()
+ return false
+}
+
+// PostAdd 添加文章/页面
+func PostAdd(mod *Post) bool {
+ sess := Db.NewSession()
+ defer sess.Close()
+ sess.Begin()
+ affect, _ := sess.InsertOne(mod)
+ if affect != 1 {
+ sess.Rollback()
+ return false
+ }
+ sess.Commit()
+ return true
+}
+
+// PostDrop 删除
+func PostDrop(id int) bool {
+ sess := Db.NewSession()
+ defer sess.Close()
+ sess.Begin()
+ if affect, err := sess.ID(id).Delete(&Post{}); affect > 0 && err == nil {
+ sess.Commit()
+ Db.ClearCacheBean(&Post{}, strconv.Itoa(id))
+ return true
+ }
+ sess.Rollback()
+ return false
+}
+
+func atoi(raw string, def int) (int, error) {
+ out, err := strconv.Atoi(raw)
+ if err != nil {
+ return def, err
+ }
+ return out, nil
+}
diff --git a/router/router.go b/router/router.go
index b511038..9d5c6b4 100644
--- a/router/router.go
+++ b/router/router.go
@@ -1,49 +1,57 @@
-package router
-
-import (
- "blog/conf"
- "blog/control"
- "log"
-
- "github.com/labstack/echo/v4"
- "github.com/labstack/echo/v4/middleware"
-)
-
-// RunApp 入口
-func RunApp() {
- engine := echo.New()
- engine.Renderer = initRender() // 初始渲染引擎
- engine.Use(midRecover, midLogger) // 恢复 日志记录
- engine.Use(middleware.CORSWithConfig(crosConfig)) // 跨域设置
- engine.HideBanner = true // 不显示横幅
- engine.HTTPErrorHandler = HTTPErrorHandler // 自定义错误处理
- engine.Debug = conf.App.IsDev() // 运行模式 - echo框架好像没怎么使用这个
- RegDocs(engine) // 注册文档
- engine.Static(`/dist`, "dist") // 静态目录 - 后端专用
- engine.Static(`/static`, "static") // 静态目录
- engine.File(`/favicon.ico`, "favicon.ico") // ico
- engine.File("/dashboard*", "dist/index.html") // 前后端分离页面
-
- //--- 页面 -- start
- engine.GET(`/`, control.IndexView) // 首页
- engine.GET(`/archives`, control.ArchivesView) // 归档
- engine.GET(`/archives.json`, control.ArchivesJson) // 归档 json
- engine.GET(`/tags`, control.TagsView) // 标签
- engine.GET(`/tags.json`, control.TagsJson) // 标签 json
- engine.GET(`/tag/:tag`, control.TagPostView) // 具体某个标签
- engine.GET(`/cate/:cate`, control.CatePostView) // 分类
- engine.GET(`/about`, control.AboutView) // 关于
- engine.GET(`/links`, control.LinksView) // 友链
- engine.GET(`/post/*`, control.PostView) // 具体某个文章
- engine.GET(`/page/*`, control.PageView) // 具体某个页面
- //--- 页面 -- end
-
- api := engine.Group("/api") // api/
- apiRouter(api) // 注册分组路由
- adm := engine.Group("/adm", midJwt) // adm/ 需要登陆才能访问
- admRouter(adm) // 注册分组路由
- err := engine.Start(conf.App.Addr)
- if err != nil {
- log.Fatalln("run error :", err)
- }
-}
+package router
+
+import (
+ "blog/conf"
+ "blog/control"
+ "log"
+
+ "github.com/labstack/echo/v4"
+ "github.com/labstack/echo/v4/middleware"
+)
+
+// RunApp 入口
+func RunApp() {
+ engine := echo.New()
+ engine.Renderer = initRender() // 初始渲染引擎
+ engine.Use(midRecover, midLogger) // 恢复 日志记录
+ engine.Use(middleware.CORSWithConfig(crosConfig)) // 跨域设置
+ engine.HideBanner = true // 不显示横幅
+ engine.HTTPErrorHandler = HTTPErrorHandler // 自定义错误处理
+ engine.Debug = conf.App.IsDev() // 运行模式 - echo框架好像没怎么使用这个
+ RegDocs(engine) // 注册文档
+ engine.Static(`/dist`, "dist") // 静态目录 - 后端专用
+ engine.Static(`/static`, "static") // 静态目录
+ engine.File(`/favicon.ico`, "favicon.ico") // ico
+ engine.File("/dashboard*", "dist/index.html") // 前后端分离页面
+
+ //--- admin --
+ engine.GET("/admin", func(context echo.Context) error {
+ context.Redirect(302, "/dist/index.html")
+ return nil
+ })
+
+ //--- 页面 -- start
+ engine.GET(`/`, control.IndexView) // 首页
+ engine.GET(`/archives`, control.ArchivesView) // 归档
+ engine.GET(`/archives.json`, control.ArchivesJson) // 归档 json
+ engine.GET(`/tags`, control.TagsView) // 标签
+ engine.GET(`/tags.json`, control.TagsJson) // 标签 json
+ engine.GET(`/tag/:tag`, control.TagPostView) // 具体某个标签
+ engine.GET(`/cate/:cate`, control.CatePostView) // 分类
+ engine.GET(`/about`, control.AboutView) // 关于
+ engine.GET(`/links`, control.LinksView) // 友链
+ engine.GET(`/post/*`, control.PostView) // 具体某个文章
+ engine.GET(`/page/*`, control.PageView) // 具体某个页面
+ engine.GET(`/search`, control.SearchView) // 搜索
+ engine.GET(`/series`, control.Series) // 专题
+ //--- 页面 -- end
+
+ api := engine.Group("/api") // api/
+ apiRouter(api) // 注册分组路由
+ adm := engine.Group("/adm", midJwt) // adm/ 需要登陆才能访问
+ admRouter(adm) // 注册分组路由
+ err := engine.Start(conf.App.Addr)
+ if err != nil {
+ log.Fatalln("run error :", err)
+ }
+}
diff --git a/static/css/app.css b/static/css/app.css
index 45ae6ed..5924e91 100644
--- a/static/css/app.css
+++ b/static/css/app.css
@@ -1,12 +1,1008 @@
-body{margin:0;padding:0;color:#666;-webkit-text-size-adjust:none;-webkit-transition:-webkit-transform .2s cubic-bezier(.4,.01,.165,.99);transition:-webkit-transform .2s cubic-bezier(.4,.01,.165,.99);transition:transform .2s cubic-bezier(.4,.01,.165,.99);transition:transform .2s cubic-bezier(.4,.01,.165,.99),-webkit-transform .2s cubic-bezier(.4,.01,.165,.99);-webkit-tap-highlight-color:transparent;font-family:"Helvetica Neue",Arial,"Hiragino Sans GB",STHeiti,"Microsoft YaHei";-webkit-font-smoothing:antialiased;-webkit-overflow-scrolling:touch}body,html{width:100%;height:100%}h1,h2,h3,h4,h5,h6{margin:0;padding:0}a,a:hover{color:#2479CC;text-decoration:none}ol,ul{padding:0}*{-webkit-box-sizing:border-box;box-sizing:border-box}body.side{position:fixed;-webkit-transform:translate3D(250px,0,0);-ms-transform:translate3D(250px,0,0);transform:translate3D(250px,0,0)}#main{background-color:#fff;padding-left:290px;padding-right:40px;max-width:1390px;-webkit-overflow-scrolling:touch}h1.intro{padding:20px 30px;background-color:#f6f9fa;text-align:center;color:#999}
-@font-face{font-family:iconfont;src:url(../font/iconfont.eot);src:url(../font/iconfont.eot?#iefix) format("embedded-opentype"),url(../font/iconfont.ttf) format("truetype"),url(../font/iconfont.svg#iconfont) format("svg")}.iconfont{font-family:iconfont!important;font-size:16px;font-style:normal;-webkit-font-smoothing:antialiased;-webkit-text-stroke-width:.2px;-moz-osx-font-smoothing:grayscale}.icon-weibo:before{content:"\e600"}.icon-archive:before{content:"\e601"}.icon-user:before{content:"\e602"}.icon-rss-v:before{content:"\e603"}.icon-tags:before{content:"\e604"}.icon-home:before{content:"\e605"}.icon-search:before{content:"\e606"}.icon-googleplus:before{content:"\e607"}.icon-weixin:before{content:"\e608"}.icon-mail:before{content:"\e609"}.icon-twitter-v:before{content:"\e60a"}.icon-linkedin:before{content:"\e60b"}.icon-stackoverflow:before{content:"\e60c"}.icon-github-v:before{content:"\e60d"}.icon-facebook:before{content:"\e60e"}.icon-right:before{content:"\e60f"}.icon-left:before{content:"\e610"}.icon-link:before{content:"\e611"}.icon-https:before{content:"\e612"}
-.hljs{display:block;background:#fff;padding:.5em;color:#333;overflow-x:auto;-webkit-text-size-adjust:none}.hljs-comment,.lang-bash .hljs-shebang,.lang-java .hljs-javadoc,.lang-javascript .hljs-javadoc,.lang-rust .hljs-preprocessor{color:#969896}.hljs-string,.lang-apache .hljs-sqbracket,.lang-c .hljs-preprocessor,.lang-coffeescript .hljs-regexp,.lang-coffeescript .hljs-subst,.lang-cpp .hljs-preprocessor,.lang-javascript .hljs-regexp,.lang-json .hljs-attribute,.lang-less .hljs-built_in,.lang-makefile .hljs-variable,.lang-markdown .hljs-blockquote,.lang-markdown .hljs-emphasis,.lang-markdown .hljs-link_label,.lang-markdown .hljs-strong,.lang-markdown .hljs-value,.lang-nginx .hljs-number,.lang-nginx .hljs-regexp,.lang-objectivec .hljs-preprocessor .hljs-title,.lang-perl .hljs-regexp,.lang-php .hljs-regexp,.lang-scss .hljs-built_in,.lang-xml .hljs-value{color:#df5000}.hljs-keyword,.lang-css .hljs-at_rule,.lang-css .hljs-important,.lang-go .hljs-typename,.lang-haskell .hljs-type,.lang-http .hljs-request,.lang-ini .hljs-setting,.lang-java .hljs-javadoctag,.lang-javascript .hljs-javadoctag,.lang-javascript .hljs-tag,.lang-less .hljs-at_rule,.lang-less .hljs-tag,.lang-nginx .hljs-title,.lang-objectivec .hljs-preprocessor,.lang-php .hljs-phpdoc,.lang-scss .hljs-at_rule,.lang-scss .hljs-important,.lang-scss .hljs-tag,.lang-sql .hljs-built_in,.lang-stylus .hljs-at_rule,.lang-swift .hljs-preprocessor{color:#a71d5d}.lang-apache .hljs-cbracket,.lang-apache .hljs-common,.lang-apache .hljs-keyword,.lang-bash .hljs-built_in,.lang-bash .hljs-literal,.lang-c .hljs-built_in,.lang-c .hljs-number,.lang-coffeescript .hljs-built_in,.lang-coffeescript .hljs-literal,.lang-coffeescript .hljs-number,.lang-cpp .hljs-built_in,.lang-cpp .hljs-number,.lang-cs .hljs-built_in,.lang-cs .hljs-number,.lang-css .hljs-attribute,.lang-css .hljs-function,.lang-css .hljs-hexcolor,.lang-css .hljs-number,.lang-go .hljs-built_in,.lang-go .hljs-constant,.lang-haskell .hljs-number,.lang-http .hljs-attribute,.lang-http .hljs-literal,.lang-java .hljs-number,.lang-javascript .hljs-built_in,.lang-javascript .hljs-literal,.lang-javascript .hljs-number,.lang-json .hljs-number,.lang-less .hljs-attribute,.lang-less .hljs-function,.lang-less .hljs-hexcolor,.lang-less .hljs-number,.lang-makefile .hljs-keyword,.lang-markdown .hljs-link_reference,.lang-nginx .hljs-built_in,.lang-objectivec .hljs-built_in,.lang-objectivec .hljs-literal,.lang-objectivec .hljs-number,.lang-php .hljs-literal,.lang-php .hljs-number,.lang-puppet .hljs-function,.lang-python .hljs-number,.lang-ruby .hljs-constant,.lang-ruby .hljs-number,.lang-ruby .hljs-prompt,.lang-ruby .hljs-subst .hljs-keyword,.lang-ruby .hljs-symbol,.lang-rust .hljs-number,.lang-scss .hljs-attribute,.lang-scss .hljs-function,.lang-scss .hljs-hexcolor,.lang-scss .hljs-number,.lang-scss .hljs-preprocessor,.lang-sql .hljs-number,.lang-stylus .hljs-attribute,.lang-stylus .hljs-hexcolor,.lang-stylus .hljs-number,.lang-stylus .hljs-params,.lang-swift .hljs-built_in,.lang-swift .hljs-number{color:#0086b3}.lang-apache .hljs-tag,.lang-cs .hljs-xmlDocTag,.lang-css .hljs-tag,.lang-stylus .hljs-tag,.lang-xml .hljs-title{color:#63a35c}.lang-bash .hljs-variable,.lang-cs .hljs-preprocessor,.lang-cs .hljs-preprocessor .hljs-keyword,.lang-css .hljs-attr_selector,.lang-css .hljs-value,.lang-ini .hljs-keyword,.lang-ini .hljs-value,.lang-javascript .hljs-tag .hljs-title,.lang-makefile .hljs-constant,.lang-nginx .hljs-variable,.lang-scss .hljs-variable,.lang-xml .hljs-tag{color:#333}.lang-bash .hljs-title,.lang-c .hljs-title,.lang-coffeescript .hljs-title,.lang-cpp .hljs-title,.lang-cs .hljs-title,.lang-css .hljs-class,.lang-css .hljs-id,.lang-css .hljs-pseudo,.lang-diff .hljs-chunk,.lang-haskell .hljs-pragma,.lang-haskell .hljs-title,.lang-ini .hljs-title,.lang-java .hljs-title,.lang-javascript .hljs-title,.lang-less .hljs-class,.lang-less .hljs-id,.lang-less .hljs-pseudo,.lang-makefile .hljs-title,.lang-objectivec .hljs-title,.lang-perl .hljs-sub,.lang-php .hljs-title,.lang-puppet .hljs-title,.lang-python .hljs-decorator,.lang-python .hljs-title,.lang-ruby .hljs-parent,.lang-ruby .hljs-title,.lang-rust .hljs-title,.lang-scss .hljs-class,.lang-scss .hljs-id,.lang-scss .hljs-pseudo,.lang-stylus .hljs-class,.lang-stylus .hljs-id,.lang-stylus .hljs-pseudo,.lang-stylus .hljs-title,.lang-swift .hljs-title,.lang-xml .hljs-attribute{color:#795da3}.lang-coffeescript .hljs-attribute,.lang-coffeescript .hljs-reserved{color:#1d3e81}.lang-diff .hljs-chunk{font-weight:700}.lang-diff .hljs-addition{color:#55a532;background-color:#eaffea}.lang-diff .hljs-deletion{color:#bd2c00;background-color:#ffecec}.lang-markdown .hljs-link_url{text-decoration:underline}
-#sidebar{width:250px;height:100%;position:fixed;left:0;top:0;background-image: url('/static/bg.jpg');background-size: cover;background-color: #9e9e9e;overflow:auto;z-index:1;-webkit-overflow-scrolling:touch}#sidebar li,#sidebar ul{margin:0;padding:0;list-style:none}#sidebar .profile{padding-top:40px;padding-bottom:10px}#sidebar .profile a,#sidebar .profile img{width:140px;height:140px;border-radius:70px;overflow:hidden}#sidebar .profile a{display:block;margin:0 auto}#sidebar .profile span{display:block;padding:10px 0;font-size:18px;color:#e5e3e9;text-align:center}#sidebar .buttons{margin:0 0 20px}#sidebar .buttons li{display:block;width:100%;height:45px;line-height:45px;font-size:16px}#sidebar .buttons li a{padding-left:25px;display:block;color:#e5e3e9;-webkit-transition:color .2s cubic-bezier(.4,.01,.165,.99);transition:color .2s cubic-bezier(.4,.01,.165,.99);text-decoration:none}#sidebar .buttons li a i,#sidebar .buttons li a span{display:inline-block;vertical-align:middle}#sidebar .buttons li a i{font-size:20px;width:25px;height:45px;line-height:45px;text-align:center;margin-right:20px}#sidebar .buttons li a:hover{color:#e5e3e9}#sidebar .buttons li a.inline{display:inline-block;width:40px}#sidebar-mask{position:absolute;left:0;top:0;right:0;bottom:0;z-index:999;overflow:hidden;display:none;background-color:rgba(255,255,255,0)}
-#header{display:none}#header{width:100%;height:50px;line-height:50px;overflow:hidden;position:fixed;left:0;top:0;z-index:9;background-color:#323436}body.side #header .btn-bar:before{width:24px;-webkit-transform:rotate(-45deg);-ms-transform:rotate(-45deg);transform:rotate(-45deg);top:25px}body.side #header .btn-bar:after{width:24px;-webkit-transform:rotate(45deg);-ms-transform:rotate(45deg);transform:rotate(45deg);bottom:24px}body.side #header .btn-bar i{opacity:0}#header h1{text-align:center;font-size:16px}#header h1 a{color:#999}#header .btn-bar{width:50px;height:50px;position:absolute;left:0;top:0}#header .btn-bar i,#header .btn-bar:after,#header .btn-bar:before{width:22px;height:1px;position:absolute;left:14px;background-color:#999;-webkit-transition:all .2s cubic-bezier(.4,.01,.165,.99) .3s;transition:all .2s cubic-bezier(.4,.01,.165,.99) .3s}#header .btn-bar i{top:25px;opacity:1}#header .btn-bar:before{content:'';top:17px}#header .btn-bar:after{content:'';bottom:16px}#header a.me,#header a.me img{width:30px;height:30px;border-radius:30px;overflow:hidden}#header a.me{position:absolute;right:10px;top:10px}
-.pagination{width:100%;line-height:20px;position:relative;border-top:1px solid #fff;border-bottom:1px solid #ddd;padding:20px 0;overflow:hidden}.pagination .prev{float:left}.pagination .next{float:right}.pagination .center{text-align:center;width:80px;margin:auto}
-article{border-bottom:1px solid #ddd;border-top:1px solid #fff;position:relative;padding:30px 0;word-wrap:break-word}article .meta{position:relative;float:right;color:#555;font-size:.9em;line-height:2;width:auto;text-align:right}article .meta a{color:#999}article .meta .comment,article .meta .date,article .meta .tags{position:relative}article h1.title{color:#333;font-size:2em;font-weight:300;line-height:35px;margin-bottom:25px}article h1.title a{color:#333}article h1.title a:hover{color:#2479CC;transition:color .3s}article button,article input.runcode{line-height:1;border:none;cursor:pointer;padding:.625em .5em;box-shadow:inset 0 -5px 20px rgba(0,0,0,.1);background:#12b0e6;color:#fff;font-size:14px;margin-top:10px;-webkit-appearance:button}article input.runcode:active,article input.runcode:focus,article input.runcode:hover{background:#f6ad08}article strong{font-weight:700}article em{font-style:italic}article blockquote{margin:10px 0 0 0;padding:15px 20px;border-left:5px solid #2479CC;background-color:#f8f8f8}article blockquote p{margin-bottom:0}article blockquote a{word-break:break-all;word-wrap:break-word}article code{font-family:Consolas,"Courier New",Courier,mono,serif;font-size:80%;margin:0 2px;padding:4px 5px;background-color:#f2f2f2;vertical-align:middle;border-radius:5px}article pre{font-family:Consolas,"Liberation Mono",Courier,monospace;font-size:14px;line-height:1.6;color:#5d6a6a;padding:.6em;border-left:5px solid #ccc;word-break:break-all;word-wrap:break-word;white-space:pre-wrap;position:relative;overflow:hidden}article pre code{border-radius:0;background-color:transparent;border:0;padding:0;margin:0;font-size:100%;display:block;position:relative}article pre b.name{position:absolute;line-height:1;top:10px;right:10px;font-size:60px;color:#eee;pointer-events:none}@media screen and (max-width:768px){article pre b.name{font-size:30px}}article img{padding:0;display:block;border:1px solid #ccc;margin:10px 0 5px 0;max-width:100%}article table{border:0;border-collapse:collapse;border-spacing:0}article table td,article table th{border:0}article table th{border-bottom:2px solid #848484;text-align:left;padding:6px 20px}article table td{border-bottom:1px solid #d0d0d0;padding:6px 20px}article .expire-tips{padding:5px 10px;font-size:15px;border:1px solid #e2e2e2;background-color:#ffffc0;border-left:5px solid #fff000;color:#333}article .aliyun-tips{padding:5px 10px;font-size:15px;border:1px solid #e2e2e2;background-color:#f0f8f4;border-left:5px solid #7cc4a0}article .post-info{font-size:14px}article .entry-content{font-size:16px;line-height:1.8;word-wrap:break-word}article .entry-content .date{color:#999;font-size:14px;font-style:italic}article .entry-content blockquote,article .entry-content dl,article .entry-content h1,article .entry-content h2,article .entry-content h3,article .entry-content h4,article .entry-content h5,article .entry-content h6,article .entry-content iframe,article .entry-content ol,article .entry-content p,article .entry-content pre,article .entry-content table,article .entry-content ul{margin-top:15px}article .entry-content blockquote>p:first-of-type,article .entry-content dl dl,article .entry-content dl ol,article .entry-content dl ul,article .entry-content ol dl,article .entry-content ol ol,article .entry-content ol ul,article .entry-content ul dl,article .entry-content ul ol,article .entry-content ul ul{margin-top:0}article .entry-content dl,article .entry-content ol,article .entry-content ul{margin-left:25px}article.tags section a{display:inline-block;font-size:14px;padding:0 15px;height:40px;line-height:40px;color:rgba(36,121,204,.8);border:1px solid rgba(36,121,204,.8);border-radius:4px;margin:0 15px 10px 0;text-decoration:none;-webkit-transition:color .2s cubic-bezier(.4,.01,.165,.99),border .2s cubic-bezier(.4,.01,.165,.99);transition:color .2s cubic-bezier(.4,.01,.165,.99),border .2s cubic-bezier(.4,.01,.165,.99)}article.tags section a:hover{color:#2479CC;border-color:#2479CC}a.anchor{display:block;position:relative;visibility:hidden}article .app-code>ul{list-style:decimal;background-color:#fff;margin:0;margin-left:40px;padding:0}article .app-code li{list-style:decimal-leading-zero;border-left:1px solid #ddd;padding-left:2px;position:relative}article .app-code li.mark{background-color:#fffbdd!important}article .app-code li:hover{background-color:#f3f3f3!important}article .app-code .line-num{width:40px;position:absolute;left:0;top:0;height:100%;left:-40px;cursor:pointer}article .app-code li:nth-of-type(even){background-color:#fcfcfc;color:inherit}article .entry-content pre .app-code{background-color:#eee}article pre{border-left:none;padding:0}article .entry-content pre code{font-size:12px;background-color:#fff;border:1px solid #eee;padding:0;line-height:26px}
-#search .wrapper{margin-right:72px}#search form{position:relative}#search .wrapper input{-webkit-appearance:none;border:1px solid #bbb;border-radius:0;box-sizing:border-box;display:block;font-size:16px;height:40px;outline:0;padding:4px 6px;width:100%}#search .submit{-webkit-appearance:none;background-color:#e7e7e7;border:1px solid #bbb;border-left:0;border-radius:0;color:#222;display:block;font-size:16px;height:40px;outline:0;position:absolute;right:0;top:0;width:72px}#searchResult{min-height:350px;overflow-x:hidden}#searchResult .info{color:#676767;font-size:13px;padding:15px 0;border-bottom:1px solid #e9e9e9}#searchResult .no-result{padding:5px;margin:15px 0;border:1px solid #fc3;background-color:#fff4c2;font-size:13px}#searchResult .loading{margin-top:20px}#searchResult .hot-words{margin-top:20px}#searchResult .hot-words a{margin-right:20px}#searchResult .item{padding:.5em 0 .3em 0}#searchResult .item .title a{font-size:16px;text-decoration:underline}#searchResult .item .title .type{display:inline-block;background-color:#eee;color:#888;margin-right:8px;padding:0 5px;font-size:13px;border-radius:3px}#searchResult .item .desc{font-size:14px;line-height:1.6}#searchResult .item .tags{font-size:14px;line-height:1.8}#searchResult .item .tags a{margin-right:12px;color:#666}#searchResult .item .desc b,#searchResult .item .title b{color:#C00;font-weight:400}
-#footer{line-height:1.8;text-align:center;padding:15px;border-top:1px solid #fff;font-size:.9em}#footer .beian{color:#666}
-#comments{border-top:1px solid #fff;border-bottom:1px solid #ddd;padding:30px 0;min-height:350px}#comments h1.title{font-size:25px;font-weight:300;line-height:35px;margin-bottom:20px}
+body {
+ margin: 0;
+ padding: 0;
+ color: #666;
+ -webkit-text-size-adjust: none;
+ -webkit-transition: -webkit-transform .2s cubic-bezier(.4, .01, .165, .99);
+ transition: -webkit-transform .2s cubic-bezier(.4, .01, .165, .99);
+ transition: transform .2s cubic-bezier(.4, .01, .165, .99);
+ transition: transform .2s cubic-bezier(.4, .01, .165, .99), -webkit-transform .2s cubic-bezier(.4, .01, .165, .99);
+ -webkit-tap-highlight-color: transparent;
+ font-family: "Helvetica Neue", Arial, "Hiragino Sans GB", STHeiti, "Microsoft YaHei";
+ -webkit-font-smoothing: antialiased;
+ -webkit-overflow-scrolling: touch
+}
+
+body, html {
+ width: 100%;
+ height: 100%
+}
+
+h1, h2, h3, h4, h5, h6 {
+ margin: 0;
+ padding: 0
+}
+
+a, a:hover {
+ color: #2479CC;
+ text-decoration: none
+}
+
+ol, ul {
+ padding: 0
+}
+
+* {
+ -webkit-box-sizing: border-box;
+ box-sizing: border-box
+}
+
+body.side {
+ position: fixed;
+ -webkit-transform: translate3D(250px, 0, 0);
+ -ms-transform: translate3D(250px, 0, 0);
+ transform: translate3D(250px, 0, 0)
+}
+
+#main {
+ background-color: #fff;
+ padding-left: 290px;
+ padding-right: 40px;
+ max-width: 1390px;
+ -webkit-overflow-scrolling: touch
+}
+
+h1.intro {
+ padding: 20px 30px;
+ background-color: #f6f9fa;
+ text-align: center;
+ color: #999
+}
+
+@font-face {
+ font-family: iconfont;
+ src: url(../font/iconfont.eot);
+ src: url(../font/iconfont.eot?#iefix) format("embedded-opentype"), url(../font/iconfont.ttf) format("truetype"), url(../font/iconfont.svg#iconfont) format("svg")
+}
+
+.iconfont {
+ font-family: iconfont !important;
+ font-size: 16px;
+ font-style: normal;
+ -webkit-font-smoothing: antialiased;
+ -webkit-text-stroke-width: .2px;
+ -moz-osx-font-smoothing: grayscale
+}
+
+.icon-weibo:before {
+ content: "\e600"
+}
+
+.icon-archive:before {
+ content: "\e601"
+}
+
+.icon-user:before {
+ content: "\e602"
+}
+
+.icon-rss-v:before {
+ content: "\e603"
+}
+
+.icon-tags:before {
+ content: "\e604"
+}
+
+.icon-home:before {
+ content: "\e605"
+}
+
+.icon-search:before {
+ content: "\e606"
+}
+
+.icon-googleplus:before {
+ content: "\e607"
+}
+
+.icon-weixin:before {
+ content: "\e608"
+}
+
+.icon-mail:before {
+ content: "\e609"
+}
+
+.icon-twitter-v:before {
+ content: "\e60a"
+}
+
+.icon-linkedin:before {
+ content: "\e60b"
+}
+
+.icon-stackoverflow:before {
+ content: "\e60c"
+}
+
+.icon-github-v:before {
+ content: "\e60d"
+}
+
+.icon-facebook:before {
+ content: "\e60e"
+}
+
+.icon-right:before {
+ content: "\e60f"
+}
+
+.icon-left:before {
+ content: "\e610"
+}
+
+.icon-link:before {
+ content: "\e611"
+}
+
+.icon-https:before {
+ content: "\e612"
+}
+
+.hljs {
+ display: block;
+ background: #fff;
+ padding: .5em;
+ color: #333;
+ overflow-x: auto;
+ -webkit-text-size-adjust: none
+}
+
+.hljs-comment, .lang-bash .hljs-shebang, .lang-java .hljs-javadoc, .lang-javascript .hljs-javadoc, .lang-rust .hljs-preprocessor {
+ color: #969896
+}
+
+.hljs-string, .lang-apache .hljs-sqbracket, .lang-c .hljs-preprocessor, .lang-coffeescript .hljs-regexp, .lang-coffeescript .hljs-subst, .lang-cpp .hljs-preprocessor, .lang-javascript .hljs-regexp, .lang-json .hljs-attribute, .lang-less .hljs-built_in, .lang-makefile .hljs-variable, .lang-markdown .hljs-blockquote, .lang-markdown .hljs-emphasis, .lang-markdown .hljs-link_label, .lang-markdown .hljs-strong, .lang-markdown .hljs-value, .lang-nginx .hljs-number, .lang-nginx .hljs-regexp, .lang-objectivec .hljs-preprocessor .hljs-title, .lang-perl .hljs-regexp, .lang-php .hljs-regexp, .lang-scss .hljs-built_in, .lang-xml .hljs-value {
+ color: #df5000
+}
+
+.hljs-keyword, .lang-css .hljs-at_rule, .lang-css .hljs-important, .lang-go .hljs-typename, .lang-haskell .hljs-type, .lang-http .hljs-request, .lang-ini .hljs-setting, .lang-java .hljs-javadoctag, .lang-javascript .hljs-javadoctag, .lang-javascript .hljs-tag, .lang-less .hljs-at_rule, .lang-less .hljs-tag, .lang-nginx .hljs-title, .lang-objectivec .hljs-preprocessor, .lang-php .hljs-phpdoc, .lang-scss .hljs-at_rule, .lang-scss .hljs-important, .lang-scss .hljs-tag, .lang-sql .hljs-built_in, .lang-stylus .hljs-at_rule, .lang-swift .hljs-preprocessor {
+ color: #a71d5d
+}
+
+.lang-apache .hljs-cbracket, .lang-apache .hljs-common, .lang-apache .hljs-keyword, .lang-bash .hljs-built_in, .lang-bash .hljs-literal, .lang-c .hljs-built_in, .lang-c .hljs-number, .lang-coffeescript .hljs-built_in, .lang-coffeescript .hljs-literal, .lang-coffeescript .hljs-number, .lang-cpp .hljs-built_in, .lang-cpp .hljs-number, .lang-cs .hljs-built_in, .lang-cs .hljs-number, .lang-css .hljs-attribute, .lang-css .hljs-function, .lang-css .hljs-hexcolor, .lang-css .hljs-number, .lang-go .hljs-built_in, .lang-go .hljs-constant, .lang-haskell .hljs-number, .lang-http .hljs-attribute, .lang-http .hljs-literal, .lang-java .hljs-number, .lang-javascript .hljs-built_in, .lang-javascript .hljs-literal, .lang-javascript .hljs-number, .lang-json .hljs-number, .lang-less .hljs-attribute, .lang-less .hljs-function, .lang-less .hljs-hexcolor, .lang-less .hljs-number, .lang-makefile .hljs-keyword, .lang-markdown .hljs-link_reference, .lang-nginx .hljs-built_in, .lang-objectivec .hljs-built_in, .lang-objectivec .hljs-literal, .lang-objectivec .hljs-number, .lang-php .hljs-literal, .lang-php .hljs-number, .lang-puppet .hljs-function, .lang-python .hljs-number, .lang-ruby .hljs-constant, .lang-ruby .hljs-number, .lang-ruby .hljs-prompt, .lang-ruby .hljs-subst .hljs-keyword, .lang-ruby .hljs-symbol, .lang-rust .hljs-number, .lang-scss .hljs-attribute, .lang-scss .hljs-function, .lang-scss .hljs-hexcolor, .lang-scss .hljs-number, .lang-scss .hljs-preprocessor, .lang-sql .hljs-number, .lang-stylus .hljs-attribute, .lang-stylus .hljs-hexcolor, .lang-stylus .hljs-number, .lang-stylus .hljs-params, .lang-swift .hljs-built_in, .lang-swift .hljs-number {
+ color: #0086b3
+}
+
+.lang-apache .hljs-tag, .lang-cs .hljs-xmlDocTag, .lang-css .hljs-tag, .lang-stylus .hljs-tag, .lang-xml .hljs-title {
+ color: #63a35c
+}
+
+.lang-bash .hljs-variable, .lang-cs .hljs-preprocessor, .lang-cs .hljs-preprocessor .hljs-keyword, .lang-css .hljs-attr_selector, .lang-css .hljs-value, .lang-ini .hljs-keyword, .lang-ini .hljs-value, .lang-javascript .hljs-tag .hljs-title, .lang-makefile .hljs-constant, .lang-nginx .hljs-variable, .lang-scss .hljs-variable, .lang-xml .hljs-tag {
+ color: #333
+}
+
+.lang-bash .hljs-title, .lang-c .hljs-title, .lang-coffeescript .hljs-title, .lang-cpp .hljs-title, .lang-cs .hljs-title, .lang-css .hljs-class, .lang-css .hljs-id, .lang-css .hljs-pseudo, .lang-diff .hljs-chunk, .lang-haskell .hljs-pragma, .lang-haskell .hljs-title, .lang-ini .hljs-title, .lang-java .hljs-title, .lang-javascript .hljs-title, .lang-less .hljs-class, .lang-less .hljs-id, .lang-less .hljs-pseudo, .lang-makefile .hljs-title, .lang-objectivec .hljs-title, .lang-perl .hljs-sub, .lang-php .hljs-title, .lang-puppet .hljs-title, .lang-python .hljs-decorator, .lang-python .hljs-title, .lang-ruby .hljs-parent, .lang-ruby .hljs-title, .lang-rust .hljs-title, .lang-scss .hljs-class, .lang-scss .hljs-id, .lang-scss .hljs-pseudo, .lang-stylus .hljs-class, .lang-stylus .hljs-id, .lang-stylus .hljs-pseudo, .lang-stylus .hljs-title, .lang-swift .hljs-title, .lang-xml .hljs-attribute {
+ color: #795da3
+}
+
+.lang-coffeescript .hljs-attribute, .lang-coffeescript .hljs-reserved {
+ color: #1d3e81
+}
+
+.lang-diff .hljs-chunk {
+ font-weight: 700
+}
+
+.lang-diff .hljs-addition {
+ color: #55a532;
+ background-color: #eaffea
+}
+
+.lang-diff .hljs-deletion {
+ color: #bd2c00;
+ background-color: #ffecec
+}
+
+.lang-markdown .hljs-link_url {
+ text-decoration: underline
+}
+
+#sidebar {
+ width: 250px;
+ height: 100%;
+ position: fixed;
+ left: 0;
+ top: 0;
+ background-image: url('/static/bg.jpg');
+ background-size: cover;
+ background-color: #9e9e9e;
+ overflow: auto;
+ z-index: 1;
+ -webkit-overflow-scrolling: touch
+}
+
+#sidebar li, #sidebar ul {
+ margin: 0;
+ padding: 0;
+ list-style: none
+}
+
+#sidebar .profile {
+ padding-top: 40px;
+ padding-bottom: 10px
+}
+
+#sidebar .profile a, #sidebar .profile img {
+ width: 140px;
+ height: 140px;
+ border-radius: 70px;
+ overflow: hidden
+}
+
+#sidebar .profile a {
+ display: block;
+ margin: 0 auto
+}
+
+#sidebar .profile span {
+ display: block;
+ padding: 10px 0;
+ font-size: 18px;
+ color: #e5e3e9;
+ text-align: center
+}
+
+#sidebar .buttons {
+ margin: 0 0 20px
+}
+
+#sidebar .buttons li {
+ display: block;
+ width: 100%;
+ height: 45px;
+ line-height: 45px;
+ font-size: 16px
+}
+
+#sidebar .buttons li a {
+ padding-left: 25px;
+ display: block;
+ color: #e5e3e9;
+ -webkit-transition: color .2s cubic-bezier(.4, .01, .165, .99);
+ transition: color .2s cubic-bezier(.4, .01, .165, .99);
+ text-decoration: none
+}
+
+#sidebar .buttons li a i, #sidebar .buttons li a span {
+ display: inline-block;
+ vertical-align: middle
+}
+
+#sidebar .buttons li a i {
+ font-size: 20px;
+ width: 25px;
+ height: 45px;
+ line-height: 45px;
+ text-align: center;
+ margin-right: 20px
+}
+
+#sidebar .buttons li a:hover {
+ color: #e5e3e9
+}
+
+#sidebar .buttons li a.inline {
+ display: inline-block;
+ width: 40px
+}
+
+#sidebar-mask {
+ position: absolute;
+ left: 0;
+ top: 0;
+ right: 0;
+ bottom: 0;
+ z-index: 999;
+ overflow: hidden;
+ display: none;
+ background-color: rgba(255, 255, 255, 0)
+}
+
+#header {
+ display: none
+}
+
+#header {
+ width: 100%;
+ height: 50px;
+ line-height: 50px;
+ overflow: hidden;
+ position: fixed;
+ left: 0;
+ top: 0;
+ z-index: 9;
+ background-color: #323436
+}
+
+body.side #header .btn-bar:before {
+ width: 24px;
+ -webkit-transform: rotate(-45deg);
+ -ms-transform: rotate(-45deg);
+ transform: rotate(-45deg);
+ top: 25px
+}
+
+body.side #header .btn-bar:after {
+ width: 24px;
+ -webkit-transform: rotate(45deg);
+ -ms-transform: rotate(45deg);
+ transform: rotate(45deg);
+ bottom: 24px
+}
+
+body.side #header .btn-bar i {
+ opacity: 0
+}
+
+#header h1 {
+ text-align: center;
+ font-size: 16px
+}
+
+#header h1 a {
+ color: #999
+}
+
+#header .btn-bar {
+ width: 50px;
+ height: 50px;
+ position: absolute;
+ left: 0;
+ top: 0
+}
+
+#header .btn-bar i, #header .btn-bar:after, #header .btn-bar:before {
+ width: 22px;
+ height: 1px;
+ position: absolute;
+ left: 14px;
+ background-color: #999;
+ -webkit-transition: all .2s cubic-bezier(.4, .01, .165, .99) .3s;
+ transition: all .2s cubic-bezier(.4, .01, .165, .99) .3s
+}
+
+#header .btn-bar i {
+ top: 25px;
+ opacity: 1
+}
+
+#header .btn-bar:before {
+ content: '';
+ top: 17px
+}
+
+#header .btn-bar:after {
+ content: '';
+ bottom: 16px
+}
+
+#header a.me, #header a.me img {
+ width: 30px;
+ height: 30px;
+ border-radius: 30px;
+ overflow: hidden
+}
+
+#header a.me {
+ position: absolute;
+ right: 10px;
+ top: 10px
+}
+
+.pagination {
+ width: 100%;
+ line-height: 20px;
+ position: relative;
+ border-top: 1px solid #fff;
+ border-bottom: 1px solid #ddd;
+ padding: 20px 0;
+ overflow: hidden
+}
+
+.pagination .prev {
+ float: left
+}
+
+.pagination .next {
+ float: right
+}
+
+.pagination .center {
+ text-align: center;
+ width: 80px;
+ margin: auto
+}
+
+article {
+ border-bottom: 1px solid #ddd;
+ border-top: 1px solid #fff;
+ position: relative;
+ padding: 30px 0;
+ word-wrap: break-word
+}
+
+article .meta {
+ position: relative;
+ float: right;
+ color: #555;
+ font-size: .9em;
+ line-height: 2;
+ width: auto;
+ text-align: right
+}
+
+article .meta a {
+ color: #999
+}
+
+article .meta .comment, article .meta .date, article .meta .tags {
+ position: relative
+}
+
+article h1.title {
+ color: #333;
+ font-size: 2em;
+ font-weight: 300;
+ line-height: 35px;
+ margin-bottom: 25px
+}
+
+article h1.title a {
+ color: #333
+}
+
+article h1.title a:hover {
+ color: #2479CC;
+ transition: color .3s
+}
+
+article button, article input.runcode {
+ line-height: 1;
+ border: none;
+ cursor: pointer;
+ padding: .625em .5em;
+ box-shadow: inset 0 -5px 20px rgba(0, 0, 0, .1);
+ background: #12b0e6;
+ color: #fff;
+ font-size: 14px;
+ margin-top: 10px;
+ -webkit-appearance: button
+}
+
+article input.runcode:active, article input.runcode:focus, article input.runcode:hover {
+ background: #f6ad08
+}
+
+article strong {
+ font-weight: 700
+}
+
+article em {
+ font-style: italic
+}
+
+article blockquote {
+ margin: 10px 0 0 0;
+ padding: 15px 20px;
+ border-left: 5px solid #2479CC;
+ background-color: #f8f8f8
+}
+
+article blockquote p {
+ margin-bottom: 0
+}
+
+article blockquote a {
+ word-break: break-all;
+ word-wrap: break-word
+}
+
+article code {
+ font-family: Consolas, "Courier New", Courier, mono, serif;
+ font-size: 80%;
+ margin: 0 2px;
+ padding: 4px 5px;
+ background-color: #f2f2f2;
+ vertical-align: middle;
+ border-radius: 5px
+}
+
+article pre {
+ font-family: Consolas, "Liberation Mono", Courier, monospace;
+ font-size: 14px;
+ line-height: 1.6;
+ color: #5d6a6a;
+ padding: .6em;
+ border-left: 5px solid #ccc;
+ word-break: break-all;
+ word-wrap: break-word;
+ white-space: pre-wrap;
+ position: relative;
+ overflow: hidden
+}
+
+article pre code {
+ border-radius: 0;
+ background-color: transparent;
+ border: 0;
+ padding: 0;
+ margin: 0;
+ font-size: 100%;
+ display: block;
+ position: relative
+}
+
+article pre b.name {
+ position: absolute;
+ line-height: 1;
+ top: 10px;
+ right: 10px;
+ font-size: 60px;
+ color: #eee;
+ pointer-events: none
+}
+
+@media screen and (max-width: 768px) {
+ article pre b.name {
+ font-size: 30px
+ }
+}
+
+article img {
+ padding: 0;
+ display: block;
+ border: 1px solid #ccc;
+ margin: 10px 0 5px 0;
+ max-width: 100%
+}
+
+article table {
+ border: 0;
+ border-collapse: collapse;
+ border-spacing: 0
+}
+
+article table td, article table th {
+ border: 0
+}
+
+article table th {
+ border-bottom: 2px solid #848484;
+ text-align: left;
+ padding: 6px 20px
+}
+
+article table td {
+ border-bottom: 1px solid #d0d0d0;
+ padding: 6px 20px
+}
+
+article .expire-tips {
+ padding: 5px 10px;
+ font-size: 15px;
+ border: 1px solid #e2e2e2;
+ background-color: #ffffc0;
+ border-left: 5px solid #fff000;
+ color: #333
+}
+
+article .aliyun-tips {
+ padding: 5px 10px;
+ font-size: 15px;
+ border: 1px solid #e2e2e2;
+ background-color: #f0f8f4;
+ border-left: 5px solid #7cc4a0
+}
+
+article .post-info {
+ font-size: 14px
+}
+
+article .entry-content {
+ font-size: 16px;
+ line-height: 1.8;
+ word-wrap: break-word
+}
+
+article .entry-content .date {
+ color: #999;
+ font-size: 14px;
+ font-style: italic
+}
+
+article .entry-content blockquote, article .entry-content dl, article .entry-content h1, article .entry-content h2, article .entry-content h3, article .entry-content h4, article .entry-content h5, article .entry-content h6, article .entry-content iframe, article .entry-content ol, article .entry-content p, article .entry-content pre, article .entry-content table, article .entry-content ul {
+ margin-top: 15px
+}
+
+article .entry-content blockquote > p:first-of-type, article .entry-content dl dl, article .entry-content dl ol, article .entry-content dl ul, article .entry-content ol dl, article .entry-content ol ol, article .entry-content ol ul, article .entry-content ul dl, article .entry-content ul ol, article .entry-content ul ul {
+ margin-top: 0
+}
+
+article .entry-content dl, article .entry-content ol, article .entry-content ul {
+ margin-left: 25px
+}
+
+article.tags section a {
+ display: inline-block;
+ font-size: 14px;
+ padding: 0 15px;
+ height: 40px;
+ line-height: 40px;
+ color: rgba(36, 121, 204, .8);
+ border: 1px solid rgba(36, 121, 204, .8);
+ border-radius: 4px;
+ margin: 0 15px 10px 0;
+ text-decoration: none;
+ -webkit-transition: color .2s cubic-bezier(.4, .01, .165, .99), border .2s cubic-bezier(.4, .01, .165, .99);
+ transition: color .2s cubic-bezier(.4, .01, .165, .99), border .2s cubic-bezier(.4, .01, .165, .99)
+}
+
+article.tags section a:hover {
+ color: #2479CC;
+ border-color: #2479CC
+}
+
+a.anchor {
+ display: block;
+ position: relative;
+ visibility: hidden
+}
+
+article .app-code > ul {
+ list-style: decimal;
+ background-color: #fff;
+ margin: 0;
+ margin-left: 40px;
+ padding: 0
+}
+
+article .app-code li {
+ list-style: decimal-leading-zero;
+ border-left: 1px solid #ddd;
+ padding-left: 2px;
+ position: relative
+}
+
+article .app-code li.mark {
+ background-color: #fffbdd !important
+}
+
+article .app-code li:hover {
+ background-color: #f3f3f3 !important
+}
+
+article .app-code .line-num {
+ width: 40px;
+ position: absolute;
+ left: 0;
+ top: 0;
+ height: 100%;
+ left: -40px;
+ cursor: pointer
+}
+
+article .app-code li:nth-of-type(even) {
+ background-color: #fcfcfc;
+ color: inherit
+}
+
+article .entry-content pre .app-code {
+ background-color: #eee
+}
+
+article pre {
+ border-left: none;
+ padding: 0
+}
+
+article .entry-content pre code {
+ font-size: 12px;
+ background-color: #fff;
+ border: 1px solid #eee;
+ padding: 0;
+ line-height: 26px
+}
+
+#search .wrapper {
+ margin-right: 72px
+}
+
+#search form {
+ position: relative
+}
+
+#search .wrapper input {
+ -webkit-appearance: none;
+ border: 1px solid #bbb;
+ border-radius: 0;
+ box-sizing: border-box;
+ display: block;
+ font-size: 16px;
+ height: 40px;
+ outline: 0;
+ padding: 4px 6px;
+ width: 100%
+}
+
+#search .submit {
+ -webkit-appearance: none;
+ background-color: #e7e7e7;
+ border: 1px solid #bbb;
+ border-left: 0;
+ border-radius: 0;
+ color: #222;
+ display: block;
+ font-size: 16px;
+ height: 40px;
+ outline: 0;
+ position: absolute;
+ right: 0;
+ top: 0;
+ width: 72px
+}
+
+#searchResult {
+ min-height: 350px;
+ overflow-x: hidden
+}
+
+#searchResult .info {
+ color: #676767;
+ font-size: 13px;
+ padding: 15px 0;
+ border-bottom: 1px solid #e9e9e9
+}
+
+#searchResult .no-result {
+ padding: 5px;
+ margin: 15px 0;
+ border: 1px solid #fc3;
+ background-color: #fff4c2;
+ font-size: 13px
+}
+
+#searchResult .loading {
+ margin-top: 20px
+}
+
+#searchResult .hot-words {
+ margin-top: 20px
+}
+
+#searchResult .hot-words a {
+ margin-right: 20px
+}
+
+#searchResult .item {
+ padding: .5em 0 .3em 0
+}
+
+#searchResult .item .title a {
+ font-size: 16px;
+ text-decoration: underline
+}
+
+#searchResult .item .title .type {
+ display: inline-block;
+ background-color: #eee;
+ color: #888;
+ margin-right: 8px;
+ padding: 0 5px;
+ font-size: 13px;
+ border-radius: 3px
+}
+
+#searchResult .item .desc {
+ font-size: 14px;
+ line-height: 1.6
+}
+
+#searchResult .item .tags {
+ font-size: 14px;
+ line-height: 1.8
+}
+
+#searchResult .item .tags a {
+ margin-right: 12px;
+ color: #666
+}
+
+#searchResult .item .desc b, #searchResult .item .title b {
+ color: #C00;
+ font-weight: 400
+}
+
+#footer {
+ line-height: 1.8;
+ text-align: center;
+ padding: 15px;
+ border-top: 1px solid #fff;
+ font-size: .9em
+}
+
+#footer .beian {
+ color: #666
+}
+
+#comments {
+ border-top: 1px solid #fff;
+ border-bottom: 1px solid #ddd;
+ padding: 30px 0;
+ min-height: 350px
+}
+
+#comments h1.title {
+ font-size: 25px;
+ font-weight: 300;
+ line-height: 35px;
+ margin-bottom: 20px
+}
+
/* responsive */
-@media screen and (max-width:768px){#header{-webkit-transform:translate3D(0,0,0);-ms-transform:translate3D(0,0,0);transform:translate3D(0,0,0);-webkit-transition:all .2s cubic-bezier(.4,.01,.165,.99);transition:all .2s cubic-bezier(.4,.01,.165,.99);display:block}a.anchor{top:-50px}}@media screen and (max-width:768px){#sidebar.behavior_1{-webkit-transform:translate3D(-250px,0,0);-ms-transform:translate3D(-250px,0,0);transform:translate3D(-250px,0,0)}#sidebar.behavior_2{-webkit-transform:translate3D(0,0,0);-ms-transform:translate3D(0,0,0);transform:translate3D(0,0,0)}#sidebar{-webkit-transition:-webkit-transform .2s cubic-bezier(.4,.01,.165,.99);transition:-webkit-transform .2s cubic-bezier(.4,.01,.165,.99);transition:transform .2s cubic-bezier(.4,.01,.165,.99);transition:transform .2s cubic-bezier(.4,.01,.165,.99),-webkit-transform .2s cubic-bezier(.4,.01,.165,.99)}#sidebar .profile{padding-top:20px;padding-bottom:20px}#sidebar .profile a,#sidebar .profile img{width:100px;height:100px;border-radius:100px}#sidebar .profile span{display:none}}@media screen and (min-width:769px) and (max-width:1024px){#sidebar{width:75px}#sidebar .profile{padding-top:20px}#sidebar .profile a,#sidebar .profile img{width:40px;height:40px;border-radius:40px}#sidebar .profile span{display:none}#sidebar .buttons li a{padding:0}#sidebar .buttons li a.inline{width:100%}#sidebar .buttons li a i{font-size:18px;display:block;margin:0 auto}#sidebar .buttons li a span{display:none}}@media screen and (min-width:768px) and (max-width:1024px){#main{padding-left:115px}}@media screen and (max-width:769px){#main{width:100%;min-height:100%;padding-top:50px;padding-left:10px;padding-right:10px}}@media screen and (max-width:769px){article{background-color:#fff;padding:10px}article .meta{display:none}article h1{font-size:22px;padding:5px 0 10px;margin:0}article .desc{color:#999;font-size:14px}article p.more{font-size:14px;margin:5px 0}}
\ No newline at end of file
+@media screen and (max-width: 768px) {
+ #header {
+ -webkit-transform: translate3D(0, 0, 0);
+ -ms-transform: translate3D(0, 0, 0);
+ transform: translate3D(0, 0, 0);
+ -webkit-transition: all .2s cubic-bezier(.4, .01, .165, .99);
+ transition: all .2s cubic-bezier(.4, .01, .165, .99);
+ display: block
+ }
+
+ a.anchor {
+ top: -50px
+ }
+}
+
+@media screen and (max-width: 768px) {
+ #sidebar.behavior_1 {
+ -webkit-transform: translate3D(-250px, 0, 0);
+ -ms-transform: translate3D(-250px, 0, 0);
+ transform: translate3D(-250px, 0, 0)
+ }
+
+ #sidebar.behavior_2 {
+ -webkit-transform: translate3D(0, 0, 0);
+ -ms-transform: translate3D(0, 0, 0);
+ transform: translate3D(0, 0, 0)
+ }
+
+ #sidebar {
+ -webkit-transition: -webkit-transform .2s cubic-bezier(.4, .01, .165, .99);
+ transition: -webkit-transform .2s cubic-bezier(.4, .01, .165, .99);
+ transition: transform .2s cubic-bezier(.4, .01, .165, .99);
+ transition: transform .2s cubic-bezier(.4, .01, .165, .99), -webkit-transform .2s cubic-bezier(.4, .01, .165, .99)
+ }
+
+ #sidebar .profile {
+ padding-top: 20px;
+ padding-bottom: 20px
+ }
+
+ #sidebar .profile a, #sidebar .profile img {
+ width: 100px;
+ height: 100px;
+ border-radius: 100px
+ }
+
+ #sidebar .profile span {
+ display: none
+ }
+}
+
+@media screen and (min-width: 769px) and (max-width: 1024px) {
+ #sidebar {
+ width: 75px
+ }
+
+ #sidebar .profile {
+ padding-top: 20px
+ }
+
+ #sidebar .profile a, #sidebar .profile img {
+ width: 40px;
+ height: 40px;
+ border-radius: 40px
+ }
+
+ #sidebar .profile span {
+ display: none
+ }
+
+ #sidebar .buttons li a {
+ padding: 0
+ }
+
+ #sidebar .buttons li a.inline {
+ width: 100%
+ }
+
+ #sidebar .buttons li a i {
+ font-size: 18px;
+ display: block;
+ margin: 0 auto
+ }
+
+ #sidebar .buttons li a span {
+ display: none
+ }
+}
+
+@media screen and (min-width: 768px) and (max-width: 1024px) {
+ #main {
+ padding-left: 115px
+ }
+}
+
+@media screen and (max-width: 769px) {
+ #main {
+ width: 100%;
+ min-height: 100%;
+ padding-top: 50px;
+ padding-left: 10px;
+ padding-right: 10px
+ }
+}
+
+@media screen and (max-width: 769px) {
+ article {
+ background-color: #fff;
+ padding: 10px
+ }
+
+ article .meta {
+ display: none
+ }
+
+ article h1 {
+ font-size: 22px;
+ padding: 5px 0 10px;
+ margin: 0
+ }
+
+ article .desc {
+ color: #999;
+ font-size: 14px
+ }
+
+ article p.more {
+ font-size: 14px;
+ margin: 5px 0
+ }
+}
+
+@media screen and (min-width: 768px) {
+ article .entry-content .toc {
+ right: 10%;
+ padding: 8px;
+ position: fixed;
+ font-size: 14px;
+ margin: 0 0 15px 20px;
+ max-width: 260px;
+ min-width: 120px;
+ max-height: 400px;
+ overflow-y: auto;
+ opacity: 0.7;
+ z-index: 1001;
+ border: 1px solid #e2e2e2;
+ }
+
+ article .entry-content .toc p {
+ margin: 0;
+ padding: 0 4px;
+ border-bottom: 1px solid #e2e2e2;
+ display: block;
+ }
+}
\ No newline at end of file
diff --git a/static/logo.png b/static/logo.png
index 241c1d7..191295a 100644
Binary files a/static/logo.png and b/static/logo.png differ
diff --git a/views/index.html b/views/index.html
index 2c88672..bc94fd4 100644
--- a/views/index.html
+++ b/views/index.html
@@ -1 +1,22 @@
-{{.title}} {{template "tpl-linker.html" .}}{{template "tpl-naver.html" .}}{{ range $k, $v := .Posts }}{{ str2html $v.Summary }}
阅读全文 »
{{ end }} {{template "tpl-footer.html" .}}
\ No newline at end of file
+
+
+
{{.title}}
+
{{template "tpl-linker.html" .}}
+{{template "tpl-naver.html" .}}
+
+
{{ range $k, $v := .Posts }}
+
+
+
+ {{ str2html $v.Summary }}
阅读全文
+ »
+ {{ end }}
+
+ {{template "tpl-footer.html" .}}
+
\ No newline at end of file
diff --git a/views/page.html b/views/page.html
index 7d93b29..4b304ba 100644
--- a/views/page.html
+++ b/views/page.html
@@ -1,4 +1,17 @@
-
{{.title}}·{{.Page.Title}} {{template "tpl-linker.html" .}}{{template "tpl-naver.html" .}}
{{.Page.Title}} {{if .Show}}{{str2html .Page.Content}}{{else}}
Sorry,主人还在思考 (●ˇ∀ˇ●) ! [ =======> 60% ] {{end}}
-{{if .Page.AllowComment}}
-{{end}}
-
{{template "tpl-footer.html" .}}
\ No newline at end of file
+
+
+
{{.title}}·{{.Page.Title}}
+
{{template "tpl-linker.html" .}}
+{{template "tpl-naver.html" .}}
+
+
+
{{.Page.Title}}
+ {{if .Show}}{{str2html .Page.Content}}{{else}}
+
Sorry,主人还在思考 (●ˇ∀ˇ●) ! [ =======> 60% ] {{end}}
+
+ {{if .Page.AllowComment}}
+ {{end}}
+
{{template "tpl-footer.html" .}}
+
\ No newline at end of file
diff --git a/views/post.html b/views/post.html
index f3d5135..5e2885c 100644
--- a/views/post.html
+++ b/views/post.html
@@ -1,4 +1,30 @@
-
{{.title}}·{{.Post.Title}} {{template "tpl-linker.html" .}}{{template "tpl-naver.html" .}}
{{.Post.Title}} {{str2html .Post.Content}}
本文链接:{{.site_url}}/post/{{.Post.Path}}.html
-- EOF --
发表于 {{ date .Post.CreateTime "2006-01-02 15:04:05"}} {{if .HasCate}},添加在分类{{.Post.Cate.Intro}}
下{{end}}{{if .HasTag}},并被添加「{{range $k, $v := .Tags }}{{$v.Tag.Intro}}
{{end}}」标签{{end}},最后修改于 {{ date .Post.UpdateTime "2006-01-02 15:04:05"}}
-{{if .Post.AllowComment}}
-{{end}}
-
{{template "tpl-footer.html" .}}
\ No newline at end of file
+
+
+
{{.title}}·{{.Post.Title}}
+
{{template "tpl-linker.html" .}}
+{{template "tpl-naver.html" .}}
+
+
+
+
+ {{.Post.Title}}
+ {{str2html .Post.Content}}
+ 本文链接:{{.site_url}}/post/{{.Post.Path}}.html
+ -- EOF --
+ 发表于
+ {{ date .Post.CreateTime "2006-01-02 15:04:05"}} {{if .HasCate}}
+ ,添加在分类{{.Post.Cate.Intro}}
下{{end}}{{if .HasTag}}
+ ,并被添加「{{range $k, $v := .Tags }}
+ {{$v.Tag.Intro}}
{{end}}
+ 」标签{{end}},最后修改于 {{ date .Post.UpdateTime "2006-01-02 15:04:05"}}
+
+
+ {{if .Post.AllowComment}}
+ {{end}}
+
{{template "tpl-footer.html" .}}
+
\ No newline at end of file
diff --git a/views/search.html b/views/search.html
new file mode 100644
index 0000000..31f6555
--- /dev/null
+++ b/views/search.html
@@ -0,0 +1,70 @@
+
+
+
{{.title}}·搜索
+
{{template "tpl-linker.html" .}}
+{{template "tpl-naver.html" .}}
+
+
站内搜索
+
+
+
+ {{if .NotSearch}}
+
+
+ {{else}}
+
本次搜索共找到结果 {{.Total}} 条 (用时 {{.Duration}} 秒)
+ {{range .Posts}}
+
+
+
+
+ {{ date .CreateTime "2006-01-02"}} ... {{str2html .Summary}} ...
+
+
+
+ {{end}}
+
+ {{if .Naver.Prev}}
+ « 上一页
+ {{end}}
+ {{if .Naver.Next}}
+ 下一页 »
+ {{end}}
+ {{end}}
+
+
+ {{template "tpl-footer.html" .}}
+
+
\ No newline at end of file
diff --git a/views/series.html b/views/series.html
new file mode 100644
index 0000000..de05b6a
--- /dev/null
+++ b/views/series.html
@@ -0,0 +1,53 @@
+
+
+
{{.title}}·专题
+
{{template "tpl-linker.html" .}}
+{{template "tpl-naver.html" .}}
+
+
专题
+
+
+
+
这里,记录着我对某件事物、某个新兴技术的学习过程。善于总结,善于收拾。这里可以说是自己资料的回忆录,但更希望的是对需要了解到相关知识的朋友有所帮助。
+
+ {{range .Cates}}
+
{{.Name}}
+
+
{{.Intro}}
+
+
+ {{range .Posts}}
+ {{.Title}} ({{date .CreateTime "2006-01-02" }})
+ {{end}}
+
+ {{end}}
+
+ {{template "tpl-footer.html" .}}
+
+
\ No newline at end of file
diff --git a/views/tag-post.html b/views/tag-post.html
index df7fccb..263cdfd 100644
--- a/views/tag-post.html
+++ b/views/tag-post.html
@@ -1 +1,23 @@
-
{{.title}}·{{.Tag.Name}} {{template "tpl-linker.html" .}}{{template "tpl-naver.html" .}}
{{ range $k, $v := .TagPosts }}{{ str2html $v.Post.Summary }}
阅读全文»
{{ end }} {{template "tpl-footer.html" .}}
\ No newline at end of file
+
+
+
{{.title}}·{{.Tag.Name}}
+
{{template "tpl-linker.html" .}}
+{{template "tpl-naver.html" .}}
+
+
{{ range $k, $v := .TagPosts }}
+
+
+
+ {{ str2html $v.Post.Summary }}
阅读全文»
+ {{ end }}
+
+ {{template "tpl-footer.html" .}}
+
\ No newline at end of file
diff --git a/views/tags.html b/views/tags.html
index 25b0476..91f9e9e 100644
--- a/views/tags.html
+++ b/views/tags.html
@@ -1 +1,13 @@
-
{{.title}}·标签 {{template "tpl-linker.html" .}}{{template "tpl-naver.html" .}}
标签 {{template "tpl-footer.html" .}}
\ No newline at end of file
+
+
+
{{.title}}·标签
+
{{template "tpl-linker.html" .}}
+{{template "tpl-naver.html" .}}
+
+
标签
+
+ {{template "tpl-footer.html" .}}
+
\ No newline at end of file
diff --git a/views/tpl-linker.html b/views/tpl-linker.html
index 9123a0b..ae366cf 100644
--- a/views/tpl-linker.html
+++ b/views/tpl-linker.html
@@ -1 +1,19 @@
-
\ No newline at end of file
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/views/tpl-naver.html b/views/tpl-naver.html
index 0a05ec9..5b010d3 100644
--- a/views/tpl-naver.html
+++ b/views/tpl-naver.html
@@ -1 +1,28 @@
-
\ No newline at end of file
+
+
+
\ No newline at end of file
diff --git a/vue/.env.production b/vue/.env.production
index ca324e8..08568d9 100644
--- a/vue/.env.production
+++ b/vue/.env.production
@@ -1 +1 @@
-VUE_APP_SRV = https://blog.zxysilent.com
\ No newline at end of file
+VUE_APP_SRV = http://localhost:88
\ No newline at end of file
diff --git a/vue/src/assets/logo.png b/vue/src/assets/logo.png
index 241c1d7..191295a 100644
Binary files a/vue/src/assets/logo.png and b/vue/src/assets/logo.png differ
diff --git a/vue/src/views/article/article.vue b/vue/src/views/article/article.vue
index 60d5425..fef9274 100644
--- a/vue/src/views/article/article.vue
+++ b/vue/src/views/article/article.vue
@@ -1,351 +1,367 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- 设置
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 设置
+
+
+
+
+
+
+
diff --git a/vue/src/views/cate/list.vue b/vue/src/views/cate/list.vue
index 77cfcdc..700bae5 100644
--- a/vue/src/views/cate/list.vue
+++ b/vue/src/views/cate/list.vue
@@ -11,6 +11,9 @@
+
+
+
@@ -32,6 +35,7 @@ export default {
{ type: "index", minWidth: 60, maxWidth: 100, align: "center" },
{ title: "分类名", minWidth: 100, maxWidth: 300, key: "name" },
{ title: "分类介绍", minWidth: 100, maxWidth: 300, key: "intro" },
+ { title: "排序ID", minWidth: 100, maxWidth: 300, key: "sort" },
{
title: "Action",
minWidth: 100,
Comments