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, `$2`) - 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-- - } - sb.WriteString(`
`) - return sb.String() + html - } - if len(hs) == 1 { - sb := strings.Builder{} - 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, `$2`) + 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-- + } + sb.WriteString(`
`) + return sb.String() + html + } + if len(hs) == 1 { + sb := strings.Builder{} + 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 « 上一页 - naver.Prev = `` - } - 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 = `` - } - 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 = `` + } + 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 = `` + } + 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 }}{{ end }}
{{template "tpl-footer.html" .}} \ No newline at end of file + + +{{.title}} + {{template "tpl-linker.html" .}} +{{template "tpl-naver.html" .}} +
+
{{ range $k, $v := .Posts }} + {{ 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}} -

Comments

{{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}} +

Comments

+
+
{{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" .}}
{{ date .Post.CreateTime "2006-01-02 15:04:05" }}
{{if .Post.AllowComment}}{{end}}

{{.Post.Title}}

{{str2html .Post.Content}}

本文链接:{{.site_url}}/post/{{.Post.Path}}.html

-- EOF --

-{{if .Post.AllowComment}} -

Comments

{{end}} -
{{template "tpl-footer.html" .}} \ No newline at end of file + + +{{.title}}·{{.Post.Title}} + {{template "tpl-linker.html" .}} +{{template "tpl-naver.html" .}} +
+
+
+
+
{{ date .Post.CreateTime "2006-01-02 15:04:05" }}
{{if .Post.AllowComment}} + {{end}}
+

{{.Post.Title}}

+
{{str2html .Post.Content}}
+

本文链接:{{.site_url}}/post/{{.Post.Path}}.html

+

-- EOF --

+ +
+ + {{if .Post.AllowComment}} +

Comments

+
+
{{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}} + +

支持的搜索格式:

+
    +
  1. 输入关键词全文搜索:Let's Encrypt
  2. +
  3. 指定时间段搜索:date:2016date:2016-10; +
  4. +
  5. 指定标签搜索:tag:githubtag:HTTPS
  6. +
  7. 组合搜索:date:2016 tag:docker
  8. +
+
+ {{else}} +
本次搜索共找到结果 {{.Total}} 条 (用时 {{.Duration}} 秒)
+ {{range .Posts}} +
+ +
+
+ {{ date .CreateTime "2006-01-02"}} ... {{str2html .Summary}} ... +
+
+
+ {{end}} + + {{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" .}}

标签「{{.Tag.Intro}}」下的文章

{{ range $k, $v := .TagPosts }}{{ end }}
{{template "tpl-footer.html" .}} \ No newline at end of file + + +{{.title}}·{{.Tag.Name}} + {{template "tpl-linker.html" .}} +{{template "tpl-naver.html" .}} +
+

标签「{{.Tag.Intro}}」下的文章 +

{{ range $k, $v := .TagPosts }} + {{ 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,