package handler import ( "bufio" "errors" "html/template" "io/ioutil" "os" "path/filepath" "sort" "strconv" "strings" "time" "github.com/gin-gonic/gin" "github.com/russross/blackfriday" ) type ArticleConf struct { Title string Time int64 } type Article struct { Id string Uri string Conf ArticleConf Content string Path string Date string } func (a *Article) GetArticleById(id string) (*Article, error) { path := os.Getenv("ARTICLE_PATH") + strings.Replace(id, "<-", "/", -1) + ".md" return a.GetArticleByPath(path) } func (a *Article) GetArticleByPath(path string) (*Article, error) { a.Path = path a.Uri = strings.Replace(a.Path, os.Getenv("ARTICLE_PATH"), "", -1) a.Id = a.Uri[:len(a.Uri)-len(filepath.Ext(a.Uri))] a.Id = strings.Replace(a.Id, "\\", "/", -1) a.Id = strings.Replace(a.Id, "/", "<-", -1) // 读取文件内容 fileByte, err := ioutil.ReadFile(a.Path) if err != nil { return a, errors.New("文章不存在") } parts := strings.Split(string(fileByte), "<-->") var articleConf map[string]string if len(parts) == 2 { if len(parts[0]) > 0 { articleConf = GetArticleConf(parts[0]) if len(articleConf["date"]) > 0 { t, err := time.Parse("2006-1-2 15:04", articleConf["date"]) if err == nil { a.Conf.Time = t.Unix() a.Date = time.Unix(a.Conf.Time, 0).Format("2006-01-02") } } if len(articleConf["title"]) > 0 { a.Conf.Title = articleConf["title"] } } a.Content = parts[1] } else { a.Conf.Title = a.Id info, _ := os.Stat(a.Path) mtime := info.ModTime() a.Conf.Time = mtime.Unix() a.Content = parts[0] a.Date = time.Unix(a.Conf.Time, 0).Format("2006-01-02") } return a, nil } func GetArticle(c *gin.Context) { article, err := new(Article).GetArticleById(c.Param("id")) if err != nil { c.String(200, err.Error()) return } // 转换为HTML output := blackfriday.MarkdownCommon([]byte(article.Content)) c.HTML(200, "article.html", gin.H{ "content": template.HTML(string(output)), "title": article.Conf.Title, "date": article.Date, }) } func MakeArticleOrder() { articleBasePath := os.Getenv("ARTICLE_PATH") list := make(map[string]int64) aritcleNew := new(Article) _ = filepath.Walk(articleBasePath, func(path string, info os.FileInfo, err error) error { if info.IsDir() || filepath.Ext(path) != ".md" { return nil } article, err := aritcleNew.GetArticleByPath(path) if err != nil { return nil } list[article.Id] = article.Conf.Time return nil }) if len(list) == 0 { return } sortList := sortArticleByTime(list) filename := "./data/index_sort_list" file, err := os.Create(filename) if err != nil { return } defer file.Close() writer := bufio.NewWriter(file) total := len(sortList) writer.WriteString(strconv.Itoa(total) + "\n") for _, info := range sortList { writer.WriteString(info.Title + "\n") } writer.Flush() } func GetArticleConf(conf string) map[string]string { data := make(map[string]string) conf = strings.Replace(conf, "\r\n", "\n", -1) list := strings.Split(conf, "\n") for _, conf := range list { index := strings.Index(conf, ":") if index == -1 { continue } key := conf[0:index] value := conf[index+1:] data[key] = value } return data } func sortArticleByTime(m map[string]int64) []ArticleConf { pairs := make([]ArticleConf, 0, len(m)) for k, v := range m { pairs = append(pairs, ArticleConf{k, v}) } // 对结构体切片按照值进行排序 sort.Slice(pairs, func(i, j int) bool { return pairs[i].Time > pairs[j].Time }) return pairs }