From 3fe728bef5d14d94c33c86f61b068bbe5b5aa853 Mon Sep 17 00:00:00 2001 From: xuxinhua Date: Wed, 21 Jun 2017 07:55:45 +0800 Subject: [PATCH 001/411] =?UTF-8?q?=E8=AE=BF=E9=97=AE=E4=B8=8D=E4=BA=86?= =?UTF-8?q?=EF=BC=8C=E5=8F=AF=E4=BB=A5=E9=80=9A=E8=BF=87golang.top=20?= =?UTF-8?q?=E8=AE=BF=E9=97=AE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 23 ++++++++++------------- 1 file changed, 10 insertions(+), 13 deletions(-) diff --git a/README.md b/README.md index bb9dd4bb..8638e5a0 100644 --- a/README.md +++ b/README.md @@ -1,21 +1,18 @@ studygolang =========== -[Go语言中文网 | Golang中文社区 | Go语言学习园地](http://studygolang.com "Go语言中文网 | Golang中文社区 | Go语言学习园地") 源码 +[Go语言中文网 - Golang中文社区](http://studygolang.com "Go语言中文网 - Golang中文社区") 源码 网站上线时间:2013-03-15 14:38:09 -目前开发了大部分功能,还有不少功能在不断开发完善中。欢迎有兴趣的 gopher 们参与进来,一起构建一个完善的 Go 语言中文网,Go语言爱好者的学习家园。 - -#目前需要开发的功能 -1. 小贴士 -2. 关注 -3. 用第三方账号登录 -4. 绑定 github 后显示其代码 -5. 评论直接支持内嵌wide -6. 评论支持编辑、删除自己的评论 -7. 代码片段分享 -8. rss 订阅 -9. ... +收到不少人反馈,网站访问不了,初步判断,上海电信和广东电信遇到比较多,如果您访问不了,请通过 https://golang.top 访问 + +目前在线运行的是 V3.0。欢迎有兴趣的 gopher 们参与进来,一起构建一个完善的 Go 语言中文网,Go 语言爱好者的学习家园。 + +# 目前需要开发的功能 +1. 关注 +2. 绑定 github 后显示其代码 +3. rss 订阅 +4. ... # 本地搭建一个 Go语言中文网 # From b0764d3a10fa2b503558cb8234db31b6ad12f274 Mon Sep 17 00:00:00 2001 From: xuxinhua Date: Wed, 21 Jun 2017 08:12:52 +0800 Subject: [PATCH 002/411] =?UTF-8?q?=E5=A2=9E=E5=8A=A0=E5=88=86=E4=BA=AB?= =?UTF-8?q?=E5=88=B0=E5=BE=AE=E5=8D=9A=E5=8A=9F=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/logic/article.go | 5 +++++ template/articles/detail.html | 3 ++- template/projects/detail.html | 3 ++- template/resources/detail.html | 3 ++- template/topics/detail.html | 3 ++- 5 files changed, 13 insertions(+), 4 deletions(-) diff --git a/src/logic/article.go b/src/logic/article.go index a0000e10..38dd03ec 100644 --- a/src/logic/article.go +++ b/src/logic/article.go @@ -497,6 +497,11 @@ func (ArticleLogic) findByIds(ids []int) map[int]*model.Article { func (ArticleLogic) FindByIdAndPreNext(ctx context.Context, id int) (curArticle *model.Article, prevNext []*model.Article, err error) { objLog := GetLogger(ctx) + if id == 0 { + err = errors.New("id 不能为0") + return + } + articles := make([]*model.Article, 0) err = MasterDB.Where("id BETWEEN ? AND ? AND status!=?", id-5, id+5, model.ArticleStatusOffline).Find(&articles) diff --git a/template/articles/detail.html b/template/articles/detail.html index 20f376ea..69a272da 100644 --- a/template/articles/detail.html +++ b/template/articles/detail.html @@ -55,7 +55,8 @@

{{.article.Viewnum}} 次点击  {{if .article.Likenum}}∙  {{.article.Likenum}} 赞   {{end}}
- {{if .hadcollect}}取消收藏{{else}}加入收藏{{end}}   + {{if .hadcollect}}取消收藏{{else}}加入收藏{{end}} + 微博 diff --git a/template/projects/detail.html b/template/projects/detail.html index cb5af0bd..1659180d 100644 --- a/template/projects/detail.html +++ b/template/projects/detail.html @@ -58,7 +58,8 @@

{{.project.Viewnum}} 次点击  {{if .project.Likenum}}∙  {{.project.Likenum}} 赞   {{end}}
- {{if .hadcollect}}取消收藏{{else}}加入收藏{{end}}   + {{if .hadcollect}}取消收藏{{else}}加入收藏{{end}} + 微博 diff --git a/template/resources/detail.html b/template/resources/detail.html index 16d7b9ca..86b3eda2 100644 --- a/template/resources/detail.html +++ b/template/resources/detail.html @@ -37,7 +37,8 @@

{{add .resource.viewnum 1}} 次点击  {{if .resource.likenum}}∙  {{.resource.likenum}} 赞   {{end}}
- {{if .hadcollect}}取消收藏{{else}}加入收藏{{end}}   + {{if .hadcollect}}取消收藏{{else}}加入收藏{{end}} + 微博 diff --git a/template/topics/detail.html b/template/topics/detail.html index b8522b3d..e5131073 100644 --- a/template/topics/detail.html +++ b/template/topics/detail.html @@ -39,7 +39,8 @@

{{add .topic.view 1}} 次点击  {{if .topic.like}}∙  {{.topic.like}} 赞   {{end}}
- {{if .hadcollect}}取消收藏{{else}}加入收藏{{end}}   + {{if .hadcollect}}取消收藏{{else}}加入收藏{{end}} + 微博 From 2b63272a971aae1e21094d70051a7442382c8b9f Mon Sep 17 00:00:00 2001 From: xuxinhua Date: Wed, 21 Jun 2017 11:49:09 +0800 Subject: [PATCH 003/411] =?UTF-8?q?=E5=9B=BE=E7=89=87=E7=9B=B8=E5=AF=B9?= =?UTF-8?q?=E8=B7=AF=E5=BE=84=20bugfix?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/logic/article.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/logic/article.go b/src/logic/article.go index 38dd03ec..aa711918 100644 --- a/src/logic/article.go +++ b/src/logic/article.go @@ -141,7 +141,7 @@ func (self ArticleLogic) ParseArticle(ctx context.Context, articleUrl string, au s.SetAttr("src", v) } else if v, ok := s.Attr("src"); ok { if !strings.HasPrefix(v, "http") { - s.SetAttr("src", domain+v) + s.SetAttr("src", "http://"+domain+"/"+v) } } }) From decb28b712b35c1c44775cceb9e463e8d79b42fe Mon Sep 17 00:00:00 2001 From: xuxinhua Date: Wed, 21 Jun 2017 13:52:27 +0800 Subject: [PATCH 004/411] =?UTF-8?q?=E4=BF=AE=E5=A4=8D=E9=80=9A=E8=BF=87=20?= =?UTF-8?q?ineffassign=20=E5=B7=A5=E5=85=B7=E5=8F=91=E7=8E=B0=E7=9A=84?= =?UTF-8?q?=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/logic/auto_crawl.go | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/logic/auto_crawl.go b/src/logic/auto_crawl.go index d17a9157..17aec3a6 100644 --- a/src/logic/auto_crawl.go +++ b/src/logic/auto_crawl.go @@ -143,7 +143,8 @@ func (self AutoCrawlLogic) parseArticleList(strUrl string, autoCrawlConf *model. req.Header.Add("Referer", referer) } - resp, err := http.DefaultClient.Do(req) + var resp *http.Response + resp, err = http.DefaultClient.Do(req) if err != nil { return err } From 274311c83e6c12dbddf616e45396928e5165c6d6 Mon Sep 17 00:00:00 2001 From: xuxinhua Date: Wed, 21 Jun 2017 13:53:38 +0800 Subject: [PATCH 005/411] =?UTF-8?q?=E4=BF=AE=E5=A4=8D=E9=80=9A=E8=BF=87=20?= =?UTF-8?q?ineffassign=20=E5=B7=A5=E5=85=B7=E5=8F=91=E7=8E=B0=E7=9A=84?= =?UTF-8?q?=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/logic/auto_crawl.go | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/logic/auto_crawl.go b/src/logic/auto_crawl.go index 17aec3a6..0d512b0c 100644 --- a/src/logic/auto_crawl.go +++ b/src/logic/auto_crawl.go @@ -135,7 +135,8 @@ func (self AutoCrawlLogic) parseArticleList(strUrl string, autoCrawlConf *model. if autoCrawlConf.ExtMap == nil { doc, err = goquery.NewDocument(strUrl) } else { - req, err := http.NewRequest("GET", strUrl, nil) + var req *http.Request + req, err = http.NewRequest("GET", strUrl, nil) if err != nil { return err } From f84217b7652d635a99afbeac145bab8f69d43387 Mon Sep 17 00:00:00 2001 From: xuxinhua Date: Wed, 21 Jun 2017 14:32:58 +0800 Subject: [PATCH 006/411] =?UTF-8?q?=E5=9B=BE=E4=B9=A6=E8=AF=84=E8=AE=BA?= =?UTF-8?q?=E4=BF=A1=E6=81=AF?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/logic/gobook.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/logic/gobook.go b/src/logic/gobook.go index dcd36b00..6e435385 100644 --- a/src/logic/gobook.go +++ b/src/logic/gobook.go @@ -194,7 +194,7 @@ func (self BookComment) SetObjinfo(ids []int, commentMap map[int][]*model.Commen for _, book := range books { objinfo := make(map[string]interface{}) - objinfo["name"] = book.Name + objinfo["title"] = book.Name objinfo["uri"] = model.PathUrlMap[model.TypeBook] objinfo["type_name"] = model.TypeNameMap[model.TypeBook] From f945d20564fdad71c813515fbd06a842bc77a9a1 Mon Sep 17 00:00:00 2001 From: xuxinhua Date: Thu, 22 Jun 2017 11:14:22 +0800 Subject: [PATCH 007/411] =?UTF-8?q?=E6=96=87=E7=AB=A0=E7=BC=96=E8=BE=91?= =?UTF-8?q?=E7=9A=84bug?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- static/js/sidebar.js | 17 +---------------- template/articles/detail.html | 2 +- template/new_index.html | 9 +++++++++ 3 files changed, 11 insertions(+), 17 deletions(-) diff --git a/static/js/sidebar.js b/static/js/sidebar.js index 447016a1..e2a4a351 100644 --- a/static/js/sidebar.js +++ b/static/js/sidebar.js @@ -124,22 +124,7 @@ $(function(){ var content = ''; for(var i in comments) { - var url = ''; - switch(comments[i].objtype) { - case 0: - url = '/topics/'; - break; - case 1: - url = '/articles/'; - break; - case 2: - url = '/resources/'; - break; - case 4: - url = '/p/'; - break; - } - url += comments[i].objid; + var url = comments[i].objinfo.uri+comments[i].objid; var user = data[comments[i].uid]; diff --git a/template/articles/detail.html b/template/articles/detail.html index 69a272da..12f1d6a7 100644 --- a/template/articles/detail.html +++ b/template/articles/detail.html @@ -19,7 +19,7 @@
{{end}} -

+

{{.article.Title}}

diff --git a/template/new_index.html b/template/new_index.html index d98bc54b..07622ac6 100644 --- a/template/new_index.html +++ b/template/new_index.html @@ -78,6 +78,15 @@
+ {{if eq $i 4}} + {{if $.pos_ad.banner}} +
+ {{if eq $.pos_ad.banner.AdType 0}} + {{noescape $.pos_ad.banner.Code}} + {{end}} +
+ {{end}} + {{end}} {{end}} {{range $.topics}} From 3dd3e00b05d526a0fae5e5bc073d6c14022aa957 Mon Sep 17 00:00:00 2001 From: xuxinhua Date: Fri, 23 Jun 2017 13:56:22 +0800 Subject: [PATCH 008/411] =?UTF-8?q?zhihu=20=E7=89=B9=E6=AE=8A=E5=A4=84?= =?UTF-8?q?=E7=90=86?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- getpkg.sh | 2 +- src/logic/article.go | 65 ++++++++++++++++++++++++++++++++++++++++++++ src/vendor/manifest | 24 ++++++++++++++++ 3 files changed, 90 insertions(+), 1 deletion(-) diff --git a/getpkg.sh b/getpkg.sh index f45e9945..bbbbef80 100755 --- a/getpkg.sh +++ b/getpkg.sh @@ -31,7 +31,7 @@ else "github.com/robfig/cron" "github.com/gorilla/sessions" "github.com/polaris1119/echoutils" "golang.org/x/net/websocket" "github.com/polaris1119/slices" "github.com/qiniu/api.v6" "github.com/polaris1119/times" "github.com/PuerkitoBio/goquery" "github.com/go-validator/validator" - "github.com/polaris1119/email" + "github.com/polaris1119/email" "github.com/jaytaylor/html2text" "github.com/gorilla/schema" "github.com/facebookgo/grace/gracehttp") for pkg in "${pkgs[@]}"; do diff --git a/src/logic/article.go b/src/logic/article.go index aa711918..b7a82ae0 100644 --- a/src/logic/article.go +++ b/src/logic/article.go @@ -17,11 +17,13 @@ import ( "time" "github.com/PuerkitoBio/goquery" + "github.com/jaytaylor/html2text" "github.com/polaris1119/config" "github.com/polaris1119/goutils" "github.com/polaris1119/logger" "github.com/polaris1119/set" "github.com/polaris1119/times" + "github.com/tidwall/gjson" "golang.org/x/net/context" "golang.org/x/text/encoding/simplifiedchinese" ) @@ -76,6 +78,11 @@ func (self ArticleLogic) ParseArticle(ctx context.Context, articleUrl string, au return nil, errors.New("domain not exists") } + // 知乎特殊处理 + if domain == "zhuanlan.zhihu.com" { + return self.ParseZhihuArticle(ctx, articleUrl, rule) + } + var doc *goquery.Document if doc, err = goquery.NewDocument(articleUrl); err != nil { logger.Errorln("goquery newdocument error:", err) @@ -217,6 +224,64 @@ func (self ArticleLogic) ParseArticle(ctx context.Context, articleUrl string, au return article, nil } +func (self ArticleLogic) ParseZhihuArticle(ctx context.Context, articleUrl string, rule *model.CrawlRule) (*model.Article, error) { + var ( + doc *goquery.Document + err error + ) + if doc, err = goquery.NewDocument(articleUrl); err != nil { + logger.Errorln("goquery newdocument error:", err) + return nil, err + } + + var ( + jsonContentKey string + ok bool + ) + + extMap := rule.ParseExt() + if jsonContentKey, ok = extMap["json_content"]; !ok { + return nil, errors.New("zhihu config error, not json_content key") + } + + jsonContent := doc.Find(jsonContentKey).Text() + if jsonContent == "" { + return nil, errors.New("zhihu json content is empty") + } + + pos := strings.LastIndex(articleUrl, "/") + articleId := articleUrl[pos+1:] + + result := gjson.Parse(jsonContent) + database := result.Get("database") + post := database.Get("Post").Get(articleId) + author := database.Get("User").Get(post.Get("author").String()).Get("name").String() + content := post.Get("content").String() + txt, _ := html2text.FromString(content) + pubDate, _ := time.Parse("2006-01-02T15:04:05+08:00", post.Get("publishedTime").String()) + + article := &model.Article{ + Domain: rule.Domain, + Name: rule.Name, + Author: author, + AuthorTxt: author, + Title: post.Get("title").String(), + Content: content, + Txt: txt, + PubDate: times.Format("Y-m-d H:i:s", pubDate), + Url: articleUrl, + Lang: rule.Lang, + } + + _, err = MasterDB.Insert(article) + if err != nil { + logger.Errorln("insert article error:", err) + return nil, err + } + + return article, nil +} + func (self ArticleLogic) Publish(ctx context.Context, me *model.Me, form url.Values) error { objLog := GetLogger(ctx) diff --git a/src/vendor/manifest b/src/vendor/manifest index 2dc657fc..80c41308 100644 --- a/src/vendor/manifest +++ b/src/vendor/manifest @@ -163,6 +163,12 @@ "revision": "d06fe1b3abe3877ab593b57e5e43daf6c4c25add", "branch": "master" }, + { + "importpath": "github.com/jaytaylor/html2text", + "repository": "https://github.com/jaytaylor/html2text", + "revision": "7c7a33a7a158a5ce395c803d2b6a209b2bbc14c8", + "branch": "master" + }, { "importpath": "github.com/jmcvetta/randutil", "repository": "https://github.com/jmcvetta/randutil", @@ -253,12 +259,24 @@ "revision": "56b76bdf51f7708750eac80fa38b952bb9f32639", "branch": "master" }, + { + "importpath": "github.com/mattn/go-runewidth", + "repository": "https://github.com/mattn/go-runewidth", + "revision": "97311d9f7767e3d6f422ea06661bc2c7a19e8a5d", + "branch": "master" + }, { "importpath": "github.com/mattn/go-sqlite3", "repository": "https://github.com/mattn/go-sqlite3", "revision": "37aa7c6f5bc95b7264de70cd1f0ca1d39228ebd6", "branch": "master" }, + { + "importpath": "github.com/olekukonko/tablewriter", + "repository": "https://github.com/olekukonko/tablewriter", + "revision": "febf2d34b54a69ce7530036c7503b1c9fbfdf0bb", + "branch": "master" + }, { "importpath": "github.com/pmezard/go-difflib/difflib", "repository": "https://github.com/pmezard/go-difflib", @@ -362,6 +380,12 @@ "revision": "0f39cf7ebc65a602f45692f9894bd6a193faf8fa", "branch": "master" }, + { + "importpath": "github.com/ssor/bom", + "repository": "https://github.com/ssor/bom", + "revision": "6ed919a936d5ab554e4b40bc51f7c522488122c6", + "branch": "master" + }, { "importpath": "github.com/stretchr/testify/assert", "repository": "https://github.com/stretchr/testify", From c0e5f0b714b8eeab974ea6b700b39436953af64a Mon Sep 17 00:00:00 2001 From: xuxinhua Date: Sat, 24 Jun 2017 14:40:32 +0800 Subject: [PATCH 009/411] =?UTF-8?q?=E8=AF=84=E8=AE=BA=E5=88=97=E8=A1=A8=20?= =?UTF-8?q?=E5=9B=BE=E4=B9=A6=E5=90=8D=20=E6=98=BE=E7=A4=BA?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/logic/article.go | 5 +++++ src/logic/gobook.go | 15 +++++++++++++++ src/logic/message.go | 9 +++++++++ 3 files changed, 29 insertions(+) diff --git a/src/logic/article.go b/src/logic/article.go index b7a82ae0..2e0b4609 100644 --- a/src/logic/article.go +++ b/src/logic/article.go @@ -594,6 +594,11 @@ func (ArticleLogic) FindByIdAndPreNext(ctx context.Context, id int) (curArticle } } + if curArticle == nil { + objLog.Errorln("ArticleLogic FindByIdAndPreNext not find current article, id:", id) + return + } + if prevId == id { prevNext[0] = nil } diff --git a/src/logic/gobook.go b/src/logic/gobook.go index 6e435385..f0a41099 100644 --- a/src/logic/gobook.go +++ b/src/logic/gobook.go @@ -145,6 +145,21 @@ func (GoBookLogic) FindByIds(ids []int) []*model.Book { return books } +// findByIds 获取多个图书详细信息 包内使用 +func (GoBookLogic) findByIds(ids []int) map[int]*model.Book { + if len(ids) == 0 { + return nil + } + + books := make(map[int]*model.Book) + err := MasterDB.In("id", ids).Find(&books) + if err != nil { + logger.Errorln("GoBookLogic findByIds error:", err) + return nil + } + return books +} + // FindById 获取一本图书信息 func (GoBookLogic) FindById(ctx context.Context, id interface{}) (*model.Book, error) { book := &model.Book{} diff --git a/src/logic/message.go b/src/logic/message.go index 7a792162..96e430b6 100644 --- a/src/logic/message.go +++ b/src/logic/message.go @@ -192,6 +192,7 @@ func (self MessageLogic) FindSysMsgsByUid(ctx context.Context, uid int, paginato resIdSet := set.New(set.NonThreadSafe) wikiIdSet := set.New(set.NonThreadSafe) pidSet := set.New(set.NonThreadSafe) + bookIdSet := set.New(set.NonThreadSafe) // 评论ID cidSet := set.New(set.NonThreadSafe) uidSet := set.New(set.NonThreadSafe) @@ -228,6 +229,8 @@ func (self MessageLogic) FindSysMsgsByUid(ctx context.Context, uid int, paginato wikiIdSet.Add(objid) case model.TypeProject: pidSet.Add(objid) + case model.TypeBook: + bookIdSet.Add(objid) } } if val, ok := ext["cid"]; ok { @@ -247,6 +250,7 @@ func (self MessageLogic) FindSysMsgsByUid(ctx context.Context, uid int, paginato resourceMap := DefaultResource.findByIds(set.IntSlice(resIdSet)) wikiMap := DefaultWiki.findByIds(set.IntSlice(wikiIdSet)) projectMap := DefaultProject.findByIds(set.IntSlice(pidSet)) + bookMap := DefaultGoBook.findByIds(set.IntSlice(bookIdSet)) result := make([]map[string]interface{}, len(messages)) for i, message := range messages { @@ -315,6 +319,11 @@ func (self MessageLogic) FindSysMsgsByUid(ctx context.Context, uid int, paginato } objUrl += "#commentForm" title += "项目:" + case model.TypeBook: + book := bookMap[objid] + objTitle = book.Name + objUrl = "/book/" + strconv.Itoa(book.Id) + "#commentForm" + title += "图书:" } case model.MsgtypePublishAtMe: From 7f9c694d88961bc66f7168d5f7f33a880a86f2d1 Mon Sep 17 00:00:00 2001 From: xuxinhua Date: Sat, 24 Jun 2017 18:43:10 +0800 Subject: [PATCH 010/411] =?UTF-8?q?=E5=8E=BB=E6=8E=89=E6=B3=A8=E9=87=8A?= =?UTF-8?q?=E4=BB=A3=E7=A0=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/http/controller/admin/article.go | 25 ------------------------- 1 file changed, 25 deletions(-) diff --git a/src/http/controller/admin/article.go b/src/http/controller/admin/article.go index d416eeda..3510d395 100644 --- a/src/http/controller/admin/article.go +++ b/src/http/controller/admin/article.go @@ -150,28 +150,3 @@ func (self ArticleController) Modify(ctx echo.Context) error { return render(ctx, "article/modify.html", data) } - -// /crawl/article/del -// func DelArticleHandler(rw http.ResponseWriter, req *http.Request) { -// var data = make(map[string]interface{}) - -// id := req.FormValue("id") - -// if _, err := strconv.Atoi(id); err != nil { -// data["ok"] = 0 -// data["error"] = "id不是整型" - -// filter.SetData(req, data) -// return -// } - -// if err := service.DelArticle(id); err != nil { -// data["ok"] = 0 -// data["error"] = "删除失败!" -// } else { -// data["ok"] = 1 -// data["msg"] = "删除成功!" -// } - -// filter.SetData(req, data) -// } From 7f241ee0932a908ebbbabbcd43e2fd243702babb Mon Sep 17 00:00:00 2001 From: xuxinhua Date: Sun, 25 Jun 2017 14:34:42 +0800 Subject: [PATCH 011/411] bugfix --- src/http/controller/image.go | 3 +++ src/logic/uploader.go | 8 ++++---- static/js/admin/forms.js | 1 + 3 files changed, 8 insertions(+), 4 deletions(-) diff --git a/src/http/controller/image.go b/src/http/controller/image.go index 9a9cc07e..fda284f9 100644 --- a/src/http/controller/image.go +++ b/src/http/controller/image.go @@ -9,6 +9,7 @@ package controller import ( "encoding/json" "global" + "io" "io/ioutil" "logic" "net/http" @@ -59,6 +60,7 @@ func (self ImageController) QuickUpload(ctx echo.Context) error { fileName := goutils.Md5Buf(buf) + filepath.Ext(fileHeader.Filename) imgDir := times.Format("ymd") + file.Seek(0, io.SeekStart) path, err := logic.DefaultUploader.UploadImage(ctx, file, imgDir, buf, filepath.Ext(fileHeader.Filename)) if err != nil { return self.quickUploadFail(ctx, "文件上传失败!") @@ -133,6 +135,7 @@ func (ImageController) Upload(ctx echo.Context) error { cdnDomain += "/" } + file.Seek(0, io.SeekStart) path, err := logic.DefaultUploader.UploadImage(ctx, file, imgDir, buf, filepath.Ext(fileHeader.Filename)) if err != nil { return fail(ctx, 5, "文件上传失败!") diff --git a/src/logic/uploader.go b/src/logic/uploader.go index 82bbb9af..14ba5734 100644 --- a/src/logic/uploader.go +++ b/src/logic/uploader.go @@ -114,7 +114,7 @@ func (this *UploaderLogic) uploadLocalFile(localFile, key string) (err error) { return } -func (this *UploaderLogic) uploadMemoryFile(r gio.Reader, key string) (err error) { +func (this *UploaderLogic) uploadMemoryFile(r gio.Reader, key string, size int) (err error) { this.genUpToken() var ret io.PutRet @@ -130,7 +130,7 @@ func (this *UploaderLogic) uploadMemoryFile(r gio.Reader, key string) (err error // key 为文件存储的标识 // r 为io.Reader类型,用于从其读取数据 // extra 为上传文件的额外信息,可为空, 详情见 io.PutExtra, 可选 - err = io.Put(nil, &ret, this.uptoken, key, r, extra) + err = io.Put2(nil, &ret, this.uptoken, key, r, int64(size), extra) // 上传产生错误 if err != nil { @@ -172,7 +172,7 @@ func (this *UploaderLogic) UploadImage(ctx context.Context, reader gio.Reader, i } path := imgDir + "/" + md5 + ext - if err = this.uploadMemoryFile(reader, path); err != nil { + if err = this.uploadMemoryFile(reader, path, len(buf)); err != nil { return "", err } @@ -226,7 +226,7 @@ func (this *UploaderLogic) TransferUrl(ctx context.Context, origUrl string, pref return origUrl, errors.New("文件太大") } - err = this.uploadMemoryFile(reader, path) + err = this.uploadMemoryFile(reader, path, len(buf)) if err != nil { return origUrl, err } diff --git a/static/js/admin/forms.js b/static/js/admin/forms.js index ce340060..af78d13a 100644 --- a/static/js/admin/forms.js +++ b/static/js/admin/forms.js @@ -104,6 +104,7 @@ jQuery(document).ready(function($){ jAlert("操作成功", "信息"); } else { jAlert(data.error, "出错"); + return; } // $('#tooltip').text("操作成功!"); if (typeof formSuccCallback !== "undefined") { From 3de6d79ec8d20fe147d1874459e12bb673182a01 Mon Sep 17 00:00:00 2001 From: xuxinhua Date: Tue, 4 Jul 2017 11:11:06 +0800 Subject: [PATCH 012/411] flysnow --- static/css/outer/flysnow.css | 503 +++++++++++++++++++++++++++++++++++ 1 file changed, 503 insertions(+) create mode 100644 static/css/outer/flysnow.css diff --git a/static/css/outer/flysnow.css b/static/css/outer/flysnow.css new file mode 100644 index 00000000..249af8bf --- /dev/null +++ b/static/css/outer/flysnow.css @@ -0,0 +1,503 @@ +/* syntax highlight*/ +figure.highlight, +.codeblock { + background: #f7f8f8; + margin: 10px 0; + line-height: 1.1em; + color: #333; + padding-top: 15px; + overflow: hidden; } + figure.highlight table, + .codeblock table { + display: block; + width: 100%; } + figure.highlight pre, + figure.highlight .gutter, + figure.highlight .code, + figure.highlight .tag, + .codeblock pre, + .codeblock .gutter, + .codeblock .code, + .codeblock .tag { + background-color: inherit; + font-family: Menlo, Consolas, monospace; + border: none; + padding: 0; + margin: 0; + cursor: text; } + figure.highlight .gutter, + figure.highlight .code, + .codeblock .gutter, + .codeblock .code { + vertical-align: top; } + figure.highlight.plain .gutter, + .codeblock.plain .gutter { + display: none; } + figure.highlight figcaption, + .codeblock figcaption { + font-size: 13px; + padding: 0 15px 20px; + margin: 0; + background: #f7f8f8; + color: #999999; } + figure.highlight figcaption a, + .codeblock figcaption a { + float: right; + color: #01579f; } + figure.highlight .gutter, + .codeblock .gutter { + background: #f7f8f8; + border-right: 1px solid #e6e6e6; + padding: 0.3em 15px; } + figure.highlight .gutter .line, + .codeblock .gutter .line { + color: #aaaaaa; } + figure.highlight .code, + .codeblock .code { + padding: 0.3em 15px 0.3em 1em; + width: 100%; } + figure.highlight .code pre, + .codeblock .code pre { + max-width: 700px; + overflow-x: auto; + overflow-y: hidden; } + figure.highlight .line, + .codeblock .line { + height: 1.3em; + font-size: 13px; } + +.gist .line, +.gist .line-number { + font-family: Menlo, Consolas, monospace; + font-size: 1em; + margin: 0 0 5px 0; } + +.highlight .comment { + color: #969896; } + +.highlight .string { + color: #183691; } + +.highlight .keyword { + color: #a71d5d; } + +.highlight.apacheconf .code .common, +.highlight.apacheconf .code .nomarkup, +.highlight.apacheconf .code .attribute, +.highlight.apacheconf .code .variable, +.highlight.apacheconf .code .cbracket, +.highlight.apacheconf .code .keyword { + color: #0086b3; } + +.highlight.apacheconf .code .sqbracket { + color: #df5000; } + +.highlight.apacheconf .code .section, +.highlight.apacheconf .code .tag { + color: #63a35c; } + +.highlight.bash .code .shebang { + color: #969896; } + +.highlight.bash .code .literal, +.highlight.bash .code .built_in { + color: #0086b3; } + +.highlight.bash .code .variable { + color: #333; } + +.highlight.bash .code .title { + color: #795da3; } + +.highlight.coffeescript .code .title { + color: #795da3; } + +.highlight.coffeescript .code .literal, +.highlight.coffeescript .code .built_in, +.highlight.coffeescript .code .number { + color: #0086b3; } + +.highlight.coffeescript .code .reserved, +.highlight.coffeescript .code .attribute { + color: #1d3e81; } + +.highlight.coffeescript .code .subst, +.highlight.coffeescript .code .regexp, +.highlight.coffeescript .code .attribute { + color: #df5000; } + +.highlight.cpp .code .preprocessor, +.highlight.c .code .preprocessor { + color: #df5000; } + +.highlight.cpp .code .meta-keyword, +.highlight.c .code .meta-keyword { + color: #a71d5d; } + +.highlight.cpp .code .title, +.highlight.c .code .title { + color: #795da3; } + +.highlight.cpp .code .number, +.highlight.cpp .code .built_in, +.highlight.c .code .number, +.highlight.c .code .built_in { + color: #0086b3; } + +.highlight.cs .code .preprocessor, +.highlight.cs .code .preprocessor .keyword { + color: #333; } + +.highlight.cs .code .title { + color: #795da3; } + +.highlight.cs .code .number, +.highlight.cs .code .built_in { + color: #0086b3; } + +.highlight.cs .code .xmlDocTag, +.highlight.cs .code .doctag { + color: #63a35c; } + +.highlight.css .code .at_rule, +.highlight.css .code .important, +.highlight.css .code .meta { + color: #a71d5d; } + +.highlight.css .code .attribute, +.highlight.css .code .hexcolor, +.highlight.css .code .number, +.highlight.css .code .function { + color: #0086b3; } + +.highlight.css .code .attr_selector, +.highlight.css .code .value { + color: #333; } + +.highlight.css .code .id, +.highlight.css .code .class, +.highlight.css .code .pseudo, +.highlight.css .code .selector-pseudo { + color: #795da3; } + +.highlight.css .code .tag, +.highlight.css .code .selector-tag { + color: #63a35c; } + +.highlight.diff .code .chunk, +.highlight.diff .code .meta { + color: #795da3; + font-weight: bold; } + +.highlight.diff .code .addition { + color: #55a532; + background-color: #eaffea; } + +.highlight.diff .code .deletion { + color: #bd2c00; + background-color: #ffecec; } + +.highlight.http .code .attribute, +.highlight.http .code .attr { + color: #183691; } + +.highlight.http .code .literal { + color: #0086b3; } + +.highlight.http .code .request { + color: #a71d5d; } + +.highlight.ini .code .title, +.highlight.ini .code .section { + color: #795da3; } + +.highlight.ini .code .setting, +.highlight.ini .code .attr { + color: #a71d5d; } + +.highlight.ini .code .value, +.highlight.ini .code .keyword { + color: #333; } + +.highlight.java .code .title { + color: #795da3; } + +.highlight.java .code .javadoc { + color: #969896; } + +.highlight.java .code .meta, +.highlight.java .code .annotation, +.highlight.java .code .javadoctag { + color: #a71d5d; } + +.highlight.java .code .number { + color: #0086b3; } + +.highlight.java .code .params { + color: #1d3e81; } + +.highlight.js .code .built_in, +.highlight.js .code .title { + color: #795da3; } + +.highlight.js .code .javadoc { + color: #969896; } + +.highlight.js .code .tag, +.highlight.js .code .javadoctag { + color: #a71d5d; } + +.highlight.js .code .tag .title { + color: #333; } + +.highlight.js .code .regexp { + color: #df5000; } + +.highlight.js .code .literal, +.highlight.js .code .number { + color: #0086b3; } + +.highlight.json .code .attribute { + color: #183691; } + +.highlight.json .code .number, +.highlight.json .code .literal { + color: #0086b3; } + +.highlight.mak .code .constant { + color: #333; } + +.highlight.mak .code .title { + color: #795da3; } + +.highlight.mak .code .keyword, +.highlight.mak .code .meta-keyword { + color: #0086b3; } + +.highlight.md .code .value, +.highlight.md .code .link_label, +.highlight.md .code .strong, +.highlight.md .code .emphasis, +.highlight.md .code .blockquote, +.highlight.md .code .quote, +.highlight.md .code .section { + color: #183691; } + +.highlight.md .code .link_reference, +.highlight.md .code .symbol, +.highlight.md .code .code { + color: #0086b3; } + +.highlight.md .code .link_url, +.highlight.md .code .link { + text-decoration: underline; } + +.highlight.nginx .code .title, +.highlight.nginx .code .attribute { + color: #a71d5d; } + +.highlight.nginx .code .built_in, +.highlight.nginx .code .literal { + color: #0086b3; } + +.highlight.nginx .code .regexp { + color: #183691; } + +.highlight.nginx .code .variable { + color: #333; } + +.highlight.objectivec .code .preprocessor, +.highlight.objectivec .code .meta { + color: #a71d5d; } + .highlight.objectivec .code .preprocessor .title, + .highlight.objectivec .code .meta .title { + color: #df5000; } + +.highlight.objectivec .code .meta-string { + color: #183691; } + +.highlight.objectivec .code .title { + color: #795da3; } + +.highlight.objectivec .code .literal, +.highlight.objectivec .code .number, +.highlight.objectivec .code .built_in { + color: #0086b3; } + +.highlight.perl .code .sub { + color: #795da3; } + +.highlight.perl .code .title { + color: #795da3; } + +.highlight.perl .code .regexp { + color: #df5000; } + +.highlight.php .code .phpdoc, +.highlight.php .code .doctag { + color: #a71d5d; } + +.highlight.php .code .regexp { + color: #df5000; } + +.highlight.php .code .literal, +.highlight.php .code .number { + color: #0086b3; } + +.highlight.php .code .title { + color: #795da3; } + +.highlight.python .code .decorator, +.highlight.python .code .title, +.highlight.python .code .meta { + color: #795da3; } + +.highlight.python .code .number { + color: #0086b3; } + +.highlight.ruby .code .parent, +.highlight.ruby .code .title { + color: #795da3; } + +.highlight.ruby .code .prompt, +.highlight.ruby .code .constant, +.highlight.ruby .code .number, +.highlight.ruby .code .subst .keyword, +.highlight.ruby .code .symbol { + color: #0086b3; } + +.highlight.sql .built_in { + color: #a71d5d; } + +.highlight.sql .number { + color: #0086b3; } + +.highlight.xml .tag { + color: #333; } + +.highlight.xml .value { + color: #183691; } + +.highlight.xml .attribute, +.highlight.xml .attr { + color: #795da3; } + +.highlight.xml .title, +.highlight.xml .name { + color: #63a35c; } + +.highlight.puppet .title { + color: #795da3; } + +.highlight.puppet .function { + color: #0086b3; } + +.highlight.puppet .name { + color: #a71d5d; } + +.highlight.puppet .attr { + color: #0086b3; } + +.highlight.less .tag, +.highlight.less .at_rule { + color: #a71d5d; } + +.highlight.less .number, +.highlight.less .hexcolor, +.highlight.less .function, +.highlight.less .attribute { + color: #0086b3; } + +.highlight.less .built_in { + color: #df5000; } + +.highlight.less .id, +.highlight.less .pseudo, +.highlight.less .class, +.highlight.less .selector-id, +.highlight.less .selector-class, +.highlight.less .selector-tag { + color: #795da3; } + +.highlight.scss .tag, +.highlight.scss .at_rule, +.highlight.scss .important { + color: #a71d5d; } + +.highlight.scss .number, +.highlight.scss .hexcolor, +.highlight.scss .function, +.highlight.scss .attribute { + color: #0086b3; } + +.highlight.scss .variable { + color: #333; } + +.highlight.scss .built_in { + color: #df5000; } + +.highlight.scss .id, +.highlight.scss .pseudo, +.highlight.scss .class, +.highlight.scss .preprocessor, +.highlight.scss .selector-class, +.highlight.scss .selector-id { + color: #795da3; } + +.highlight.scss .tag, +.highlight.scss .selector-tag { + color: #63a35c; } + +.highlight.stylus .at_rule { + color: #a71d5d; } + +.highlight.stylus .tag, +.highlight.stylus .selector-tag { + color: #63a35c; } + +.highlight.stylus .number, +.highlight.stylus .hexcolor, +.highlight.stylus .attribute, +.highlight.stylus .params { + color: #0086b3; } + +.highlight.stylus .class, +.highlight.stylus .id, +.highlight.stylus .pseudo, +.highlight.stylus .title, +.highlight.stylus .selector-id, +.highlight.stylus .selector-pseudo, +.highlight.stylus .selector-class { + color: #795da3; } + +.highlight.go .typename { + color: #a71d5d; } + +.highlight.go .built_in, +.highlight.go .constant { + color: #0086b3; } + +.highlight.swift .preprocessor { + color: #a71d5d; } + +.highlight.swift .title { + color: #795da3; } + +.highlight.swift .built_in, +.highlight.swift .number, +.highlight.swift .type { + color: #0086b3; } + +.highlight.yml .line, +.highlight.yml .attr { + color: #63a35c; } + +.highlight.yml .line, +.highlight.yml .string, +.highlight.yml .type, +.highlight.yml .literal, +.highlight.yml .meta { + color: #183691; } + +.highlight.yml .number { + color: #0086b3; } \ No newline at end of file From 9139280fefbacd43739610ee2096694a5d1eb26a Mon Sep 17 00:00:00 2001 From: xuxinhua Date: Tue, 4 Jul 2017 11:14:09 +0800 Subject: [PATCH 013/411] flysnow --- static/css/outer/flysnow.css | 1 + 1 file changed, 1 insertion(+) diff --git a/static/css/outer/flysnow.css b/static/css/outer/flysnow.css index 249af8bf..91467e78 100644 --- a/static/css/outer/flysnow.css +++ b/static/css/outer/flysnow.css @@ -64,6 +64,7 @@ figure.highlight, figure.highlight .line, .codeblock .line { height: 1.3em; + line-height: 1.3em; font-size: 13px; } .gist .line, From eeba0763b7120d7f57b852dd0ab3df752d9b88a1 Mon Sep 17 00:00:00 2001 From: xuxinhua Date: Tue, 4 Jul 2017 12:33:17 +0800 Subject: [PATCH 014/411] =?UTF-8?q?=E9=80=9A=E8=BF=87=20github=20=E7=99=BB?= =?UTF-8?q?=E5=BD=95=EF=BC=8C=E9=BB=98=E8=AE=A4=E4=BD=BF=E7=94=A8=E7=AC=AC?= =?UTF-8?q?=E4=B8=89=E6=96=B9=E5=A4=B4=E5=83=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/logic/third_user.go | 1 + src/logic/user.go | 2 +- src/util/tool.go | 3 +++ static/js/sidebar.js | 41 ++++++++++++++++++------------------ template/common/layout.html | 2 +- template/common/my_info.html | 2 +- template/new_index.html | 8 +++---- template/user/users.html | 2 +- 8 files changed, 32 insertions(+), 29 deletions(-) diff --git a/src/logic/third_user.go b/src/logic/third_user.go index 09658a27..8a569e10 100644 --- a/src/logic/third_user.go +++ b/src/logic/third_user.go @@ -102,6 +102,7 @@ func (self ThirdUserLogic) LoginFromGithub(ctx context.Context, code string) (*m Company: githubUser.Company, Github: githubUser.Login, Website: githubUser.Blog, + Avatar: githubUser.AvatarUrl, IsThird: 1, Status: model.UserStatusAudit, } diff --git a/src/logic/user.go b/src/logic/user.go index e13924ea..3f19ddfe 100644 --- a/src/logic/user.go +++ b/src/logic/user.go @@ -568,7 +568,7 @@ func (UserLogic) FindBindUsers(ctx context.Context, uid int) []*model.BindUser { func (UserLogic) doCreateUser(ctx context.Context, session *xorm.Session, user *model.User, passwd ...string) error { - if len(DefaultAvatars) > 0 { + if user.Avatar == "" && len(DefaultAvatars) > 0 { // 随机给一个默认头像 user.Avatar = DefaultAvatars[rand.Intn(len(DefaultAvatars))] } diff --git a/src/util/tool.go b/src/util/tool.go index 321197e4..21f5e500 100644 --- a/src/util/tool.go +++ b/src/util/tool.go @@ -25,6 +25,9 @@ func Gravatar(avatar string, emailI interface{}, size uint16, isHttps bool) stri gravatarDomain = "https://secure.gravatar.com" } if avatar != "" { + if strings.HasPrefix(avatar, "http") { + return fmt.Sprintf("%s&s=%d", avatar, size) + } return fmt.Sprintf("%savatar/%s?imageView2/2/w/%d", cdnDomain, avatar, size) } diff --git a/static/js/sidebar.js b/static/js/sidebar.js index e2a4a351..7ac2f0cf 100644 --- a/static/js/sidebar.js +++ b/static/js/sidebar.js @@ -28,6 +28,24 @@ $(function(){ $(this).parents('.top').children('.bar').animate({left: left}, "fast"); }); + var gravatar = function(avatar, email, size) { + if (avatar == "") { + if (isHttps) { + avatar = 'https://secure.gravatar.com/avatar/'+md5(email)+"?s="+size; + } else { + avatar = 'http://gravatar.com/avatar/'+md5(email)+"?s="+size; + } + } else { + if (avatar.indexOf('http') == 0) { + avatar += '&s='+size; + } else { + avatar = cdnDomain+'avatar/'+avatar+'?imageView2/2/w/'+size; + } + } + + return avatar; + } + // 侧边栏——最新帖子 var topicRecent = function(data) { if (data.ok) { @@ -127,17 +145,7 @@ $(function(){ var url = comments[i].objinfo.uri+comments[i].objid; var user = data[comments[i].uid]; - - var avatar = user.avatar; - if (avatar == "") { - if (isHttps) { - avatar = 'https://secure.gravatar.com/avatar/'+md5(user.email)+"?s=48"; - } else { - avatar = 'http://gravatar.com/avatar/'+md5(user.email)+"?s=48"; - } - } else { - avatar = cdnDomain+'avatar/'+avatar+'?imageView2/2/w/40'; - } + var avatar = gravatar(user.avatar, user.email, 40); var cmtTime = SG.timeago(comments[i].ctime); if (cmtTime == comments[i].ctime) { @@ -184,16 +192,7 @@ $(function(){ var content = ''; for(var i in data) { - var avatar = data[i].avatar; - if (avatar == "") { - if (isHttps) { - avatar = 'https://secure.gravatar.com/avatar/'+md5(data[i].email)+"?s=48"; - } else { - avatar = 'http://gravatar.com/avatar/'+md5(data[i].email)+"?s=48"; - } - } else { - avatar = cdnDomain+'avatar/'+avatar+'?imageView2/2/w/40'; - } + var avatar = gravatar(data[i].avatar, data[i].email, 48); content += '
  • '+ '
    '+ diff --git a/template/common/layout.html b/template/common/layout.html index 535d507e..a06f3d80 100644 --- a/template/common/layout.html +++ b/template/common/layout.html @@ -261,6 +261,6 @@ // $.views.settings.debugMode(true); - + \ No newline at end of file diff --git a/template/common/my_info.html b/template/common/my_info.html index b2d62756..a5c2fcd2 100644 --- a/template/common/my_info.html +++ b/template/common/my_info.html @@ -2,7 +2,7 @@ {{if .me.Uid}}
    - 个人首页 + 个人首页
    {{if .me.Monlog}} diff --git a/template/new_index.html b/template/new_index.html index 07622ac6..9dc80570 100644 --- a/template/new_index.html +++ b/template/new_index.html @@ -28,7 +28,7 @@ {{if .User}} - + {{else}} @@ -94,7 +94,7 @@ - + @@ -132,7 +132,7 @@ {{else}} - + {{end}} @@ -183,7 +183,7 @@ {{else}} - + {{end}} @@ -299,6 +299,7 @@ {{end}} {{define "js"}} + {{if .pos_ad.banner}} {{if eq .pos_ad.banner.AdType 1}} diff --git a/template/top/dau.html b/template/top/dau.html index cd77f80e..0d203707 100644 --- a/template/top/dau.html +++ b/template/top/dau.html @@ -17,7 +17,7 @@ {{range $i, $user := .users}} - - - - - + + + + + + {{range .gifts}} {{if eq .State 1}} + diff --git a/template/top/dau.html b/template/top/dau.html index 5c9fdc47..b97009a3 100644 --- a/template/top/dau.html +++ b/template/top/dau.html @@ -3,62 +3,70 @@ {{end}} {{define "content"}}
    -
    -
    +
    +
    + +
    + + +
    - -
    -
    -
    @@ -129,7 +129,7 @@ {{if .User}} - + {{else}} @@ -180,7 +180,7 @@ {{if .Uid}} {{$user := index $.users .Uid}} - + {{else}} diff --git a/template/user/users.html b/template/user/users.html index 1bbcb23d..24ff18d9 100644 --- a/template/user/users.html +++ b/template/user/users.html @@ -31,7 +31,7 @@

    最新加入的会员

    {{with $root := .}} {{range .news}}
    {{end}} From d6647a323ce6ba8d3940772b64b68d8d7a01310e Mon Sep 17 00:00:00 2001 From: xuxinhua Date: Wed, 5 Jul 2017 21:34:36 +0800 Subject: [PATCH 015/411] =?UTF-8?q?identicon.js=20=E4=BB=BF=E7=85=A7=20git?= =?UTF-8?q?hub=20=E5=A4=B4=E5=83=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- template/new_index.html | 19 ++++++++++++++++--- template/top/dau.html | 2 +- template/user/users.html | 8 ++++---- 3 files changed, 21 insertions(+), 8 deletions(-) diff --git a/template/new_index.html b/template/new_index.html index 9dc80570..43696c18 100644 --- a/template/new_index.html +++ b/template/new_index.html @@ -31,7 +31,7 @@ {{else}} - + {{end}}
    - +

    {{add $i 1}}. {{.Username}}

    diff --git a/template/user/users.html b/template/user/users.html index 24ff18d9..e3a4fbc3 100644 --- a/template/user/users.html +++ b/template/user/users.html @@ -14,9 +14,9 @@

    活跃会员

    {{with $root := .}} {{range .actives}} -
    + {{end}} {{end}} @@ -30,9 +30,9 @@

    活跃会员

    最新加入的会员

    {{with $root := .}} {{range .news}} -
    + {{end}} {{end}} From d4c0026455caba28b3ced3d2a336c9dd20d1e101 Mon Sep 17 00:00:00 2001 From: xuxinhua Date: Thu, 6 Jul 2017 15:40:55 +0800 Subject: [PATCH 016/411] https sitemap --- config/db.sql | 1 + src/http/http.go | 4 ++++ src/logic/sitemap.go | 6 +++++- src/model/website_setting.go | 1 + 4 files changed, 11 insertions(+), 1 deletion(-) diff --git a/config/db.sql b/config/db.sql index af21bfd7..550f5ba5 100644 --- a/config/db.sql +++ b/config/db.sql @@ -2,6 +2,7 @@ CREATE TABLE IF NOT EXISTS `website_setting` ( `id` int(10) unsigned NOT NULL AUTO_INCREMENT, `name` varchar(63) NOT NULL DEFAULT '' COMMENT '网站名称', `domain` varchar(63) NOT NULL DEFAULT '' COMMENT '网站域名', + `only_https` tinyint(3) unsigned NOT NULL DEFAULT '0' COMMENT '是否只支持HTTPS', `title_suffix` varchar(63) NOT NULL DEFAULT '' COMMENT '标题后缀', `favicon` varchar(127) NOT NULL DEFAULT '' COMMENT '自定义favicon', `logo` varchar(127) NOT NULL DEFAULT '' COMMENT '自定义logo', diff --git a/src/http/http.go b/src/http/http.go index 57220fa6..cdb95e7f 100644 --- a/src/http/http.go +++ b/src/http/http.go @@ -299,6 +299,10 @@ func executeTpl(ctx echo.Context, tpl *template.Template, data map[string]interf global.App.SetCopyright() isHttps := goutils.MustBool(ctx.Request().Header().Get("X-Https")) + if logic.WebsiteSetting.OnlyHttps { + isHttps = true + } + cdnDomain := global.App.CDNHttp if isHttps { cdnDomain = global.App.CDNHttps diff --git a/src/logic/sitemap.go b/src/logic/sitemap.go index 22d290f3..001dbc16 100644 --- a/src/logic/sitemap.go +++ b/src/logic/sitemap.go @@ -49,9 +49,13 @@ func init() { func GenSitemap() { sitemapFiles := []string{} + loc := "http://" + WebsiteSetting.Domain + if WebsiteSetting.OnlyHttps { + loc = "https://" + WebsiteSetting.Domain + } // 首页 home := map[string]string{ - "loc": "http://" + WebsiteSetting.Domain, + "loc": loc, "lastmode": time.Now().Format(time.RFC3339), } diff --git a/src/model/website_setting.go b/src/model/website_setting.go index fbe28ead..a3778c48 100644 --- a/src/model/website_setting.go +++ b/src/model/website_setting.go @@ -50,6 +50,7 @@ type websiteSetting struct { Id int `xorm:"pk autoincr"` Name string Domain string + OnlyHttps bool TitleSuffix string Favicon string Logo string From fe6fd4bb460f23bb663adc11972d3dcd497a3b63 Mon Sep 17 00:00:00 2001 From: xuxinhua Date: Wed, 12 Jul 2017 10:11:02 +0800 Subject: [PATCH 017/411] =?UTF-8?q?=E5=8E=BB=E6=8E=89=E8=A3=81=E5=89=AA?= =?UTF-8?q?=E5=8A=9F=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- static/js/puploader.js | 5 +---- template/projects/new.html | 2 +- template/topics/detail.html | 2 +- template/topics/new.html | 2 +- 4 files changed, 4 insertions(+), 7 deletions(-) diff --git a/static/js/puploader.js b/static/js/puploader.js index 92ffb1ed..afd2d3ec 100644 --- a/static/js/puploader.js +++ b/static/js/puploader.js @@ -11,10 +11,7 @@ $(function(){ prevent_duplicates : true // 不允许选取重复文件 }, multi_selection: false, - file_data_name: 'img', - resize: { - width: 600 - } + file_data_name: 'img' }); // 在实例对象上调用init()方法进行初始化 diff --git a/template/projects/new.html b/template/projects/new.html index e607c367..ed724df7 100644 --- a/template/projects/new.html +++ b/template/projects/new.html @@ -171,7 +171,7 @@ - + - + - + - + {{template "js" .}} - + - + {{template "js" .}} - + - + {{end}} \ No newline at end of file From 645d99a149cf1d1d163d5803bebf58cf432cc71f Mon Sep 17 00:00:00 2001 From: xuxinhua Date: Fri, 28 Jul 2017 20:39:38 +0800 Subject: [PATCH 032/411] =?UTF-8?q?=E7=BD=91=E7=AB=99=E5=90=8D=E7=A7=B0?= =?UTF-8?q?=E5=BD=93=E6=88=90=E4=BD=9C=E8=80=85?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/logic/html2article.go | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/src/logic/html2article.go b/src/logic/html2article.go index c2514768..a2bec5ca 100644 --- a/src/logic/html2article.go +++ b/src/logic/html2article.go @@ -50,13 +50,15 @@ func (self ArticleLogic) ParseArticleByAccuracy(articleUrl string) (*model.Artic pubDate = time.Unix(htmlArticle.Publishtime, 0).UTC().Format("2006-02-01 15:04") } article := &model.Article{ - Domain: urlTyp.Hostname(), - Name: name, - Title: title, - Content: htmlArticle.Html, - Txt: htmlArticle.Content, - PubDate: pubDate, - Url: articleUrl, + Domain: urlTyp.Hostname(), + Name: name, + Title: title, + Author: name, + AuthorTxt: name, + Content: htmlArticle.Html, + Txt: htmlArticle.Content, + PubDate: pubDate, + Url: articleUrl, } _, err = MasterDB.Insert(article) From 910dff2d5a73e55a5cc7de43af500dc5091cdfab Mon Sep 17 00:00:00 2001 From: xuxinhua Date: Fri, 28 Jul 2017 23:05:05 +0800 Subject: [PATCH 033/411] =?UTF-8?q?=E7=A7=BB=E5=8A=A8node?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/http/controller/topic.go | 9 ++++++++- src/logic/feed.go | 9 +++++++++ src/logic/topic.go | 5 +++++ template/new_index.html | 2 +- 4 files changed, 23 insertions(+), 2 deletions(-) diff --git a/src/http/controller/topic.go b/src/http/controller/topic.go index ae8956e3..fd1503a7 100644 --- a/src/http/controller/topic.go +++ b/src/http/controller/topic.go @@ -209,7 +209,14 @@ func (TopicController) Modify(ctx echo.Context) error { return ctx.Redirect(http.StatusSeeOther, "/topics") } - return render(ctx, "topics/new.html", map[string]interface{}{"nodes": nodes, "topic": topics[0], "activeTopics": "active"}) + hotNodes := logic.DefaultTopic.FindHotNodes(ctx) + + return render(ctx, "topics/new.html", map[string]interface{}{ + "nodes": nodes, + "topic": topics[0], + "activeTopics": "active", + "tab_list": hotNodes, + }) } me := ctx.Get("user").(*model.Me) diff --git a/src/logic/feed.go b/src/logic/feed.go index 74e9348d..42153379 100644 --- a/src/logic/feed.go +++ b/src/logic/feed.go @@ -107,3 +107,12 @@ func (FeedLogic) updateComment(objid, objtype, uid int, cmttime time.Time) { }) }() } + +func (self FeedLogic) modifyTopicNode(tid, nid int) { + go func() { + MasterDB.Table(new(model.Feed)).Where("objid=? AND objtype=?", tid, model.TypeTopic). + Update(map[string]interface{}{ + "nid": nid, + }) + }() +} diff --git a/src/logic/topic.go b/src/logic/topic.go index fe779eb4..735b04b1 100644 --- a/src/logic/topic.go +++ b/src/logic/topic.go @@ -52,6 +52,11 @@ func (self TopicLogic) Publish(ctx context.Context, me *model.Me, form url.Value objLog.Errorln("Publish Topic modif error:", err) return } + + nid := goutils.MustInt(form.Get("nid")) + if nid != topic.Nid { + DefaultFeed.modifyTopicNode(tid, nid) + } } else { usernames := form.Get("usernames") form.Del("usernames") diff --git a/template/new_index.html b/template/new_index.html index 43696c18..a584cdf8 100644 --- a/template/new_index.html +++ b/template/new_index.html @@ -299,7 +299,7 @@ {{end}} {{define "js"}} - + +{{end}} diff --git a/template/gift/mine.html b/template/gift/mine.html new file mode 100644 index 00000000..b04e4502 --- /dev/null +++ b/template/gift/mine.html @@ -0,0 +1,69 @@ +{{define "title"}}我的兑换记录 {{end}} +{{define "seo"}} +{{end}} +{{define "content"}} +
    +
    +
    + +
    + + +
    + +
    + {{if .me.Uid}} +
    +

    当前账户余额

    +
    + {{if .me.Gold}} + {{.me.Gold}} + {{end}} + {{if .me.Silver}} + {{.me.Silver}} + {{end}} + {{.me.Copper}} +
    +
    + {{end}} +
    + + + + + + + + + {{range .records}} + + + + + + + + {{end}} +
    序号物品编号兑换时间详情过期时间
    {{.Id}}{{.GiftId}}{{.CreatedAt}}{{.Remark}}{{.ExpireTime}}
    +
    +
    +
    +
    +
    + + {{include "common/my_info.html" .}} +
    +
    +{{end}} +{{define "css"}} + +{{end}} +{{define "js"}} +{{end}} diff --git a/template/rich/add.html b/template/rich/add.html new file mode 100644 index 00000000..5eccc912 --- /dev/null +++ b/template/rich/add.html @@ -0,0 +1,115 @@ +{{define "title"}}充值 {{end}} +{{define "seo"}} +{{end}} +{{define "content"}} +
    +
    +
    + +
    + + +
    + +
    +
    + 你可以通过支付宝或微信转账方式向我们充值。目前的实现方式是手工的,我们在收到你的充值之后,就会尽快向你的账户发放铜币及开通充值会员的额外功能。请在支付宝或微信的付款说明中填入你的 {{.setting.Name}} 用户名。充值金额越大,获得的铜币、银币甚至金币就会越多。 +
    + 如果你在扫码支付的过程中,忘记了或者没有机会填入你的 {{.setting.Name}} 用户名的话,你可以在支付结束后联系我们,并且附上交易尾号的末 4 位。 +
    +
    +
    +

    支付宝

    +
    +
    +
    +

    微信

    +
    +
    +
    +
    + 并且,充值会员还可以使用以下额外功能: +
    +
      +
    • 置顶自己的主题或文章 1 天 / 每次消耗 200 铜币
    • + +
    +
    + +
    + 充值 5 元获得 2,000 铜币 +
    +
    + 充值 10 元获得 5,000 铜币 +
    +
    + 充值 20 元获得 12,000 铜币 +
    +
    + 充值 30 元获得 16,000 铜币 +
    +
    + 充值 50 元获得 30,000 铜币 +
    +
    + 历史充值金额总计 ¥0 +
    +
    +

    当前账户余额

    +
    + {{if .me.Gold}} + {{.me.Gold}} + {{end}} + {{if .me.Silver}} + {{.me.Silver}} + {{end}} + {{.me.Copper}} +
    +
    +
    + + + + + + + + + {{range .details}} + + + + + + + + {{end}} +
    时间类型数额余额描述
    {{.CreatedAt}}{{.TypeShow}} + {{.Num}} + {{.Balance}}{{noescape .Desc}}
    +
    +
    +
    +
    +
    + + {{include "common/my_info.html" .}} +
    +
    +{{end}} +{{define "css"}} + + +{{end}} +{{define "js"}} +{{end}} diff --git a/template/rich/balance.html b/template/rich/balance.html index d7a6f19b..58671ca5 100644 --- a/template/rich/balance.html +++ b/template/rich/balance.html @@ -3,110 +3,88 @@ {{end}} {{define "content"}}
    -
    -
    +
    +
    + +
    + + +
    - -
    -
    -

    当前账户余额

    -
    - {{if .me.Gold}} - {{.me.Gold}} - {{end}} - {{if .me.Silver}} - {{.me.Silver}} - {{end}} - {{.me.Copper}} -
    -
    -
    - - - - - - - - - {{range .details}} - - - - - - - - {{end}} -
    时间类型数额余额描述
    {{.CreatedAt}}{{.TypeShow}} - {{.Num}} - {{.Balance}}{{noescape .Desc}}
    -
    -
    +
    +
    +

    当前账户余额

    +
    + {{if .me.Gold}} + {{.me.Gold}} + {{end}} + {{if .me.Silver}} + {{.me.Silver}} + {{end}} + {{.me.Copper}} +
    +
    +
    + + + + + + + + + {{range .details}} + + + + + + + + {{end}} +
    时间类型数额余额描述
    {{.CreatedAt}}{{.TypeShow}} + {{.Num}} + {{.Balance}}{{noescape .Desc}}
    +
    +
    - {{if not .details}} -
    -
    -
    可完成的任务
    -
    -

    获得初始资本

    - 欢迎来到 {{.setting.Name}},这是一个关于分享和探索的社区。你在进入这里时,你会获得 2000 铜币。接下来你在社区内的一切行为,包括创建主题和回复等,都将会消耗铜币。而当你完成了一些有意义的事情时,你就会收获铜币,以及,好心情。 -
    - 任务奖励 -
    -
    20
    -
    - 完成任务 -
    -
    -
    - {{end}} -
    -
    -
    - - {{include "common/my_info.html" .}} -
    + {{if not .details}} +
    +
    +
    可完成的任务
    +
    +

    获得初始资本

    + 欢迎来到 {{.setting.Name}},这是一个关于分享和探索的社区。你在进入这里时,你会获得 2000 铜币。接下来你在社区内的一切行为,包括创建主题和回复等,都将会消耗铜币。而当你完成了一些有意义的事情时,你就会收获铜币,以及,好心情。 +
    + 任务奖励 +
    +
    20
    +
    + 完成任务 +
    +
    +
    + {{end}} +
    +
    +
    + + {{include "common/my_info.html" .}} +
    {{end}} {{define "css"}} + {{end}} {{define "js"}} diff --git a/template/top/dau.html b/template/top/dau.html index 0d203707..5c9fdc47 100644 --- a/template/top/dau.html +++ b/template/top/dau.html @@ -25,7 +25,7 @@

    {{.Monlog}}
    - {{.Website}} + {{.Website}}
    第 {{.Uid}} 号会员 diff --git a/template/top/rich.html b/template/top/rich.html new file mode 100644 index 00000000..7e3328dc --- /dev/null +++ b/template/top/rich.html @@ -0,0 +1,80 @@ +{{define "title"}}社区财富排行榜 {{end}} +{{define "seo"}} +{{end}} +{{define "content"}} +
    +
    +
    +
    + + +
    + +
    +
    + + {{range $i, $user := .users}} + + + + + + + + + {{end}} +
    + + +

    {{add $i 1}}. {{.Username}}

    + + {{.Monlog}} +
    + + {{.Website}} +
    + + 第 {{.Uid}} 号会员 + +
    +
    + {{if .Gold}} + {{.Gold}} + {{end}} + {{if .Silver}} + {{.Silver}} + {{end}} + {{.Copper}} +
    +
    +
    +
    + +
    +
    +
    + {{include "common/my_info.html" .}} + +
    +
    +{{end}} +{{define "css"}} + +{{end}} +{{define "js"}} +{{end}} From 189d1af37dda2bb793e6a9f426f05d0418b406a9 Mon Sep 17 00:00:00 2001 From: xuxinhua Date: Sun, 30 Jul 2017 12:56:55 +0800 Subject: [PATCH 037/411] =?UTF-8?q?=E5=A2=9E=E5=8A=A0=E6=8F=8F=E8=BF=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- config/db.sql | 1 + src/model/gift.go | 23 ++++----- template/gift/list.html | 12 +++-- template/top/dau.html | 104 +++++++++++++++++++++------------------- 4 files changed, 76 insertions(+), 64 deletions(-) diff --git a/config/db.sql b/config/db.sql index 5dfacfb0..71d6d361 100644 --- a/config/db.sql +++ b/config/db.sql @@ -585,6 +585,7 @@ CREATE TABLE `view_record` ( CREATE TABLE `gift` ( `id` int unsigned NOT NULL AUTO_INCREMENT, `name` varchar(63) NOT NULL DEFAULT '' COMMENT '物品名称', + `description` varchar(255) NOT NULL DEFAULT '' COMMENT '详细描述', `price` int unsigned NOT NULL DEFAULT 0 COMMENT '价格(铜币数)', `total_num` int unsigned NOT NULL DEFAULT 0 COMMENT '总数量', `remain_num` int unsigned NOT NULL DEFAULT 0 COMMENT '剩余数量', diff --git a/src/model/gift.go b/src/model/gift.go index f0251e4a..8050b89e 100644 --- a/src/model/gift.go +++ b/src/model/gift.go @@ -26,17 +26,18 @@ var GiftTypeMap = map[int]string{ } type Gift struct { - Id int `json:"id" xorm:"pk autoincr"` - Name string - Price int - TotalNum int - RemainNum int - ExpireTime time.Time `xorm:"int"` - Supplier string - BuyLimit int - Typ int - State int - CreatedAt OftenTime `xorm:"<-"` + Id int `json:"id" xorm:"pk autoincr"` + Name string + Description string + Price int + TotalNum int + RemainNum int + ExpireTime time.Time `xorm:"int"` + Supplier string + BuyLimit int + Typ int + State int + CreatedAt OftenTime `xorm:"<-"` TypShow string `xorm:"-"` } diff --git a/template/gift/list.html b/template/gift/list.html index 8e94050f..0040178c 100644 --- a/template/gift/list.html +++ b/template/gift/list.html @@ -38,17 +38,19 @@

    编号 名称类型合作提供方价格剩余操作说明类型合作提供方价格剩余操作
    {{.Id}} {{.Name}}{{noescape .Description}} {{.TypShow}} {{.Supplier}} {{.Price}} 铜币
    - {{range $i, $user := .users}} - - - - - - - - - {{end}} - - - - -
    - - -

    {{add $i 1}}. {{.Username}}

    - - {{.Monlog}} -
    - - {{.Website}} -
    - - 第 {{.Uid}} 号会员 - -
    -
     {{.Weight}} 
    -
    {{.active_num}}
    -
    -
    +
    +
    + + {{range $i, $user := .users}} + + + + + + + + + {{end}} + + + + +
    + + +

    {{add $i 1}}. {{.Username}}

    + + {{.Monlog}} +
    + + {{.Website}} +
    + + 第 {{.Uid}} 号会员 + +
    +
     {{.Weight}} 
    +
    {{.active_num}}
    +
    +
    -
    -
    -
    - {{include "common/my_info.html" .}} +
    +
    +
    + {{include "common/my_info.html" .}} -
    +
  • {{end}} {{define "css"}} @@ -143,12 +155,18 @@

     发布文章 init(); $('#cke_myeditor').show(); $('#markdown-editor').hide(); + + $('.markdown-help').hide(); + $('.ckeditor-help').show(); } else { $('#cke_myeditor').hide(); $('#markdown-editor').show(); + + $('.markdown-help').show(); + $('.ckeditor-help').hide(); } }); }); - + {{end}} \ No newline at end of file From 31ae42263836add03b1459e7c0ceac741b2d07f4 Mon Sep 17 00:00:00 2001 From: xuxinhua Date: Sun, 13 Aug 2017 18:46:42 +0800 Subject: [PATCH 046/411] =?UTF-8?q?tab=20=E4=B8=8D=E5=AD=98=E5=9C=A8?= =?UTF-8?q?=E6=97=B6=20bugfix?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/http/controller/index.go | 2 +- src/logic/index.go | 5 +++++ 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/src/http/controller/index.go b/src/http/controller/index.go index adf3429a..47bb1f91 100644 --- a/src/http/controller/index.go +++ b/src/http/controller/index.go @@ -41,9 +41,9 @@ func (IndexController) NewIndex(ctx echo.Context) error { if tab == "" { tab = logic.WebsiteSetting.IndexNavs[0].Tab } - SetCookie(ctx, "INDEX_TAB", tab) data := logic.DefaultIndex.FindData(ctx, tab) + SetCookie(ctx, "INDEX_TAB", data["tab"].(string)) data["all_nodes"] = logic.GenNodes() return render(ctx, "new_index.html", data) diff --git a/src/logic/index.go b/src/logic/index.go index 41301c48..44f3a764 100644 --- a/src/logic/index.go +++ b/src/logic/index.go @@ -21,6 +21,11 @@ var DefaultIndex = IndexLogic{} func (IndexLogic) FindData(ctx context.Context, tab string) map[string]interface{} { indexNav := GetCurIndexNav(tab) + if indexNav == nil { + indexNav = WebsiteSetting.IndexNavs[0] + tab = indexNav.Tab + } + data := map[string]interface{}{ "tab": tab, "index_navs": WebsiteSetting.IndexNavs, From 7cee262efe5b5297065fad4e90cc9afe6bb78c9c Mon Sep 17 00:00:00 2001 From: xuxinhua Date: Mon, 14 Aug 2017 15:46:12 +0800 Subject: [PATCH 047/411] =?UTF-8?q?=E5=AF=B9=E7=94=A8=E6=88=B7=E5=8F=91?= =?UTF-8?q?=E5=B8=83=E6=9D=83=E9=99=90=E8=BF=9B=E8=A1=8C=E9=99=90=E5=88=B6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- config/db.sql | 1 + src/http/controller/admin/routes.go | 1 + src/http/controller/admin/user.go | 73 +++++++++++++++++++++++++++++ src/http/http.go | 3 +- src/logic/common.go | 27 +++++++++++ src/logic/user.go | 59 +++++++++++++++++++++++ src/model/user.go | 20 ++++++++ template/admin/user/detail.html | 18 +++++++ template/articles/new.html | 16 +++++++ template/common/comment.html | 2 +- template/common/my_info.html | 14 ++++++ template/resources/new.html | 14 ++++++ 12 files changed, 246 insertions(+), 2 deletions(-) create mode 100644 src/http/controller/admin/user.go diff --git a/config/db.sql b/config/db.sql index 4bfb534f..cb08f2e3 100644 --- a/config/db.sql +++ b/config/db.sql @@ -135,6 +135,7 @@ CREATE TABLE IF NOT EXISTS `user_info` ( `unsubscribe` tinyint unsigned NOT NULL DEFAULT 0 COMMENT '是否退订本站邮件,0-否;1-是', `is_third` tinyint unsigned NOT NULL DEFAULT 0 COMMENT '是否通过第三方账号注册', `balance` int unsigned NOT NULL DEFAULT 0 COMMENT '财富余额(铜币)', + `dau_auth` int unsigned NOT NULL DEFAULT 0 COMMENT '控制用户权限,如能否发文章等', `status` tinyint unsigned NOT NULL DEFAULT 0 COMMENT '用户账号状态。0-默认;1-已审核;2-拒绝;3-冻结;4-停号', `is_root` tinyint unsigned NOT NULL DEFAULT 0 COMMENT '是否超级用户,不受权限控制:1-是', `ctime` timestamp NOT NULL DEFAULT 0, diff --git a/src/http/controller/admin/routes.go b/src/http/controller/admin/routes.go index ae1ac468..8099eb0c 100644 --- a/src/http/controller/admin/routes.go +++ b/src/http/controller/admin/routes.go @@ -10,6 +10,7 @@ import "github.com/labstack/echo" func RegisterRoutes(g *echo.Group) { new(AuthorityController).RegisterRoute(g) + new(UserController).RegisterRoute(g) new(ArticleController).RegisterRoute(g) new(ProjectController).RegisterRoute(g) new(RuleController).RegisterRoute(g) diff --git a/src/http/controller/admin/user.go b/src/http/controller/admin/user.go new file mode 100644 index 00000000..2e8f1a90 --- /dev/null +++ b/src/http/controller/admin/user.go @@ -0,0 +1,73 @@ +// Copyright 2013 The StudyGolang Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. +// http://studygolang.com +// Author: polaris polaris@studygolang.com + +package admin + +import ( + "logic" + + "github.com/labstack/echo" +) + +type UserController struct{} + +// 注册路由 +func (self UserController) RegisterRoute(g *echo.Group) { + g.GET("/user/user/list", self.UserList) + g.POST("/user/user/query.html", self.UserQuery) + g.GET("/user/user/detail", self.Detail) + g.POST("/user/user/modify", self.Modify) +} + +// UserList 所有用户(分页) +func (UserController) UserList(ctx echo.Context) error { + curPage, limit := parsePage(ctx) + + users, total := logic.DefaultUser.FindUserByPage(ctx, nil, curPage, limit) + + data := map[string]interface{}{ + "datalist": users, + "total": total, + "totalPages": (total + limit - 1) / limit, + "page": curPage, + "limit": limit, + } + + return render(ctx, "user/list.html,user/query.html", data) +} + +func (UserController) UserQuery(ctx echo.Context) error { + curPage, limit := parsePage(ctx) + conds := parseConds(ctx, []string{"uid", "username", "email"}) + + users, total := logic.DefaultUser.FindUserByPage(ctx, conds, curPage, limit) + + data := map[string]interface{}{ + "datalist": users, + "total": total, + "totalPages": (total + limit - 1) / limit, + "page": curPage, + "limit": limit, + } + + return renderQuery(ctx, "user/query.html", data) +} + +func (UserController) Detail(ctx echo.Context) error { + user := logic.DefaultUser.FindOne(ctx, "uid", ctx.QueryParam("uid")) + + data := map[string]interface{}{ + "user": user, + } + + return render(ctx, "user/detail.html", data) +} + +func (UserController) Modify(ctx echo.Context) error { + uid := ctx.FormValue("uid") + logic.DefaultUser.SetDauAuth(ctx, uid, ctx.FormParams()) + return success(ctx, nil) +} diff --git a/src/http/http.go b/src/http/http.go index cdb95e7f..96d6ff0c 100644 --- a/src/http/http.go +++ b/src/http/http.go @@ -139,7 +139,8 @@ var funcMap = template.FuncMap{ return int(time.Now().Sub(t).Hours() / 24) }, - "canEdit": logic.CanEdit, + "canEdit": logic.CanEdit, + "canPublish": logic.CanPublish, } func tplInclude(file string, dot map[string]interface{}) template.HTML { diff --git a/src/logic/common.go b/src/logic/common.go index 3af90ed1..b2eafd5a 100644 --- a/src/logic/common.go +++ b/src/logic/common.go @@ -148,6 +148,33 @@ func CanEdit(me *model.Me, curModel interface{}) bool { return false } +func CanPublish(dauAuth, objtype int) bool { + if dauAuth == 0 { + return true + } + + switch objtype { + case model.TypeTopic: + return (dauAuth & model.DauAuthTopic) == model.DauAuthTopic + case model.TypeArticle: + return (dauAuth & model.DauAuthArticle) == model.DauAuthArticle + case model.TypeResource: + return (dauAuth & model.DauAuthResource) == model.DauAuthResource + case model.TypeProject: + return (dauAuth & model.DauAuthProject) == model.DauAuthProject + case model.TypeWiki: + return (dauAuth & model.DauAuthWiki) == model.DauAuthWiki + case model.TypeBook: + return (dauAuth & model.DauAuthBook) == model.DauAuthBook + case model.TypeComment: + return (dauAuth & model.DauAuthComment) == model.DauAuthComment + case model.TypeTop: + return (dauAuth & model.DauAuthTop) == model.DauAuthTop + default: + return true + } +} + func website() string { host := "http://" if WebsiteSetting.OnlyHttps { diff --git a/src/logic/user.go b/src/logic/user.go index 3f19ddfe..7e3d9ee0 100644 --- a/src/logic/user.go +++ b/src/logic/user.go @@ -268,6 +268,7 @@ func (self UserLogic) FindCurrentUser(ctx context.Context, username interface{}) Status: user.Status, IsRoot: user.IsRoot, MsgNum: DefaultMessage.FindNotReadMsgNum(ctx, user.Uid), + DauAuth: user.DauAuth, Balance: user.Balance, Gold: user.Gold, @@ -522,6 +523,64 @@ func (UserLogic) FindNewUsers(ctx context.Context, limit int, offset ...int) []* return users } +// 获取用户列表(分页):后台用 +func (UserLogic) FindUserByPage(ctx context.Context, conds map[string]string, curPage, limit int) ([]*model.User, int) { + objLog := GetLogger(ctx) + + session := MasterDB.NewSession() + session.IsAutoClose = true + + for k, v := range conds { + session.And(k+"=?", v) + } + + totalSession := session.Clone() + + offset := (curPage - 1) * limit + userList := make([]*model.User, 0) + err := session.OrderBy("uid DESC").Limit(limit, offset).Find(&userList) + if err != nil { + objLog.Errorln("UserLogic find error:", err) + return nil, 0 + } + + total, err := totalSession.Count(new(model.User)) + if err != nil { + objLog.Errorln("UserLogic find count error:", err) + return nil, 0 + } + + return userList, int(total) +} + +func (self UserLogic) SetDauAuth(ctx context.Context, uid string, form url.Values) { + user := self.FindOne(ctx, "uid", uid) + user.DauAuth = 0 + + for k := range form { + switch k { + case "topic": + user.DauAuth |= model.DauAuthTopic + case "article": + user.DauAuth |= model.DauAuthArticle + case "resource": + user.DauAuth |= model.DauAuthResource + case "project": + user.DauAuth |= model.DauAuthProject + case "wiki": + user.DauAuth |= model.DauAuthWiki + case "book": + user.DauAuth |= model.DauAuthBook + case "comment": + user.DauAuth |= model.DauAuthComment + case "top": + user.DauAuth |= model.DauAuthTop + } + } + + MasterDB.Id(user.Uid).Update(user) +} + // GetUserMentions 获取 @ 的 suggest 列表 func (UserLogic) GetUserMentions(term string, limit int, isHttps bool) []map[string]string { userActives := make([]*model.UserActive, 0) diff --git a/src/model/user.go b/src/model/user.go index a2a7dba3..9a79281a 100644 --- a/src/model/user.go +++ b/src/model/user.go @@ -49,6 +49,24 @@ const ( UserStatusOutage // 停用 ) +const ( + // 用户拥有的权限设置 + DauAuthTopic = 1 << iota + DauAuthArticle + DauAuthResource + DauAuthWiki + DauAuthProject + DauAuthBook + DauAuthComment // 评论 + DauAuthTop // 置顶 +) + +// 置顶 +const ( + TypeComment = 100 + TypeTop = 101 +) + // 用户基本信息 type User struct { Uid int `json:"uid" xorm:"pk autoincr"` @@ -67,6 +85,7 @@ type User struct { Unsubscribe int `json:"unsubscribe"` Balance int `json:"balance"` IsThird int `json:"is_third"` + DauAuth int `json:"dau_auth"` Status int `json:"status"` IsRoot bool `json:"is_root"` Ctime OftenTime `json:"ctime" xorm:"created"` @@ -121,6 +140,7 @@ type Me struct { MsgNum int `json:"msgnum"` IsAdmin bool `json:"isadmin"` IsRoot bool `json:"is_root"` + DauAuth int `json:"dau_auth"` Balance int `json:"balance"` Gold int `json:"gold"` diff --git a/template/admin/user/detail.html b/template/admin/user/detail.html index 006d99fc..2c26ddb4 100644 --- a/template/admin/user/detail.html +++ b/template/admin/user/detail.html @@ -155,6 +155,24 @@

    角色信息

    +
    +

    DAU 权限设置

    +
    +
    +

    + + + 发布主题:   + 发布文章:   + 分享资源:   + 发布Wiki:   + 发布项目:   + 发布图书:   + 发布评论:   + 置顶: + +

    +
    diff --git a/template/articles/new.html b/template/articles/new.html index debe64f7..12194c96 100644 --- a/template/articles/new.html +++ b/template/articles/new.html @@ -9,6 +9,7 @@
  • {{if .article.Id}}编辑{{else}}写{{end}}文章
  • + {{if canPublish .me.DauAuth 1}}
    {{if .article.Id}} @@ -56,12 +57,27 @@ {{if not .article.Id}} {{end}} +
    (Ctrl+Enter)
    + {{else}} +
    +
    +
    + 您没有权限发布文章,请通过主题发布帖子 +
    +
    + +
    +
    + {{end}} +
    diff --git a/template/common/comment.html b/template/common/comment.html index 7485eaa6..52270d91 100644 --- a/template/common/comment.html +++ b/template/common/comment.html @@ -28,6 +28,7 @@
    +
    • 请尽量让自己的回复能够对别人有帮助
    • @@ -38,7 +39,6 @@
    -
    @@ -134,6 +145,10 @@

     发布文章 + + @@ -140,6 +172,20 @@

     发布主题 select2.val(node).trigger('change'); // saveComposeDraft(memberId); } + + $('#content').on('change', function() { + var markdownString = $(this).val(); + // 配置 marked 语法高亮 + marked = SG.markSetting(); + + var contentHtml = marked(markdownString); + contentHtml = SG.replaceCodeChar(contentHtml); + + $('#content-preview').html(contentHtml); + + // emoji 表情解析 + emojify.run($('#content-preview').get(0)); + }); }); {{end}} \ No newline at end of file From e44e69676354351b8d415778766a1c6390cbd263 Mon Sep 17 00:00:00 2001 From: xuxinhua Date: Wed, 16 Aug 2017 23:41:35 +0800 Subject: [PATCH 054/411] =?UTF-8?q?=E5=AE=9E=E6=97=B6=E8=A7=A6=E5=8F=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- template/articles/new.html | 2 +- template/topics/new.html | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/template/articles/new.html b/template/articles/new.html index 18ede5f6..62f969a4 100644 --- a/template/articles/new.html +++ b/template/articles/new.html @@ -181,7 +181,7 @@

     发布文章 // 文本框自动伸缩 $('.need-autogrow').autoGrow(); - $('#markdown-content').on('change', function() { + $('#markdown-content').on('input propertychange', function() { var markdownString = $(this).val(); // 配置 marked 语法高亮 marked = SG.markSetting(); diff --git a/template/topics/new.html b/template/topics/new.html index 1b0431d7..6702ff11 100644 --- a/template/topics/new.html +++ b/template/topics/new.html @@ -173,7 +173,7 @@

     发帖提示 // saveComposeDraft(memberId); } - $('#content').on('change', function() { + $('#content').on('input propertychange', function() { var markdownString = $(this).val(); // 配置 marked 语法高亮 marked = SG.markSetting(); From 9e6c9bdb7a6da063b68146b7c0309f1175e0db95 Mon Sep 17 00:00:00 2001 From: xuxinhua Date: Thu, 17 Aug 2017 21:29:26 +0800 Subject: [PATCH 055/411] =?UTF-8?q?=E8=AF=84=E8=AE=BA=20markdown=20?= =?UTF-8?q?=E8=A7=A3=E6=9E=90?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- static/js/comment.js | 27 ++++++++------------------- template/articles/detail.html | 2 +- template/common/layout.html | 2 +- template/topics/detail.html | 2 +- 4 files changed, 11 insertions(+), 22 deletions(-) diff --git a/static/js/comment.js b/static/js/comment.js index 1ffcd105..51751d82 100644 --- a/static/js/comment.js +++ b/static/js/comment.js @@ -18,25 +18,23 @@ $('.page-comment .md-toolbar .preview').removeClass('cur'); $('.page-comment .content-preview').hide(); - $('.page-comment #commentForm').show(); + $('.page-comment #commentForm .text').show(); }); $('.page-comment .md-toolbar .preview').on('click', function(evt){ evt.preventDefault(); - // 配置 marked 语法高亮 - marked.setOptions({ - highlight: function (code) { - return hljs.highlightAuto(code).value; - } - }); + var marked = SG.markSetting(); $(this).addClass('cur'); $('.page-comment .md-toolbar .edit').removeClass('cur'); - $('.page-comment #commentForm').hide(); + $('.page-comment #commentForm .text').hide(); var content = $('.page-comment #commentForm textarea').val(); $('.page-comment .content-preview').html(marked(content)); + // emoji 表情解析 + emojify.run($('.page-comment .content-preview').get(0)); $('.page-comment .content-preview').show(); + }); $('#replies').on('mouseenter', '.reply', function(evt) { @@ -160,17 +158,7 @@ } var parseCmtContent = function(content) { - // 配置 marked 语法高亮 - marked.setOptions({ - highlight: function (code) { - code = code.replace(/"/g, '"'); - code = code.replace(/'/g, "'"); - code = code.replace(/</g, '<'); - code = code.replace(/>/g, '>'); - code = code.replace(/&/g, '&'); - return hljs.highlightAuto(code).value; - } - }); + var marked = SG.markSetting(); content = SG.preProcess(content); content = marked(content); return SG.replaceCodeChar(content); @@ -226,6 +214,7 @@ user.avatar = $pageComment.data('avatar'), comment.cmt_time = SG.timeago(comment.ctime); comment.reply_floor = 0; + comment.content = parseCmtContent(comment.content); var oneCmt = $.templates('#one-comment').render({comment: comment, user: user, is_new: true}); diff --git a/template/articles/detail.html b/template/articles/detail.html index 0151bcc6..18ed7e3b 100644 --- a/template/articles/detail.html +++ b/template/articles/detail.html @@ -184,7 +184,7 @@

    - + {{if .article.IsSelf}} - + {{template "js" .}} - + diff --git a/template/books/detail.html b/template/books/detail.html index 6b1fa652..e9c4c862 100644 --- a/template/books/detail.html +++ b/template/books/detail.html @@ -113,32 +113,9 @@

    目录

    + {{include "common/my_info.html" .}} - + {{include "sidebar/view_rank.html" (parseJSON `{"rank_title":"今日阅读排行","objtype":5,"limit":10,"rank_type":"today"}`)}} {{if .pos_ad.right1}} {{end}} - {{include "sidebar/project.html" .}} + {{include "sidebar/view_rank.html" (parseJSON `{"rank_title":"一周阅读排行","objtype":5,"limit":10,"rank_type":"week"}`)}}
    @@ -177,10 +154,7 @@

    目录

    diff --git a/template/common/layout.html b/template/common/layout.html index f09f37cb..cfd5c365 100644 --- a/template/common/layout.html +++ b/template/common/layout.html @@ -261,6 +261,6 @@ // $.views.settings.debugMode(true); - + \ No newline at end of file diff --git a/template/projects/detail.html b/template/projects/detail.html index 1659180d..6340a745 100644 --- a/template/projects/detail.html +++ b/template/projects/detail.html @@ -113,31 +113,7 @@

    {{end}} - + {{include "sidebar/view_rank.html" (parseJSON `{"rank_title":"今日阅读排行","objtype":4,"limit":10,"rank_type":"today"}`)}} {{if .pos_ad.right2}} {{end}} + + {{include "sidebar/view_rank.html" (parseJSON `{"rank_title":"一周阅读排行","objtype":4,"limit":10,"rank_type":"week"}`)}} @@ -175,9 +153,7 @@

    diff --git a/template/readings/list.html b/template/readings/list.html index b21fc473..d2bad9da 100644 --- a/template/readings/list.html +++ b/template/readings/list.html @@ -74,31 +74,7 @@

      关注 {{include "sidebar/article.html" .}} - + {{include "sidebar/topic.html" .}} {{if .pos_ad.right1}} {{end}} - + {{include "sidebar/view_rank.html" (parseJSON `{"rank_title":"今日阅读排行","objtype":2,"limit":10,"rank_type":"today"}`)}} {{if .pos_ad.right2}} {{end}} + + {{include "sidebar/view_rank.html" (parseJSON `{"rank_title":"一周阅读排行","objtype":2,"limit":10,"rank_type":"week"}`)}} + + {{include "sidebar/topic.html" .}} @@ -152,9 +132,9 @@

    diff --git a/template/topics/node.html b/template/topics/node.html index 919c2656..6d122e56 100644 --- a/template/topics/node.html +++ b/template/topics/node.html @@ -40,6 +40,10 @@

    {{.node.name}}

    {{end}} {{include "sidebar/hot_node.html" .}} + + {{include "sidebar/view_rank.html" (parseJSON `{"rank_title":"今日阅读排行","objtype":0,"limit":10,"rank_type":"today"}`)}} + + {{include "sidebar/view_rank.html" (parseJSON `{"rank_title":"一周阅读排行","objtype":0,"limit":10,"rank_type":"week"}`)}} {{include "sidebar/stat.html" .}} @@ -57,7 +61,8 @@

    {{.node.name}}

    "/comments/recent", "/articles/recent", "/nodes/hot", - "/websites/stat" + "/websites/stat", + "/rank/view" ]; From 16de45e9be7ace840cbeeba61b7eeb9befbe09ea Mon Sep 17 00:00:00 2001 From: xuxinhua Date: Sat, 19 Aug 2017 11:49:13 +0800 Subject: [PATCH 057/411] fixbug:#33 --- config/init.sql | 2 +- template/articles/detail.html | 18 +++++++++++++----- 2 files changed, 14 insertions(+), 6 deletions(-) diff --git a/config/init.sql b/config/init.sql index 2b440bee..a804a4a1 100644 --- a/config/init.sql +++ b/config/init.sql @@ -55,7 +55,7 @@ VALUES INSERT INTO `website_setting` (`id`, `name`, `domain`, `title_suffix`, `favicon`, `logo`, `start_year`, `blog_url`, `reading_menu`, `docs_menu`, `slogan`, `beian`, `friends_logo`, `footer_nav`, `project_df_logo`, `index_nav`, `created_at`, `updated_at`) VALUES - (1, 'Go语言中文网', 'studygolang.com', '- Go语言中文网 - Golang中文社区', '/static/img/go.ico', '/static/img/logo1.png', 2013, 'http://blog.studygolang.com', '', '', 'Go语言中文网,中国 Golang 社区,致力于构建完善的 Golang 中文社区,Go语言爱好者的学习家园。', '京ICP备14030343号-1', '[{\"image\":\"http://qiniutek.com/images/logo-2.png\",\"url\":\"https://portal.qiniu.com/signup?code=3lfz4at7pxfma\",\"name\":\"\",\"width\":\"290px\",\"height\":\"45px\"}]', '[{\"name\":\"关于\",\"url\":\"/wiki/about\",\"outer_site\":false},{\"name\":\"贡献者\",\"url\":\"/wiki/contributors\",\"outer_site\":false},{\"name\":\"帮助推广\",\"url\":\"/wiki\",\"outer_site\":false},{\"name\":\"反馈\",\"url\":\"/topics/node/16\",\"outer_site\":false},{\"name\":\"Github\",\"url\":\"https://github.com/studygolang\",\"outer_site\":true},{\"name\":\"新浪微博\",\"url\":\"http://weibo.com/studygolang\",\"outer_site\":true},{\"name\":\"内嵌Wide\",\"url\":\"/wide/playground\",\"outer_site\":false},{\"name\":\"免责声明\",\"url\":\"/wiki/duty\",\"outer_site\":false}]', '', '{["tab":"all"]}', '2017-05-21 10:22:00', '2017-05-21 21:30:56'); + (1, 'Go语言中文网', 'studygolang.com', '- Go语言中文网 - Golang中文社区', '/static/img/go.ico', '/static/img/logo1.png', 2013, 'http://blog.studygolang.com', '', '', 'Go语言中文网,中国 Golang 社区,致力于构建完善的 Golang 中文社区,Go语言爱好者的学习家园。', '京ICP备14030343号-1', '[{\"image\":\"http://qiniutek.com/images/logo-2.png\",\"url\":\"https://portal.qiniu.com/signup?code=3lfz4at7pxfma\",\"name\":\"\",\"width\":\"290px\",\"height\":\"45px\"}]', '[{\"name\":\"关于\",\"url\":\"/wiki/about\",\"outer_site\":false},{\"name\":\"贡献者\",\"url\":\"/wiki/contributors\",\"outer_site\":false},{\"name\":\"帮助推广\",\"url\":\"/wiki\",\"outer_site\":false},{\"name\":\"反馈\",\"url\":\"/topics/node/16\",\"outer_site\":false},{\"name\":\"Github\",\"url\":\"https://github.com/studygolang\",\"outer_site\":true},{\"name\":\"新浪微博\",\"url\":\"http://weibo.com/studygolang\",\"outer_site\":true},{\"name\":\"内嵌Wide\",\"url\":\"/wide/playground\",\"outer_site\":false},{\"name\":\"免责声明\",\"url\":\"/wiki/duty\",\"outer_site\":false}]', '', '[{"tab":"all"}]', '2017-05-21 10:22:00', '2017-05-21 21:30:56'); INSERT INTO `friend_link` (`id`, `name`, `url`, `seq`, `logo`, `created_at`) VALUES diff --git a/template/articles/detail.html b/template/articles/detail.html index ad67aa77..41e8c32b 100644 --- a/template/articles/detail.html +++ b/template/articles/detail.html @@ -74,12 +74,12 @@

    -
    - {{if .next}} - 下一篇:{{.next.Title}} - {{end}} +
    {{if .prev}} - 上一篇:{{.prev.Title}} +
    上一篇:{{.prev.Title}}
    + {{end}} + {{if .next}} +
    下一篇:{{.next.Title}}
    {{end}}
    @@ -162,6 +162,14 @@

    {{end}} + + {{end}} {{define "js"}} From d40c16f972b9d5b01c8eff89511a42af5722bdb4 Mon Sep 17 00:00:00 2001 From: xuxinhua Date: Sat, 19 Aug 2017 12:59:49 +0800 Subject: [PATCH 058/411] =?UTF-8?q?node=20=E7=AE=80=E4=BB=8B=E6=94=AF?= =?UTF-8?q?=E6=8C=81=20markdown=20=E8=AF=AD=E6=B3=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- template/topics/node.html | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/template/topics/node.html b/template/topics/node.html index 6d122e56..efd00a49 100644 --- a/template/topics/node.html +++ b/template/topics/node.html @@ -20,7 +20,7 @@

    {{.node.name}}

    共有 {{.total}} 个主题

    -

    {{.node.intro}}

    +

    {{.node.intro}}

    @@ -54,6 +54,7 @@

    {{.node.name}}

    {{end}} {{define "js"}} + {{if .pos_ad.right1}} From 51f53b7aeb74a83f12d8a68a691f7591255d6fad Mon Sep 17 00:00:00 2001 From: xuxinhua Date: Sat, 19 Aug 2017 17:21:24 +0800 Subject: [PATCH 059/411] hot node --- static/js/sidebar.js | 2 +- template/common/layout.html | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/static/js/sidebar.js b/static/js/sidebar.js index 8a2405fe..72cb1ebc 100644 --- a/static/js/sidebar.js +++ b/static/js/sidebar.js @@ -274,7 +274,7 @@ $(function(){ var content = ''; for(var i in data) { - content += '
  • '+data[i].name+'
  • '; + content += '
  • '+data[i].name+'
  • '; } $('.sb-content .node-list ul').html(content); diff --git a/template/common/layout.html b/template/common/layout.html index cfd5c365..7a3d44f6 100644 --- a/template/common/layout.html +++ b/template/common/layout.html @@ -261,6 +261,6 @@ // $.views.settings.debugMode(true); - + \ No newline at end of file From d5e97f27c5ad3012391b0b6e2221ffb0b9203fca Mon Sep 17 00:00:00 2001 From: xuxinhua Date: Sat, 19 Aug 2017 17:52:15 +0800 Subject: [PATCH 060/411] =?UTF-8?q?=E5=8E=BB=E6=8E=89=E6=97=A0=E7=94=A8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- static/js/common.js | 9 --------- 1 file changed, 9 deletions(-) diff --git a/static/js/common.js b/static/js/common.js index d62293d2..f0fa7d2f 100644 --- a/static/js/common.js +++ b/static/js/common.js @@ -474,15 +474,6 @@ if (window.WebSocket) { var hadPop = false; $(function(){ - if (Math.random()*50 <= 1) { - $('.ad').each(function(){ - var url = $(this).attr('href'); - - var adImg = new Image(); - adImg.src = url; - }); - } - $(window).scroll(function() { // 滚动条所在位置的高度 var totalheight = parseFloat($(window).height()) + parseFloat($(window).scrollTop()); From 6a37794bc6aeafc19a4d23df16e91fb7363ffcd8 Mon Sep 17 00:00:00 2001 From: xuxinhua Date: Sun, 20 Aug 2017 12:55:41 +0800 Subject: [PATCH 061/411] =?UTF-8?q?Go=20=E5=AE=89=E8=A3=85=E5=8C=85?= =?UTF-8?q?=E4=B8=8B=E8=BD=BD=E5=8A=9F=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- robots.txt | 3 +- src/http/controller/download.go | 65 + src/http/controller/routes.go | 1 + static/js/godl.js | 171 + template/articles/detail.html | 2 +- template/download/dl.html | 170 - template/download/go.html | 5248 +++++++++++++++++++++++++++++++ 7 files changed, 5488 insertions(+), 172 deletions(-) create mode 100644 src/http/controller/download.go create mode 100644 static/js/godl.js delete mode 100644 template/download/dl.html create mode 100644 template/download/go.html diff --git a/robots.txt b/robots.txt index b8a6a0cf..d1ec1705 100644 --- a/robots.txt +++ b/robots.txt @@ -1,3 +1,4 @@ User-agent: * Allow: / -Sitemap: \ No newline at end of file +Sitemap: +Disallow:/dl/golang/ \ No newline at end of file diff --git a/src/http/controller/download.go b/src/http/controller/download.go new file mode 100644 index 00000000..2fb86cd1 --- /dev/null +++ b/src/http/controller/download.go @@ -0,0 +1,65 @@ +// Copyright 2017 The StudyGolang Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. +// http://studygolang.com +// Author: polaris polaris@studygolang.com + +package controller + +import ( + "fmt" + "net/http" + "regexp" + "strings" + + "github.com/labstack/echo" + "github.com/polaris1119/config" +) + +const GoStoragePrefix = "https://storage.googleapis.com/golang/" + +type DownloadController struct{} + +// 注册路由 +func (self DownloadController) RegisterRoute(g *echo.Group) { + g.Get("/dl", self.GoDl) + g.Get("/dl/golang/:filename", self.FetchGoInstallPackage) +} + +// GoDl Go 语言安装包下载 +func (DownloadController) GoDl(ctx echo.Context) error { + + data := map[string]interface{}{ + "activeBooks": "active", + } + + return render(ctx, "download/go.html", data) +} + +var filenameReg = regexp.MustCompile(`go\d+\.\d[a-z\.]*\d+`) + +func (DownloadController) FetchGoInstallPackage(ctx echo.Context) error { + filename := ctx.Param("filename") + + officalUrl := GoStoragePrefix + filename + resp, err := http.Head(officalUrl) + if err == nil && resp.StatusCode == http.StatusOK { + return ctx.Redirect(http.StatusSeeOther, officalUrl) + } + + goVersion := filenameReg.FindString(filename) + filePath := fmt.Sprintf("/go/%s/%s", goVersion, filename) + + dlUrls := strings.Split(config.ConfigFile.MustValue("download", "dl_urls"), ",") + for _, dlUrl := range dlUrls { + dlUrl += filePath + resp, err = http.Head(dlUrl) + if err == nil && resp.StatusCode == http.StatusOK { + return ctx.Redirect(http.StatusSeeOther, dlUrl) + } + } + + getLogger(ctx).Infoln("download:", filename, "from the site static directory") + + return ctx.Redirect(http.StatusSeeOther, "/static/"+filePath) +} diff --git a/src/http/controller/routes.go b/src/http/controller/routes.go index 9e850c63..72ff5e25 100644 --- a/src/http/controller/routes.go +++ b/src/http/controller/routes.go @@ -34,6 +34,7 @@ func RegisterRoutes(g *echo.Group) { new(GiftController).RegisterRoute(g) new(OAuthController).RegisterRoute(g) new(WebsocketController).RegisterRoute(g) + new(DownloadController).RegisterRoute(g) new(WechatController).RegisterRoute(g) diff --git a/static/js/godl.js b/static/js/godl.js new file mode 100644 index 00000000..058c4a27 --- /dev/null +++ b/static/js/godl.js @@ -0,0 +1,171 @@ +(function() { +'use strict'; + +function bindToggle(el) { + $('.toggleButton', el).click(function() { + if ($(this).closest(".toggle, .toggleVisible")[0] != el) { + // Only trigger the closest toggle header. + return; + } + + if ($(el).is('.toggle')) { + $(el).addClass('toggleVisible').removeClass('toggle'); + } else { + $(el).addClass('toggle').removeClass('toggleVisible'); + } + }); +} + +function bindToggles(selector) { + $(selector).each(function(i, el) { + bindToggle(el); + }); +} + +function bindToggleLink(el, prefix) { + $(el).click(function() { + var href = $(el).attr('href'); + var i = href.indexOf('#'+prefix); + if (i < 0) { + return; + } + var id = '#' + prefix + href.slice(i+1+prefix.length); + if ($(id).is('.toggle')) { + $(id).find('.toggleButton').first().click(); + } + }); +} +function bindToggleLinks(selector, prefix) { + $(selector).each(function(i, el) { + bindToggleLink(el, prefix); + }); +} + +function toggleHash() { + var id = window.location.hash.substring(1); + // Open all of the toggles for a particular hash. + var els = $( + document.getElementById(id), + $('a[name]').filter(function() { + return $(this).attr('name') == id; + }) + ); + + while (els.length) { + for (var i = 0; i < els.length; i++) { + var el = $(els[i]); + if (el.is('.toggle')) { + el.find('.toggleButton').first().click(); + } + } + els = el.parent(); + } +} + +function personalizeInstallInstructions() { + var prefix = '?download='; + var s = window.location.search; + if (s.indexOf(prefix) != 0) { + // No 'download' query string; detect "test" instructions from User Agent. + if (navigator.platform.indexOf('Win') != -1) { + $('.testUnix').hide(); + $('.testWindows').show(); + } else { + $('.testUnix').show(); + $('.testWindows').hide(); + } + return; + } + + var filename = s.substr(prefix.length); + var filenameRE = /^go1\.\d+(\.\d+)?([a-z0-9]+)?\.([a-z0-9]+)(-[a-z0-9]+)?(-osx10\.[68])?\.([a-z.]+)$/; + $('.downloadFilename').text(filename); + $('.hideFromDownload').hide(); + var m = filenameRE.exec(filename); + if (!m) { + // Can't interpret file name; bail. + return; + } + + var os = m[3]; + var ext = m[6]; + if (ext != 'tar.gz') { + $('#tarballInstructions').hide(); + } + if (os != 'darwin' || ext != 'pkg') { + $('#darwinPackageInstructions').hide(); + } + if (os != 'windows') { + $('#windowsInstructions').hide(); + $('.testUnix').show(); + $('.testWindows').hide(); + } else { + if (ext != 'msi') { + $('#windowsInstallerInstructions').hide(); + } + if (ext != 'zip') { + $('#windowsZipInstructions').hide(); + } + $('.testUnix').hide(); + $('.testWindows').show(); + } + + var download = "https://storage.googleapis.com/golang/" + filename; + + var message = $('

    '+ + 'Your download should begin shortly. '+ + 'If it does not, click this link.

    '); + message.find('a').attr('href', download); + message.insertAfter('#nav'); + + window.location = download; +} + +function updateVersionTags() { + var v = window.goVersion; + if (/^go[0-9.]+$/.test(v)) { + $(".versionTag").empty().text(v); + $(".whereTag").hide(); + } +} + +function addPermalinks() { + function addPermalink(source, parent) { + var id = source.attr("id"); + if (id == "" || id.indexOf("tmp_") === 0) { + // Auto-generated permalink. + return; + } + if (parent.find("> .permalink").length) { + // Already attached. + return; + } + parent.append(" ").append($("").attr("href", "#" + id)); + } + + $("#page .container").find("h2[id], h3[id]").each(function() { + var el = $(this); + addPermalink(el, el); + }); + + $("#page .container").find("dl[id]").each(function() { + var el = $(this); + // Add the anchor to the "dt" element. + addPermalink(el, el.find("> dt").first()); + }); +} + +$(document).ready(function() { + addPermalinks(); + bindToggles(".toggle"); + bindToggles(".toggleVisible"); + bindToggleLinks(".exampleLink", "example_"); + bindToggleLinks(".overviewLink", ""); + bindToggleLinks(".examplesLink", ""); + bindToggleLinks(".indexLink", ""); + toggleHash(); + personalizeInstallInstructions(); + updateVersionTags(); +}); + +})(); \ No newline at end of file diff --git a/template/articles/detail.html b/template/articles/detail.html index 41e8c32b..d25dbed9 100644 --- a/template/articles/detail.html +++ b/template/articles/detail.html @@ -14,7 +14,7 @@
    {{if .article.IsSelf}} diff --git a/template/download/dl.html b/template/download/dl.html deleted file mode 100644 index 130bf52a..00000000 --- a/template/download/dl.html +++ /dev/null @@ -1,170 +0,0 @@ -{{define "title"}}社区主题 {{end}} -{{define "seo"}} -{{end}} -{{define "content"}} - -
    -
    - - -
    -
    -
    - {{with $root := .}} - {{range .topics}} -
    -
    - {{.user.Username}} -
    -
    - -
    - {{.node}} - • - {{.user.Username}} - {{if .lastreplyuid}} - - • - 最后由 {{.lastreplyusername}}回复 - - {{else}} - - • - 于发布 - - {{end}} -
    - {{if .reply}} - {{.reply}} - {{end}} - {{if .like}}{{.like}} {{end}} - {{.view}} -
    -
    -
    -
    - {{else}} -

    暂时没有任何帖子

    - {{end}} - {{end}} -
    - {{if .page}} - - {{end}} -
    -
    -

    讨论节点分类导航

    -
      - {{range .nodes}} -
    • - {{range $parent, $children := .}} - - - {{range $children}} - {{.name}}  - {{end}} - - {{end}} -
    • - {{end}} -
    -
    -
    -
    - - - - - - - - - - -
    -
    -{{end}} -{{define "css"}} - -{{end}} -{{define "js"}} - -{{end}} \ No newline at end of file diff --git a/template/download/go.html b/template/download/go.html new file mode 100644 index 00000000..a76f7cc7 --- /dev/null +++ b/template/download/go.html @@ -0,0 +1,5248 @@ +{{define "title"}}Go下载 {{end}} +{{define "seo"}} +{{end}} +{{define "content"}} +
    +
    +
    + + + +
    +

    Go 安装包下载

    + +

    + 为你的系统下载了相应的安装包后,请按照 安装说明 进行安装。 +

    + +

    + 如果你选择从源码构建,请参考 从源码进行安装。 +

    + +

    + 查看 发布历史 了解更多关于 Go 各版本的发布说明。 +

    + + + + + + +
    Microsoft Windows
    +
    Windows XP SP2 or later, Intel 64-bit 处理器
    +
    + go1.8.3.windows-amd64.msi + (78MB) +
    +
    + + +
    Apple macOS
    +
    macOS 10.8 or later, Intel 64-bit 处理器
    +
    + go1.8.3.darwin-amd64.pkg + (85MB) +
    +
    + + +
    Linux
    +
    Linux 2.6.23 or later, Intel 64-bit 处理器
    +
    + go1.8.3.linux-amd64.tar.gz + (86MB) +
    +
    + + +
    源码
    +
    + go1.8.3.src.tar.gz + (15MB) +
    +
    + +
    + +

    稳定版本

    + + +
    + +
    +

    go1.8.3 ▾

    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    文件名类型操作系统(OS)架构(Arch)大小SHA256 Checksum
    go1.8.3.src.tar.gzSource15MB5f5dea2447e7dcfdc50fa6b94c512e58bfba5673c039259fd843f68829d99fa6
    go1.8.3.darwin-amd64.tar.gzArchivemacOSx86-6486MBf20b92bc7d4ab22aa18270087c478a74463bd64a893a94264434a38a4b167c05
    go1.8.3.darwin-amd64.pkgInstallermacOSx86-6485MBf81c8911dc76cd2b4ddd3d7ea845fe7ed83abd493b382fff216e1a8f637b5e7f
    go1.8.3.linux-386.tar.gzArchiveLinuxx8674MBff4895eb68fb1daaec41c540602e8bb4c1e8bb2f0e7017367171913fc9995ed2
    go1.8.3.linux-amd64.tar.gzArchiveLinuxx86-6486MB1862f4c3d3907e59b04a757cfda0ea7aa9ef39274af99a784f5be843c80c6772
    go1.8.3.linux-armv6l.tar.gzArchiveLinuxARMv674MB3c30a3e24736ca776fc6314e5092fb8584bd3a4a2c2fa7307ae779ba2735e668
    go1.8.3.windows-386.zipArchiveWindowsx8680MB9e2bfcb8110a3c56f23b91f859963269bc29fd114190fecfd0a539395272a1c7
    go1.8.3.windows-386.msiInstallerWindowsx8667MBc1df97e6f9afc2db1705f0f1d04fa31804d5c9b995cca26680881baaa1543eb4
    go1.8.3.windows-amd64.zipArchiveWindowsx86-6492MBde026caef4c5b4a74f359737dcb2d14c67ca45c45093755d3b0d2e0ee3aafd96
    go1.8.3.windows-amd64.msiInstallerWindowsx86-6478MB35734d9331fe4ee19725213d8e98840660460fd1b90518fffc79c0f856a3586a
    Other Ports
    go1.8.3.freebsd-386.tar.gzArchiveFreeBSDx8674MBd301cc7c2b8b0ccb384ac564531beee8220727fd27ca190b92031a2e3e230224
    go1.8.3.freebsd-amd64.tar.gzArchiveFreeBSDx86-6486MB1bf5f076d48609012fe01b95e2a58e71e56719a04d576fe3484a216ad4b9c495
    go1.8.3.linux-ppc64le.tar.gzArchiveLinuxppc64le73MBe5fb00adfc7291e657f1f3d31c09e74890b5328e6f991a3f395ca72a8c4dc0b3
    go1.8.3.linux-s390x.tar.gzArchiveLinuxs390x72MBe2ec3e7c293701b57ca1f32b37977ac9968f57b3df034f2cc2d531e80671e6c8
    + +
    +
    + +
    + +
    +

    go1.7.6 ▾

    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    文件名类型操作系统(OS)架构(Arch)大小SHA256 Checksum
    go1.7.6.src.tar.gzSource14MB1a67a4e688673fdff7ba41e73482b0e59ac5bd0f7acf703bc6d50cc775c5baba
    go1.7.6.darwin-amd64.tar.gzArchivemacOSx86-6480MB2eec332ac3162d9e19125645176a9477245b47f4657c2f2715818f2a4739f245
    go1.7.6.darwin-amd64.pkgInstallermacOSx86-6480MB0015000e4de8900b2d988ea45adcaf47931c3f838ad3fa8d3789cce775299870
    go1.7.6.linux-386.tar.gzArchiveLinuxx8671MB99f79d4e0f966f492794963ecbf4b08c16a9a268f2c09053a5ce10b343ee4082
    go1.7.6.linux-amd64.tar.gzArchiveLinuxx86-6480MBad5808bf42b014c22dd7646458f631385003049ded0bb6af2efc7f1f79fa29ea
    go1.7.6.linux-armv6l.tar.gzArchiveLinuxARMv669MBfc5c40fb1f76d0978504b94cd06b5ea6e0e216ba1d494060d081e022540900f8
    go1.7.6.windows-386.zipArchiveWindowsx8676MBadc772f1d38a38a985d95247df3d068a42db841489f72a228f51080125f78b8f
    go1.7.6.windows-386.msiInstallerWindowsx8663MBf2e7a0d35c5bdc2b09b491e41103d7de624094bbda5ba9f0dae22d29edc08d90
    go1.7.6.windows-amd64.zipArchiveWindowsx86-6486MB3c648f9b89b7e0ed746c211dbf959aa230c8034506dd70c9852bf0f94d06065d
    go1.7.6.windows-amd64.msiInstallerWindowsx86-6473MBe684807a9be72f10ed158b729e1cd188b2f96066c6c028b1da150e6971ecba6b
    Other Ports
    go1.7.6.freebsd-386.tar.gzArchiveFreeBSDx8671MB43559a1489b5aa670a3b78da54aebc8064d32c3c6eecd2430270e399e2e0a278
    go1.7.6.freebsd-amd64.tar.gzArchiveFreeBSDx86-6480MB79f6afb90980159bfec10165d8102dbb6cf2a1aee018fb66b2eb799ba5e51205
    go1.7.6.linux-ppc64le.tar.gzArchiveLinuxppc64le69MB8b5b602958396f165a3547a1308ab91ae3f2ad8ecb56063571a37aadc2df2332
    go1.7.6.linux-s390x.tar.gzArchiveLinuxs390x67MBd692643d1ac4f4dea8fb6d949ffa750e974e63ff0ee6ca2a7c38fc7c90da8b5b
    + +
    +
    + + +

    不稳定版本

    + + +
    + +
    +

    go1.9rc2 ▾

    + +

    这是 Go 一个 不稳定 的版本。请谨慎使用。

    +

    如果你已经安装了 Go,你可以通过运行如下命令安装此版本:

    +
    go get golang.org/x/build/version/go1.9rc2
    +			
    +

    之后,使用命令 go1.9rc2 代替使用命令 go 来试用 go1.9rc2。

    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    文件名类型操作系统(OS)架构(Arch)大小SHA256 Checksum
    go1.9rc2.src.tar.gzSource16MB12b09ea6cb3189ea5e4c057f7047b5709ae8edd14706421b188f7e4ae8d8d3e4
    go1.9rc2.darwin-amd64.tar.gzArchivemacOSx86-6494MB18f7d7d4c85331aca3b2a8e1a92849834f1068a78b911d308a3ce1a8edab76db
    go1.9rc2.darwin-amd64.pkgInstallermacOSx86-6493MB334429bd0a84fd949632454a1e4b0709de355fc04822a90f36fbdef09f124c21
    go1.9rc2.freebsd-386.tar.gzArchiveFreeBSDx8682MBfeaa2ca8617bc383f8d9558e0c4eb3171f87ea5e8c760f1ad60edcf9ca132aa0
    go1.9rc2.freebsd-amd64.tar.gzArchiveFreeBSDx86-6494MB8e8e2cab27aa4758e6c171e09694e631c60d7d88d855f2070de243a11292db88
    go1.9rc2.linux-386.tar.gzArchiveLinuxx8682MBb4d9e1f2f0f4f406150f21f7d166fa6f6ca54d7370752dc77e5b9f2ca2850dd0
    go1.9rc2.linux-amd64.tar.gzArchiveLinuxx86-6494MB0d17d440f02505d8fbf6becb777175c242486c1d71046705876dcd20e0574002
    go1.9rc2.linux-arm64.tar.gzArchiveLinuxARMv880MBc53bdbc41fcd980f4ad6e5f216913053709479871cd395990fa4bf4f01c21e7d
    go1.9rc2.linux-armv6l.tar.gzArchiveLinuxARMv681MBc61a2efe5127e88c20a49278b9748a326af197bb38949387710119914d1d77a4
    go1.9rc2.linux-ppc64le.tar.gzArchiveLinuxppc64le80MB765f844aec22328d5f3347c42b22f240ad0ecb78cc6f5f55d35e47d0379cfc79
    go1.9rc2.linux-s390x.tar.gzArchiveLinuxs390x79MB1ec407c52ed02c472a71412733940c065666ceb76b83192c0ca09c70502b409d
    go1.9rc2.windows-386.zipArchiveWindowsx8688MB7610058833bb57a22d3939166e43473b0de88ad6dff4bf6c8a879fdc516bb734
    go1.9rc2.windows-386.msiInstallerWindowsx8675MBd0b6bef3a995dbd6deddf2e7d49b3deca089a2773005e1770563cf71aaa6d213
    go1.9rc2.windows-amd64.zipArchiveWindowsx86-64100MB9bd0642fe169723732adc3300dda9b0fdf5f1ff7fab921553d2a4f482c677a3f
    go1.9rc2.windows-amd64.msiInstallerWindowsx86-6486MBda62ebb8d921b09d03e0ffc514f0c637483c299939ff5d59bda5677970dfb72e
    + +
    +
    + + + +
    + +
    +

    历史版本归档▾

    + + +
    + +
    +

    go1.8.2 ▾

    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    文件名类型操作系统(OS)架构(Arch)大小SHA256 Checksum
    go1.8.2.src.tar.gzSource15MBe10401faaa8ae29dbe87349c1814b07b1903d453f822215d7b274bbc335cbf79
    go1.8.2.darwin-amd64.tar.gzArchivemacOSx86-6486MB3f783c33686e6d74f6c811725eb3775c6cf80b9761fa6d4cebc06d6d291be137
    go1.8.2.darwin-amd64.pkgInstallermacOSx86-6485MB20ba1a69e99898fa3aecbf4b16f4d06218e8c0f536e9a9c0939c1f02aa923a6e
    go1.8.2.freebsd-386.tar.gzArchiveFreeBSDx8674MBcea0948d7b5e721d2be871c903b4a57488b8a0253979d32609de010f32f9624b
    go1.8.2.freebsd-amd64.tar.gzArchiveFreeBSDx86-6486MB8accaa61671d4ac2c75106963960a3720a2bd8757e1ac1738f2e58a4b0644b58
    go1.8.2.linux-386.tar.gzArchiveLinuxx8674MB00bc94606610bf25c660d6106fa8e61cca6a276c046f3ceb9091053e99ceebe9
    go1.8.2.linux-amd64.tar.gzArchiveLinuxx86-6486MB5477d6c9a4f96fa120847fafa88319d7b56b5d5068e41c3587eebe248b939be7
    go1.8.2.linux-armv6l.tar.gzArchiveLinuxARMv674MBa1942b2833e7d2685d7dbb7ac81c66125c351f24c7f006e8ae4a4283905257d1
    go1.8.2.linux-ppc64le.tar.gzArchiveLinuxppc64le73MB031035eab11903237e02007fc69c085bd4769ff2e2aa5e9af427ddaed3d37e2b
    go1.8.2.linux-s390x.tar.gzArchiveLinuxs390x72MBf091afb86501191270e14a653a056e8e7635e18a72e43cfbd13093b2482ca7a8
    go1.8.2.windows-386.zipArchiveWindowsx8679MB75e295f5cd0eb3236e68324ac51b9e54a1aad1fa3a3b259f62cc11e05d948aed
    go1.8.2.windows-386.msiInstallerWindowsx8667MBe0f57dc6ef1df0952c3f5fb343cda4a336212ee3fbce93fd124e062c7e7049ac
    go1.8.2.windows-amd64.zipArchiveWindowsx86-6492MB9bfa4d497caee1b7ec8720acdea2fa8af8d51b525ddc7e4648a63a3138a6a8e3
    go1.8.2.windows-amd64.msiInstallerWindowsx86-6478MB710c5dcbfcb5a71dfdb24d4536617cb4d0d7786488f45ca1602bf2648edbff0a
    + +
    +
    + +
    + +
    +

    go1.8.1 ▾

    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    文件名类型操作系统(OS)架构(Arch)大小SHA256 Checksum
    go1.8.1.src.tar.gzSource15MB33daf4c03f86120fdfdc66bddf6bfff4661c7ca11c5da473e537f4d69b470e57
    go1.8.1.darwin-amd64.tar.gzArchivemacOSx86-6485MB25b026fe2f4de7c80b227f69588b06b93787f5b5f134fbf2d652926c08c04bcd
    go1.8.1.darwin-amd64.pkgInstallermacOSx86-6485MBd938193b8b230c23b596f3fbc1125e506c6090d6a7679204a7daeeb64b071b5a
    go1.8.1.freebsd-386.tar.gzArchiveFreeBSDx8674MB8f6dd6acd2076e21b4e154d3daa8243fcedbdfd63be7cb54a3dae8be66e46bd9
    go1.8.1.freebsd-amd64.tar.gzArchiveFreeBSDx86-6486MB91065d4bb311bba74d7c1e3e6bab82fbba24c9da8aeca9e803caabcc66de1af7
    go1.8.1.linux-386.tar.gzArchiveLinuxx8675MBcb3f4527112075a8b045d708f793aeee2709d2f5ddd320973a1413db06fddb50
    go1.8.1.linux-amd64.tar.gzArchiveLinuxx86-6487MBa579ab19d5237e263254f1eac5352efcf1d70b9dacadb6d6bb12b0911ede8994
    go1.8.1.linux-armv6l.tar.gzArchiveLinuxARMv674MBe8a8326913640409028ef95c2107773f989b1b2a6e11ceb463c77c42887381da
    go1.8.1.linux-ppc64le.tar.gzArchiveLinuxppc64le73MBb7b47572a2676449716865a66901090c057f6f1d8dfb1e19528fcd0372e5ce74
    go1.8.1.linux-s390x.tar.gzArchiveLinuxs390x72MB0a59f4034a27fc51431989da520fd244d5261f364888134cab737e5bc2158cb2
    go1.8.1.windows-386.zipArchiveWindowsx8679MB9738365e64d4d80ea54487915c9bfc0c3bbaa7d68ec78487988f80ebe8129c57
    go1.8.1.windows-386.msiInstallerWindowsx8667MB1bd07af205d723e33dbcc45c1ce59fc78c4f6463dd3d4d65d7834de1f8fe909e
    go1.8.1.windows-amd64.zipArchiveWindowsx86-6492MBbb6f0fbef8b80c382455af8699bfbb7fe89256d4baf06d927feaeceb7342e4ee
    go1.8.1.windows-amd64.msiInstallerWindowsx86-6478MBe99c4086e7b8a62cc0d9dcedb7fdd70a36733b53e2cb67b55ae7a1bc76f4036d
    + +
    +
    + +
    + +
    +

    go1.8 ▾

    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    文件名类型操作系统(OS)架构(Arch)大小SHA256 Checksum
    go1.8.src.tar.gzSource15MB406865f587b44be7092f206d73fc1de252600b79b3cacc587b74b5ef5c623596
    go1.8.darwin-amd64.tar.gzArchivemacOSx86-6485MB6fdc9f98b76a28655a8770a1fc8197acd8ef746dd4d8a60589ce19604ba2a120
    go1.8.darwin-amd64.pkgInstallermacOSx86-6485MBf9d511eb88baecf8a2e3457bf85eaae73dfb7cade4dd4eaba744947efea586e1
    go1.8.freebsd-386.tar.gzArchiveFreeBSDx8674MB9965b73686fcf82a7d002e75b30d4125cc9f47906c1e2b2f0ef036a6665f0348
    go1.8.freebsd-amd64.tar.gzArchiveFreeBSDx86-6485MBe750579f390fe5c95de30c2a52d7ce88250cf971c435323373d22bfab8a63431
    go1.8.linux-386.tar.gzArchiveLinuxx8674MB8f618dc8b01c2e53e639a38d780645b8424e671e292c7b518248022205d6a448
    go1.8.linux-amd64.tar.gzArchiveLinuxx86-6486MB53ab94104ee3923e228a2cb2116e5e462ad3ebaeea06ff04463479d7f12d27ca
    go1.8.linux-armv6l.tar.gzArchiveLinuxARMv674MB32553dbb342f74a821ed5069cb72ec7e135c031102e7d01c6bc4da8ad6df5202
    go1.8.linux-ppc64le.tar.gzArchiveLinuxppc64le73MB7e78afe33377b4d4c04817d48feb9f2a904406d32216df015d44462f0432643b
    go1.8.linux-s390x.tar.gzArchiveLinuxs390x76MBfb893a546902c2afdff929ddf5a9fbc0fd50b9017126ee85e80604d8620010fe
    go1.8.windows-386.zipArchiveWindowsx8679MBb8199a4af9327807803d2892268dfbffb615f98d717cd824833a97e77f981f46
    go1.8.windows-386.msiInstallerWindowsx8667MBab95f48fc86e6e3c4a5cd7851d66414c3e6b551df4bc905a9e5dcde802ad7377
    go1.8.windows-amd64.zipArchiveWindowsx86-6492MBcb27fe210f3a9d10329d48514895d2a1e3651125a7c3c758f0358a5bfc0e3060
    go1.8.windows-amd64.msiInstallerWindowsx86-6478MBb2e20d9d7cd7ce95812ba6762df641cc1d3a71c218469f155a0bf9fb0ba9d994
    + +
    +
    + +
    + +
    +

    go1.7.5 ▾

    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    文件名类型操作系统(OS)架构(Arch)大小SHA256 Checksum
    go1.7.5.src.tar.gzSource14MB4e834513a2079f8cbbd357502cccaac9507fd00a1efe672375798858ff291815
    go1.7.5.darwin-amd64.tar.gzArchivemacOSx86-6480MB2e2a5e0a5c316cf922cf7d59ee5724d49fc35b07a154f6c4196172adfc14b2ca
    go1.7.5.darwin-amd64.pkgInstallermacOSx86-6479MB2faab21628af53c9193d17a0cdd2c03584615796853bd19cd7c41478d140235c
    go1.7.5.freebsd-386.tar.gzArchiveFreeBSDx8670MBa47c56c7f5bd33e0a0877fbee0daa1eceb6885954796ef63ffa25a570d73aa78
    go1.7.5.freebsd-amd64.tar.gzArchiveFreeBSDx86-6480MBc52e55a25d7925b5075de2266453d4ddf7b9245e26dbcaccb700129481ac9842
    go1.7.5.linux-386.tar.gzArchiveLinuxx8671MB432cb92ae656f6fe1fa96a981782ef5948438b6da6691423aae900918b1eb955
    go1.7.5.linux-amd64.tar.gzArchiveLinuxx86-6480MB2e4dd6c44f0693bef4e7b46cc701513d74c3cc44f2419bf519d7868b12931ac3
    go1.7.5.linux-armv6l.tar.gzArchiveLinuxARMv668MBcf93c8171dda189c226fe337e3aae11db24bd600841caab36c91d753f631aa2b
    go1.7.5.linux-ppc64le.tar.gzArchiveLinuxppc64le68MBced737e36f2b2017b59f31cce86f50a2519245f017a81b8dce93bf986717e3ed
    go1.7.5.linux-s390x.tar.gzArchiveLinuxs390x67MB858df47609594570479ff937e3704c58e06b40e485ce29d7f934eae87b7a4450
    go1.7.5.windows-386.zipArchiveWindowsx8675MBde367304d1d654ff23d74a2644a457b7740c2da46bc3abedc46f1317f97316ad
    go1.7.5.windows-386.msiInstallerWindowsx8663MB1ff1ce677c7a6d18ba88e0518e7fa2167943f2f3c2d56173666f6ef56d52d0e0
    go1.7.5.windows-amd64.zipArchiveWindowsx86-6486MB01eb518cb5a12edd6cf7380ec17ebedee755e3ce7e5362febeebb9e70e45fcaa
    go1.7.5.windows-amd64.msiInstallerWindowsx86-6473MB23064bb5bab2f8a96322b7630c6c8cfbd6fa81ef3350977227df328a76e8e861
    + +
    +
    + +
    + +
    +

    go1.7.4 ▾

    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    文件名类型操作系统(OS)架构(Arch)大小SHA256 Checksum
    go1.7.4.src.tar.gzSource14MB4c189111e9ba651a2bb3ee868aa881fab36b2f2da3409e80885ca758a6b614cc
    go1.7.4.darwin-amd64.tar.gzArchivemacOSx86-6480MBf86c727012e33f3f482b049281aaee24211fe29dfafd121d93f32799a6b6ba2d
    go1.7.4.darwin-amd64.pkgInstallermacOSx86-6479MBee7ffc75b80434b8c0aac587a887d45d2ec2e15a1e6692a8641a4fa8c5dcbdc9
    go1.7.4.freebsd-386.tar.gzArchiveFreeBSDx8670MB5f70cb139dec6c8b6b1788afd0905eea1b719e05c1d5e815d0d2779e00a28bbf
    go1.7.4.freebsd-amd64.tar.gzArchiveFreeBSDx86-6480MBc560bd755f04528385b35c561bc6b07ec43311cef82143d96cb347ee600ec333
    go1.7.4.linux-386.tar.gzArchiveLinuxx8670MB31d27752bada47de84e8884cabe6dc13140e459e3aad540c17abc0fcac370c54
    go1.7.4.linux-amd64.tar.gzArchiveLinuxx86-6480MB47fda42e46b4c3ec93fa5d4d4cc6a748aa3f9411a2a2b7e08e3a6d80d753ec8b
    go1.7.4.linux-armv6l.tar.gzArchiveLinuxARMv668MB075c5f4446234e26c1380003ff2b050f0c7e63591410bab65355a945601bf245
    go1.7.4.linux-ppc64le.tar.gzArchiveLinuxppc64le68MBfe13807365c2ceb871ba30c10695b1d9cffddba7703cbce07bd9e539bbf2cd56
    go1.7.4.linux-s390x.tar.gzArchiveLinuxs390x67MBd9c95281a08282c8f3c6e66648164214c02bc4af0b1aa28a8142ecdb2309d602
    go1.7.4.windows-386.zipArchiveWindowsx8676MB49df7846ab04d6106cc501526c14c055788e8c67590a967fb4abef7b8b70751f
    go1.7.4.windows-386.msiInstallerWindowsx8663MB7a465629d7122f1c00f59b25381f2d7efc245f1ad6cee0aa5fe6a5b54adc759a
    go1.7.4.windows-amd64.zipArchiveWindowsx86-6486MB36739164fed38a6da908813aba48d72fb22fea923de5611a85a81135b7cfceb9
    go1.7.4.windows-amd64.msiInstallerWindowsx86-6473MB1d8b5a79f0d73b4a5b78f701eef8526ee212b3c54486498a2016fc83958e3c50
    + +
    +
    + +
    + +
    +

    go1.7.3 ▾

    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    文件名类型操作系统(OS)架构(Arch)大小SHA256 Checksum
    go1.7.3.src.tar.gzSource14MB79430a0027a09b0b3ad57e214c4c1acfdd7af290961dd08d322818895af1ef44
    go1.7.3.darwin-amd64.tar.gzArchivemacOSx86-6478MB2ef310fa48b43dfed7b4ae063b5facba130ed0db95745c538dfc3e30e7c0de04
    go1.7.3.darwin-amd64.pkgInstallermacOSx86-6478MBc2b0e222ab32c92283fbebea61d54c1fbd015d94654384e0fc40162a68898c22
    go1.7.3.freebsd-386.tar.gzArchiveFreeBSDx8669MBe3ac58b1ea8272570adb646bcf4f313d52afe453c83f155ef3f931f472261f0e
    go1.7.3.freebsd-amd64.tar.gzArchiveFreeBSDx86-6479MB78e8987603ab379c9aa1707e027e46978a26f71caf5c0df4cf3a4627570efff5
    go1.7.3.linux-386.tar.gzArchiveLinuxx8669MBd39d562c3247b11ae659afe1e131a3287c60b7de207ca5f25684c26f1c1dff5c
    go1.7.3.linux-amd64.tar.gzArchiveLinuxx86-6479MB508028aac0654e993564b6e2014bf2d4a9751e3b286661b0b0040046cf18028e
    go1.7.3.linux-armv6l.tar.gzArchiveLinuxARMv666MBd02912d121e1455e775a5aa4ecdb2a04f8483ba846e6d2341e1f35b8e507d7b5
    go1.7.3.linux-s390x.tar.gzArchiveLinuxs390x66MBcadbf9cab94c91b4e8d37884cbe4dd237f983b4c92238c0e93628c166440fb50
    go1.7.3.windows-386.zipArchiveWindowsx8674MBd0ac2d3aaa20452d0f09112f034cca1c5b8560452a45e10523af7f0a1089c792
    go1.7.3.windows-386.msiInstallerWindowsx8662MBdd2ae25fc099003f5207c6125ceb4cd9444a866d4d28084a653e178514d41727
    go1.7.3.windows-amd64.zipArchiveWindowsx86-6485MB9fe41313b97e2a6a703f5ae22938c7d9ac4336a128b522376c224ba97e8c7f01
    go1.7.3.windows-amd64.msiInstallerWindowsx86-6472MB1e73eb0c36af1b714389328a39de28254aca35956933ec84ca2d93175471f41a
    + +
    +
    + +
    + +
    +

    go1.7.1 ▾

    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    文件名类型操作系统(OS)架构(Arch)大小SHA256 Checksum
    go1.7.1.src.tar.gzSource13MB2b843f133b81b7995f26d0cb64bbdbb9d0704b90c44df45f844d28881ad442d3
    go1.7.1.darwin-amd64.tar.gzArchivemacOSx86-6478MB9fd80f19cc0097f35eaa3a52ee28795c5371bb6fac69d2acf70c22c02791f912
    go1.7.1.darwin-amd64.pkgInstallermacOSx86-6478MB62544484135af780c2069416ca58ab79023d1bcdb0f667ae1c862ed568d7fa7e
    go1.7.1.freebsd-386.tar.gzArchiveFreeBSDx8668MBfa1de564c006471b1db7232b5dffb668f5365e8e6e41947d28d7d345af235b60
    go1.7.1.freebsd-amd64.tar.gzArchiveFreeBSDx86-6478MB012c84e7fbb3b8d8feeda2e5f21914d3ca96ca7b22b3f022a1250ebd3c6fc6ae
    go1.7.1.linux-386.tar.gzArchiveLinuxx8668MBff6f52de513002b6abb0897654eeb6a7280b420fab3108a382b4f4aba07ad4a6
    go1.7.1.linux-amd64.tar.gzArchiveLinuxx86-6478MB43ad621c9b014cde8db17393dc108378d37bc853aa351a6c74bf6432c1bbd182
    go1.7.1.linux-armv6l.tar.gzArchiveLinuxARMv666MB42d0330734d09cb9f5bae86dad6d0cdf580afcc94242babae0217bdde0d08ec0
    go1.7.1.linux-s390x.tar.gzArchiveLinuxs390x65MBc479f9cf58b29fb4ec7fd9aa9fa4f8204f51a0dea8eccf48683e9d16dd108ab0
    go1.7.1.windows-386.zipArchiveWindowsx8674MB312fcbb84c0b4268e6e0351dccf0d6e9bb226c9934b5ee81bd7865a693a68aaa
    go1.7.1.windows-386.msiInstallerWindowsx8661MBffb26e5b080e6fead2a1973af34e44b22884fcdd9c61f01e967844cb747d006f
    go1.7.1.windows-amd64.zipArchiveWindowsx86-6485MBaf2b836bb894672cf4c28df32a2ee3ff560e2b463e1ab44bb99833064ba09e5f
    go1.7.1.windows-amd64.msiInstallerWindowsx86-6472MBc043eebd653e84fac259f725621e600ffed80d45bea62e35855fd21dfc7075dc
    + +
    +
    + +
    + +
    +

    go1.7 ▾

    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    文件名类型操作系统(OS)架构(Arch)大小SHA256 Checksum
    go1.7.src.tar.gzSource13MB72680c16ba0891fcf2ccf46d0f809e4ecf47bbf889f5d884ccb54c5e9a17e1c0
    go1.7.darwin-amd64.tar.gzArchivemacOSx86-6478MB51d905e0b43b3d0ed41aaf23e19001ab4bc3f96c3ca134b48f7892485fc52961
    go1.7.darwin-amd64.pkgInstallermacOSx86-6478MBe7089843bc7148ffcc147759985b213604d22bb9fd19bd930b515aa981bf1b22
    go1.7.freebsd-386.tar.gzArchiveFreeBSDx8668MB5c24520f5366ca44cf0019dc5b22c8695726f3dc26553d24d56d0c7d4389d00f
    go1.7.freebsd-amd64.tar.gzArchiveFreeBSDx86-6478MB97e1c2f4720d710db948cf94e9c30536f2e653ad49edf684e6f3821296008d55
    go1.7.linux-386.tar.gzArchiveLinuxx8668MB1207477aa3471222f0555825f9d6ac2a39abc75839f2dfd357f19f5077f710f2
    go1.7.linux-amd64.tar.gzArchiveLinuxx86-6478MB702ad90f705365227e902b42d91dd1a40e48ca7f67a2f4b2fd052aaa4295cd95
    go1.7.linux-armv6l.tar.gzArchiveLinuxARMv666MB4192592728e2f9fac8ae43abedb4b98d811836c3965035e7cb8c603aa5e65be4
    go1.7.windows-386.zipArchiveWindowsx8674MB9a4323fde431f1638ac40a504c1a96f584b6a7a53931599f95df4c8dd530b627
    go1.7.windows-386.msiInstallerWindowsx8662MB8fe71ebf78ab68ef7466c8496312a0c6f8af5f9ec8b186b02eb5f3bdfabd5b17
    go1.7.windows-amd64.zipArchiveWindowsx86-6485MBf51aad06644cc8bd119d2f6933334fa8da24d26e6676fde022cecf5978f1a0c7
    go1.7.windows-amd64.msiInstallerWindowsx86-6472MB795cc0353deb5f7bd54eff95444b9124d803b0adf28636c64d914bffee14b81c
    + +
    +
    + +
    + +
    +

    go1.6.4 ▾

    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    文件名类型操作系统(OS)架构(Arch)大小SHA256 Checksum
    go1.6.4.src.tar.gzSource12MB8796cc48217b59595832aa9de6db45f58706dae68c9c7fbbd78c9fdbe3cd9032
    go1.6.4.darwin-amd64.tar.gzArchivemacOSx86-6483MB8db84ba3237ba57250bc1ce41ecba0fd5c28b0b14d026b9a3c62498404fa4d20
    go1.6.4.darwin-amd64.pkgInstallermacOSx86-6482MB3224760f93b3ec418f0ad09a80448d9d5083ff620895f2abf92a5f24fea43c59
    go1.6.4.freebsd-386.tar.gzArchiveFreeBSDx8671MBe1c7e6b8a5c54d4964afbe1879e0ba174c4b592ac8daaa540a6e2a9ac2ed19cc
    go1.6.4.freebsd-amd64.tar.gzArchiveFreeBSDx86-6483MB39a04a209f1bc96f9e6cdc844b70860c3fe0016e95d86f41ca9c51f824c6adb4
    go1.6.4.linux-386.tar.gzArchiveLinuxx8671MBd9a4524dd6192bfa180fe462a468aa92fbeb0cca4887d16a9496064ceef1e94b
    go1.6.4.linux-amd64.tar.gzArchiveLinuxx86-6483MBb58bf5cede40b21812dfa031258db18fc39746cc0972bc26dae0393acc377aaf
    go1.6.4.linux-armv6l.tar.gzArchiveLinuxARMv669MBff60747ff08c6cb3521b0557b91fbbe7c419937e5f0332acccf308e82f28dbc6
    go1.6.4.linux-ppc64le.tar.gzArchiveLinuxppc64le69MB57c6e80fb2ea26601f5185e4ae31d12ce79af3f1a4a588047e1f341ad107d2ec
    go1.6.4.windows-386.zipArchiveWindowsx8677MB91fb3e13dfba94c13334a3ce8362ed6dfd0e5e94c4a1251517223571c2410d73
    go1.6.4.windows-386.msiInstallerWindowsx8663MB5cec63c74ba440f476ae03654d3c1bea4baadd767de192d9af9eadac5d4623b4
    go1.6.4.windows-amd64.zipArchiveWindowsx86-6489MB4fc871ac03f5ca5978ad2ae860192e6a39dc2b1286afbe86f4947faab84ab231
    go1.6.4.windows-amd64.msiInstallerWindowsx86-6472MBa0bf243f9a2fe17485bf460f3ac0b2fc66ea5b37d64de01da428f942e5108ce3
    + +
    +
    + +
    + +
    +

    go1.6.3 ▾

    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    文件名类型操作系统(OS)架构(Arch)大小SHA256 Checksum
    go1.6.3.src.tar.gzSource12MB6326aeed5f86cf18f16d6dc831405614f855e2d416a91fd3fdc334f772345b00
    go1.6.3.darwin-amd64.tar.gzArchivemacOSx86-6481MB2cd8c824d485a7e73522287278981a528e8f9cb8d3dea41719e29e1bd31ca70a
    go1.6.3.darwin-amd64.pkgInstallermacOSx86-6481MBf0795efa3b1dc25d6ae086ddf4ad69c9a585ec6941e1cdf16e2b669cb4f978d0
    go1.6.3.freebsd-386.tar.gzArchiveFreeBSDx8669MBb22bd392afe8b6bbfb6af80bb728a03a66304cc025bd9964dbeac426a1f03c75
    go1.6.3.freebsd-amd64.tar.gzArchiveFreeBSDx86-6481MBd1e7c0b0cdb86edcfe20dfbf46f0bcfd34c4b4088972660f2b48d205ac1beb0b
    go1.6.3.linux-386.tar.gzArchiveLinuxx8669MB4d0657f4760c81c1b208939ae58f6fc06f936ee51b8cdcf75e5136d0d0c6df94
    go1.6.3.linux-amd64.tar.gzArchiveLinuxx86-6481MBcdde5e08530c0579255d6153b08fdb3b8e47caabbe717bc7bcd7561275a87aeb
    go1.6.3.linux-armv6l.tar.gzArchiveLinuxARMv668MB5fc3bd911898e1c9eaf418f56609ce426efd52a4b04b6b59a9af345e8da4a6db
    go1.6.3.windows-386.zipArchiveWindowsx8674MB3aa8c3208272143c2eadb67976e6e41048a95ff5ac0b55ea4b3b0c88a9ca1a8a
    go1.6.3.windows-386.msiInstallerWindowsx8661MB7838ded5a07c316fdd2f2f5613b68d0b05b7f3094e024f8c8336f789e1960525
    go1.6.3.windows-amd64.zipArchiveWindowsx86-6487MB6a18e5ed8b39785338986aecc6a3f36f5c4be286ff52db0ae3bcd2275ab70df0
    go1.6.3.windows-amd64.msiInstallerWindowsx86-6471MBf71e929dd0846f12d9b683cb2896e9b651a33c69bdbab9f62e9cc001dcc61798
    + +
    +
    + +
    + +
    +

    go1.6.2 ▾

    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    文件名类型操作系统(OS)架构(Arch)大小SHA256 Checksum
    go1.6.2.src.tar.gzSource12MB787b0b750d037016a30c6ed05a8a70a91b2e9db4bd9b1a2453aa502a63f1bccc
    go1.6.2.darwin-amd64.tar.gzArchivemacOSx86-6481MB6ebbafcac53bbbf8c4105fa84b63cca3d6ce04370f5a04ac2ac065782397fc26
    go1.6.2.darwin-amd64.pkgInstallermacOSx86-6481MB3acb72fc5da5b6b12b683a4cd13b5be2f6e976b0342436844d881bf7fc50dcc9
    go1.6.2.freebsd-386.tar.gzArchiveFreeBSDx8669MBefa6025948c9c56decee300e5e6eca4de8e38c30e8cde91944dcef2fcfa8d8fe
    go1.6.2.freebsd-amd64.tar.gzArchiveFreeBSDx86-6481MBa0b5c9eef56dc5f32ca26c8e5cefa7bebd6c06540b382a52db055a1d8da7e92a
    go1.6.2.linux-386.tar.gzArchiveLinuxx8669MB76ae80990f3b46fe1e0457cc0899979e49a2e927eb33af7ddb7611b400b7d6af
    go1.6.2.linux-amd64.tar.gzArchiveLinuxx86-6481MBe40c36ae71756198478624ed1bb4ce17597b3c19d243f3f0899bb5740d56212a
    go1.6.2.linux-armv6l.tar.gzArchiveLinuxARMv667MB337a08dcf0c4199e1ad84ac0fb1e07422b2603cc1c5f44ebb093a9e864320f3a
    go1.6.2.windows-386.zipArchiveWindowsx8675MBbaf8b0412145911fd1034875fe95f1f0b7d4e7f59271c5642f0ad78a017d724e
    go1.6.2.windows-386.msiInstallerWindowsx8661MBf30d9aedf4e448ebe6353302c0479ef493d80683b4eab4c890e5ab6b7626b02a
    go1.6.2.windows-amd64.zipArchiveWindowsx86-6488MB4367a147b6351c4975732375a21a098c90d26ca0e948245f602295aab389e0d0
    go1.6.2.windows-amd64.msiInstallerWindowsx86-6471MB9c853bbb54734ddc54c1d57f6315724deb1a3878a3c0ad36b6fdc0e14a7be300
    + +
    +
    + +
    + +
    +

    go1.6.1 ▾

    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    文件名类型操作系统(OS)架构(Arch)大小SHA256 Checksum
    go1.6.1.src.tar.gzSource12MB1d4b53cdee51b2298afcf50926a7fa44b286f0bf24ff8323ce690a66daa7193f
    go1.6.1.darwin-amd64.tar.gzArchivemacOSx86-6481MB3c3801d784043cca19388b3e09fa0e4706a97452c3a506049593bad7fa126978
    go1.6.1.darwin-amd64.pkgInstallermacOSx86-6481MB51f8ecbd113e4addb5107501e12628dad245cbbd704e3174375025b40d0764ab
    go1.6.1.freebsd-386.tar.gzArchiveFreeBSDx8669MB8d9ad38e89ca4cee50b639e0a9886b020594f0b093781e938d4a6188505310d4
    go1.6.1.freebsd-amd64.tar.gzArchiveFreeBSDx86-6481MB938f15cc399c7af9dbb88804d3c2c1cc1c8bf78a25c4b70ffc865d1a476cf5c4
    go1.6.1.linux-386.tar.gzArchiveLinuxx8669MBf1c07a6689405cf91e06f0c25ef99b892f10eb2c49d7fd5b7b015a14576d7760
    go1.6.1.linux-amd64.tar.gzArchiveLinuxx86-6481MB6d894da8b4ad3f7f6c295db0d73ccc3646bce630e1c43e662a0120681d47e988
    go1.6.1.linux-armv6l.tar.gzArchiveLinuxARMv667MBbb963abf71c0b80bc6b3befa5f3a0f60552bbe3cc19ef5b77ce81f0a2ecc00fe
    go1.6.1.windows-386.zipArchiveWindowsx8675MB7ecd878015b0bc60254b58e02ee4fea6b8904195edcbc8779d8472a95f48a09d
    go1.6.1.windows-386.msiInstallerWindowsx8661MBaebc1947de9e51ff277c3b227be19d56141dd94d093f3384fb79a001a64fa6da
    go1.6.1.windows-amd64.zipArchiveWindowsx86-6488MB1505afbcc5f71598c6ffd2a56ad550e4e8728c05649e9085f725e38d6b5a0fb8
    go1.6.1.windows-amd64.msiInstallerWindowsx86-6471MB345322f554822176337f9fbf86fa42b6e0430412fea24cd814182f0a394687a3
    + +
    +
    + +
    + +
    +

    go1.6 ▾

    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    文件名类型操作系统(OS)架构(Arch)大小SHA256 Checksum
    go1.6.src.tar.gzSource12MBa96cce8ce43a9bf9b2a4c7d470bc7ee0cb00410da815980681c8353218dcf146
    go1.6.darwin-amd64.tar.gzArchivemacOSx86-6481MB8b686ace24c0166738fd9f6003503f9d55ce03b7f24c963b043ba7bb56f43000
    go1.6.darwin-amd64.pkgInstallermacOSx86-6481MBcabae263fe1a8c3bb42539943348a69f94e3f96b5310a96e24df29ff745aaf5c
    go1.6.freebsd-386.tar.gzArchiveFreeBSDx8669MB67f0278e0650b303156adbfe012317b9ce75396e3a28cbc0a8210284bb07ab85
    go1.6.freebsd-amd64.tar.gzArchiveFreeBSDx86-6481MB3763015cdc7971e10f90fb5bec80d885e9956f836277dcb35a2166ffbd7af9b5
    go1.6.linux-386.tar.gzArchiveLinuxx8669MB7a240a0f45e559d47ea07319d9faf838225eb9e18174f56a76ccaf9860dbb9b1
    go1.6.linux-amd64.tar.gzArchiveLinuxx86-6481MB5470eac05d273c74ff8bac7bef5bad0b5abbd1c4052efbdbc8db45332e836b0b
    go1.6.linux-armv6l.tar.gzArchiveLinuxARMv667MBc6c1859acd3727f23f900bde855b5fd0f74d36b1d10f6dd7beddebfb57513d0b
    go1.6.windows-386.zipArchiveWindowsx8674MBac41a46f44d0ea5b83ad7e6a55ee1d58c6a01b7ab7342e243f232510342f16f0
    go1.6.windows-386.msiInstallerWindowsx8661MBbe2f9e1c85bfc55b3bea8f1e48acf4a8117fbcd6c7f372aa9ff9f74429f18a35
    go1.6.windows-amd64.zipArchiveWindowsx86-6487MB1be06afa469666d636a00928755c4bcd6403a01f5761946b2b13b8a664f86bac
    go1.6.windows-amd64.msiInstallerWindowsx86-6471MB9e185fe7985505e3a65633f5e4db76664607f67f8331f0ce4986ba69b51015b7
    + +
    +
    + +
    + +
    +

    go1.5.4 ▾

    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    文件名类型操作系统(OS)架构(Arch)大小SHA256 Checksum
    go1.5.4.src.tar.gzSource12MB002acabce7ddc140d0d55891f9d4fcfbdd806b9332fb8b110c91bc91afb0bc93
    go1.5.4.darwin-amd64.tar.gzArchivemacOSx86-6476MBc48f9b0a6dd65708291a5a7a6f733b77604980acf18b8357824aba2b5fd0d250
    go1.5.4.darwin-amd64.pkgInstallermacOSx86-6476MB84fe392ba7c1690358458cfa5c523b4022de226c48766680983c6152daf10eda
    go1.5.4.freebsd-amd64.tar.gzArchiveFreeBSDx86-6476MB0e1d2c7d6bc7b7f052006fa0867e825530b3f32950dfe14e63c158cbdbb154c7
    go1.5.4.linux-386.tar.gzArchiveLinuxx8665MB4b2b29d44144d0d306ba34ca5559aa9314c8f31165421ade2b59c74c28059690
    go1.5.4.linux-amd64.tar.gzArchiveLinuxx86-6476MBa3358721210787dc1e06f5ea1460ae0564f22a0fbd91be9dcd947fb1d19b9560
    go1.5.4.windows-386.zipArchiveWindowsx8671MB16b28315291b8cbf73614b675a7198015a35bf2ec7d2692d95cbf4ee27c555d9
    go1.5.4.windows-386.msiInstallerWindowsx8658MB716054681f6a4c64e23b81b4399f29f7e6f10fd543fe9d66e420e933b5a96b64
    go1.5.4.windows-amd64.zipArchiveWindowsx86-6483MB1201053d5659a5fc5c82dff58c3eaee66ecd02901621725cfdfff1681278bd1a
    go1.5.4.windows-amd64.msiInstallerWindowsx86-6467MBd3023d462d6391aff4e75350cbf0abbe44b3eac26213413c08aa30f87421d393
    + +
    +
    + +
    + +
    +

    go1.5.3 ▾

    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    文件名类型操作系统(OS)架构(Arch)大小SHA256 Checksum
    go1.5.3.src.tar.gzSource11MB754e06dab1c31ab168fc9db9e32596734015ea9e24bc44cae7f237f417ce4efe
    go1.5.3.darwin-amd64.tar.gzArchivemacOSx86-6476MB18723e4d486f3b743397273806f360275c2f8305b34a2c913b03c5be07b47654
    go1.5.3.darwin-amd64.pkgInstallermacOSx86-6476MB2948a0778cb8f493165ab51ede4fefb36d93df50722fd66ec35adf01e571f38b
    go1.5.3.freebsd-amd64.tar.gzArchiveFreeBSDx86-6476MBd2720ca9d69ad3e805b114263f3cf861a62c486c6acd045fb199343c76ce78d2
    go1.5.3.linux-386.tar.gzArchiveLinuxx8665MBc1ce206b7296db1b10ff7896044d9ca50e87efa5bc3477e8fd8c2fb149bfca8f
    go1.5.3.linux-amd64.tar.gzArchiveLinuxx86-6476MB43afe0c5017e502630b1aea4d44b8a7f059bf60d7f29dfd58db454d4e4e0ae53
    go1.5.3.windows-386.zipArchiveWindowsx8670MBf35cefa3f834611611249bc6607df804b0bb81ce06e444078e1fa00a1d811e06
    go1.5.3.windows-386.msiInstallerWindowsx8658MB30f9fc4d8df5f327a6a31fa170e282029b92f115dcb03a92f58564ac95d5ec30
    go1.5.3.windows-amd64.zipArchiveWindowsx86-6482MB0a863ba10560c51fa6c4d4ad1180abbc3220b7ecd41159160c322f0b19e06460
    go1.5.3.windows-amd64.msiInstallerWindowsx86-6467MB5ac73c76bc3a03757091ee225299ef325b56a85798f7e4142b8f4329b24bfa44
    + +
    +
    + +
    + +
    +

    go1.5.2 ▾

    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    文件名类型操作系统(OS)架构(Arch)大小SHA256 Checksum
    go1.5.2.src.tar.gzSource11MBc7d78ba4df574b5f9a9bb5d17505f40c4d89b81c
    go1.5.2.darwin-amd64.tar.gzArchivemacOSx86-6473MB4f30332a56e9c8a36daeeff667bab3608e4dffd2
    go1.5.2.darwin-amd64.pkgInstallermacOSx86-6473MB102b4e946b7bb40f0e8aa508e41340a696ead752
    go1.5.2.freebsd-amd64.tar.gzArchiveFreeBSDx86-6473MB34bbe347a95908ca440e4bf584a200522bba1985
    go1.5.2.linux-386.tar.gzArchiveLinuxx8665MB49ff1c2510eaba80423e55a633901464b28437ef
    go1.5.2.linux-amd64.tar.gzArchiveLinuxx86-6473MBcae87ed095e8d94a81871281d35da7829bd1234e
    go1.5.2.windows-386.zipArchiveWindowsx8670MBa9b265268a4632ad6f7ca8769e6a34eb1522f784
    go1.5.2.windows-386.msiInstallerWindowsx8658MB31bf4feb763385cc6e87a4c2aac9d8c711e3b378
    go1.5.2.windows-amd64.zipArchiveWindowsx86-6479MB5eb85b0eec36cfef05700935f2420b6104986733
    go1.5.2.windows-amd64.msiInstallerWindowsx86-6464MB101a612d3ce65a51459667340d1991d594f9b8e7
    + +
    +
    + +
    + +
    +

    go1.5.1 ▾

    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    文件名类型操作系统(OS)架构(Arch)大小SHA256 Checksum
    go1.5.1.src.tar.gzSource11MB0df564746d105f4180c2b576a1553ebca9d9a124
    go1.5.1.darwin-amd64.tar.gzArchivemacOSx86-6474MB02451b1f3b2c715edc5587174e35438982663672
    go1.5.1.darwin-amd64.pkgInstallermacOSx86-6474MB857b77a85ba111af1b0928a73cca52136780a75d
    go1.5.1.freebsd-amd64.tar.gzArchiveFreeBSDx86-6474MB78ac27b7c009142ed0d86b899f1711bb9811b7e1
    go1.5.1.linux-386.tar.gzArchiveLinuxx8666MB6ce7328f84a863f341876658538dfdf10aff86ee
    go1.5.1.linux-amd64.tar.gzArchiveLinuxx86-6474MB46eecd290d8803887dec718c691cc243f2175fe0
    go1.5.1.windows-386.zipArchiveWindowsx8670MBbb071ec45ef39cd5ed9449b54c5dd083b8233bfa
    go1.5.1.windows-386.msiInstallerWindowsx8658MB034065452b7233b2a570d4be1218a97c475cded0
    go1.5.1.windows-amd64.zipArchiveWindowsx86-6479MB7815772347ad3e11a096d927c65bfb15d5b0f490
    go1.5.1.windows-amd64.msiInstallerWindowsx86-6464MB0a439f49b546b82f85adf84a79bbf40de2b3d5ba
    + +
    +
    + +
    + +
    +

    go1.5 ▾

    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    文件名类型操作系统(OS)架构(Arch)大小SHA256 Checksum
    go1.5.src.tar.gzSource11MB7242bb5ae29594641c75bdc3453d5854cc0a8604
    go1.5.darwin-amd64.tar.gzArchivemacOSx86-6474MBb269242c39739ffcf05b8d969fb9787799f48c48
    go1.5.darwin-amd64.pkgInstallermacOSx86-6474MB0d37bb75adc6eb2ce72fc500a0584b20618abf1d
    go1.5.freebsd-amd64.tar.gzArchiveFreeBSDx86-6474MBea81cc0c2c499a54cd44e0eea81c98a1673a6dae
    go1.5.linux-386.tar.gzArchiveLinuxx8666MBbbb21e32d2f8fe97696d2bb5b29f7ff5ecd5edda
    go1.5.linux-amd64.tar.gzArchiveLinuxx86-6474MB5817fa4b2252afdb02e11e8b9dc1d9173ef3bd5a
    go1.5.windows-386.zipArchiveWindowsx8670MBf5014cd70be18b79bc401f1e35c8d73062124bf0
    go1.5.windows-386.msiInstallerWindowsx8658MBdf0d8c19e7d34af9c33a69debde4b281ae665b01
    go1.5.windows-amd64.zipArchiveWindowsx86-6479MB559cddfd341c20531689efad5412dcc304f8d85b
    go1.5.windows-amd64.msiInstallerWindowsx86-6464MBae369d86e796d767a8d536a5d78998a908a4b9e6
    + +
    +
    + +
    + +
    +

    go1.4.3 ▾

    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    文件名类型操作系统(OS)架构(Arch)大小SHA256 Checksum
    go1.4.3.src.tar.gzSource10MB486db10dc571a55c8d795365070f66d343458c48
    go1.4.3.darwin-amd64.tar.gzArchivemacOSx86-6458MB945666c36b42bf859d98775c4f02f807a5bdb6b0
    go1.4.3.darwin-amd64.pkgInstallermacOSx86-6458MB3d91a21e3217370b80ca26e89a994e8199d583e7
    go1.4.3.freebsd-amd64.tar.gzArchiveFreeBSDx86-6457MB573217c097f78143ea7c54212445c31944750144
    go1.4.3.linux-386.tar.gzArchiveLinuxx8648MB405777725abe566989cdb436d2efeb2667be670f
    go1.4.3.linux-amd64.tar.gzArchiveLinuxx86-6458MB332b64236d30a8805fc8dd8b3a269915b4c507fe
    go1.4.3.windows-386.zipArchiveWindowsx8650MB77ec9b61c1e1bf475463c62c36c395ba9d69aa9e
    go1.4.3.windows-386.msiInstallerWindowsx8642MBcad793895b258929ee796ef9ea77855626740ecd
    go1.4.3.windows-amd64.zipArchiveWindowsx86-6460MB821a6773adadd7409380addc4791771f2b057fa0
    go1.4.3.windows-amd64.msiInstallerWindowsx86-6450MB5e7c6cb012cbf09242b040b84b78b5e52d980337
    + +
    +
    + +
    + +
    +

    go1.4.2 ▾

    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    文件名类型操作系统(OS)架构(Arch)大小SHA256 Checksum
    go1.4.2.src.tar.gzSource460caac03379f746c473814a65223397e9c9a2f6
    go1.4.2.darwin-386-osx10.6.tar.gzArchiveOS X 10.6+x86fb3e6b30f4e1b1be47bbb98d79dd53da8dec24ec
    go1.4.2.darwin-386-osx10.8.tar.gzArchiveOS X 10.8+x8665f5610fdb38febd869aeffbd426c83b650bb408
    go1.4.2.darwin-386-osx10.6.pkgInstallerOS X 10.6+x863ed569ce33616d5d36f963e5d7cefb55727c8621
    go1.4.2.darwin-386-osx10.8.pkgInstallerOS X 10.8+x867f3fb2438fa0212febef13749d8d144934bb1c80
    go1.4.2.darwin-amd64-osx10.6.tar.gzArchiveOS X 10.6+x86-6400c3f9a03daff818b2132ac31d57f054925c60e7
    go1.4.2.darwin-amd64-osx10.8.tar.gzArchiveOS X 10.8+x86-6458a04b3eb9853c75319d9076df6f3ac8b7430f7f
    go1.4.2.darwin-amd64-osx10.6.pkgInstallerOS X 10.6+x86-643fa5455e211a70c0a920abd53cb3093269c5149c
    go1.4.2.darwin-amd64-osx10.8.pkgInstallerOS X 10.8+x86-648fde619d48864cb1c77ddc2a1aec0b7b20406b38
    go1.4.2.linux-386.tar.gzArchiveLinuxx8650557248e89b6e38d395fda93b2f96b2b860a26a
    go1.4.2.linux-amd64.tar.gzArchiveLinuxx86-645020af94b52b65cc9b6f11d50a67e4bae07b0aff
    go1.4.2.windows-386.zipArchiveWindowsx860e074e66a7816561d7947ff5c3514be96f347dc4
    go1.4.2.windows-386.msiInstallerWindowsx86e8bd3d87cb52441b2c9aee7c2c5f5ce7ffccc832
    go1.4.2.windows-amd64.zipArchiveWindowsx86-6491b229a3ff0a1ce6e791c832b0b4670bfc5457b5
    go1.4.2.windows-amd64.msiInstallerWindowsx86-64a914f3dad5521a8f658dce3e1575f3b6792975f0
    + +
    +
    + +
    + +
    +

    go1.4.1 ▾

    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    文件名类型操作系统(OS)架构(Arch)大小SHA256 Checksum
    go1.4.1.src.tar.gzSourcec7a683e8d39b835e333199d68d0c0baefcd24a68
    go1.4.1.darwin-386-osx10.6.tar.gzArchiveOS X 10.6+x86c6336247f0f2e734be7d59cb13e9517abe2e75ca
    go1.4.1.darwin-386-osx10.8.tar.gzArchiveOS X 10.8+x867b1b94a120738565a740f56d0bd4771e841ef4e8
    go1.4.1.darwin-386-osx10.6.pkgInstallerOS X 10.6+x864632cbf1b65d104f59b463ba4a587a701d56e36b
    go1.4.1.darwin-386-osx10.8.pkgInstallerOS X 10.8+x86664c143a983d4d3f6db4037590dcf77de16cb5b8
    go1.4.1.darwin-amd64-osx10.6.tar.gzArchiveOS X 10.6+x86-64aba30d6ef5cacc9cb508cff12cc54bc843b4e5de
    go1.4.1.darwin-amd64-osx10.8.tar.gzArchiveOS X 10.8+x86-6495d0ff29347e44c80a4545b84ca4eafcbfddcdb7
    go1.4.1.darwin-amd64-osx10.6.pkgInstallerOS X 10.6+x86-64efffecb7a660319dde78460eff64a16d5b1a365a
    go1.4.1.darwin-amd64-osx10.8.pkgInstallerOS X 10.8+x86-647854446cf2c5fe21910f03ba85e53ab8678d22cb
    go1.4.1.freebsd-386.tar.gzArchiveFreeBSDx86e1e98054a3c741e890d24744653e642410afac8f
    go1.4.1.freebsd-amd64.tar.gzArchiveFreeBSDx86-64ff05fa5255473a314b61f9ed6aa61c22e11ba606
    go1.4.1.linux-386.tar.gzArchiveLinuxx868d0d0fde13062373c70986ef0afd1c19d90d173a
    go1.4.1.linux-amd64.tar.gzArchiveLinuxx86-643e871200e13c0b059b14866d428910de0a4c51ed
    go1.4.1.windows-386.zipArchiveWindowsx865f1b6b8b29fddf5265217e0423b896551bbb85ab
    go1.4.1.windows-386.msiInstallerWindowsx8674e0eb60bb812edb1170f229f21cea27b93b621b
    go1.4.1.windows-amd64.zipArchiveWindowsx86-64a2cb84516e08c6a26323764af443786733e3132c
    go1.4.1.windows-amd64.msiInstallerWindowsx86-64295e8b9f81be161a5f73ed6aab2b894ec84632ef
    + +
    +
    + +
    + +
    +

    go1.4 ▾

    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    文件名类型操作系统(OS)架构(Arch)大小SHA256 Checksum
    go1.4.src.tar.gzSource6a7d9bd90550ae1e164d7803b3e945dc8309252b
    go1.4.darwin-386-osx10.6.tar.gzArchiveOS X 10.6+x86ee31cd0e26245d0e48f11667e4298e2e7f54f9b6
    go1.4.darwin-386-osx10.8.tar.gzArchiveOS X 10.8+x864d2ae2f5c0216c44e432c6044b1e1f0aea99f712
    go1.4.darwin-386-osx10.6.pkgInstallerOS X 10.6+x8605f2a1ab9d2aaae06c968fbdf1a6a9c28d380ceb
    go1.4.darwin-386-osx10.8.pkgInstallerOS X 10.8+x8681534c4eec80729b81b8e5f5889dfc2a3ba37131
    go1.4.darwin-amd64-osx10.6.tar.gzArchiveOS X 10.6+x86-6409621b9226abe12c2179778b015a33c1787b29d6
    go1.4.darwin-amd64-osx10.8.tar.gzArchiveOS X 10.8+x86-6428b2b731f86ada85246969e8ffc77d50542cdcb5
    go1.4.darwin-amd64-osx10.6.pkgInstallerOS X 10.6+x86-6429271b54d3ce7108270a9b7b64342950026704bf
    go1.4.darwin-amd64-osx10.8.pkgInstallerOS X 10.8+x86-642043aaf5c1363e483c6042f8685acd70ec9e41f8
    go1.4.freebsd-386.tar.gzArchiveFreeBSDx8636c5cc2ebef4b4404b12f2b5f2dfd23d73ecdbcc
    go1.4.freebsd-amd64.tar.gzArchiveFreeBSDx86-649441745b9c61002feedee8f0016c082b56319e44
    go1.4.linux-386.tar.gzArchiveLinuxx86cb18d8122bfd3bbba20fa1a19b8f7566dcff795d
    go1.4.linux-amd64.tar.gzArchiveLinuxx86-64cd82abcb0734f82f7cf2d576c9528cebdafac4c6
    go1.4.windows-386.zipArchiveWindowsx86f44240a1750dd051476ae78e9ad0502bc5c7661d
    go1.4.windows-386.msiInstallerWindowsx86b26151702cba760d6eec94214c457bee01f6d859
    go1.4.windows-amd64.zipArchiveWindowsx86-6444f103d558b293919eb680041625c262dd00eb9a
    go1.4.windows-amd64.msiInstallerWindowsx86-64359124f2bba4c59df1eb81d11e16e388d0a996f9
    + +
    +
    + +
    + +
    +

    go1.3.3 ▾

    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    文件名类型操作系统(OS)架构(Arch)大小SHA256 Checksum
    go1.3.3.src.tar.gzSourceb54b7deb7b7afe9f5d9a3f5dd830c7dede35393a
    go1.3.3.darwin-386-osx10.6.tar.gzArchiveOS X 10.6+x8604b3e38549183e984f509c07ad40d8bcd577a702
    go1.3.3.darwin-386-osx10.8.tar.gzArchiveOS X 10.8+x8688f35d3327a84107aac4f2f24cb0883e5fdbe0e5
    go1.3.3.darwin-386-osx10.6.pkgInstallerOS X 10.6+x8649756b700670ae4109e555f2e5f9bedbaa3c50da
    go1.3.3.darwin-386-osx10.8.pkgInstallerOS X 10.8+x86a89b570a326e5f8c9509f40be9fa90e54b3bf7a7
    go1.3.3.darwin-amd64-osx10.6.tar.gzArchiveOS X 10.6+x86-64dfe68de684f6e8d9c371d01e6d6a522efe3b8942
    go1.3.3.darwin-amd64-osx10.8.tar.gzArchiveOS X 10.8+x86-64be686ec7ba68d588735cc2094ccab8bdd651de9e
    go1.3.3.darwin-amd64-osx10.6.pkgInstallerOS X 10.6+x86-649aec7e9eff11100a6db026d1b423d1250925e4c4
    go1.3.3.darwin-amd64-osx10.8.pkgInstallerOS X 10.8+x86-646435e50059fe7fa0d60f1b15aab7f255a61816ce
    go1.3.3.freebsd-386.tar.gzArchiveFreeBSDx86875a5515dd7d3e5826c7c003bb2450f3129ccbad
    go1.3.3.freebsd-amd64.tar.gzArchiveFreeBSDx86-648531ae5e745c887f8dad1a3f00ca873cfcace56e
    go1.3.3.linux-386.tar.gzArchiveLinuxx869eb426d5505de55729e2656c03d85722795dd85e
    go1.3.3.linux-amd64.tar.gzArchiveLinuxx86-6414068fbe349db34b838853a7878621bbd2b24646
    go1.3.3.windows-386.zipArchiveWindowsx86ba99083b22e0b22b560bb2d28b9b99b405d01b6b
    go1.3.3.windows-386.msiInstallerWindowsx866017a0e1667a5a41109f527b405bf6e0c83580f5
    go1.3.3.windows-amd64.zipArchiveWindowsx86-645f0b3b104d3db09edd32ef1d086ba20bafe01ada
    go1.3.3.windows-amd64.msiInstallerWindowsx86-6425112a8c4df93dc4009e65eff00bc4ef76f94e46
    + +
    +
    + +
    + +
    +

    go1.3.2 ▾

    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    文件名类型操作系统(OS)架构(Arch)大小SHA256 Checksum
    go1.3.2.src.tar.gzSource67d3a692588c259f9fe9dca5b80109e5b99271df
    go1.3.2.darwin-386-osx10.6.tar.gzArchiveOS X 10.6+x86d1652f6e0ed3063b7b43d2bc12981d927bc85deb
    go1.3.2.darwin-386-osx10.8.tar.gzArchiveOS X 10.8+x86d040c85698c749fdbe25e8568c4d71648a5e3a75
    go1.3.2.darwin-386-osx10.6.pkgInstallerOS X 10.6+x86d20375615cf8e36e3c9a9b6ddeef16eff7a4ea89
    go1.3.2.darwin-386-osx10.8.pkgInstallerOS X 10.8+x86f11930cfb032d39ab445f342742865c93c60ec14
    go1.3.2.darwin-amd64-osx10.6.tar.gzArchiveOS X 10.6+x86-6436ca7e8ac9af12e70b1e01182c7ffc732ff3b876
    go1.3.2.darwin-amd64-osx10.8.tar.gzArchiveOS X 10.8+x86-64323bf8088614d58fee2b4d2cb07d837063d7d77e
    go1.3.2.darwin-amd64-osx10.6.pkgInstallerOS X 10.6+x86-64e1529241fcef643e5f752c37dc4c86911df91338
    go1.3.2.darwin-amd64-osx10.8.pkgInstallerOS X 10.8+x86-64fd8637658fcb133423e794c44029ce3476b48e0c
    go1.3.2.freebsd-386.tar.gzArchiveFreeBSDx86fea3ef264120b5c3b4c50a8929d56f47a8366503
    go1.3.2.freebsd-amd64.tar.gzArchiveFreeBSDx86-6495b633f45156fbbe79076638f854e76b9cd01301
    go1.3.2.linux-386.tar.gzArchiveLinuxx863cbfd62d401a6ca70779856fa8ad8c4d6c35c8cc
    go1.3.2.linux-amd64.tar.gzArchiveLinuxx86-640e4b6120eee6d45e2e4374dac4fe7607df4cbe42
    go1.3.2.windows-386.zipArchiveWindowsx8686160c478436253f51241ac1905577d337577ce0
    go1.3.2.windows-386.msiInstallerWindowsx86589c35f9ad3506c92aa944130f6a950ce9ee558b
    go1.3.2.windows-amd64.zipArchiveWindowsx86-647f7147484b1bc9e52cf034de816146977d0137f6
    go1.3.2.windows-amd64.msiInstallerWindowsx86-64a697fff05cbd4a4d902f6c33f7c42588bcc474bc
    + +
    +
    + +
    + +
    +

    go1.3.1 ▾

    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    文件名类型操作系统(OS)架构(Arch)大小SHA256 Checksum
    go1.3.1.src.tar.gzSourcebc296c9c305bacfbd7bff9e1b54f6f66ae421e6e
    go1.3.1.darwin-386-osx10.6.tar.gzArchiveOS X 10.6+x8684f70a4c83be24cea696654a5b55331ea32f8a3f
    go1.3.1.darwin-386-osx10.8.tar.gzArchiveOS X 10.8+x86244dfba1f4239b8e2eb9c3abae5ad63fc32c807a
    go1.3.1.darwin-386-osx10.6.pkgInstallerOS X 10.6+x8616e0df7b90d49c8499f71a551af8b595e2faa961
    go1.3.1.darwin-386-osx10.8.pkgInstallerOS X 10.8+x8613296cd9a980819bf2304d7d24a38a1b39719c13
    go1.3.1.darwin-amd64-osx10.6.tar.gzArchiveOS X 10.6+x86-6440716361d352c4b40252e79048e8bc084c3f3d1b
    go1.3.1.darwin-amd64-osx10.8.tar.gzArchiveOS X 10.8+x86-64a7271cbdc25173d0f8da66549258ff65cca4bf06
    go1.3.1.darwin-amd64-osx10.6.pkgInstallerOS X 10.6+x86-6449bf5f14d2683fb99161fcb7025af60ec2d3691f
    go1.3.1.darwin-amd64-osx10.8.pkgInstallerOS X 10.8+x86-645d4728e0b3c3fd9fc657cc192c6b9fb3f837823b
    go1.3.1.freebsd-386.tar.gzArchiveFreeBSDx86586debe95542b3b56841f6bd2e5257e301a1ffdc
    go1.3.1.freebsd-amd64.tar.gzArchiveFreeBSDx86-6499e23fdd33860d837912e8647ed2a4b3d2b09d3c
    go1.3.1.linux-386.tar.gzArchiveLinuxx8636f87ce21cdb4cb8920bb706003d8655b4e1fc81
    go1.3.1.linux-amd64.tar.gzArchiveLinuxx86-643af011cc19b21c7180f2604fd85fbc4ddde97143
    go1.3.1.windows-386.zipArchiveWindowsx8664f99e40e79e93a622e73d7d55a5b8340f07747f
    go1.3.1.windows-386.msiInstallerWindowsx86df37e307c52fbea02070e23ae0a49cb869d54f33
    go1.3.1.windows-amd64.zipArchiveWindowsx86-644548785cfa3bc228d18d2d06e39f58f0e4e014f1
    go1.3.1.windows-amd64.msiInstallerWindowsx86-6488c5d9a51a74c2846226a08681fc28cd3469cba0
    + +
    +
    + +
    + +
    +

    go1.3 ▾

    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    文件名类型操作系统(OS)架构(Arch)大小SHA256 Checksum
    go1.3.src.tar.gzSource9f9dfcbcb4fa126b2b66c0830dc733215f2f056e
    go1.3.darwin-386-osx10.6.tar.gzArchiveOS X 10.6+x86159d2797bee603a80b829c4404c1fb2ee089cc00
    go1.3.darwin-386-osx10.8.tar.gzArchiveOS X 10.8+x86bade975462b5610781f6a9fe8ac13031b3fb7aa6
    go1.3.darwin-386-osx10.6.pkgInstallerOS X 10.6+x8607e7142540558f432a8750eb6cb25d6b06ed80bb
    go1.3.darwin-386-osx10.8.pkgInstallerOS X 10.8+x86c908ecdb177c8a20abd61272c260b15e513f6e73
    go1.3.darwin-amd64-osx10.6.tar.gzArchiveOS X 10.6+x86-6482ffcfb7962ca7114a1ee0a96cac51c53061ea05
    go1.3.darwin-amd64-osx10.8.tar.gzArchiveOS X 10.8+x86-648d768f10cd00e0b152490291d9cd6179a8ccf0a7
    go1.3.darwin-amd64-osx10.6.pkgInstallerOS X 10.6+x86-64631d6867d7f4b92b314fd87115e1cefadeeac2ab
    go1.3.darwin-amd64-osx10.8.pkgInstallerOS X 10.8+x86-644e8f2cafa23797211fd13f3fa4893ce3d5f084c4
    go1.3.freebsd-386.tar.gzArchiveFreeBSDx868afa9574140cdd5fc97883a06a11af766e7f0203
    go1.3.freebsd-amd64.tar.gzArchiveFreeBSDx86-6471214bafabe2b5f52ee68afce96110031b446f0c
    go1.3.linux-386.tar.gzArchiveLinuxx8622db33b0c4e242ed18a77b03a60582f8014fd8a6
    go1.3.linux-amd64.tar.gzArchiveLinuxx86-64b6b154933039987056ac307e20c25fa508a06ba6
    go1.3.windows-386.zipArchiveWindowsx86e4e5279ce7d8cafdf210a522a70677d5b9c7589d
    go1.3.windows-386.msiInstallerWindowsx86d457a86ce6701bb96608e4c33778b8471c48a764
    go1.3.windows-amd64.zipArchiveWindowsx86-641e4888e1494aed7f6934acb5c4a1ffb0e9a022b1
    go1.3.windows-amd64.msiInstallerWindowsx86-64e81a0e4f551722c7682f912e0485ad20a287f2ef
    + +
    +
    + +
    + +
    +

    go1.2.2 ▾

    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    文件名类型操作系统(OS)架构(Arch)大小SHA256 Checksum
    go1.2.2.src.tar.gzSource3ce0ac4db434fc1546fec074841ff40dc48c1167
    go1.2.2.darwin-386-osx10.6.tar.gzArchiveOS X 10.6+x86360ec6cbfdec9257de029f918a881b9944718d7c
    go1.2.2.darwin-386-osx10.8.tar.gzArchiveOS X 10.8+x864219b464e82e7c23d9dc02c193e7a0a28a09af1a
    go1.2.2.darwin-386-osx10.6.pkgInstallerOS X 10.6+x86dff27e94c8ff25301cd958b0b1b629e97ea21f03
    go1.2.2.darwin-386-osx10.8.pkgInstallerOS X 10.8+x86f1fb44aa22cba3e81dc33f88393a54e49eae0d8b
    go1.2.2.darwin-amd64-osx10.6.tar.gzArchiveOS X 10.6+x86-6424c182718fd61b2621692dcdfc34937a6b5ee369
    go1.2.2.darwin-amd64-osx10.8.tar.gzArchiveOS X 10.8+x86-6419be1eca8fc01b32bb6588a70773b84cdce6bed1
    go1.2.2.darwin-amd64-osx10.6.pkgInstallerOS X 10.6+x86-642d4b49f1105a78e1ea31d7f9ea0b43909cc209be
    go1.2.2.darwin-amd64-osx10.8.pkgInstallerOS X 10.8+x86-645d78f2a3fe82b01fe5dfcb267e703e754274b253
    go1.2.2.freebsd-386.tar.gzArchiveFreeBSDx86d226b8e1c3f75d31fa426df63aa776d7e08cddac
    go1.2.2.freebsd-amd64.tar.gzArchiveFreeBSDx86-64858744ab8ff9661d42940486af63d451853914a0
    go1.2.2.linux-386.tar.gzArchiveLinuxx86d16f892173b0589945d141cefb22adce57e3be9c
    go1.2.2.linux-amd64.tar.gzArchiveLinuxx86-646bd151ca49c435462c8bf019477a6244b958ebb5
    go1.2.2.windows-386.zipArchiveWindowsx86560bb33ec70ab733f31ff15f1a48fe35963983b9
    go1.2.2.windows-386.msiInstallerWindowsx8660b91a7bf68596b23978acb109d1ff8668b7d18f
    go1.2.2.windows-amd64.zipArchiveWindowsx86-649ee22fe6c4d98124d582046aab465ab69eaab048
    go1.2.2.windows-amd64.msiInstallerWindowsx86-64c8f5629bc8d91b161840b4a05a3043c6e5fa310b
    + +
    +
    + +
    + +
    +

    go1 ▾

    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    文件名类型操作系统(OS)架构(Arch)大小SHA256 Checksum
    go1.4-bootstrap-20170518.tar.gzArchive4bootstrap11MBc17d5ef6d49ae448f61f9ae812f0750f49e405a193667b4cd330ca594b65fc3a
    go1.4-bootstrap-20170531.tar.gzArchive4bootstrap11MB49f806f66762077861b7de7081f586995940772d29d4c45068c134441a743fa2
    + +
    +
    + +
    +
    + +
    + +
    +
    +{{end}} + +{{define "css"}} + + +{{end}} + +{{define "js"}} + +{{end}} \ No newline at end of file From d017c2025b77bf403c6a3c5e096c63ff71761c78 Mon Sep 17 00:00:00 2001 From: xuxinhua Date: Sun, 20 Aug 2017 13:07:51 +0800 Subject: [PATCH 062/411] =?UTF-8?q?=E4=B8=8B=E8=BD=BD=E8=8F=9C=E5=8D=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/http/controller/download.go | 2 +- template/articles/detail.html | 2 +- template/common/layout.html | 11 +++++++---- 3 files changed, 9 insertions(+), 6 deletions(-) diff --git a/src/http/controller/download.go b/src/http/controller/download.go index 2fb86cd1..07f28b4f 100644 --- a/src/http/controller/download.go +++ b/src/http/controller/download.go @@ -30,7 +30,7 @@ func (self DownloadController) RegisterRoute(g *echo.Group) { func (DownloadController) GoDl(ctx echo.Context) error { data := map[string]interface{}{ - "activeBooks": "active", + "activeDl": "active", } return render(ctx, "download/go.html", data) diff --git a/template/articles/detail.html b/template/articles/detail.html index d25dbed9..41e8c32b 100644 --- a/template/articles/detail.html +++ b/template/articles/detail.html @@ -14,7 +14,7 @@
    {{if .article.IsSelf}} diff --git a/template/common/layout.html b/template/common/layout.html index 7a3d44f6..e25e4b71 100644 --- a/template/common/layout.html +++ b/template/common/layout.html @@ -50,27 +50,30 @@ 文章
  • - 开源项目 + 项目
  • 资源
  • - 图书 + 图书
  • +
  • + 下载 +
  • -
    @@ -415,6 +574,323 @@

    历史版本归档▹

    历史版本归档▾

    +
    + +
    +

    go1.9 ▾

    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    文件名类型操作系统(OS)架构(Arch)大小SHA256 Checksum
    go1.9.src.tar.gzSource16MBa4ab229028ed167ba1986825751463605264e44868362ca8e7accc8be057e993
    go1.9.darwin-amd64.tar.gzArchivemacOSx86-6498MBc2df361ec6c26fcf20d5569496182cb20728caa4d351bc430b2f0f1212cca3e0
    go1.9.darwin-amd64.pkgInstallermacOSx86-6497MB2197814c83fc04569f5fabf030f835c95e48562afc48cbc96264665dc552f7a1
    go1.9.linux-386.tar.gzArchiveLinuxx8686MB7cccff99dacf59162cd67f5b11070d667691397fd421b0a9ad287da019debc4f
    go1.9.linux-amd64.tar.gzArchiveLinuxx86-6498MBd70eadefce8e160638a9a6db97f7192d8463069ab33138893ad3bf31b0650a79
    go1.9.linux-armv6l.tar.gzArchiveLinuxARMv685MBf52ca5933f7a8de2daf7a3172b0406353622c6a39e67dd08bbbeb84c6496f487
    go1.9.windows-386.zipArchiveWindowsx8692MBecfe6f5be56acedc56cd9ff735f239a12a7c94f40b0ea9753bbfd17396f5e4b9
    go1.9.windows-386.msiInstallerWindowsx8679MB1db7a0bcdfcc78f816cf4f83df9edfc31ee9a3b3bc40ee751e193d92ee44cf31
    go1.9.windows-amd64.zipArchiveWindowsx86-64104MB874b144b994643cff1d3f5875369d65c01c216bb23b8edddf608facc43966c8b
    go1.9.windows-amd64.msiInstallerWindowsx86-6490MB955c91d353b9a3ca2e41a1d980850141996501b3118ab09d049a2bb267103c2b
    Other Ports
    go1.9.freebsd-386.tar.gzArchiveFreeBSDx8686MB9e415e340eaea526170b0fd59aa55939ff4f76c126193002971e8c6799e2ed3a
    go1.9.freebsd-amd64.tar.gzArchiveFreeBSDx86-6498MBba54efb2223fb4145604dcaf8605d519467f418ab02c081d3cd0632b6b43b6e7
    go1.9.linux-arm64.tar.gzArchiveLinuxARMv884MB0958dcf454f7f26d7acc1a4ddc34220d499df845bc2051c14ff8efdf1e3c29a6
    go1.9.linux-ppc64le.tar.gzArchiveLinuxppc64le84MB10b66dae326b32a56d4c295747df564616ec46ed0079553e88e39d4f1b2ae985
    go1.9.linux-s390x.tar.gzArchiveLinuxs390x83MBe06231e4918528e2eba1d3cff9bc4310b777971e5d8985f9772c6018694a3af8
    + +
    +
    + +
    + +
    +

    go1.8.3 ▾

    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    文件名类型操作系统(OS)架构(Arch)大小SHA256 Checksum
    go1.8.3.src.tar.gzSource15MB5f5dea2447e7dcfdc50fa6b94c512e58bfba5673c039259fd843f68829d99fa6
    go1.8.3.darwin-amd64.tar.gzArchivemacOSx86-6486MBf20b92bc7d4ab22aa18270087c478a74463bd64a893a94264434a38a4b167c05
    go1.8.3.darwin-amd64.pkgInstallermacOSx86-6485MBf81c8911dc76cd2b4ddd3d7ea845fe7ed83abd493b382fff216e1a8f637b5e7f
    go1.8.3.freebsd-386.tar.gzArchiveFreeBSDx8674MBd301cc7c2b8b0ccb384ac564531beee8220727fd27ca190b92031a2e3e230224
    go1.8.3.freebsd-amd64.tar.gzArchiveFreeBSDx86-6486MB1bf5f076d48609012fe01b95e2a58e71e56719a04d576fe3484a216ad4b9c495
    go1.8.3.linux-386.tar.gzArchiveLinuxx8674MBff4895eb68fb1daaec41c540602e8bb4c1e8bb2f0e7017367171913fc9995ed2
    go1.8.3.linux-amd64.tar.gzArchiveLinuxx86-6486MB1862f4c3d3907e59b04a757cfda0ea7aa9ef39274af99a784f5be843c80c6772
    go1.8.3.linux-armv6l.tar.gzArchiveLinuxARMv674MB3c30a3e24736ca776fc6314e5092fb8584bd3a4a2c2fa7307ae779ba2735e668
    go1.8.3.linux-ppc64le.tar.gzArchiveLinuxppc64le73MBe5fb00adfc7291e657f1f3d31c09e74890b5328e6f991a3f395ca72a8c4dc0b3
    go1.8.3.linux-s390x.tar.gzArchiveLinuxs390x72MBe2ec3e7c293701b57ca1f32b37977ac9968f57b3df034f2cc2d531e80671e6c8
    go1.8.3.windows-386.zipArchiveWindowsx8680MB9e2bfcb8110a3c56f23b91f859963269bc29fd114190fecfd0a539395272a1c7
    go1.8.3.windows-386.msiInstallerWindowsx8667MBc1df97e6f9afc2db1705f0f1d04fa31804d5c9b995cca26680881baaa1543eb4
    go1.8.3.windows-amd64.zipArchiveWindowsx86-6492MBde026caef4c5b4a74f359737dcb2d14c67ca45c45093755d3b0d2e0ee3aafd96
    go1.8.3.windows-amd64.msiInstallerWindowsx86-6478MB35734d9331fe4ee19725213d8e98840660460fd1b90518fffc79c0f856a3586a
    + +
    +
    +
    - -{{end}} -{{define "css"}} - - {{end}} {{define "js"}} - + - -{{if .pos_ad.banner}} - {{if eq .pos_ad.banner.AdType 1}} - {{noescape .pos_ad.banner.Code}} - {{end}} -{{end}} - -{{end}} diff --git a/template/projects/list.html b/template/projects/list.html index 68c704f4..6711188e 100644 --- a/template/projects/list.html +++ b/template/projects/list.html @@ -63,12 +63,15 @@

    + + {{include "common/my_info.html" .}} + {{include "sidebar/article.html" .}} {{if .pos_ad.right1}} diff --git a/template/resources/index.html b/template/resources/index.html index 5cc4633c..464a467d 100644 --- a/template/resources/index.html +++ b/template/resources/index.html @@ -68,6 +68,14 @@ {{include "sidebar/topic.html" .}} {{include "sidebar/view_rank.html" (parseJSON `{"rank_title":"一周阅读排行","objtype":2,"limit":10,"rank_type":"week"}`)}} + + {{if .pos_ad.right2}} + + {{end}}
    diff --git a/template/topics/common_list.html b/template/topics/common_list.html index d22d215d..5b71950d 100644 --- a/template/topics/common_list.html +++ b/template/topics/common_list.html @@ -1,6 +1,6 @@
    - {{range .topics}} + {{range $i, $topic := .topics}} {{if or ($.node) (and (not $.node) .node.ShowIndex)}}
    @@ -38,6 +38,15 @@
    + {{if eq $i 4}} + {{if $.pos_ad.banner}} +
    + {{if eq $.pos_ad.banner.AdType 0}} + {{noescape $.pos_ad.banner.Code}} + {{end}} +
    + {{end}} + {{end}} {{end}} {{else}}

    暂时没有任何主题

    diff --git a/template/topics/list.html b/template/topics/list.html index 0b6d9170..a7003585 100644 --- a/template/topics/list.html +++ b/template/topics/list.html @@ -56,6 +56,14 @@ {{include "sidebar/view_rank.html" (parseJSON `{"rank_title":"一周阅读排行","objtype":0,"limit":10,"rank_type":"week"}`)}} + {{if .pos_ad.right2}} + + {{end}} + {{include "sidebar/stat.html" .}} diff --git a/template/wiki/content.html b/template/wiki/content.html index 4d93a636..ff6116d7 100644 --- a/template/wiki/content.html +++ b/template/wiki/content.html @@ -61,6 +61,14 @@

    本页贡献者:
    {{end}} + {{if .pos_ad.right2}} + + {{end}} + {{end}} diff --git a/template/wiki/list.html b/template/wiki/list.html index f60091c5..55ba7937 100644 --- a/template/wiki/list.html +++ b/template/wiki/list.html @@ -45,31 +45,10 @@

    -
    + {{include "common/my_info.html" .}} + + {{include "sidebar/article.html" .}} + {{include "sidebar/topic.html" .}}
    @@ -80,8 +59,7 @@

    // 需要加载的侧边栏 SG.SIDE_BARS = [ "/topics/recent", - "/resources/recent", - "/comments/recent", + "/articles/recent", ]; {{end}} \ No newline at end of file From 37101a48569bc43c98c360d7145fc3ee9df7c746 Mon Sep 17 00:00:00 2001 From: xuxinhua Date: Sat, 21 Oct 2017 22:02:58 +0800 Subject: [PATCH 114/411] =?UTF-8?q?=E4=B8=BB=E9=A2=98=E5=A2=9E=E5=8A=A0?= =?UTF-8?q?=E6=9D=83=E9=99=90=EF=BC=9A=E5=85=AC=E5=BC=80=E6=88=96=E7=99=BB?= =?UTF-8?q?=E5=BD=95=E5=8F=AF=E8=A7=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- config/db.sql | 1 + src/http/controller/account.go | 11 ++++++++--- src/logic/topic.go | 2 +- src/model/topic.go | 7 +++++++ template/topics/detail.html | 7 +++++++ template/topics/new.html | 12 +++++++++++- 6 files changed, 35 insertions(+), 5 deletions(-) diff --git a/config/db.sql b/config/db.sql index 7c8bb3ef..0cd1e1d4 100644 --- a/config/db.sql +++ b/config/db.sql @@ -35,6 +35,7 @@ CREATE TABLE IF NOT EXISTS `topics` ( `editor_uid` int unsigned NOT NULL DEFAULT 0 COMMENT '最后编辑人', `top` tinyint unsigned NOT NULL DEFAULT '0' COMMENT '置顶,0否,1置顶', `tags` varchar(63) NOT NULL DEFAULT '' COMMENT 'tag,逗号分隔', + `permission` tinyint unsigned NOT NULL DEFAULT 0 COMMENT '访问权限:0-公开;1-登录用户可见;2-关注的人可见', `ctime` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00', `mtime` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, PRIMARY KEY (`tid`), diff --git a/src/http/controller/account.go b/src/http/controller/account.go index f21c042e..f6227e60 100644 --- a/src/http/controller/account.go +++ b/src/http/controller/account.go @@ -212,7 +212,12 @@ func (AccountController) Login(ctx echo.Context) error { // 支持跳转到源页面 uri := ctx.FormValue("redirect_uri") if uri == "" { - uri = "/" + referer := ctx.Request().Referer() + if referer == "" { + uri = "/" + } else { + uri = referer + } } contentTpl := "login.html" @@ -411,8 +416,8 @@ func (AccountController) Logout(ctx echo.Context) error { session := GetCookieSession(ctx) session.Options = &sessions.Options{Path: "/", MaxAge: -1} session.Save(Request(ctx), ResponseWriter(ctx)) - // 重定向得到登录页(TODO:重定向到什么页面比较好?) - return ctx.Redirect(http.StatusSeeOther, "/account/login") + // 重定向得到原页面 + return ctx.Redirect(http.StatusSeeOther, ctx.Request().Referer()) } // Unbind 第三方账号解绑 diff --git a/src/logic/topic.go b/src/logic/topic.go index 14c8317e..7e2ec3c4 100644 --- a/src/logic/topic.go +++ b/src/logic/topic.go @@ -160,7 +160,7 @@ func (TopicLogic) Modify(ctx context.Context, user *model.Me, form url.Values) ( "editor_uid": user.Uid, } - fields := []string{"title", "content", "nid"} + fields := []string{"title", "content", "nid", "permission"} for _, field := range fields { change[field] = form.Get(field) } diff --git a/src/model/topic.go b/src/model/topic.go index da9ebc88..c6063aff 100644 --- a/src/model/topic.go +++ b/src/model/topic.go @@ -20,6 +20,12 @@ const ( AppendMaxNum = 3 ) +const ( + PermissionPublic = iota // 公开 + PermissionLogin // 登录可见 + PermissionFollow // 关注可见(暂未实现) +) + // 社区主题信息 type Topic struct { Tid int `xorm:"pk autoincr" json:"tid"` @@ -33,6 +39,7 @@ type Topic struct { EditorUid int `json:"editor_uid"` Top uint8 `json:"top"` Tags string `json:"tags"` + Permission int `json:"permission"` Ctime OftenTime `json:"ctime" xorm:"created"` Mtime OftenTime `json:"mtime" xorm:"<-"` diff --git a/template/topics/detail.html b/template/topics/detail.html index 4ab92e2a..2c91ae88 100644 --- a/template/topics/detail.html +++ b/template/topics/detail.html @@ -36,7 +36,11 @@

    这是一个创建于 的主题,其中的信息可能已经有所发展或是发生改变。
    {{end}}
    {{range $i, $append := .appends}}
    @@ -164,7 +168,10 @@

    // 文本框自动伸缩 $('.need-autogrow').autoGrow(); + // 有权限查看才加载评论 + {{if or (not .topic.permission) .me.Status}} loadComments(); + {{end}} // 链接,add target=_blank $('#wrapper .content').on('mousedown', 'a', function(evt){ diff --git a/template/topics/new.html b/template/topics/new.html index c6a1d67e..02fbea75 100644 --- a/template/topics/new.html +++ b/template/topics/new.html @@ -64,7 +64,7 @@

    -
    +
    最热节点  {{range .tab_list}} @@ -72,6 +72,16 @@ {{end}}
    + +
    + +
    + +
    +
    From c9659f7e1f6e4f5322496a64943077eaabd00944 Mon Sep 17 00:00:00 2001 From: xuxinhua Date: Sat, 21 Oct 2017 22:34:18 +0800 Subject: [PATCH 115/411] =?UTF-8?q?=E8=A7=A3=E5=86=B3=20windows=20?= =?UTF-8?q?=E5=90=AF=E5=8A=A8=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- start.bat | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/start.bat b/start.bat index 9eebdbbb..2487b232 100644 --- a/start.bat +++ b/start.bat @@ -8,7 +8,7 @@ goto end :ok -start /b bin\studygolang >> log\panic.log 2>&1 & +start /b bin\studygolang.exe >> log\panic.log 2>&1 & echo start successfully From 383c6df904e9a1425d9dda5b30a4c874588589cf Mon Sep 17 00:00:00 2001 From: xuxinhua Date: Sun, 22 Oct 2017 21:38:28 +0800 Subject: [PATCH 116/411] =?UTF-8?q?=E6=94=AF=E6=8C=81=E7=94=A8=E6=88=B7?= =?UTF-8?q?=E8=87=AA=E5=B7=B1=E7=BD=AE=E9=A1=B6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- config/db.sql | 2 +- src/http/controller/topic.go | 21 +++++++ src/logic/common.go | 5 +- src/logic/feed.go | 11 ++++ src/logic/observer.go | 27 +++++++++ src/logic/topic.go | 89 ++++++++++++++++++++++++++++ src/logic/user.go | 2 + src/model/mission.go | 2 + src/model/topic.go | 1 + src/model/user.go | 2 + src/model/user_rich.go | 1 + src/server/studygolang/background.go | 7 +++ template/admin/user/detail.html | 2 +- template/topics/detail.html | 18 ++++++ 14 files changed, 187 insertions(+), 3 deletions(-) diff --git a/config/db.sql b/config/db.sql index 0cd1e1d4..a42fcfef 100644 --- a/config/db.sql +++ b/config/db.sql @@ -34,6 +34,7 @@ CREATE TABLE IF NOT EXISTS `topics` ( `flag` tinyint NOT NULL DEFAULT 0 COMMENT '审核标识,0-未审核;1-已审核;2-审核删除;3-用户自己删除', `editor_uid` int unsigned NOT NULL DEFAULT 0 COMMENT '最后编辑人', `top` tinyint unsigned NOT NULL DEFAULT '0' COMMENT '置顶,0否,1置顶', + `top_time` int unsigned NOT NULL DEFAULT 0 COMMENT '置顶时间', `tags` varchar(63) NOT NULL DEFAULT '' COMMENT 'tag,逗号分隔', `permission` tinyint unsigned NOT NULL DEFAULT 0 COMMENT '访问权限:0-公开;1-登录用户可见;2-关注的人可见', `ctime` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00', @@ -616,7 +617,6 @@ CREATE TABLE `view_record` ( INDEX `idx_uid` (`uid`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT '用户浏览记录表'; - CREATE TABLE `gift` ( `id` int unsigned NOT NULL AUTO_INCREMENT, `name` varchar(63) NOT NULL DEFAULT '' COMMENT '物品名称', diff --git a/src/http/controller/topic.go b/src/http/controller/topic.go index d2857c33..734020ac 100644 --- a/src/http/controller/topic.go +++ b/src/http/controller/topic.go @@ -42,6 +42,8 @@ func (self TopicController) RegisterRoute(g *echo.Group) { g.Match([]string{"GET", "POST"}, "/topics/new", self.Create, middleware.NeedLogin(), middleware.Sensivite(), middleware.BalanceCheck(), middleware.PublishNotice()) g.Match([]string{"GET", "POST"}, "/topics/modify", self.Modify, middleware.NeedLogin(), middleware.Sensivite()) + g.POST("/topics/set_top", self.SetTop, middleware.NeedLogin()) + g.Match([]string{"GET", "POST"}, "/append/topic/:tid", self.Append, middleware.NeedLogin(), middleware.Sensivite(), middleware.BalanceCheck()) } @@ -311,3 +313,22 @@ func (TopicController) Nodes(ctx echo.Context) error { return render(ctx, "topics/nodes.html", data) } + +func (TopicController) SetTop(ctx echo.Context) error { + tid := goutils.MustInt(ctx.FormValue("tid")) + if tid == 0 { + return ctx.Redirect(http.StatusSeeOther, "/topics") + } + + me := ctx.Get("user").(*model.Me) + err := logic.DefaultTopic.SetTop(ctx, me, tid) + if err != nil { + if err == logic.NotFoundErr { + return ctx.Redirect(http.StatusSeeOther, "/topics") + } + + return fail(ctx, 1, "出错了:"+err.Error()) + } + + return success(ctx, nil) +} diff --git a/src/logic/common.go b/src/logic/common.go index 910d9e0b..a3fe0a02 100644 --- a/src/logic/common.go +++ b/src/logic/common.go @@ -26,7 +26,10 @@ func init() { schemaDecoder.IgnoreUnknownKeys(true) } -var NotModifyAuthorityErr = errors.New("没有修改权限") +var ( + NotModifyAuthorityErr = errors.New("没有修改权限") + NotFoundErr = errors.New("Not Found") +) func GetLogger(ctx context.Context) *logger.Logger { if ctx == nil { diff --git a/src/logic/feed.go b/src/logic/feed.go index 4a8aca06..adddf15e 100644 --- a/src/logic/feed.go +++ b/src/logic/feed.go @@ -15,6 +15,7 @@ import ( . "db" + "github.com/go-xorm/xorm" "github.com/polaris1119/set" ) @@ -107,6 +108,16 @@ func (FeedLogic) publish(object interface{}, objectExt interface{}) { go model.PublishFeed(object, objectExt) } +// setTop 置顶或取消置顶 +func (FeedLogic) setTop(session *xorm.Session, objid, objtype int, top int) error { + _, err := session.Table(new(model.Feed)).Where("objid=? AND objtype=?", objid, objtype). + Update(map[string]interface{}{ + "top": top, + }) + + return err +} + // updateComment 更新动态评论数据 func (FeedLogic) updateComment(objid, objtype, uid int, cmttime time.Time) { go func() { diff --git a/src/logic/observer.go b/src/logic/observer.go index 6c0a1414..b4f93f71 100644 --- a/src/logic/observer.go +++ b/src/logic/observer.go @@ -18,6 +18,7 @@ var ( commentObservable Observable ViewObservable Observable appendObservable Observable + topObservable Observable ) func init() { @@ -44,6 +45,11 @@ func init() { appendObservable.AddObserver(&UserWeightObserver{}) appendObservable.AddObserver(&TodayActiveObserver{}) appendObservable.AddObserver(&UserRichObserver{}) + + topObservable = NewConcreteObservable(actionTop) + topObservable.AddObserver(&UserWeightObserver{}) + topObservable.AddObserver(&TodayActiveObserver{}) + topObservable.AddObserver(&UserRichObserver{}) } type Observer interface { @@ -65,6 +71,7 @@ const ( actionComment = "comment" actionView = "view" actionAppend = "append" + actionTop = "top" // 置顶 ) type ConcreteObservable struct { @@ -123,6 +130,8 @@ func (this *UserWeightObserver) Update(action string, uid, objtype, objid int) { weight = 1 case actionAppend: weight = 15 + case actionTop: + weight = 5 } DefaultUser.IncrUserWeight("uid", uid, weight) @@ -144,6 +153,8 @@ func (*TodayActiveObserver) Update(action string, uid, objtype, objid int) { weight = 1 case actionAppend: weight = 15 + case actionTop: + weight = 5 } DefaultRank.GenDAURank(uid, weight) @@ -351,6 +362,22 @@ func (UserRichObserver) Update(action string, uid, objtype, objid int) { desc = fmt.Sprintf(`为主题 › %s 增加附言`, topic.Tid, topic.Title) + } else if action == actionTop { + typ = model.MissionTypeTop + award = -200 + + switch objtype { + case model.TypeTopic: + topic := DefaultTopic.findByTid(objid) + desc = fmt.Sprintf(`将主题 › %s 置顶`, + topic.Tid, + topic.Title) + case model.TypeArticle: + article, _ := DefaultArticle.FindById(nil, objid) + desc = fmt.Sprintf(`将文章 › %s 置顶`, + article.Id, + article.Title) + } } DefaultUserRich.IncrUserRich(user, typ, award, desc) diff --git a/src/logic/topic.go b/src/logic/topic.go index 7e2ec3c4..4d8423a4 100644 --- a/src/logic/topic.go +++ b/src/logic/topic.go @@ -87,6 +87,7 @@ func (self TopicLogic) Publish(ctx context.Context, me *model.Me, form url.Value session := MasterDB.NewSession() defer session.Close() + session.Begin() _, err = session.Insert(topic) if err != nil { @@ -209,6 +210,94 @@ func (self TopicLogic) Append(ctx context.Context, uid, tid int, content string) return nil } +// SetTop 置顶 +func (self TopicLogic) SetTop(ctx context.Context, me *model.Me, tid int) error { + objLog := GetLogger(ctx) + + if !me.IsAdmin { + topic := self.findByTid(tid) + if topic.Tid == 0 || topic.Uid != me.Uid { + return NotFoundErr + } + } + + session := MasterDB.NewSession() + defer session.Close() + session.Begin() + + _, err := session.Table(new(model.Topic)).Id(tid).Update(map[string]interface{}{ + "top": 1, + "top_time": time.Now().Unix(), + }) + if err != nil { + objLog.Errorln("TopicLogic SetTop error:", err) + session.Rollback() + return err + } + + err = DefaultFeed.setTop(session, tid, model.TypeTopic, 1) + if err != nil { + objLog.Errorln("TopicLogic SetTop feed error:", err) + session.Rollback() + return err + } + + session.Commit() + + go topObservable.NotifyObservers(me.Uid, model.TypeTopic, tid) + + return nil +} + +// UnsetTop 取消置顶 +func (self TopicLogic) UnsetTop(ctx context.Context, tid int) error { + objLog := GetLogger(ctx) + + session := MasterDB.NewSession() + defer session.Close() + session.Begin() + + _, err := session.Table(new(model.Topic)).Id(tid).Update(map[string]interface{}{ + "top": 0, + }) + if err != nil { + objLog.Errorln("TopicLogic UnsetTop error:", err) + session.Rollback() + return err + } + + err = DefaultFeed.setTop(session, tid, model.TypeTopic, 0) + if err != nil { + objLog.Errorln("TopicLogic UnsetTop feed error:", err) + session.Rollback() + return err + } + + session.Commit() + + return nil +} + +// AutoUnsetTop 自动取消置顶 +func (self TopicLogic) AutoUnsetTop() error { + topics := make([]*model.Topic, 0) + err := MasterDB.Where("top=1").Find(&topics) + if err != nil { + logger.Errorln("TopicLogic AutoUnsetTop error:", err) + return err + } + + for _, topic := range topics { + if topic.TopTime == 0 || topic.TopTime+86400 > time.Now().Unix() { + continue + } + + self.UnsetTop(nil, topic.Tid) + } + + return nil +} + // FindAll 支持多页翻看 func (self TopicLogic) FindAll(ctx context.Context, paginator *Paginator, orderBy string, querystring string, args ...interface{}) []map[string]interface{} { objLog := GetLogger(ctx) diff --git a/src/logic/user.go b/src/logic/user.go index e2a704ab..1aa3f48a 100644 --- a/src/logic/user.go +++ b/src/logic/user.go @@ -638,6 +638,8 @@ func (UserLogic) doCreateUser(ctx context.Context, session *xorm.Session, user * } user.Open = 0 + user.DauAuth = model.DefaultAuth + _, err := session.Insert(user) if err != nil { return err diff --git a/src/model/mission.go b/src/model/mission.go index 8e349001..bb18950e 100644 --- a/src/model/mission.go +++ b/src/model/mission.go @@ -25,6 +25,8 @@ const ( MissionTypeBook = 57 MissionTypeAppend = 60 + // 置顶 + MissionTypeTop = 61 MissionTypeModify = 65 // 被回复 diff --git a/src/model/topic.go b/src/model/topic.go index c6063aff..2aab85b3 100644 --- a/src/model/topic.go +++ b/src/model/topic.go @@ -38,6 +38,7 @@ type Topic struct { Lastreplytime OftenTime `json:"lastreplytime"` EditorUid int `json:"editor_uid"` Top uint8 `json:"top"` + TopTime int64 `json:"top_time"` Tags string `json:"tags"` Permission int `json:"permission"` Ctime OftenTime `json:"ctime" xorm:"created"` diff --git a/src/model/user.go b/src/model/user.go index 9a79281a..d125bf94 100644 --- a/src/model/user.go +++ b/src/model/user.go @@ -67,6 +67,8 @@ const ( TypeTop = 101 ) +const DefaultAuth = DauAuthTopic | DauAuthArticle | DauAuthResource | DauAuthProject | DauAuthComment + // 用户基本信息 type User struct { Uid int `json:"uid" xorm:"pk autoincr"` diff --git a/src/model/user_rich.go b/src/model/user_rich.go index 52b7220a..8853d09d 100644 --- a/src/model/user_rich.go +++ b/src/model/user_rich.go @@ -25,6 +25,7 @@ var BalanceTypeMap = map[int]string{ MissionTypeProject: "发布项目", MissionTypeBook: "分享图书", MissionTypeAppend: "增加附言", + MissionTypeTop: "置顶", MissionTypeModify: "修改", MissionTypeReplied: "回复收益", MissionTypeAward: "额外赠予", diff --git a/src/server/studygolang/background.go b/src/server/studygolang/background.go index ccdabb40..b5e73167 100644 --- a/src/server/studygolang/background.go +++ b/src/server/studygolang/background.go @@ -60,6 +60,9 @@ func ServeBackGround() { c.AddFunc("0 0 0 * * *", logic.DefaultEmail.EmailNotice) } + // 取消置顶 + c.AddFunc("0 * * * * *", unsetTop) + // 每天对活跃用户奖励铜币 c.AddFunc("@daily", logic.DefaultUserRich.AwardCooper) } @@ -141,3 +144,7 @@ func genViewRank() { logic.DefaultRank.GenMonthRank(objtype) } } + +func unsetTop() { + logic.DefaultTopic.AutoUnsetTop() +} diff --git a/template/admin/user/detail.html b/template/admin/user/detail.html index 2054c8a2..63ca12b1 100644 --- a/template/admin/user/detail.html +++ b/template/admin/user/detail.html @@ -22,7 +22,7 @@

    基本信息

    - {{.user.Name}} + {{.user.Username}}

    diff --git a/template/topics/detail.html b/template/topics/detail.html index 2c91ae88..c0c1d8d9 100644 --- a/template/topics/detail.html +++ b/template/topics/detail.html @@ -30,6 +30,9 @@

    {{else if and (eq .me.Uid .topic.user.Uid) (lt (len .appends) 3) }} 附言 {{end}} + {{if and (canPublish .me.DauAuth 101) (not .topic.top)}} + 置顶 + {{end}}

    {{if gt (distanceDay .topic.ctime) 100 }} @@ -178,6 +181,21 @@

    var url = $(this).attr('href'); $(this).attr('target', '_blank'); }); + + $('#set-top').on('click', function(evt) { + evt.preventDefault(); + + var url = $(this).attr('href'); + $.post(url, {}, function(result) { + if (result.ok) { + comTip("置顶成功!"); + } else { + comTip(result.msg); + } + }); + + return false; + }); }); From cceb8692d31bfb7938b1d1ea8c2f8c3b175fcbed Mon Sep 17 00:00:00 2001 From: xuxinhua Date: Sun, 22 Oct 2017 23:35:39 +0800 Subject: [PATCH 117/411] =?UTF-8?q?=E8=AE=B0=E5=BD=95=E6=90=9C=E7=B4=A2?= =?UTF-8?q?=E5=BC=95=E6=93=8E=E6=9D=A5=E6=BA=90=E5=92=8C=E5=A4=96=E9=93=BE?= =?UTF-8?q?=E6=9D=A5=E6=BA=90=E8=AE=BF=E9=97=AE=E6=AC=A1=E6=95=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- config/db.sql | 15 +++++++ src/http/controller/article.go | 1 + src/http/controller/book.go | 22 +++++++--- src/http/controller/project.go | 1 + src/http/controller/resource.go | 5 ++- src/http/controller/topic.go | 5 ++- src/logic/view.go | 3 ++ src/logic/view_source.go | 76 +++++++++++++++++++++++++++++++++ src/model/view_source.go | 20 +++++++++ template/articles/detail.html | 10 +---- template/books/detail.html | 2 + template/common/view_stat.html | 19 +++++++++ template/projects/detail.html | 10 +---- template/resources/detail.html | 10 +---- template/topics/detail.html | 10 +---- 15 files changed, 166 insertions(+), 43 deletions(-) create mode 100644 src/logic/view_source.go create mode 100644 src/model/view_source.go create mode 100644 template/common/view_stat.html diff --git a/config/db.sql b/config/db.sql index a42fcfef..a4259748 100644 --- a/config/db.sql +++ b/config/db.sql @@ -617,6 +617,21 @@ CREATE TABLE `view_record` ( INDEX `idx_uid` (`uid`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT '用户浏览记录表'; +CREATE TABLE `view_source` ( + `id` int(10) unsigned NOT NULL AUTO_INCREMENT, + `objid` int(10) unsigned NOT NULL COMMENT '对象id,属主', + `objtype` tinyint(3) unsigned NOT NULL DEFAULT '0' COMMENT '类型,0-帖子;1-博客;2-资源;3-wiki;4-项目;5-图书', + `google` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '来源谷歌数量', + `baidu` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '来源百度数量', + `bing` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '来源必应数量', + `sogou` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '来源搜狗数量', + `so` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '来源360数量', + `other` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '其他来源数量', + `updated_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '最后更新时间', + PRIMARY KEY (`id`), + UNIQUE KEY `uniq_obj` (`objid`,`objtype`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='浏览来源表'; + CREATE TABLE `gift` ( `id` int unsigned NOT NULL AUTO_INCREMENT, `name` varchar(63) NOT NULL DEFAULT '' COMMENT '物品名称', diff --git a/src/http/controller/article.go b/src/http/controller/article.go index ce30a4d2..12763620 100644 --- a/src/http/controller/article.go +++ b/src/http/controller/article.go @@ -140,6 +140,7 @@ func (ArticleController) Detail(ctx echo.Context) error { if me.IsRoot || (article.IsSelf && me.Uid == article.User.Uid) { data["view_user_num"] = logic.DefaultViewRecord.FindUserNum(ctx, article.Id, model.TypeArticle) + data["view_source"] = logic.DefaultViewSource.FindOne(ctx, article.Id, model.TypeArticle) } } else { logic.Views.Incr(Request(ctx), model.TypeArticle, article.Id) diff --git a/src/http/controller/book.go b/src/http/controller/book.go index 7e0a68f3..abd3c271 100644 --- a/src/http/controller/book.go +++ b/src/http/controller/book.go @@ -83,14 +83,26 @@ func (BookController) Detail(ctx echo.Context) error { return ctx.Redirect(http.StatusSeeOther, "/books") } - likeFlag := 0 - hadCollect := 0 + data := map[string]interface{}{ + "activeBooks": "active", + "book": book, + } + me, ok := ctx.Get("user").(*model.Me) if ok { - likeFlag = logic.DefaultLike.HadLike(ctx, me.Uid, book.Id, model.TypeBook) - hadCollect = logic.DefaultFavorite.HadFavorite(ctx, me.Uid, book.Id, model.TypeBook) + data["likeflag"] = logic.DefaultLike.HadLike(ctx, me.Uid, book.Id, model.TypeBook) + data["hadcollect"] = logic.DefaultFavorite.HadFavorite(ctx, me.Uid, book.Id, model.TypeBook) logic.Views.Incr(Request(ctx), model.TypeBook, book.Id, me.Uid) + + if me.Uid != book.Uid { + go logic.DefaultViewRecord.Record(book.Id, model.TypeBook, me.Uid) + } + + if me.IsRoot || me.Uid == book.Uid { + data["view_user_num"] = logic.DefaultViewRecord.FindUserNum(ctx, book.Id, model.TypeBook) + data["view_source"] = logic.DefaultViewSource.FindOne(ctx, book.Id, model.TypeBook) + } } else { logic.Views.Incr(Request(ctx), model.TypeBook, book.Id) } @@ -98,5 +110,5 @@ func (BookController) Detail(ctx echo.Context) error { // 为了阅读数即时看到 book.Viewnum++ - return render(ctx, "books/detail.html,common/comment.html", map[string]interface{}{"activeBooks": "active", "book": book, "likeflag": likeFlag, "hadcollect": hadCollect}) + return render(ctx, "books/detail.html,common/comment.html", data) } diff --git a/src/http/controller/project.go b/src/http/controller/project.go index 8aa5f11e..6bec53a2 100644 --- a/src/http/controller/project.go +++ b/src/http/controller/project.go @@ -159,6 +159,7 @@ func (ProjectController) Detail(ctx echo.Context) error { if me.IsRoot || me.Uid == project.User.Uid { data["view_user_num"] = logic.DefaultViewRecord.FindUserNum(ctx, project.Id, model.TypeProject) + data["view_source"] = logic.DefaultViewSource.FindOne(ctx, project.Id, model.TypeProject) } } else { logic.Views.Incr(Request(ctx), model.TypeProject, project.Id) diff --git a/src/http/controller/resource.go b/src/http/controller/resource.go index ba9571d9..4b3cd45f 100644 --- a/src/http/controller/resource.go +++ b/src/http/controller/resource.go @@ -81,8 +81,11 @@ func (ResourceController) Detail(ctx echo.Context) error { if me.Uid != resource["uid"].(int) { go logic.DefaultViewRecord.Record(id, model.TypeResource, me.Uid) - } else { + } + + if me.IsRoot || me.Uid == resource["uid"].(int) { data["view_user_num"] = logic.DefaultViewRecord.FindUserNum(ctx, id, model.TypeResource) + data["view_source"] = logic.DefaultViewSource.FindOne(ctx, id, model.TypeResource) } } else { logic.Views.Incr(Request(ctx), model.TypeResource, id) diff --git a/src/http/controller/topic.go b/src/http/controller/topic.go index 734020ac..4c2b6a46 100644 --- a/src/http/controller/topic.go +++ b/src/http/controller/topic.go @@ -165,8 +165,11 @@ func (TopicController) Detail(ctx echo.Context) error { if me.Uid != topic["uid"].(int) { go logic.DefaultViewRecord.Record(tid, model.TypeTopic, me.Uid) - } else { + } + + if me.IsRoot || me.Uid == topic["uid"].(int) { data["view_user_num"] = logic.DefaultViewRecord.FindUserNum(ctx, tid, model.TypeTopic) + data["view_source"] = logic.DefaultViewSource.FindOne(ctx, tid, model.TypeTopic) } } else { logic.Views.Incr(Request(ctx), model.TypeTopic, tid) diff --git a/src/logic/view.go b/src/logic/view.go index b17c3273..3536b15f 100644 --- a/src/logic/view.go +++ b/src/logic/view.go @@ -91,6 +91,9 @@ func (this *views) Incr(req *http.Request, objtype, objid int, uids ...int) { } } + // 记录浏览来源 + go DefaultViewSource.Record(req, objtype, objid) + key := strconv.Itoa(objtype) + strconv.Itoa(objid) var userKey string diff --git a/src/logic/view_source.go b/src/logic/view_source.go new file mode 100644 index 00000000..a37099d2 --- /dev/null +++ b/src/logic/view_source.go @@ -0,0 +1,76 @@ +// Copyright 2017 The StudyGolang Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. +// http://studygolang.com +// Author:polaris polaris@studygolang.com + +package logic + +import ( + "model" + "net/http" + "strings" + + . "db" + + "github.com/polaris1119/logger" + "golang.org/x/net/context" +) + +type ViewSourceLogic struct{} + +var DefaultViewSource = ViewSourceLogic{} + +// Record 记录浏览来源 +func (ViewSourceLogic) Record(req *http.Request, objtype, objid int) { + referer := req.Referer() + if referer == "" || strings.Contains(referer, WebsiteSetting.Domain) { + return + } + + viewSource := &model.ViewSource{} + _, err := MasterDB.Where("objid=? AND objtype=?", objid, objtype).Get(viewSource) + if err != nil { + logger.Errorln("ViewSourceLogic Record find error:", err) + return + } + + if viewSource.Id == 0 { + viewSource.Objid = objid + viewSource.Objtype = objtype + _, err = MasterDB.Insert(viewSource) + if err != nil { + logger.Errorln("ViewSourceLogic Record insert error:", err) + return + } + } + + field := "other" + referer = strings.ToLower(referer) + ses := []string{"google", "baidu", "bing", "sogou", "so"} + for _, se := range ses { + if strings.Contains(referer, se+".") { + field = se + break + } + } + + _, err = MasterDB.Id(viewSource.Id).Incr(field, 1).Update(new(model.ViewSource)) + if err != nil { + logger.Errorln("ViewSourceLogic Record update error:", err) + return + } +} + +// FindOne 获得浏览来源 +func (ViewSourceLogic) FindOne(ctx context.Context, objid, objtype int) *model.ViewSource { + objLog := GetLogger(ctx) + + viewSource := &model.ViewSource{} + _, err := MasterDB.Where("objid=? AND objtype=?", objid, objtype).Get(viewSource) + if err != nil { + objLog.Errorln("ViewSourceLogic FindOne error:", err) + } + + return viewSource +} diff --git a/src/model/view_source.go b/src/model/view_source.go new file mode 100644 index 00000000..b43b2806 --- /dev/null +++ b/src/model/view_source.go @@ -0,0 +1,20 @@ +// Copyright 2017 The StudyGolang Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. +// http://studygolang.com +// Author: polaris polaris@studygolang.com + +package model + +type ViewSource struct { + Id int `xorm:"pk autoincr"` + Objid int + Objtype int + Google int + Baidu int + Bing int + Sogou int + So int + Other int + UpdatedAt OftenTime `xorm:"<-"` +} diff --git a/template/articles/detail.html b/template/articles/detail.html index 3b64e588..9427ab04 100644 --- a/template/articles/detail.html +++ b/template/articles/detail.html @@ -107,15 +107,7 @@

    {{template "comment" .}} - {{if .view_user_num}} -
    -
    -
    统计信息
    -
    - 目前已有 {{.view_user_num}} 位注册会员查看了本文 -
    -
    - {{end}} + {{include "common/view_stat.html" .}}

    diff --git a/template/books/detail.html b/template/books/detail.html index d619d45a..9ffdcdf9 100644 --- a/template/books/detail.html +++ b/template/books/detail.html @@ -108,6 +108,8 @@

    目录

    {{template "comment" .}} + + {{include "common/view_stat.html" .}} diff --git a/template/common/view_stat.html b/template/common/view_stat.html new file mode 100644 index 00000000..d8487a49 --- /dev/null +++ b/template/common/view_stat.html @@ -0,0 +1,19 @@ +{{if .view_user_num}} +
    +
    +
    统计信息
    +
    + 目前已有 {{.view_user_num}} 位注册会员查看 +
    + {{if .view_source.Id}} +
      + {{if .view_source.Google}}
    • {{.view_source.Google}} 次来自 Google 点击
    • {{end}} + {{if .view_source.Baidu}}
    • {{.view_source.Baidu}} 次来自 Baidu 点击
    • {{end}} + {{if .view_source.Bing}}
    • {{.view_source.Bing}} 次来自 Bing 点击
    • {{end}} + {{if .view_source.Sogou}}
    • {{.view_source.Sogou}} 次来自 Sogou 点击
    • {{end}} + {{if .view_source.So}}
    • {{.view_source.So}} 次来自 360搜索 点击
    • {{end}} + {{if .view_source.Other}}
    • {{.view_source.Other}} 次外链点击
    • {{end}} +
    + {{end}} +
    +{{end}} diff --git a/template/projects/detail.html b/template/projects/detail.html index 55373249..3b911099 100644 --- a/template/projects/detail.html +++ b/template/projects/detail.html @@ -89,15 +89,7 @@

    {{template "comment" .}} - {{if .view_user_num}} -
    -
    -
    统计信息
    -
    - 目前已有 {{.view_user_num}} 位注册会员查看了本项目 -
    -
    - {{end}} + {{include "common/view_stat.html" .}} diff --git a/template/resources/detail.html b/template/resources/detail.html index 17fabf98..3ada7d03 100644 --- a/template/resources/detail.html +++ b/template/resources/detail.html @@ -68,15 +68,7 @@

    {{template "comment" .}} - {{if .view_user_num}} -
    -
    -
    统计信息
    -
    - 目前已有 {{.view_user_num}} 位注册会员查看了本资源 -
    -
    - {{end}} + {{include "common/view_stat.html" .}}
    diff --git a/template/topics/detail.html b/template/topics/detail.html index c0c1d8d9..1d13fbaa 100644 --- a/template/topics/detail.html +++ b/template/topics/detail.html @@ -90,15 +90,7 @@

    {{template "comment" .}} - {{if .view_user_num}} -
    -
    -
    统计信息
    -
    - 目前已有 {{.view_user_num}} 位注册会员查看了本主题 -
    -
    - {{end}} + {{include "common/view_stat.html" .}}

    From f407061483ff222d98c240e00096408a8c75c92d Mon Sep 17 00:00:00 2001 From: xuxinhua Date: Tue, 24 Oct 2017 08:19:51 +0800 Subject: [PATCH 118/411] =?UTF-8?q?1024=E7=A8=8B=E5=BA=8F=E5=91=98?= =?UTF-8?q?=E8=8A=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/http/http.go | 8 ++++++++ static/img/activity/1024-0.jpg | Bin 0 -> 88051 bytes static/img/activity/1024-1.jpg | Bin 0 -> 90308 bytes 3 files changed, 8 insertions(+) create mode 100644 static/img/activity/1024-0.jpg create mode 100644 static/img/activity/1024-1.jpg diff --git a/src/http/http.go b/src/http/http.go index b859f478..52da439c 100644 --- a/src/http/http.go +++ b/src/http/http.go @@ -12,6 +12,7 @@ import ( "global" "html/template" "logic" + "math/rand" "model" "net/http" "path/filepath" @@ -109,6 +110,13 @@ var funcMap = template.FuncMap{ } return total }, + "mod": func(num1, num2 int) int { + if num1 == 0 { + num1 = rand.Intn(500) + } + + return num1 % num2 + }, "explode": func(s, sep string) []string { return strings.Split(s, sep) }, diff --git a/static/img/activity/1024-0.jpg b/static/img/activity/1024-0.jpg new file mode 100644 index 0000000000000000000000000000000000000000..a8c5af779ed2a4f4991bec9f41e2ecde3d389e9c GIT binary patch literal 88051 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%0ABkYO4a@v(k4Xi+Cq~8A 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�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

    Fp)kE{yd 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 literal 0 HcmV?d00001 From c6025868fb36663a78ec83df2e4074e75ef5315c Mon Sep 17 00:00:00 2001 From: xuxinhua Date: Wed, 25 Oct 2017 22:57:21 +0800 Subject: [PATCH 119/411] =?UTF-8?q?=E5=B0=BD=E5=8F=AF=E8=83=BD=20cdn=20?= =?UTF-8?q?=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- config/env.sample.ini | 3 ++ src/global/app.go | 8 +++ src/http/http.go | 8 ++- src/server/studygolang/main.go | 3 ++ template/common/analytics.html | 42 +++++++++++++++ template/common/common.css | 5 ++ template/common/common.css.cdn | 5 ++ template/common/common.js | 22 ++++++++ template/common/common.js.cdn | 23 ++++++++ template/common/layout.html | 96 +++++++++++----------------------- template/index.html | 3 +- 11 files changed, 150 insertions(+), 68 deletions(-) create mode 100644 template/common/analytics.html create mode 100644 template/common/common.css create mode 100644 template/common/common.css.cdn create mode 100644 template/common/common.js create mode 100644 template/common/common.js.cdn diff --git a/config/env.sample.ini b/config/env.sample.ini index 37557a05..2b7f83a3 100644 --- a/config/env.sample.ini +++ b/config/env.sample.ini @@ -13,6 +13,9 @@ is_master = 1 ; 搜索引擎,避免阅读次数非人为增加 spider = spider,bot,nutch,yahoo,gougou,scooter,lilina +; 静态资源是否使用 CDN +use_cdn = false + [listen] host = 127.0.0.1 port = 8088 diff --git a/src/global/app.go b/src/global/app.go index 5107684a..5a82757b 100644 --- a/src/global/app.go +++ b/src/global/app.go @@ -58,10 +58,14 @@ type app struct { Host string Port string + BaseURL string + // CDN 资源域名 CDNHttp string CDNHttps string + Domain string + locker sync.Mutex } @@ -94,6 +98,10 @@ func init() { App.CDNHttps = config.ConfigFile.MustValue("qiniu", "https_domain", DefaultCDNHttps) } +func (this *app) Init(domain string) { + this.Domain = config.ConfigFile.MustValue("global", "domain", domain) +} + func (this *app) SetUptime() { this.locker.Lock() defer this.locker.Unlock() diff --git a/src/http/http.go b/src/http/http.go index 52da439c..b471e6a9 100644 --- a/src/http/http.go +++ b/src/http/http.go @@ -307,7 +307,7 @@ func executeTpl(ctx echo.Context, tpl *template.Template, data map[string]interf // websocket主机 if global.OnlineEnv() { - data["wshost"] = config.ConfigFile.MustValue("global", "domain", logic.WebsiteSetting.Domain) + data["wshost"] = global.App.Domain } else { data["wshost"] = global.App.Host + ":" + global.App.Port } @@ -317,11 +317,17 @@ func executeTpl(ctx echo.Context, tpl *template.Template, data map[string]interf isHttps := CheckIsHttps(ctx) cdnDomain := global.App.CDNHttp if isHttps { + global.App.BaseURL = "https://" + global.App.Domain + "/" cdnDomain = global.App.CDNHttps + } else { + global.App.BaseURL = "http://" + global.App.Domain + "/" } + data["app"] = global.App data["is_https"] = isHttps data["cdn_domain"] = cdnDomain + data["use_cdn"] = config.ConfigFile.MustBool("global", "use_cdn", false) + data["is_pro"] = global.OnlineEnv() data["online_users"] = map[string]int{"online": logic.Book.Len(), "maxonline": logic.MaxOnlineNum()} diff --git a/src/server/studygolang/main.go b/src/server/studygolang/main.go index 9d7b204f..7c5e757f 100644 --- a/src/server/studygolang/main.go +++ b/src/server/studygolang/main.go @@ -12,6 +12,7 @@ import ( "http/controller/admin" "http/controller/app" "io/ioutil" + "logic" "math/rand" "os" "path/filepath" @@ -44,6 +45,8 @@ func main() { savePid() + global.App.Init(logic.WebsiteSetting.Domain) + logger.Init(ROOT+"/log", ConfigFile.MustValue("global", "log_level", "DEBUG")) go keyword.Extractor.Init(keyword.DefaultProps, true, ROOT+"/data/programming.txt,"+ROOT+"/data/dictionary.txt") diff --git a/template/common/analytics.html b/template/common/analytics.html new file mode 100644 index 00000000..1865c4c2 --- /dev/null +++ b/template/common/analytics.html @@ -0,0 +1,42 @@ + + + + + + + + \ No newline at end of file diff --git a/template/common/common.css b/template/common/common.css new file mode 100644 index 00000000..353b27c1 --- /dev/null +++ b/template/common/common.css @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/template/common/common.css.cdn b/template/common/common.css.cdn new file mode 100644 index 00000000..a8080e39 --- /dev/null +++ b/template/common/common.css.cdn @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/template/common/common.js b/template/common/common.js new file mode 100644 index 00000000..2c215929 --- /dev/null +++ b/template/common/common.js @@ -0,0 +1,22 @@ + + + + + + + + + diff --git a/template/common/common.js.cdn b/template/common/common.js.cdn new file mode 100644 index 00000000..8bc10edc --- /dev/null +++ b/template/common/common.js.cdn @@ -0,0 +1,23 @@ + + + + + + + + + + diff --git a/template/common/layout.html b/template/common/layout.html index 2864fdc3..718460c3 100644 --- a/template/common/layout.html +++ b/template/common/layout.html @@ -9,15 +9,14 @@ {{template "seo" .}} - - - - - - - - - + + + {{if .use_cdn}} + {{include "common/common.css.cdn" .}} + {{else}} + {{include "common/common.css" .}} + {{end}} + {{template "css" .}} +{{end}} \ No newline at end of file diff --git a/template/gctt/new.html b/template/gctt/new.html new file mode 100644 index 00000000..802bfe52 --- /dev/null +++ b/template/gctt/new.html @@ -0,0 +1,232 @@ +{{define "title"}}GCTT 文章发布 - Go中文翻译组 {{end}} +{{define "content"}} +

    +
    +
    + +
    +
    + {{if .gctt_user.Id}} + + + + +
    + +
    + +
    +
    +
    + +
    +
    +
    + +
    +
    + +
    +
    +
    +
    +
    + +
    +
    +
    + +
    + +
    + +
    +
    +
    +
    +
    + +
    + +
    +
    +
    + +
    +
    + +
    + +
    +
    + +
    +
    +
    + +
    + +
    + (Ctrl+Enter) +
    +
    + +
    + +
    +
    +
    +
    + {{else}} +
    +
    +
    + 您没有权限发布译文,请先成为译者 +
    +
    + +
    +
    + {{end}} + +
    +
    +
    +
    +
    + + + +
    +
    +{{end}} +{{define "css"}} + + + + + +{{end}} +{{define "js"}} + + + + + + + + + + + + + + + + + +{{end}} \ No newline at end of file diff --git a/template/gctt/user-info.html b/template/gctt/user-info.html new file mode 100644 index 00000000..f4f64282 --- /dev/null +++ b/template/gctt/user-info.html @@ -0,0 +1,20 @@ +{{define "title"}}{{.gctt_user.Username}} - Go中文翻译组(GCTT) {{end}} +{{define "content"}} +
    +
    +
    + +
    + +
    +
    +
    +
    + +
    +
    +{{end}} \ No newline at end of file diff --git a/template/gctt/user-list.html b/template/gctt/user-list.html new file mode 100644 index 00000000..dd6522bb --- /dev/null +++ b/template/gctt/user-list.html @@ -0,0 +1,20 @@ +{{define "title"}}成员列表 - Go中文翻译组(GCTT) {{end}} +{{define "content"}} +
    +
    +
    + +
    + +
    +
    +
    +
    + +
    +
    +{{end}} \ No newline at end of file diff --git a/template/topics/detail.html b/template/topics/detail.html index 1d13fbaa..1a24aa23 100644 --- a/template/topics/detail.html +++ b/template/topics/detail.html @@ -51,7 +51,7 @@

    -
    {{$append.Content}}
    +
    {{$append.Content}}
    From 9387b7fdeab3a1dcbc2f92591e91b95d1d4e892c Mon Sep 17 00:00:00 2001 From: xuxinhua Date: Sun, 19 Nov 2017 16:51:13 +0800 Subject: [PATCH 148/411] gctt github webhook support --- config/env.sample.ini | 1 + src/http/controller/gctt.go | 44 ++++++++++++++++++++++++++ src/logic/github.go | 61 ++++++++++++++++++++++++++----------- 3 files changed, 88 insertions(+), 18 deletions(-) diff --git a/config/env.sample.ini b/config/env.sample.ini index eeb5d1f7..106010c9 100644 --- a/config/env.sample.ini +++ b/config/env.sample.ini @@ -118,6 +118,7 @@ disallow_user = admin,administrator ; GCTT [gctt] repo = studygolang/GCTT +token_secret = yX56JYeIEI [include_files] ;path = config/auto_crawl_conf.ini \ No newline at end of file diff --git a/src/http/controller/gctt.go b/src/http/controller/gctt.go index 9585d4cf..44466d28 100644 --- a/src/http/controller/gctt.go +++ b/src/http/controller/gctt.go @@ -7,12 +7,20 @@ package controller import ( + "crypto/hmac" + "crypto/sha1" + "fmt" . "http" "http/middleware" + "io/ioutil" "logic" "model" "net/http" + "github.com/polaris1119/config" + + "github.com/polaris1119/logger" + "github.com/labstack/echo" "github.com/polaris1119/echoutils" ) @@ -26,6 +34,8 @@ func (self GCTTController) RegisterRoute(g *echo.Group) { g.Get("/gctt/:username", self.User) g.Get("/gctt-apply", self.Apply, middleware.NeedLogin()) g.Match([]string{"GET", "POST"}, "/gctt-new", self.Create, middleware.NeedLogin()) + + g.Post("/gctt-webhook", self.Webhook) } func (self GCTTController) Index(ctx echo.Context) error { @@ -111,3 +121,37 @@ func (GCTTController) User(ctx echo.Context) error { func (GCTTController) UserList(ctx echo.Context) error { return render(ctx, "gctt/user-list.html", map[string]interface{}{}) } + +func (GCTTController) Webhook(ctx echo.Context) error { + body, err := ioutil.ReadAll(Request(ctx).Body) + if err != nil { + logger.Errorln("GCTTController Webhook error:", err) + return err + } + + header := ctx.Request().Header() + + tokenSecret := config.ConfigFile.MustValue("gctt", "token_secret") + ok := checkMAC(body, header.Get("X-Hub-Signature"), []byte(tokenSecret)) + if !ok { + logger.Errorln("GCTTController Webhook checkMAC error", string(body)) + return nil + } + + event := header.Get("X-GitHub-Event") + switch event { + case "pull_request": + return logic.DefaultGithub.PullRequestEvent(ctx, body) + default: + fmt.Println("not deal event:", event) + } + + return nil +} + +func checkMAC(message []byte, messageMAC string, key []byte) bool { + mac := hmac.New(sha1.New, key) + mac.Write(message) + expectedMAC := fmt.Sprintf("%x", mac.Sum(nil)) + return messageMAC == "sha1="+expectedMAC +} diff --git a/src/logic/github.go b/src/logic/github.go index 45061da7..4a64b0bd 100644 --- a/src/logic/github.go +++ b/src/logic/github.go @@ -17,12 +17,39 @@ import ( "github.com/polaris1119/logger" "github.com/tidwall/gjson" + "golang.org/x/net/context" ) type GithubLogic struct{} var DefaultGithub = GithubLogic{} +func (self GithubLogic) PullRequestEvent(ctx context.Context, body []byte) error { + objLog := GetLogger(ctx) + + result := gjson.ParseBytes(body) + + thePRURL := result.Get("pull_request.url").String() + objLog.Infoln("GithubLogic PullRequestEvent, url:", thePRURL) + + if result.Get("action").String() != "closed" || !result.Get("pull_request.merged").Bool() { + objLog.Infoln("action:", result.Get("action"), "merged:", result.Get("pull_request.merged")) + return nil + } + + username := result.Get("pull_request.user.login").String() + avatar := result.Get("pull_request.user.avatar_url").String() + prTime := result.Get("pull_request.created_at").Time() + + err := self.dealFiles(username, avatar, prTime, thePRURL) + + objLog.Infoln("pull request deal successfully!") + + go self.statUserTime() + + return err +} + func (self GithubLogic) PullPR(repo string) error { prURL := fmt.Sprintf("%s/repos/%s/pulls?state=all&per_page=30", GithubAPIBaseUrl, repo) resp, err := http.Get(prURL) @@ -53,23 +80,7 @@ func (self GithubLogic) PullPR(repo string) error { username := val.Get("user.login").String() avatar := val.Get("user.avatar_url").String() - filesURL := thePRURL + "/files" - resp, err = http.Get(filesURL) - if err != nil { - outErr = err - logger.Errorln("github fetch files error:", err, "url:", filesURL) - return true - } - body, err := ioutil.ReadAll(resp.Body) - resp.Body.Close() - if err != nil { - outErr = err - logger.Errorln("github read files resp error:", err) - return true - } - filesResult := gjson.ParseBytes(body) - - err = self.dealFiles(username, avatar, prTime, filesResult) + err = self.dealFiles(username, avatar, prTime, thePRURL) if err != nil { outErr = err } @@ -83,7 +94,21 @@ func (self GithubLogic) PullPR(repo string) error { return outErr } -func (self GithubLogic) dealFiles(username, avatar string, prTime time.Time, filesResult gjson.Result) error { +func (self GithubLogic) dealFiles(username, avatar string, prTime time.Time, thePRURL string) error { + filesURL := thePRURL + "/files" + resp, err := http.Get(filesURL) + if err != nil { + logger.Errorln("github fetch files error:", err, "url:", filesURL) + return err + } + body, err := ioutil.ReadAll(resp.Body) + resp.Body.Close() + if err != nil { + logger.Errorln("github read files resp error:", err) + return err + } + filesResult := gjson.ParseBytes(body) + var outErr error filesResult.ForEach(func(key, val gjson.Result) bool { status := val.Get("status").String() From 91694c8a6b4b24260c64c12c78699422fa8765ed Mon Sep 17 00:00:00 2001 From: xuxinhua Date: Mon, 20 Nov 2017 17:33:15 +0800 Subject: [PATCH 149/411] subject --- config/db.sql | 45 ++++ docs/gctt.md | 2 +- src/http/controller/routes.go | 1 + src/http/controller/subject.go | 62 +++++ src/logic/subject.go | 114 +++++++++ src/logic/subject_test.go | 46 ++++ src/logic/user.go | 29 +++ src/model/subject.go | 64 +++++ src/util/time.go | 25 ++ src/util/time_test.go | 57 +++++ template/gctt/index.html | 4 +- template/subject/index.html | 454 +++++++++++++++++++++++++++++++++ 12 files changed, 900 insertions(+), 3 deletions(-) create mode 100644 src/http/controller/subject.go create mode 100644 src/logic/subject.go create mode 100644 src/logic/subject_test.go create mode 100644 src/model/subject.go create mode 100644 src/util/time_test.go create mode 100644 template/subject/index.html diff --git a/config/db.sql b/config/db.sql index fbd6bdbd..30ef23a7 100644 --- a/config/db.sql +++ b/config/db.sql @@ -708,3 +708,48 @@ CREATE TABLE IF NOT EXISTS `gctt_git` ( UNIQUE KEY (`username`,`title`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT 'GCTT github 文章翻译信息表'; + +CREATE TABLE IF NOT EXISTS `subject` ( + `id` int unsigned NOT NULL AUTO_INCREMENT COMMENT '专题ID', + `name` varchar(31) NOT NULL DEFAULT '' COMMENT '专题名', + `cover` varchar(127) NOT NULL DEFAULT '' COMMENT '专题封面', + `description` varchar(1023) NOT NULL DEFAULT '' COMMENT '专题描述(公告)', + `uid` int unsigned NOT NULL DEFAULT 0 COMMENT '创建者UID', + `contribute` tinyint unsigned NOT NULL DEFAULT 1 COMMENT '是否允许投稿, 0-不允许;1-允许', + `audit` tinyint unsigned NOT NULL DEFAULT 1 COMMENT '投稿是否需要审核, 0-不需要;1-需要', + `created_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP, + PRIMARY KEY (`id`), + UNIQUE KEY (`name`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT '专题'; + + +CREATE TABLE IF NOT EXISTS `subject_admin` ( + `id` int unsigned NOT NULL AUTO_INCREMENT, + `sid` int unsigned NOT NULL DEFAULT 0 COMMENT '专题ID', + `uid` int unsigned NOT NULL DEFAULT 0 COMMENT '管理员UID', + `created_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP, + PRIMARY KEY (`id`), + UNIQUE KEY (`sid`,`uid`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT '专题管理员(不包括创建者)'; + + +CREATE TABLE IF NOT EXISTS `subject_article` ( + `id` int unsigned NOT NULL AUTO_INCREMENT, + `sid` int unsigned NOT NULL DEFAULT 0 COMMENT '专题ID', + `article_id` int unsigned NOT NULL DEFAULT 0 COMMENT '文章ID', + `state` tinyint unsigned NOT NULl DEFAULT 0 COMMENT '状态:0-新投稿(待审核);1-上线;2-下线(删除)', + `created_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP, + PRIMARY KEY (`id`), + UNIQUE KEY (`sid`,`article_id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT '专题文章列表'; + + +CREATE TABLE IF NOT EXISTS `subject_follower` ( + `id` int unsigned NOT NULL AUTO_INCREMENT, + `sid` int unsigned NOT NULL DEFAULT 0 COMMENT '专题ID', + `uid` int unsigned NOT NULL DEFAULT 0 COMMENT '关注者UID', + `created_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP, + PRIMARY KEY (`id`), + UNIQUE KEY (`sid`,`uid`), + INDEX (`uid`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT '专题关注者'; diff --git a/docs/gctt.md b/docs/gctt.md index 529d2712..dd593583 100644 --- a/docs/gctt.md +++ b/docs/gctt.md @@ -2,7 +2,7 @@ ## 简介 -GCTT (Go Chinese Traslation Team) 是 Go中文网(https://studygolang.com) 翻译组,负责从国外优秀媒体翻译 Go 相关的技术、教程、资讯、杂文等内容。 +GCTT (Go Chinese Translation Team) 是 Go中文网(https://studygolang.com) 翻译组,负责从国外优秀媒体翻译 Go 相关的技术、教程、资讯、杂文等内容。 ## GCTT 的组成 diff --git a/src/http/controller/routes.go b/src/http/controller/routes.go index bf87bfbe..c5394a70 100644 --- a/src/http/controller/routes.go +++ b/src/http/controller/routes.go @@ -36,6 +36,7 @@ func RegisterRoutes(g *echo.Group) { new(WebsocketController).RegisterRoute(g) new(DownloadController).RegisterRoute(g) new(LinkController).RegisterRoute(g) + new(SubjectController).RegisterRoute(g) new(GCTTController).RegisterRoute(g) new(FeedController).RegisterRoute(g) diff --git a/src/http/controller/subject.go b/src/http/controller/subject.go new file mode 100644 index 00000000..54ea642a --- /dev/null +++ b/src/http/controller/subject.go @@ -0,0 +1,62 @@ +// Copyright 2017 The StudyGolang Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. +// http://studygolang.com +// Author: polaris polaris@studygolang.com + +package controller + +import ( + "http/middleware" + "logic" + "net/http" + + "github.com/labstack/echo" + "github.com/polaris1119/goutils" +) + +type SubjectController struct{} + +// 注册路由 +func (self SubjectController) RegisterRoute(g *echo.Group) { + g.Get("/subject/:id", self.Index) + g.Post("/subject/follow", self.Follow, middleware.NeedLogin()) +} + +func (SubjectController) Index(ctx echo.Context) error { + id := goutils.MustInt(ctx.Param("id")) + if id == 0 { + return ctx.Redirect(http.StatusSeeOther, "/") + } + + subject := logic.DefaultSubject.FindOne(ctx, id) + if subject.Id == 0 { + return ctx.Redirect(http.StatusSeeOther, "/") + } + + orderBy := ctx.QueryParam("order_by") + articles := logic.DefaultSubject.FindArticles(ctx, id, orderBy) + if orderBy == "" { + orderBy = "added_at" + } + + articleNum := logic.DefaultSubject.FindArticleTotal(ctx, id) + + followers := logic.DefaultSubject.FindFollowers(ctx, id) + followerNum := logic.DefaultSubject.FindFollowerTotal(ctx, id) + + data := map[string]interface{}{ + "subject": subject, + "articles": articles, + "article_num": articleNum, + "followers": followers, + "follower_num": followerNum, + "order_by": orderBy, + } + + return render(ctx, "subject/index.html", data) +} + +func (self SubjectController) Follow(ctx echo.Context) error { + +} diff --git a/src/logic/subject.go b/src/logic/subject.go new file mode 100644 index 00000000..dd2dd024 --- /dev/null +++ b/src/logic/subject.go @@ -0,0 +1,114 @@ +// Copyright 2017 The StudyGolang Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. +// http://studygolang.com +// Author:polaris polaris@studygolang.com + +package logic + +import ( + "model" + "util" + + "github.com/polaris1119/slices" + "golang.org/x/net/context" + + . "db" +) + +type SubjectLogic struct{} + +var DefaultSubject = SubjectLogic{} + +func (self SubjectLogic) FindOne(ctx context.Context, sid int) *model.Subject { + objLog := GetLogger(ctx) + + subject := &model.Subject{} + _, err := MasterDB.Id(sid).Get(subject) + if err != nil { + objLog.Errorln("SubjectLogic FindOne get error:", err) + } + + if subject.Uid > 0 { + subject.User = DefaultUser.findUser(ctx, subject.Uid) + } + + return subject +} + +func (self SubjectLogic) FindArticles(ctx context.Context, sid int, orderBy string) []*model.Article { + objLog := GetLogger(ctx) + + order := "subject_article.created_at DESC" + if orderBy == "commented_at" { + order = "articles.lastreplytime DESC" + } + + subjectArticles := make([]*model.SubjectArticles, 0) + err := MasterDB.Join("INNER", "subject_article", "subject_article.article_id = articles.id"). + Where("subject_article.sid=?", sid).OrderBy(order).Find(&subjectArticles) + if err != nil { + objLog.Errorln("SubjectLogic FindArticles Find subject_article error:", err) + return nil + } + + articles := make([]*model.Article, 0, len(subjectArticles)) + for _, subjectArticle := range subjectArticles { + if subjectArticle.Status == model.ArticleStatusOffline { + continue + } + + articles = append(articles, &subjectArticle.Article) + } + + DefaultArticle.fillUser(articles) + return articles +} + +// FindArticleTotal 专题收录的文章数 +func (self SubjectLogic) FindArticleTotal(ctx context.Context, sid int) int64 { + objLog := GetLogger(ctx) + + total, err := MasterDB.Where("sid=?", sid).Count(new(model.SubjectArticle)) + if err != nil { + objLog.Errorln("SubjectLogic FindArticleTotal error:", err) + } + + return total +} + +// FindFollowers 专题关注的用户 +func (self SubjectLogic) FindFollowers(ctx context.Context, sid int) []*model.SubjectFollower { + objLog := GetLogger(ctx) + + followers := make([]*model.SubjectFollower, 0) + err := MasterDB.Where("sid=?", sid).OrderBy("id DESC").Limit(8).Find(&followers) + if err != nil { + objLog.Errorln("SubjectLogic FindFollowers error:", err) + } + + if len(followers) == 0 { + return followers + } + + uids := slices.StructsIntSlice(followers, "Uid") + usersMap := DefaultUser.FindUserInfos(ctx, uids) + for _, follower := range followers { + follower.User = usersMap[follower.Uid] + follower.TimeAgo = util.TimeAgo(follower.CreatedAt) + } + + return followers +} + +// FindFollowerTotal 专题关注的用户数 +func (self SubjectLogic) FindFollowerTotal(ctx context.Context, sid int) int64 { + objLog := GetLogger(ctx) + + total, err := MasterDB.Where("sid=?", sid).Count(new(model.SubjectFollower)) + if err != nil { + objLog.Errorln("SubjectLogic FindFollowerTotal error:", err) + } + + return total +} diff --git a/src/logic/subject_test.go b/src/logic/subject_test.go new file mode 100644 index 00000000..ce9e4bec --- /dev/null +++ b/src/logic/subject_test.go @@ -0,0 +1,46 @@ +// Copyright 2017 The StudyGolang Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. +// http://studygolang.com +// Author:polaris polaris@studygolang.com + +package logic_test + +import ( + "logic" + "model" + "reflect" + "testing" + + "golang.org/x/net/context" +) + +func TestFindArticles(t *testing.T) { + type args struct { + ctx context.Context + sid int + } + tests := []struct { + name string + self logic.SubjectLogic + args args + want []*model.Article + }{ + { + name: "subject1", + args: args{ + nil, + 1, + }, + want: nil, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + self := logic.SubjectLogic{} + if got := self.FindArticles(tt.args.ctx, tt.args.sid, ""); !reflect.DeepEqual(got, tt.want) { + t.Errorf("SubjectLogic.FindArticles() = %v, want %v", got, tt.want) + } + }) + } +} diff --git a/src/logic/user.go b/src/logic/user.go index a3a830f4..34755594 100644 --- a/src/logic/user.go +++ b/src/logic/user.go @@ -16,6 +16,8 @@ import ( "time" "util" + "github.com/polaris1119/slices" + "github.com/go-validator/validator" "github.com/go-xorm/xorm" "github.com/polaris1119/config" @@ -311,6 +313,33 @@ func (self UserLogic) FindCurrentUser(ctx context.Context, username interface{}) return me } +// findUsers 获得用户信息,包内使用。 +// s 是包含用户 UID 的二维数组 +func (self UserLogic) findUsers(ctx context.Context, s interface{}) []*model.User { + objLog := GetLogger(ctx) + + uids := slices.StructsIntSlice(s, "Uid") + + users := make([]*model.User, 0) + if err := MasterDB.In("uid", uids).Find(&users); err != nil { + objLog.Errorln("user logic findUsers not record found:", err) + return nil + } + return users +} + +func (self UserLogic) findUser(ctx context.Context, uid int) *model.User { + objLog := GetLogger(ctx) + + user := &model.User{} + _, err := MasterDB.Id(uid).Get(user) + if err != nil { + objLog.Errorln("user logic findUser not record found:", err) + } + + return user +} + // 会员总数 func (UserLogic) Total() int64 { total, err := MasterDB.Count(new(model.User)) diff --git a/src/model/subject.go b/src/model/subject.go new file mode 100644 index 00000000..106b426e --- /dev/null +++ b/src/model/subject.go @@ -0,0 +1,64 @@ +// Copyright 2017 The StudyGolang Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. +// https://studygolang.com +// Author: polaris polaris@studygolang.com + +package model + +import ( + "time" +) + +// Subject 专题 +type Subject struct { + Id int `xorm:"pk autoincr" json:"id"` + Name string `json:"name"` + Cover string `json:"cover"` + Description string `json:"description"` + Uid int `json:"uid"` + Contribute bool `json:"contribute"` + Audit bool `json:"audit"` + CreatedAt time.Time `json:"created_at" xorm:"<-"` + + User *User `json:"user" xorm:"-"` +} + +// SubjectAdmin 专题管理员 +type SubjectAdmin struct { + Id int `xorm:"pk autoincr" json:"id"` + Sid int `json:"sid"` + Uid int `json:"uid"` + CreatedAt time.Time `json:"created_at" xorm:"<-"` +} + +// SubjectArticle 专题文章 +type SubjectArticle struct { + Id int `xorm:"pk autoincr" json:"id"` + Sid int `json:"sid"` + ArticleId int `json:"article_id"` + State int `json:"state"` + CreatedAt time.Time `json:"created_at" xorm:"<-"` +} + +// SubjectArticles xorm join 需要 +type SubjectArticles struct { + Article `xorm:"extends"` + Sid int + CreatedAt time.Time +} + +func (*SubjectArticles) TableName() string { + return "articles" +} + +// SubjectFollower 专题关注者 +type SubjectFollower struct { + Id int `xorm:"pk autoincr" json:"id"` + Sid int `json:"sid"` + Uid int `json:"uid"` + CreatedAt time.Time `json:"created_at" xorm:"<-"` + + User *User `xorm:"-"` + TimeAgo string `xorm:"-"` +} diff --git a/src/util/time.go b/src/util/time.go index fd537308..164bbfcf 100644 --- a/src/util/time.go +++ b/src/util/time.go @@ -7,6 +7,7 @@ package util import "time" +import "fmt" // MonthDayNum t 所在时间的月份总天数 func MonthDayNum(t time.Time) int { @@ -27,6 +28,30 @@ func MonthDayNum(t time.Time) int { } } +func TimeAgo(t time.Time) string { + now := time.Now() + diff := now.Sub(t) + hours := diff.Hours() + if hours < 1.0 { + return fmt.Sprintf("约 %.0f 分钟前", diff.Minutes()) + } + + if hours < 24.0 { + return fmt.Sprintf("约 %.0f 小时前", hours) + } + + if hours < 72.0 { + return fmt.Sprintf("约 %.0f 天前", hours/24.0) + } + + // 同一年,不用年份 + if now.Year() == t.Year() { + return t.Format("01-02 15:04") + } + + return t.Format("2006-01-02") +} + // 是否闰年 func isLeap(year int) bool { return year%4 == 0 && (year%100 != 0 || year%400 == 0) diff --git a/src/util/time_test.go b/src/util/time_test.go new file mode 100644 index 00000000..006d62fc --- /dev/null +++ b/src/util/time_test.go @@ -0,0 +1,57 @@ +// Copyright 2017 The StudyGolang Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. +// http://studygolang.com +// Author: polaris polaris@studygolang.com + +package util_test + +import ( + "testing" + "time" + "util" +) + +func TestTimeAgo(t *testing.T) { + type args struct { + t time.Time + } + tests := []struct { + name string + args args + want string + }{ + { + "小于1分钟", + args{time.Now().Add(-30 * time.Second)}, + "约 1 分钟前", + }, + { + "约2小时前", + args{time.Now().Add(-100 * time.Minute)}, + "约 2 小时前", + }, + { + "约1天前", + args{time.Now().Add(-25 * time.Hour)}, + "约 1 天前", + }, + { + "11-02 14:00", + args{time.Date(2017, 11, 2, 14, 0, 0, 0, time.Local)}, + "11-02 14:00", + }, + { + "2016-02-02", + args{time.Date(2016, 2, 2, 0, 0, 0, 0, time.Local)}, + "2016-02-02", + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if got := util.TimeAgo(tt.args.t); got != tt.want { + t.Errorf("TimeAgo() = %v, want %v", got, tt.want) + } + }) + } +} diff --git a/template/gctt/index.html b/template/gctt/index.html index f57148b4..2aaf97de 100644 --- a/template/gctt/index.html +++ b/template/gctt/index.html @@ -13,7 +13,7 @@

    简介

    -

    GCTT (Go Chinese Traslation Team) 是 Go中文网(https://studygolang.com) 翻译组,负责从国外优秀媒体翻译 Go 相关的技术、教程、资讯、杂文等内容。

    +

    GCTT (Go Chinese Translation Team) 是 Go中文网(https://studygolang.com) 翻译组,负责从国外优秀媒体翻译 Go 相关的技术、教程、资讯、杂文等内容。

    GCTT 的组成

    选题,负责选择合适的内容,并将原文转换为 markdown 格式(可以使用 https://domchristie.github.io/to-markdown/ 做转换),提交到 GCTT 库中。

    译者,负责从选题中选择内容进行翻译。

    @@ -44,7 +44,7 @@

     
  • - tk103331 + tk103331
    diff --git a/template/subject/index.html b/template/subject/index.html new file mode 100644 index 00000000..597c2056 --- /dev/null +++ b/template/subject/index.html @@ -0,0 +1,454 @@ +{{define "title"}}{{.subject.Name}} - 专题 {{end}} +{{define "seo"}} +{{end}} +{{define "content"}} +
    +
    +
    +
    + +
    + +
    +
    +
    + + + +
    +

    {{.subject.Name}}

    +

    收录了 {{.article_num}} 篇文章 · {{.follower_num}} 人关注

    +
    +
    +
    + {{if eq .me.Uid .subject.Uid}} + + {{else}} + + {{end}} + +
    +
    + + + +
    + +
    +
    +
    +
    +
    + + + + {{if .follower_num}} + + {{end}} +
    +
    +{{end}} +{{define "css"}} + + +{{end}} + +{{define "js"}} + + + +{{end}} \ No newline at end of file From bda72cc93d2056d2380998ae326bb5a89c10627f Mon Sep 17 00:00:00 2001 From: meission Date: Tue, 21 Nov 2017 01:20:09 +0800 Subject: [PATCH 150/411] update message & fix sql 1064 --- src/logic/reading.go | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/logic/reading.go b/src/logic/reading.go index 7aa791da..6b5002ba 100644 --- a/src/logic/reading.go +++ b/src/logic/reading.go @@ -8,6 +8,7 @@ package logic import ( . "db" + "errors" "model" "net/url" "strconv" @@ -113,7 +114,7 @@ func (ReadingLogic) SaveReading(ctx context.Context, form url.Values, username s readings := make([]*model.MorningReading, 0) if reading.Inner != 0 { reading.Url = "" - err = MasterDB.Where("inner=?", reading.Inner).OrderBy("id DESC").Find(&readings) + err = MasterDB.Where("`inner`=?", reading.Inner).OrderBy("id DESC").Find(&readings) } else { err = MasterDB.Where("url=?", reading.Url).OrderBy("id DESC").Find(&readings) } @@ -136,6 +137,7 @@ func (ReadingLogic) SaveReading(ctx context.Context, form url.Values, username s } else { if len(readings) > 0 { logger.Errorln("reading report:", reading) + errMsg, err = "已经存在了!!", errors.New("已经存在了!!") return } _, err = MasterDB.Insert(reading) From 6b7dbe08aa966a1dba430a9bb7676c383449e8a3 Mon Sep 17 00:00:00 2001 From: xuxinhua Date: Tue, 21 Nov 2017 15:19:05 +0800 Subject: [PATCH 151/411] =?UTF-8?q?=E4=B8=93=E9=A2=98=E5=8A=9F=E8=83=BD?= =?UTF-8?q?=E5=AE=8C=E6=88=90?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/http/controller/subject.go | 61 ++++++ src/logic/article.go | 47 +++++ src/logic/subject.go | 90 ++++++++ src/model/subject.go | 6 + static/css/subject.css | 316 ++++++++++++++++++++++++++++ static/js/subject.js | 156 ++++++++++++++ template/common/modal.html | 365 +++++++++++++++++++++++++++++++++ template/subject/index.html | 327 ++--------------------------- 8 files changed, 1057 insertions(+), 311 deletions(-) create mode 100644 static/css/subject.css create mode 100644 static/js/subject.js create mode 100644 template/common/modal.html diff --git a/src/http/controller/subject.go b/src/http/controller/subject.go index 54ea642a..9b2d56d3 100644 --- a/src/http/controller/subject.go +++ b/src/http/controller/subject.go @@ -9,6 +9,7 @@ package controller import ( "http/middleware" "logic" + "model" "net/http" "github.com/labstack/echo" @@ -21,6 +22,9 @@ type SubjectController struct{} func (self SubjectController) RegisterRoute(g *echo.Group) { g.Get("/subject/:id", self.Index) g.Post("/subject/follow", self.Follow, middleware.NeedLogin()) + g.Get("/subject/my_articles", self.MyArticles, middleware.NeedLogin()) + g.Post("/subject/contribute", self.Contribute, middleware.NeedLogin()) + g.Post("/subject/remove_contribute", self.RemoveContribute, middleware.NeedLogin()) } func (SubjectController) Index(ctx echo.Context) error { @@ -45,6 +49,13 @@ func (SubjectController) Index(ctx echo.Context) error { followers := logic.DefaultSubject.FindFollowers(ctx, id) followerNum := logic.DefaultSubject.FindFollowerTotal(ctx, id) + // 是否已关注 + followed := false + me, ok := ctx.Get("user").(*model.Me) + if ok { + followed = logic.DefaultSubject.HadFollow(ctx, id, me) + } + data := map[string]interface{}{ "subject": subject, "articles": articles, @@ -52,11 +63,61 @@ func (SubjectController) Index(ctx echo.Context) error { "followers": followers, "follower_num": followerNum, "order_by": orderBy, + "followed": followed, } return render(ctx, "subject/index.html", data) } func (self SubjectController) Follow(ctx echo.Context) error { + sid := goutils.MustInt(ctx.FormValue("sid")) + + me := ctx.Get("user").(*model.Me) + err := logic.DefaultSubject.Follow(ctx, sid, me) + if err != nil { + return fail(ctx, 1, "关注失败!") + } + + return success(ctx, nil) +} + +func (self SubjectController) MyArticles(ctx echo.Context) error { + kw := ctx.QueryParam("kw") + sid := goutils.MustInt(ctx.FormValue("sid")) + + me := ctx.Get("user").(*model.Me) + + articles := logic.DefaultArticle.SearchMyArticles(ctx, me, sid, kw) + + return success(ctx, map[string]interface{}{ + "articles": articles, + }) +} + +// Contribute 投稿 +func (self SubjectController) Contribute(ctx echo.Context) error { + sid := goutils.MustInt(ctx.FormValue("sid")) + articleId := goutils.MustInt(ctx.FormValue("article_id")) + + me := ctx.Get("user").(*model.Me) + + err := logic.DefaultSubject.Contribute(ctx, me, sid, articleId) + if err != nil { + return fail(ctx, 1, err.Error()) + } + + return success(ctx, nil) +} + +// RemoveContribute 删除投稿 +func (self SubjectController) RemoveContribute(ctx echo.Context) error { + sid := goutils.MustInt(ctx.FormValue("sid")) + articleId := goutils.MustInt(ctx.FormValue("article_id")) + + err := logic.DefaultSubject.RemoveContribute(ctx, sid, articleId) + if err != nil { + return fail(ctx, 1, err.Error()) + } + return success(ctx, nil) } diff --git a/src/logic/article.go b/src/logic/article.go index 8d8cb6c8..3fd59a12 100644 --- a/src/logic/article.go +++ b/src/logic/article.go @@ -17,6 +17,8 @@ import ( "strings" "time" + "github.com/polaris1119/slices" + "github.com/PuerkitoBio/goquery" "github.com/jaytaylor/html2text" "github.com/polaris1119/config" @@ -503,6 +505,51 @@ func (self ArticleLogic) FindByUser(ctx context.Context, username string, limit return articles } +func (self ArticleLogic) SearchMyArticles(ctx context.Context, me *model.Me, sid int, kw string) []map[string]interface{} { + objLog := GetLogger(ctx) + + articles := make([]*model.Article, 0) + session := MasterDB.Where("author_txt=?", me.Username).OrderBy("id DESC").Limit(8) + if kw != "" { + session.Where("title LIKE ?", "%"+kw+"%") + } + err := session.Find(&articles) + if err != nil { + objLog.Errorln("ArticleLogic SearchMyArticles Error:", err) + return nil + } + + subjectArticles := make([]*model.SubjectArticle, 0) + articleIds := slices.StructsIntSlice(articles, "Id") + err = MasterDB.Where("sid=?", sid).In("article_id", articleIds).Find(&subjectArticles) + if err != nil { + objLog.Errorln("ArticleLogic SearchMyArticles find subject article Error:", err) + return nil + } + + subjectArticleMap := make(map[int]struct{}) + for _, subjectArticle := range subjectArticles { + subjectArticleMap[subjectArticle.ArticleId] = struct{}{} + } + + articleMapSlice := make([]map[string]interface{}, len(articles)) + for i, article := range articles { + articleMap := map[string]interface{}{ + "id": article.Id, + "title": article.Title, + } + if _, ok := subjectArticleMap[article.Id]; ok { + articleMap["had_add"] = 1 + } else { + articleMap["had_add"] = 0 + } + + articleMapSlice[i] = articleMap + } + + return articleMapSlice +} + // FindAll 支持多页翻看 func (self ArticleLogic) FindAll(ctx context.Context, paginator *Paginator, orderBy string, querystring string, args ...interface{}) []*model.Article { objLog := GetLogger(ctx) diff --git a/src/logic/subject.go b/src/logic/subject.go index dd2dd024..47e8d91e 100644 --- a/src/logic/subject.go +++ b/src/logic/subject.go @@ -7,6 +7,7 @@ package logic import ( + "errors" "model" "util" @@ -112,3 +113,92 @@ func (self SubjectLogic) FindFollowerTotal(ctx context.Context, sid int) int64 { return total } + +// Follow 关注或取消关注 +func (self SubjectLogic) Follow(ctx context.Context, sid int, me *model.Me) (err error) { + objLog := GetLogger(ctx) + + follower := &model.SubjectFollower{} + _, err = MasterDB.Where("sid=? AND uid=?", sid, me.Uid).Get(follower) + if err != nil { + objLog.Errorln("SubjectLogic Follow Get error:", err) + } + + if follower.Id > 0 { + _, err = MasterDB.Where("sid=? AND uid=?", sid, me.Uid).Delete(new(model.SubjectFollower)) + if err != nil { + objLog.Errorln("SubjectLogic Follow Delete error:", err) + } + + return + } + + follower.Sid = sid + follower.Uid = me.Uid + _, err = MasterDB.Insert(follower) + if err != nil { + objLog.Errorln("SubjectLogic Follow insert error:", err) + } + return +} + +func (self SubjectLogic) HadFollow(ctx context.Context, sid int, me *model.Me) bool { + objLog := GetLogger(ctx) + + num, err := MasterDB.Where("sid=? AND uid=?", sid, me.Uid).Count(new(model.SubjectFollower)) + if err != nil { + objLog.Errorln("SubjectLogic Follow insert error:", err) + } + + return num > 0 +} + +// Contribute 投稿 +func (self SubjectLogic) Contribute(ctx context.Context, me *model.Me, sid, articleId int) error { + objLog := GetLogger(ctx) + + subject := self.FindOne(ctx, sid) + if subject.Id == 0 { + return errors.New("该专题不存在") + } + + count, _ := MasterDB.Where("article_id=?", articleId).Count(new(model.SubjectArticle)) + if count >= 5 { + return errors.New("该文超过 5 次投稿") + } + + article, err := DefaultArticle.FindById(ctx, articleId) + if article.AuthorTxt != me.Username { + return errors.New("该文不是你的文章,不能投稿") + } + + subjectArticle := &model.SubjectArticle{ + Sid: sid, + ArticleId: articleId, + State: model.ContributeStateNew, + } + if subject.Uid == me.Uid { + subjectArticle.State = model.ContributeStateOnline + } + + _, err = MasterDB.Insert(subjectArticle) + if err != nil { + objLog.Errorln("SubjectLogic Contribute insert error:", err) + return errors.New("投稿失败:" + err.Error()) + } + + return nil +} + +// RemoveContribute 删除投稿 +func (self SubjectLogic) RemoveContribute(ctx context.Context, sid, articleId int) error { + objLog := GetLogger(ctx) + + _, err := MasterDB.Where("sid=? AND article_id=?", sid, articleId).Delete(new(model.SubjectArticle)) + if err != nil { + objLog.Errorln("SubjectLogic RemoveContribute delete error:", err) + return errors.New("删除投稿失败:" + err.Error()) + } + + return nil +} diff --git a/src/model/subject.go b/src/model/subject.go index 106b426e..0791abf0 100644 --- a/src/model/subject.go +++ b/src/model/subject.go @@ -32,6 +32,12 @@ type SubjectAdmin struct { CreatedAt time.Time `json:"created_at" xorm:"<-"` } +const ( + ContributeStateNew = iota + ContributeStateOnline + ContributeStateOffline +) + // SubjectArticle 专题文章 type SubjectArticle struct { Id int `xorm:"pk autoincr" json:"id"` diff --git a/static/css/subject.css b/static/css/subject.css new file mode 100644 index 00000000..20469b1f --- /dev/null +++ b/static/css/subject.css @@ -0,0 +1,316 @@ +.subject-header { + display: -webkit-flex; + display: flex; + justify-content: space-between; + padding: 10px; + font-size: 13px; + line-height: 120%; +} + +.subject-info { + display: -webkit-flex; + display: flex; +} + +.subject-meta { + margin-left: 10px; +} + +.subject-meta p { + padding-left: 10px; +} + +.subject-op { + align-self: center; +} + +.subject-meta .title { + font-size: 1.75rem; + font-weight: bold; +} + +.btn-success { + border-radius: 40px; + color: #fff; + background-color: #42c02e; + border-color: #42c02e; + width: 90px; + outline: none; +} + +.btn-followed { + border-radius: 40px; + color: #8c8c8c; + border: 1px solid hsla(0,0%,59%,.6); + background: none; + width: 90px; + padding-left: 9px; + outline: none; +} + +.btn-followed:focus,.btn-followed:hover { + color: #8c8c8c; + background-color: #8c8c8c; + border-color: #969696!important; + background-color: hsla(0,0%,39%,.05)!important +} + +.btn-hollow { + border: 1px solid rgba(59,194,29,.7); + color: #42c02e!important; + border-radius: 40px; + background-color: white; + width: 90px; + outline: none; +} + +.btn-hollow:focus,.btn-hollow:hover { + border: 1px solid #42c02e; + color: #42c02e!important; + background-color: rgba(59,194,29,.05) +} + +.trigger-menu { + margin-bottom: 20px; + border-bottom: 1px solid #f0f0f0; + font-size: 0; + list-style: none; + padding-left: 10px; +} + +.trigger-menu li { + position: relative; + display: inline-block; + padding: 8px 0; + margin-bottom: -1px; +} + +.trigger-menu li.active { + border-bottom: 2px solid #646464; + padding: 8px 0; + margin: 0; +} + +.trigger-menu a { + padding: 13px 20px; + font-size: 15px; + font-weight: 700; + color: #969696; + line-height: 25px; +} + +.trigger-menu .active a, .trigger-menu a:hover { + color: #646464; + text-decoration: none; +} + +.trigger-menu i { + margin-right: 5px; + font-size: 17px; +} + +.trigger-menu li:after { + content: ""; + position: absolute; + left: 50%; + bottom: -2px; + width: 100%; + opacity: 0; + border-bottom: 2px solid #646464; + transform: translate(-50%) scaleX(0); + -webkit-transform: translate(-50%) scaleX(0); + -moz-transform: translate(-50%) scaleX(0); + -o-transform: translate(-50%) scaleX(0); + -ms-transform: translate(-50%) scaleX(0) +} + +.trigger-menu li:after,.trigger-menu li:hover:after { + transition: .2s ease-in-out; + -webkit-transition: .2s ease-in-out; + -moz-transition: .2s ease-in-out; + -o-transition: .2s ease-in-out; + -ms-transition: .2s ease-in-out +} + +.trigger-menu li:hover:after { + opacity: 1; + transform: translate(-50%) scaleX(1); + -webkit-transform: translate(-50%) scaleX(1); + -moz-transform: translate(-50%) scaleX(1); + -o-transform: translate(-50%) scaleX(1); + -ms-transform: translate(-50%) scaleX(1) +} + +#list-container { + padding: 0 10px; +} + +.sidebar .tag { + padding: 1px 3px; + margin-left: 2px; + border-radius: 3px; + font-size: 12px; + color: #969696; + border: 1px solid #969696; +} + +.sidebar .tag:hover {background-color:white; text-decoration: none; } + +.note-list { + margin: 0; + padding: 0; + list-style: none; +} + +.note-list li { + position: relative; + width: 100%; + margin: 0 0 17px; + padding: 0 2px 17px 0; + border-bottom: 1px solid #f0f0f0; + word-wrap: break-word; +} + +.note-list li.have-img { + min-height: 140px; +} + +.note-list .have-img .wrap-img { + position: absolute; + top: 50%; + margin-top: -68px; + right: 0; + width: 150px; + height: 120px; +} + +.note-list .have-img .wrap-img img { + width: 100%; + height: 100%; + border-radius: 4px; + border: 1px solid #f0f0f0; +} + +.note-list .have-img>div { + padding-right: 160px; +} + +.note-list .author { + margin-bottom: 14px; + font-size: 13px; +} + +.note-list .author .avatar, .note-list .author .info { + display: inline-block; + vertical-align: middle; +} + +.note-list .author .avatar { + margin: 0 5px 0 0; +} + +.note-list .author a { + color: #333; +} + +.avatar { + width: 32px; + height: 32px; + display: block; + cursor: pointer; +} + +.avatar img { + width: 100%; + height: 100%; + border: 1px solid #ddd; + border-radius: 50%; +} + +.note-list .author .avatar, .note-list .author .info { + display: inline-block; + vertical-align: middle; +} + +.note-list .author .info .nickname { + vertical-align: middle; +} + +.note-list .author .info span { + display: inline-block; + padding-left: 3px; + color: #969696; + vertical-align: middle; +} + +.note-list .author .time { + color: #969696; +} + +.note-list .article-title { + margin: -7px 0 4px; + display: inherit; + font-size: 18px; + font-weight: 700; + line-height: 1.5; + color: #333; +} + +.note-list .article-title:visited { + color: #969696; +} + +.note-list .abstract { + margin: 0 0 8px; + font-size: 13px; + line-height: 24px; +} + +.note-list .article-meta { + padding-right: 0!important; + font-size: 12px; + font-weight: 400; + line-height: 20px; +} + +.note-list .article-meta a, .note-list .article-meta a:hover { + transition: .1s ease-in; + -webkit-transition: .1s ease-in; + -moz-transition: .1s ease-in; + -o-transition: .1s ease-in; + -ms-transition: .1s ease-in; +} + +.note-list .article-meta a { + margin-right: 10px; + color: #b4b4b4; +} + +.note-list .article-meta a:hover { + color: #787878; + text-decoration: none; +} + +.note-list .article-meta span { + margin-right: 10px; + color: #b4b4b4; +} + +.sidebar .users {} + +.sidebar .users li { + display: inline-block; +} +.sidebar .users li:first-child { + margin-left: -3px; +} + +.sidebar .users li a { + margin-right: -12px; + display: inline-block; +} + +.sidebar .users li img { + border: 3px solid #fff; + background-color: #fff; +} \ No newline at end of file diff --git a/static/js/subject.js b/static/js/subject.js new file mode 100644 index 00000000..a2e909e3 --- /dev/null +++ b/static/js/subject.js @@ -0,0 +1,156 @@ +$(function() { + marked = SG.markSetting(); + $('.desc').html(marked($('.desc').text().trim())); + + $('.noavatar').each(function() { + var author = $(this).data('author'); + var hash = md5(author+""); + var data = new Identicon(hash, {format: 'svg', size: 32}).toString(); + var imgData = 'data:image/svg+xml;base64,' + data; + $(this).attr('src', imgData); + }); + + var followed = $('#follow').data('follow'); + + $('#follow').on('click', function() { + var that = this; + $.post('/subject/follow', {sid: $(this).data('sid')}, function(result) { + if (result.ok) { + if (followed) { + followed = false; + $(that).removeClass('btn-followed').addClass('btn-success'); + $(that).html(' 关注'); + } else { + followed = true; + $(that).removeClass('btn-success').addClass('btn-followed'); + $(that).html(' 已关注'); + } + } + }); + }); + + $('#follow').on('mouseenter', function() { + if (!followed) { + return; + } + $(this).html(' 取消关注'); + }) + + $('#follow').on('mouseleave', function() { + if (!followed) { + return; + } + $(this).html(' 已关注'); + }) + + $('#contribute').on('click', function() { + var sid = $('#follow').data('sid'); + $.getJSON('/subject/my_articles?sid='+sid, function(result) { + if (result.ok) { + var articles = result.data.articles; + fillArticles(articles); + + $('body').addClass('modal-open'); + $('.contribute-modal').fadeIn(); + } + }); + }); + + $('.contribute-modal .close').on('click', function() { + $('body').removeClass('modal-open'); + $('.contribute-modal').fadeOut(); + }) + + var noteListHtml = ''; + $('.contribute-modal .search-btn').on('click', function() { + var kw = $('.contribute-modal .search-input').val(); + if (kw == "") { + $('#contribute-note-list').html(noteListHtml); + return; + } + + noteListHtml = $('#contribute-note-list').html(); + $('#contribute-note-list').html(''); + var placeholder = $('.contribute-modal .modal-notes-placeholder'); + placeholder.show(); + + var sid = $('#follow').data('sid'); + $.getJSON('/subject/my_articles?kw='+encodeURIComponent(kw)+'&sid='+sid, function(result) { + placeholder.hide(); + + if (result.ok) { + var articles = result.data.articles; + if (articles.length == 0) { + $('#contribute-note-list').html('
    未找到相关文章
    '); + } else { + fillArticles(articles); + } + } else { + $('#contribute-note-list').html('
    '+result.msg+'
    '); + } + }) + }) + + $('.contribute-modal .search-input').on('change', function() { + if ($(this).val() == '') { + $('#contribute-note-list').html(noteListHtml); + } + }); + + $(document).keypress(function(evt){ + if (evt.which == 10 || evt.which == 13) { + $('.contribute-modal .search-btn').click(); + } + }); + + $('.contribute-modal').on('click', '.action-btn', function() { + var $articleDiv = $(this).parent(), + articleId = $articleDiv.data('id'), + sid = $('#follow').data('sid'); + + var that = this; + + if ($(this).hasClass('push')) { + $.post('/subject/contribute', {sid: sid, article_id: articleId}, function(result) { + if (result.ok) { + $articleDiv.children('.note-name').addClass('has-add'); + $(that).removeClass('push').addClass('remove'). + before('已加入').text('移除'); + } else { + alert(result.error); + } + }); + } else { + $.post('/subject/remove_contribute', {sid: sid, article_id: articleId}, function(result) { + if (result.ok) { + $articleDiv.children('.note-name').removeClass('has-add'); + $(that).removeClass('remove').addClass('push').text('投稿'); + $articleDiv.children('.status').remove(); + } else { + alert(result.error); + } + }); + } + }); + + function fillArticles(articles) { + var listHtml = ''; + for(var i in articles) { + listHtml += '
  • '+ + '
    '; + + if (articles[i].had_add) { + listHtml += '
    '+articles[i].title+'
    '+ + '已加入'+ + '移除'; + } else { + + listHtml += '
    '+articles[i].title+'
    '+ + '投稿'; + } + + listHtml += '
  • '; + } + $('#contribute-note-list').html(listHtml); + } +}); \ No newline at end of file diff --git a/template/common/modal.html b/template/common/modal.html new file mode 100644 index 00000000..f6a00074 --- /dev/null +++ b/template/common/modal.html @@ -0,0 +1,365 @@ + + \ No newline at end of file diff --git a/template/subject/index.html b/template/subject/index.html index 597c2056..a051892b 100644 --- a/template/subject/index.html +++ b/template/subject/index.html @@ -25,11 +25,17 @@

    {{if eq .me.Uid .subject.Uid}} - + {{else}} - + {{end}} - +
    @@ -93,7 +99,7 @@

     专题公告

    -
    +
    {{.subject.Description}}
    @@ -136,319 +142,18 @@

     关注 {{end}}

    + +{{include "common/modal.html" .}} {{end}} {{define "css"}} - + {{end}} {{define "js"}} - + + + {{end}} \ No newline at end of file From 176b8b75f24c4be70a3b2213bd036b51350efe3c Mon Sep 17 00:00:00 2001 From: xuxinhua Date: Tue, 21 Nov 2017 15:29:33 +0800 Subject: [PATCH 152/411] =?UTF-8?q?=E8=BF=87=E6=BB=A4=E7=8A=B6=E6=80=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/logic/subject.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/logic/subject.go b/src/logic/subject.go index 47e8d91e..345647bf 100644 --- a/src/logic/subject.go +++ b/src/logic/subject.go @@ -47,7 +47,7 @@ func (self SubjectLogic) FindArticles(ctx context.Context, sid int, orderBy stri subjectArticles := make([]*model.SubjectArticles, 0) err := MasterDB.Join("INNER", "subject_article", "subject_article.article_id = articles.id"). - Where("subject_article.sid=?", sid).OrderBy(order).Find(&subjectArticles) + Where("sid=? AND state=?", sid, model.ContributeStateOnline).OrderBy(order).Find(&subjectArticles) if err != nil { objLog.Errorln("SubjectLogic FindArticles Find subject_article error:", err) return nil From d02df7f20ab581645ef7f30293a8ba5bb30ab8a7 Mon Sep 17 00:00:00 2001 From: xuxinhua Date: Tue, 21 Nov 2017 20:54:24 +0800 Subject: [PATCH 153/411] =?UTF-8?q?=E5=8E=BB=E9=99=A4=E5=86=99=E6=AD=BBimg?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- template/subject/index.html | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/template/subject/index.html b/template/subject/index.html index a051892b..2e77a6e0 100644 --- a/template/subject/index.html +++ b/template/subject/index.html @@ -15,8 +15,8 @@
    - - + +

    {{.subject.Name}}

    From 024cb4ed890f2d76da7c7bff00679ed14e83696f Mon Sep 17 00:00:00 2001 From: polaris1119 Date: Wed, 22 Nov 2017 14:10:17 +0800 Subject: [PATCH 154/411] =?UTF-8?q?=E5=8F=91=E5=B8=83GCTT=E6=96=87?= =?UTF-8?q?=E7=AB=A0=EF=BC=8C=E5=A6=82=E6=9E=9C=E8=AF=91=E8=80=85=E7=BB=91?= =?UTF-8?q?=E5=AE=9A=E4=BA=86=E4=B8=AD=E6=96=87=E7=BD=91=E7=94=A8=E6=88=B7?= =?UTF-8?q?=EF=BC=8C=E5=8F=91=E5=B8=83=E8=80=85=E5=8F=98=E4=B8=BA=E8=AF=91?= =?UTF-8?q?=E8=80=85?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/logic/article.go | 23 ++++++++++++++++++++++- src/model/article.go | 10 +++++++++- template/articles/detail.html | 2 +- template/gctt/new.html | 2 +- 4 files changed, 33 insertions(+), 4 deletions(-) diff --git a/src/logic/article.go b/src/logic/article.go index 3fd59a12..a70f3a19 100644 --- a/src/logic/article.go +++ b/src/logic/article.go @@ -286,9 +286,12 @@ func (self ArticleLogic) ParseZhihuArticle(ctx context.Context, articleUrl strin return article, nil } +// Publish 发布文章 func (self ArticleLogic) Publish(ctx context.Context, me *model.Me, form url.Values) (int, error) { objLog := GetLogger(ctx) + var uid = me.Uid + article := &model.Article{ Domain: WebsiteSetting.Domain, Name: WebsiteSetting.Name, @@ -318,6 +321,24 @@ func (self ArticleLogic) Publish(ctx context.Context, me *model.Me, form url.Val return 0, errors.New("request_id is empty!") } + // GCTT 译文,如果译者关联了本站账号,author 改为译者 + if article.GCTT { + translator := form.Get("translator") + gcttUser := &model.GCTTUser{} + _, err := MasterDB.Where("username=?", translator).Get(gcttUser) + if err != nil { + objLog.Errorln("article publish find gctt user error:", err) + } + + if gcttUser.Uid > 0 { + user := DefaultUser.findUser(ctx, gcttUser.Uid) + article.Author = user.Username + article.AuthorTxt = user.Username + + uid = user.Uid + } + } + session := MasterDB.NewSession() defer session.Close() session.Begin() @@ -354,7 +375,7 @@ func (self ArticleLogic) Publish(ctx context.Context, me *model.Me, form url.Val session.Commit() - go publishObservable.NotifyObservers(me.Uid, model.TypeArticle, article.Id) + go publishObservable.NotifyObservers(uid, model.TypeArticle, article.Id) return article.Id, nil } diff --git a/src/model/article.go b/src/model/article.go index 7868db1d..e59cea87 100644 --- a/src/model/article.go +++ b/src/model/article.go @@ -9,6 +9,7 @@ package model import ( "encoding/json" "strconv" + "strings" "time" "github.com/go-xorm/xorm" @@ -98,13 +99,20 @@ type ArticleGCTT struct { Checker string URL string `xorm:"url"` - Avatar string `xorm:"-"` + Avatar string `xorm:"-"` + Checkers []string `xorm:"-"` } func (*ArticleGCTT) TableName() string { return "article_gctt" } +func (this *ArticleGCTT) AfterSet(name string, cell xorm.Cell) { + if name == "checker" { + this.Checkers = strings.Split(this.Checker, ",") + } +} + // 抓取网站文章的规则 type CrawlRule struct { Id int `json:"id" xorm:"pk autoincr"` diff --git a/template/articles/detail.html b/template/articles/detail.html index 1cdac5ef..671603bc 100644 --- a/template/articles/detail.html +++ b/template/articles/detail.html @@ -63,7 +63,7 @@

    作者:{{.article_gctt.Author}} 译者:{{.article_gctt.Translator}} - 校对:{{.article_gctt.Translator}} + 校对:{{range .article_gctt.Checkers}}{{.}} {{end}}

    本文由 GCTT 原创编译,{{.setting.Name}} 荣誉推出

    diff --git a/template/gctt/new.html b/template/gctt/new.html index 802bfe52..cb3e6979 100644 --- a/template/gctt/new.html +++ b/template/gctt/new.html @@ -43,7 +43,7 @@

    - +
    From 9d5a720ebd2bb5db079c9dbd748e7515756cb517 Mon Sep 17 00:00:00 2001 From: polaris1119 Date: Fri, 24 Nov 2017 10:21:06 +0800 Subject: [PATCH 155/411] =?UTF-8?q?=E4=BF=AE=E5=A4=8D=E8=AF=84=E8=AE=BA?= =?UTF-8?q?=E6=A5=BC=E5=B1=82=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/logic/article.go | 3 +++ src/logic/comment.go | 8 ++++---- template/articles/detail.html | 2 +- template/gctt/index.html | 2 +- 4 files changed, 9 insertions(+), 6 deletions(-) diff --git a/src/logic/article.go b/src/logic/article.go index a70f3a19..2772e7cd 100644 --- a/src/logic/article.go +++ b/src/logic/article.go @@ -336,6 +336,9 @@ func (self ArticleLogic) Publish(ctx context.Context, me *model.Me, form url.Val article.AuthorTxt = user.Username uid = user.Uid + + // 【编辑】 + article.OpUser = me.Username } } diff --git a/src/logic/comment.go b/src/logic/comment.go index 21713629..96123cd7 100644 --- a/src/logic/comment.go +++ b/src/logic/comment.go @@ -163,14 +163,14 @@ func (self CommentLogic) Publish(ctx context.Context, uid, objid int, form url.V // 暂时只是从数据库中取出最后的评论楼层 tmpCmt := &model.Comment{} - _, err := MasterDB.Where("objid=? AND objtype=?", objid, objtype).OrderBy("ctime DESC").Get(tmpCmt) + _, err := MasterDB.Where("objid=? AND objtype=?", objid, objtype).OrderBy("floor DESC").Get(tmpCmt) if err != nil { - objLog.Errorln("post comment service error:", err) + objLog.Errorln("post comment find last floor error:", err) return nil, err - } else { - comment.Floor = tmpCmt.Floor + 1 } + comment.Floor = tmpCmt.Floor + 1 + if tmpCmt.Uid == comment.Uid && tmpCmt.Content == comment.Content { objLog.Infof("had post comment: %+v", *comment) return tmpCmt, nil diff --git a/template/articles/detail.html b/template/articles/detail.html index 671603bc..36349272 100644 --- a/template/articles/detail.html +++ b/template/articles/detail.html @@ -59,7 +59,7 @@

    {{if .article.GCTT}}
    -

    via: {{.article_gctt.URL}}

    +

    via: {{.article_gctt.URL}}

    作者:{{.article_gctt.Author}} 译者:{{.article_gctt.Translator}} diff --git a/template/gctt/index.html b/template/gctt/index.html index 2aaf97de..d63eec0f 100644 --- a/template/gctt/index.html +++ b/template/gctt/index.html @@ -15,7 +15,7 @@

    简介

    GCTT (Go Chinese Translation Team) 是 Go中文网(https://studygolang.com) 翻译组,负责从国外优秀媒体翻译 Go 相关的技术、教程、资讯、杂文等内容。

    GCTT 的组成

    -

    选题,负责选择合适的内容,并将原文转换为 markdown 格式(可以使用 https://domchristie.github.io/to-markdown/ 做转换),提交到 GCTT 库中。

    +

    选题,负责选择合适的内容,并将原文转换为 markdown 格式(可以使用 https://domchristie.github.io/to-markdown/ 做转换) (为了减轻选题的工作,经大家讨论,转 markdown 的工作取消,文件中只保留标题和原文链接。)提交到 GCTT 库中。

    译者,负责从选题中选择内容进行翻译。

    校对,负责将初译的文章进行文字润色、技术校对等工作。

    发布,负责将校对后的文章,排版发布到 Go中文网 的文章中。

    From bfeccf25aca9b4d6e71eb62aec33db4e4f9b58e6 Mon Sep 17 00:00:00 2001 From: polaris1119 Date: Sat, 25 Nov 2017 10:45:05 +0800 Subject: [PATCH 156/411] =?UTF-8?q?=E6=96=87=E7=AB=A0=E4=BD=BF=E7=94=A8=20?= =?UTF-8?q?prism=20=E9=AB=98=E4=BA=AE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- static/js/common.js | 25 +++++++++++++++++++++++++ template/articles/detail.html | 6 +++--- template/gctt/new.html | 3 +-- 3 files changed, 29 insertions(+), 5 deletions(-) diff --git a/static/js/common.js b/static/js/common.js index 962ff276..d39583c1 100644 --- a/static/js/common.js +++ b/static/js/common.js @@ -107,6 +107,31 @@ SG.markSetting = function() { return marked; } +SG.markSettingNoHightlight = function() { + var renderer = new marked.Renderer(); + + // 对 html 进行处理 + renderer.html = function(html) { + if (html.indexOf('& 等字符 SG.replaceCodeChar = function(code) { return code.replace(/.*<\/code>/g, function(matched, index, origin) { diff --git a/template/articles/detail.html b/template/articles/detail.html index 36349272..4c8faf81 100644 --- a/template/articles/detail.html +++ b/template/articles/detail.html @@ -176,7 +176,7 @@

    {{end}} {{define "css"}} - + {{if .article.Css}} @@ -198,8 +198,8 @@

    {{define "js"}} - - + + diff --git a/template/gctt/new.html b/template/gctt/new.html index cb3e6979..53329a4d 100644 --- a/template/gctt/new.html +++ b/template/gctt/new.html @@ -200,8 +200,7 @@

     发布文章 $('#markdown-content').on('input propertychange', function() { var markdownString = $(this).val(); - // 配置 marked 语法高亮 - marked = SG.markSetting(); + marked = SG.markSettingNoHightlight(); var contentHtml = marked(markdownString); contentHtml = SG.replaceCodeChar(contentHtml); From 137d406e10237c7cf0dcc786a83f57a96811529f Mon Sep 17 00:00:00 2001 From: polaris1119 Date: Sat, 25 Nov 2017 14:06:19 +0800 Subject: [PATCH 157/411] =?UTF-8?q?=E4=BD=BF=E7=94=A8=20prism=20=E9=AB=98?= =?UTF-8?q?=E4=BA=AE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- static/js/articles.js | 3 +-- static/js/common.js | 1 + static/js/topics.js | 2 +- template/articles/detail.html | 29 +++++++++++++---------------- template/topics/detail.html | 12 +++++++++--- 5 files changed, 25 insertions(+), 22 deletions(-) diff --git a/static/js/articles.js b/static/js/articles.js index a8028579..45fa85da 100644 --- a/static/js/articles.js +++ b/static/js/articles.js @@ -4,8 +4,7 @@ SG.Articles.prototype = new SG.Publisher(); SG.Articles.prototype.parseContent = function(selector) { var markdownString = selector.text(); - // 配置 marked 语法高亮 - marked = SG.markSetting(); + marked = SG.markSettingNoHightlight(); var contentHtml = marked(markdownString); contentHtml = SG.replaceCodeChar(contentHtml); diff --git a/static/js/common.js b/static/js/common.js index d39583c1..ef601c27 100644 --- a/static/js/common.js +++ b/static/js/common.js @@ -134,6 +134,7 @@ SG.markSettingNoHightlight = function() { // 替换 `` 代码块中的 "<>& 等字符 SG.replaceCodeChar = function(code) { + code = code.replace(/.*<\/code>/g, function(matched, index, origin) { return SG.replaceSpecialChar(matched); }); diff --git a/static/js/topics.js b/static/js/topics.js index bfdc21a4..347e3e19 100644 --- a/static/js/topics.js +++ b/static/js/topics.js @@ -17,7 +17,7 @@ SG.Topics.prototype = new SG.Publisher(); SG.Topics.prototype.parseContent = function(selector) { // 配置 marked 语法高亮 - marked = SG.markSetting(); + marked = SG.markSettingNoHightlight(); selector.each(function() { var markdownString = $(this).text(); diff --git a/template/articles/detail.html b/template/articles/detail.html index 4c8faf81..11b7ad17 100644 --- a/template/articles/detail.html +++ b/template/articles/detail.html @@ -183,7 +183,7 @@

    {{end}} {{if .article.IsSelf}} - + {{end}} @@ -148,7 +149,9 @@

     发布文章 - + + + @@ -147,10 +148,9 @@

     发布文章 - - + + + diff --git a/template/sidebar/comment.html b/template/sidebar/comment.html index c06e49d7..9af0f5d7 100644 --- a/template/sidebar/comment.html +++ b/template/sidebar/comment.html @@ -1,7 +1,8 @@