├── README.md
├── src
├── static
│ ├── img
│ │ ├── bg2.png
│ │ ├── close.png
│ │ ├── head.png
│ │ ├── tx1.png
│ │ ├── tx2.png
│ │ ├── close2.png
│ │ ├── search.png
│ │ ├── gitee-icon.png
│ │ ├── list-star.png
│ │ ├── projectbg.png
│ │ ├── github-icon.png
│ │ ├── list-rocket.png
│ │ ├── login-index.png
│ │ ├── kcoin-log-big.png
│ │ ├── kcoin-logo-blue.png
│ │ └── kcoin-project-list-half-icon.png
│ ├── js
│ │ ├── capitalInjection.js
│ │ ├── paging.js
│ │ ├── EasePack.min.js
│ │ ├── import.js
│ │ └── helloweb.js
│ └── css
│ │ ├── homepage.css
│ │ ├── loginJoin.css
│ │ ├── platformAdmin.css
│ │ ├── project.css
│ │ └── personal.css
├── main.go
├── conf
│ └── app.conf
├── controllers
│ ├── platforminformation.go
│ ├── projectFunding.go
│ ├── logout.go
│ ├── default.go
│ ├── projectNotice.go
│ ├── projectMemberWork.go
│ ├── projectInfo.go
│ ├── capitalInjection.go
│ ├── projectMemberList.go
│ ├── projectSetting.go
│ ├── personalPage.go
│ ├── homepage.go
│ ├── authorize.go
│ ├── import.go
│ ├── ccSearchPage.go
│ ├── personalProjects.go
│ └── importHelper.go
├── views
│ ├── footer.html
│ ├── platformAdminTopNav.html
│ ├── projectSetting.html
│ ├── projectTopNav.html
│ ├── projectNotice.html
│ ├── projectMemberList.html
│ ├── leftNav.html
│ ├── platformInformation.html
│ ├── projectInfo.html
│ ├── ccSearchPage.html
│ ├── import.tpl
│ ├── homePage.tpl
│ ├── projectMemberWork.html
│ ├── capitalInjection.html
│ ├── join.html
│ ├── login.html
│ ├── projectFunding.html
│ ├── personalProjects.html
│ └── personalPage.html
├── models
│ ├── ccInject.go
│ ├── getCsNum.go
│ ├── getCommiters.go
│ ├── searchCcAndCs.go
│ ├── getGithubRepos.go
│ ├── getAllJoinedProjects.go
│ ├── models.go
│ ├── k_project.go
│ ├── sendEmailToPotentialUsers.go
│ └── k_user.go
├── service
│ ├── URLUtil.go
│ ├── get_issue_info.go
│ └── github_helper.go
├── routers
│ └── router.go
└── tests
│ └── models_test.go
├── user-story
├── 1901210384.md
├── 1900022750.md
├── 1901210560.md
├── 1901210678.md
├── 1901210581.md
├── 1901210466.md
├── 1901210749.md
├── 1901210645.md
├── 1901210408.md
└── 1901210377.md
├── .gitignore
├── go.mod
├── user-story.md
├── database
└── create.sql
└── go.sum
/README.md:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/static/img/bg2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/OS-ABC/Kcoin-Golang/HEAD/src/static/img/bg2.png
--------------------------------------------------------------------------------
/src/static/img/close.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/OS-ABC/Kcoin-Golang/HEAD/src/static/img/close.png
--------------------------------------------------------------------------------
/src/static/img/head.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/OS-ABC/Kcoin-Golang/HEAD/src/static/img/head.png
--------------------------------------------------------------------------------
/src/static/img/tx1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/OS-ABC/Kcoin-Golang/HEAD/src/static/img/tx1.png
--------------------------------------------------------------------------------
/src/static/img/tx2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/OS-ABC/Kcoin-Golang/HEAD/src/static/img/tx2.png
--------------------------------------------------------------------------------
/src/static/img/close2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/OS-ABC/Kcoin-Golang/HEAD/src/static/img/close2.png
--------------------------------------------------------------------------------
/src/static/img/search.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/OS-ABC/Kcoin-Golang/HEAD/src/static/img/search.png
--------------------------------------------------------------------------------
/src/static/img/gitee-icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/OS-ABC/Kcoin-Golang/HEAD/src/static/img/gitee-icon.png
--------------------------------------------------------------------------------
/src/static/img/list-star.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/OS-ABC/Kcoin-Golang/HEAD/src/static/img/list-star.png
--------------------------------------------------------------------------------
/src/static/img/projectbg.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/OS-ABC/Kcoin-Golang/HEAD/src/static/img/projectbg.png
--------------------------------------------------------------------------------
/src/static/img/github-icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/OS-ABC/Kcoin-Golang/HEAD/src/static/img/github-icon.png
--------------------------------------------------------------------------------
/src/static/img/list-rocket.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/OS-ABC/Kcoin-Golang/HEAD/src/static/img/list-rocket.png
--------------------------------------------------------------------------------
/src/static/img/login-index.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/OS-ABC/Kcoin-Golang/HEAD/src/static/img/login-index.png
--------------------------------------------------------------------------------
/src/static/img/kcoin-log-big.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/OS-ABC/Kcoin-Golang/HEAD/src/static/img/kcoin-log-big.png
--------------------------------------------------------------------------------
/src/static/img/kcoin-logo-blue.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/OS-ABC/Kcoin-Golang/HEAD/src/static/img/kcoin-logo-blue.png
--------------------------------------------------------------------------------
/src/static/img/kcoin-project-list-half-icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/OS-ABC/Kcoin-Golang/HEAD/src/static/img/kcoin-project-list-half-icon.png
--------------------------------------------------------------------------------
/user-story/1901210384.md:
--------------------------------------------------------------------------------
1 | #用户故事
2 |
3 | 作为一个Kcoin社区使用者,我希望获得更多的收益,但是我个人精力有限,因此我希望能够通过推广社区来获得更多收益
4 |
5 | 作为一个平台用户(无论什么身份),我希望我在平台中的虚拟财产更加安全,因此我希望可以拥有自己独立的支付密码
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | #add ignore files
2 | src/src
3 | *.exe
4 | *.exe~
5 | src/.idea/
6 | src/.vscode/
7 | .idea/
8 | src/__debug_bin
9 |
10 | # Mac OS
11 | **/.DS_Store
--------------------------------------------------------------------------------
/user-story/1900022750.md:
--------------------------------------------------------------------------------
1 | # User Story
2 |
3 | 1. 作为一名想为开源项目做贡献的人,我希望使用项目搜索功能,以便快速定位到自己感兴趣的项目。
4 |
5 | 2. 作为一名开源项目的管理者,我希望使用网站通知功能,以便我在登录时就可以收到项目的信息动态,更好地管理项目。
6 |
7 |
--------------------------------------------------------------------------------
/user-story/1901210560.md:
--------------------------------------------------------------------------------
1 | ## 用户故事
2 |
3 | 作为一名投资者,我希望看到项目被哪些公司或机构使用,这样可以让我更好地决策,到底要不要给这个项目投资、要投资多少。
4 |
5 |
6 |
7 | 作为一名开发者,我希望可以推广我的项目,比如把它们分享到社交媒体,这样可以使更多同行看到、加入它们,提高它们的活跃度。
--------------------------------------------------------------------------------
/src/main.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | import (
4 | _ "Kcoin-Golang/src/routers"
5 |
6 | "github.com/astaxie/beego"
7 | )
8 |
9 | func main() {
10 |
11 | beego.Run()
12 | }
13 |
--------------------------------------------------------------------------------
/user-story/1901210678.md:
--------------------------------------------------------------------------------
1 | # User Story
2 |
3 | 1. 作为一名想为开源项目做贡献的人,我希望能够被智能推荐,避开人数过多做贡献得到CS收益过低的项目,找到符合自己技术背景并且CS收益高的项目。
4 |
5 | 2. 作为一名开源项目的管理者,我希望使用使用项目主页的图标及超链接,更好地观察项目成员的在不同项目中的CS贡献情况。
6 |
--------------------------------------------------------------------------------
/user-story/1901210581.md:
--------------------------------------------------------------------------------
1 | # 用户故事
2 |
3 | 1. 作为一名做出卓越贡献的贡献者,贾组长希望能有项目贡献与总体贡献排行榜,以便于扩大用户的社区影响力。
4 |
5 | 2. 作为一名新贡献者,我想要根据新用户问卷推荐最佳匹配项目,以便我快速上手熟悉最合适项目。
6 |
7 | 3. 作为一名项目管理者,我想要高度贡献者列表与具体工作列表,以便于增强对项目掌控。
8 |
9 |
--------------------------------------------------------------------------------
/user-story/1901210466.md:
--------------------------------------------------------------------------------
1 | # User Story
2 | 1. 作为一个游客,我想在没有登录的情况下,可以以游客的身份浏览该平台,看看平台里都哪些项目,再决定要不要注册一个账号或通过第三方授权登录该平台。
3 | 2. 作为一个想结交优秀朋友的普通用户,我希望有渠道能获得全站范围内cs数量排名前100的项目贡献者,并能够对他们添加关注。
4 | 3. 对于第一次登陆该平台的新用户,可以考虑布置几个“新手任务”给他们完成,便于快速熟悉该平台。完成“新手任务”后,即可奖励一些cs给新用户作为鼓励。
--------------------------------------------------------------------------------
/user-story/1901210749.md:
--------------------------------------------------------------------------------
1 | # 用户故事
2 |
3 | 1. 我是一名开源项目的管理者,我希望Kcoin能把我的开源项目智能推荐给参与了相似项目的人,这样能吸引更多人来我的项目中贡献代码。
4 | 2. 我是一名想在开源项目中做贡献的用户,我希望Kcoin能展示项目在Github上的star和committer数量等信息,以便我判断一个项目是否活跃且值得加入。
5 | 3. 我是一名小白用户,我希望Kcoin网站中能有一份介绍Kcoin的名词和操作的入门文档,这样我就可以快速上手了。
6 |
7 |
--------------------------------------------------------------------------------
/user-story/1901210645.md:
--------------------------------------------------------------------------------
1 | # 用户故事
2 | 1. 作为一个开源项目贡献者, 我不一定知道这个项目被托管到KCoin上, 因此当这个项目被托管到KCoin时, 我想要被正确通知. 当一个新的Contributor参与到项目时, 也需要被正确通知这个项目的托管情况.
3 | 2. 我需要知道个人所有CC的情况, 以及CC究竟能兑换什么物品, 即需要一个兑换商店.
4 | 3. 作为KCoin小白, 我需要知道KCoin有什么优势, 为什么要使用KCoin, 如何使用KCoin, 即需要一个指导文档.
--------------------------------------------------------------------------------
/user-story/1901210408.md:
--------------------------------------------------------------------------------
1 | # 用户故事
2 | 1. 我是一名项目管理者,我希望通过项目url能将我的项目导入到平台
3 | 2. 我是一名项目管理者,我希望能够通过设置规则,制定我的项目工作量和CS的兑换规则
4 | 3. 我是一名普通用户,我希望能够通过设置规则,在基金会投资CC时,按照工作量公平分配
5 | 4. 我是一名普通用户,我希望通过向开源社区提交代码,获得相应的CS
6 | 5. 我是一名普通用户,我希望通过oAuth邮箱登陆到个人中心。
7 | 6. 我是一名项目管理者,我希望查看项目总体CC和项目贡献量动态
--------------------------------------------------------------------------------
/user-story/1901210377.md:
--------------------------------------------------------------------------------
1 | # User story
2 |
3 | 1. 作为一个项目管理者,我想要在登录系统后收到项目参与者的活动消息,以便于我了解项目走向和项目参与者的动态。
4 | 2. 作为一个普通用户,我想要在网站上看到如何使用这个系统的向导信息,以便于我能够快速学会使用这个系统。
5 | 3. 作为一个项目投资人,我想要看到某个项目根据时间线展示的活跃图,以便于我能够找到有潜力的可以进行投资的项目。
6 | 4. 作为一个项目参与者,我想要在网站上了解到关于CS或CC的具体描述信息,以便于我明确对项目做出贡献后可以获取什么回报。
7 |
8 |
--------------------------------------------------------------------------------
/src/conf/app.conf:
--------------------------------------------------------------------------------
1 | appname = Kcoin-Golang
2 | httpport = 8080
3 | runmode = dev
4 | sessionon = true
5 | #这里设置oauth app的client id和client secret
6 | client_id = "c698bd09d35414343da4"
7 | client_secret ="e680c1f3ae01fab2175efa4b3366cc43d7ca36ac"
8 | secret_token="0123456789"
9 | #允許接收post請求的request body
10 | copyrequestbody = true
--------------------------------------------------------------------------------
/src/controllers/platforminformation.go:
--------------------------------------------------------------------------------
1 | package controllers
2 |
3 | import (
4 | _ "Kcoin-Golang/src/models"
5 |
6 | "github.com/astaxie/beego"
7 | )
8 |
9 | type PlatformInformationController struct {
10 | beego.Controller
11 | }
12 |
13 | func (c *PlatformInformationController) Get() {
14 | c.TplName = "platformInformation.html" //该controller对应的页面
15 | }
--------------------------------------------------------------------------------
/go.mod:
--------------------------------------------------------------------------------
1 | module Kcoin-Golang
2 |
3 | go 1.13
4 |
5 | require (
6 | github.com/PuerkitoBio/goquery v1.5.1
7 | github.com/astaxie/beego v1.12.0
8 | github.com/lib/pq v1.2.0
9 | github.com/shiena/ansicolor v0.0.0-20151119151921-a422bbe96644 // indirect
10 | github.com/smartystreets/goconvey v1.6.4 // indirect
11 | google.golang.org/appengine v1.6.5 // indirect
12 | )
13 |
--------------------------------------------------------------------------------
/src/controllers/projectFunding.go:
--------------------------------------------------------------------------------
1 | // TODO Project相关的controller可以全部放到这个文件下, 即这个文件有若干Controller.
2 | package controllers
3 |
4 | import (
5 | _ "Kcoin-Golang/src/models"
6 |
7 | "github.com/astaxie/beego"
8 | )
9 |
10 | type ProjectFundingController struct {
11 | beego.Controller
12 | }
13 |
14 | func (c *ProjectFundingController) Get() {
15 | c.TplName = "projectFunding.html" //该controller对应的页面
16 | }
17 |
--------------------------------------------------------------------------------
/src/controllers/logout.go:
--------------------------------------------------------------------------------
1 | package controllers
2 |
3 | import (
4 | _ "Kcoin-Golang/src/models"
5 | "fmt"
6 | "github.com/astaxie/beego"
7 | )
8 |
9 | type LogOutController struct {
10 | beego.Controller
11 | }
12 |
13 | func (c *LogOutController) Get() {
14 |
15 | c.Ctx.SetCookie("userName", "", 100)
16 | c.Ctx.SetCookie("headShotUrl", "", 100)
17 | c.Ctx.SetCookie("status", string('0'), 100)
18 | fmt.Println("congrat,his is log out ")
19 | c.Redirect("/homepage", 302)
20 |
21 | }
22 |
--------------------------------------------------------------------------------
/src/views/footer.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
17 |
18 |
19 |
--------------------------------------------------------------------------------
/src/controllers/default.go:
--------------------------------------------------------------------------------
1 | package controllers
2 |
3 | import (
4 | "github.com/astaxie/beego"
5 | )
6 |
7 | type MainController struct {
8 | beego.Controller
9 | }
10 |
11 | type LoginController struct {
12 | beego.Controller
13 | }
14 |
15 | type JoinController struct {
16 | beego.Controller
17 | }
18 |
19 | func (c *MainController) Get() {
20 | c.Data["Website"] = "beego.me"
21 | c.Data["Email"] = "astaxie@gmail.com"
22 | c.TplName = "index.tpl"
23 | }
24 |
25 | func (c *LoginController) Get() {
26 | c.TplName = "login.html"
27 | }
28 |
29 | func (c *JoinController) Get() {
30 | c.TplName = "join.html"
31 | }
32 |
--------------------------------------------------------------------------------
/src/static/js/capitalInjection.js:
--------------------------------------------------------------------------------
1 | function showPopup(){
2 | // var page = document.getElementById("injection");
3 | // page.style.display="block";
4 | // var button = document.getElementById("commit");
5 | // button.innerHTML="确认";
6 | var popUp = document.getElementById("injection");
7 | popUp.style.position= "absolute";
8 | popUp.style.zIndex="100";
9 | popUp.style.width = "100%";
10 | popUp.style.height = "100%";
11 | popUp.style.visibility = "visible";
12 |
13 | }
14 |
15 | function hidePopup(){
16 | var popUp = document.getElementById("injection");
17 | popUp.style.visibility = "hidden";
18 | }
19 |
20 |
21 |
--------------------------------------------------------------------------------
/src/models/ccInject.go:
--------------------------------------------------------------------------------
1 | package models
2 |
3 | import (
4 | "fmt"
5 | "github.com/astaxie/beego/orm"
6 | )
7 |
8 | func CCInject(donatorId int, projId int, cc float64, dtype int) error {
9 | o := orm.NewOrm()
10 | err := o.Using("default")
11 | if err != nil {
12 | return fmt.Errorf("database connection error:"+err.Error())
13 | }
14 | SQLQuery := `INSERT INTO "k_cc_donate_record" (donate_from, donate_into, donate_cc, donate_type, donate_time)
15 | VALUES (?, ?, ?, ?, "CURRENT_TIMESTAMP(0)")`
16 | _, err = o.Raw(SQLQuery, donatorId, projId, cc, dtype).Exec()
17 | if err != nil {
18 | return fmt.Errorf("database insert error: "+err.Error())
19 | }
20 | err = nil
21 | return err
22 | }
23 |
--------------------------------------------------------------------------------
/src/models/getCsNum.go:
--------------------------------------------------------------------------------
1 | package models
2 |
3 | import (
4 | "strconv"
5 |
6 | "github.com/astaxie/beego/orm"
7 | )
8 |
9 | func GetCsNum(github_id string) int {
10 |
11 | //db, err := sql.Open("postgres", "user=sspkukcoin password=kcoin2019 dbname=postgres host=114.115.133.140 port=5432 sslmode=disable")
12 |
13 | o := orm.NewOrm()
14 | _ = o.Using("default")
15 |
16 | querySql := `select user_cs from "k_user_in_project" where user_id in (select k_user_id from "k_user" where github_id = ?)`
17 | var maps []orm.Params
18 | _, err := o.Raw(querySql, github_id).Values(&maps)
19 | checkErr(err)
20 | var user_cs string
21 | for _, term := range maps {
22 | user_cs = term["user_cs"].(string)
23 | }
24 | res, _ := strconv.Atoi(user_cs)
25 | return res
26 | }
27 |
28 | func checkErr(err error) {
29 | if err != nil {
30 | panic(err)
31 | }
32 | }
33 |
--------------------------------------------------------------------------------
/src/models/getCommiters.go:
--------------------------------------------------------------------------------
1 | package models
2 |
3 | //api:https://api.github.com/repos/OS-ABC/Kcoin-Golang/commits
4 |
5 | import (
6 | "fmt"
7 | "io/ioutil"
8 | "net/http"
9 | )
10 |
11 | // TODO 该函数尚未完全完成, 需要完成获取某个项目的所有commiter信息
12 | //验证是否是项目commiter的接口,参数为项目名称和用户名称
13 | func checkAutho(userName string, programName string) string {
14 | //请求:获取此项目的commiter信息
15 | var url_1 string = "https://api.github.com/repos/" + userName + "/" + programName + "/" + "commits"
16 | client := &http.Client{}
17 | response, _ := client.Get(url_1)
18 | defer response.Body.Close()
19 | body, err_1 := ioutil.ReadAll(response.Body)
20 | if err_1 != nil {
21 | panic(err_1)
22 | }
23 |
24 | fmt.Println(string(body))
25 | return string(body)
26 | }
27 |
28 | //使用实例:
29 | //func main() string{
30 | // var info string=checkAutho("PHP-is-Best","Kcoin-Golang")
31 | // fmt.Println(info)
32 | // return info
33 | //}
34 |
--------------------------------------------------------------------------------
/src/views/platformAdminTopNav.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Kcoin
6 |
7 |
8 |
9 |
15 |
22 |
23 |
24 |
25 |
--------------------------------------------------------------------------------
/src/views/projectSetting.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | projectsetting
6 |
7 |
8 |
9 |
10 | {{template "./projectTopNav.html" .}}
11 |
14 |
25 |
26 |
27 | {{template "./footer.html" .}}
28 |
29 |
30 |
--------------------------------------------------------------------------------
/src/views/projectTopNav.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Kcoin
6 |
7 |
8 |
9 |
15 |
16 |

17 |
18 |
{{.id}}
19 |
stars: {{.starNum}} contributors: {{.contributorsNum}}
20 |
项目详情
21 |
项目动态
22 |
项目成员
23 |
项目设置
24 |
25 |
26 |
--------------------------------------------------------------------------------
/src/controllers/projectNotice.go:
--------------------------------------------------------------------------------
1 | package controllers
2 |
3 | import (
4 | _ "Kcoin-Golang/src/models"
5 | "Kcoin-Golang/src/service"
6 |
7 | "github.com/astaxie/beego"
8 | )
9 |
10 | type ProjectNoticeController struct {
11 | beego.Controller
12 | }
13 |
14 | func (c *ProjectNoticeController) Get() {
15 | id := c.Ctx.Input.Param(":id")
16 |
17 | c.Data["id"] = id
18 |
19 | fakeURL := "https://github.com/Darkone0/weatherForcast"
20 |
21 | // starNum := models.GetStarNum(fakeURL)
22 | // contributorsNum := models.GetContributorNum(fakeURL)
23 | starNum := c.GetSession(id + "starNum")
24 | if starNum == nil {
25 | starNum = service.GetStarNum(fakeURL)
26 | c.SetSession(id+"starNum", starNum)
27 | }
28 |
29 | contributorsNum := c.GetSession(id + "contributorsNum")
30 | if contributorsNum == nil {
31 | contributorsNum = service.GetContributorNum(fakeURL)
32 | c.SetSession(id+"contributorsNum", contributorsNum)
33 | }
34 |
35 | c.Data["starNum"] = starNum
36 | c.Data["contributorsNum"] = contributorsNum
37 | c.TplName = "projectNotice.html" //该controller对应的页面
38 | }
39 |
--------------------------------------------------------------------------------
/src/views/projectNotice.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | 项目信息
5 |
6 |
7 |
8 |
9 |
10 | {{template "./projectTopNav.html" .}}
11 |
12 |
15 |
16 |
17 |
18 |
19 | 2012
20 |
21 |
24 |
25 |
26 |
27 |
28 |
29 |
30 | {{template "./footer.html" .}}
31 |
--------------------------------------------------------------------------------
/src/controllers/projectMemberWork.go:
--------------------------------------------------------------------------------
1 | package controllers
2 |
3 | import (
4 | _ "Kcoin-Golang/src/models"
5 | "Kcoin-Golang/src/service"
6 |
7 | "github.com/astaxie/beego"
8 | )
9 |
10 | type ProjectMemberWorkController struct {
11 | beego.Controller
12 | }
13 |
14 | func (c *ProjectMemberWorkController) Get() {
15 | id := c.Ctx.Input.Param(":id")
16 | c.Data["id"] = id
17 |
18 | fakeURL := "https://github.com/Darkone0/weatherForcast"
19 |
20 | // starNum := models.GetStarNum(fakeURL)
21 | // contributorsNum := models.GetContributorNum(fakeURL)
22 | starNum := c.GetSession(id + "starNum")
23 | if starNum == nil {
24 | starNum = service.GetStarNum(fakeURL)
25 | c.SetSession(id+"starNum", starNum)
26 | c.Ctx.SetCookie(id+"starNum", starNum.(string))
27 | }
28 |
29 | contributorsNum := c.GetSession(id + "contributorsNum")
30 | if contributorsNum == nil {
31 | contributorsNum = service.GetContributorNum(fakeURL)
32 | c.SetSession(id+"contributorsNum", contributorsNum)
33 | }
34 |
35 | c.Data["starNum"] = starNum
36 | c.Data["contributorsNum"] = contributorsNum
37 | c.TplName = "projectMemberWork.html" //该controller对应的页面
38 | }
39 |
--------------------------------------------------------------------------------
/src/views/projectMemberList.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | 项目信息
5 |
6 |
7 |
8 |
9 | {{template "./projectTopNav.html" .}}
10 |
11 |
14 |
15 |
16 |
21 |
22 | {{range.membersInfo}}
23 |
24 |

25 |
26 |
27 |
用户名:{{.UserName}}
28 |
贡献度:1 收益:1
29 |
30 | {{end}}
31 |
32 |
33 | {{template "./footer.html" .}}
34 |
--------------------------------------------------------------------------------
/src/controllers/projectInfo.go:
--------------------------------------------------------------------------------
1 | package controllers
2 |
3 | import (
4 | "Kcoin-Golang/src/models"
5 | "Kcoin-Golang/src/service"
6 |
7 | "github.com/astaxie/beego"
8 | )
9 |
10 | type ProjectInfoController struct {
11 | beego.Controller
12 | }
13 |
14 | func (c *ProjectInfoController) Get() {
15 | //session获取id
16 |
17 | id := c.Ctx.Input.Param(":id")
18 | c.Data["id"] = id
19 | fakeURL := "https://github.com/Darkone0/weatherForcast"
20 |
21 | // starNum := models.GetStarNum(fakeURL)
22 | // contributorsNum := models.GetContributorNum(fakeURL)
23 | //这里的session都没有对不同项目进行区分,后续应当还需要更改
24 | starNum := c.GetSession(id + "starNum")
25 | if starNum == nil {
26 | starNum = service.GetStarNum(fakeURL)
27 | c.SetSession(id+"starNum", starNum)
28 | }
29 |
30 | contributorsNum := c.GetSession(id + "contributorsNum")
31 | if contributorsNum == nil {
32 | contributorsNum = service.GetContributorNum(fakeURL)
33 | c.SetSession(id+"contributorsNum", contributorsNum)
34 | }
35 | projectCC, _ := models.GetProjectsCC(id)
36 | c.Data["projectCC"] = projectCC
37 | c.Data["starNum"] = starNum
38 | c.Data["contributorsNum"] = contributorsNum
39 | c.TplName = "projectInfo.html"
40 | }
41 |
--------------------------------------------------------------------------------
/src/service/URLUtil.go:
--------------------------------------------------------------------------------
1 | package service
2 |
3 | import (
4 | "fmt"
5 | "net/http"
6 | "strings"
7 | )
8 |
9 | func ParseGithubHTTPSUrl(url string) (userName string, userRepo string, err error) {
10 | splitedUrl := strings.Split(url, "/")
11 | if len(splitedUrl) != 5 {
12 | return "", "", fmt.Errorf("invalid url")
13 | }
14 | userName = splitedUrl[3]
15 | userRepo = strings.Split(splitedUrl[4], ".")[0] //处理url最后可能出现的.git
16 | return userName, userRepo, nil
17 | }
18 |
19 | //查询项目url是否合法,且判断用户是否有权限导入
20 | func CheckGithubRepoUrl(githubName, url string) error {
21 | _, repoName, err := ParseGithubHTTPSUrl(url)
22 | //TODO:err处理等待解析函数pr合并后更新
23 | if err != nil {
24 | return err
25 | }
26 | //info := GithubUser[userId]
27 | //userName := info.GithubName
28 | apiUrl := "https://api.github.com/repos/" + githubName + "/" + repoName
29 | resp, err := http.Get(apiUrl)
30 | if err != nil {
31 | return err
32 | }
33 | if resp.StatusCode != 200 {
34 | if resp.StatusCode == 404 {
35 | //fmr.Errorf()可直接返回error类型,参数为error.Error()返回值
36 | return fmt.Errorf("this repo Url is not valid")
37 | } else {
38 | return fmt.Errorf("err %d", resp.StatusCode)
39 | }
40 | }
41 | return nil
42 | }
43 |
--------------------------------------------------------------------------------
/src/controllers/capitalInjection.go:
--------------------------------------------------------------------------------
1 | package controllers
2 |
3 | import (
4 | "Kcoin-Golang/src/models"
5 | "encoding/json"
6 | "fmt"
7 | "github.com/astaxie/beego"
8 | )
9 |
10 | type CapitalInjectionController struct {
11 | beego.Controller
12 | }
13 | func (c *CapitalInjectionController) Get(){
14 | //从cookie中取出状态
15 | isLogin :=c.Ctx.GetCookie("status")
16 |
17 | //把Json字符串中的数据解析到结构体中
18 | var proj models.ProjectInfo
19 | projectBuf , _ := models.GetAllProjectsInfo()
20 | err := json.Unmarshal([]byte(projectBuf),&proj)
21 | if err != nil {
22 | fmt.Println("err=", err)
23 | //return
24 | }
25 |
26 | //把结构体传到模板当中
27 | c.Data["Projects"] = proj
28 |
29 | //判断当前登录状态
30 | if isLogin == "1"{
31 | c.Data["isLogin"] = true
32 | user := models.UserInfo{Data:&models.UserData{}}//user中存放着json解析后获得的数据。
33 | user.Data.UserName = c.Ctx.GetCookie("userName")
34 | user.Data.HeadShotUrl = c.Ctx.GetCookie("headShotUrl")
35 | c.Data["user"] = user
36 | } else {
37 | c.Data["isLogin"] = false
38 | c.Ctx.SetCookie("userName","",100)
39 | c.Ctx.SetCookie("headShotUrl","",100)
40 | c.Ctx.SetCookie("status", string('0'),100)
41 | c.Ctx.SetCookie("lastUri",c.Ctx.Request.RequestURI)
42 | }
43 |
44 | //设置Get方法对应展示的模板
45 | c.TplName = "capitalInjection.html"
46 | }
--------------------------------------------------------------------------------
/src/controllers/projectMemberList.go:
--------------------------------------------------------------------------------
1 | package controllers
2 |
3 | import (
4 | "Kcoin-Golang/src/models"
5 | _ "Kcoin-Golang/src/models"
6 | "Kcoin-Golang/src/service"
7 |
8 | "github.com/astaxie/beego"
9 | )
10 |
11 | type ProjectMemberListController struct {
12 | beego.Controller
13 | }
14 |
15 | func (c *ProjectMemberListController) Get() {
16 | id := c.Ctx.Input.Param(":id")
17 | c.Data["id"] = id
18 | //解决了session造成的bug后,通过读取项目id返回所有项目的信息
19 | membersInfo, _ := models.GetMembersInfoByProjectName(id)
20 | c.Data["membersInfo"] = membersInfo
21 |
22 | fakeURL := "https://github.com/Darkone0/weatherForcast"
23 |
24 | // starNum := models.GetStarNum(fakeURL)
25 | // contributorsNum := models.GetContributorNum(fakeURL)
26 | starNum := c.GetSession(id + "starNum")
27 | if starNum == nil {
28 | starNum = service.GetStarNum(fakeURL)
29 | c.SetSession(id+"starNum", starNum)
30 | }
31 |
32 | contributorsNum := c.GetSession(id + "contributorsNum")
33 | if contributorsNum == nil {
34 | contributorsNum = service.GetContributorNum(fakeURL)
35 | c.SetSession(id+"contributorsNum", contributorsNum)
36 | }
37 |
38 | c.Data["starNum"] = starNum
39 | c.Data["contributorsNum"] = contributorsNum
40 |
41 | c.TplName = "projectMemberList.html" //该controller对应的页面
42 | }
43 |
--------------------------------------------------------------------------------
/src/controllers/projectSetting.go:
--------------------------------------------------------------------------------
1 | package controllers
2 |
3 | import (
4 | _ "Kcoin-Golang/src/models"
5 | "Kcoin-Golang/src/service"
6 |
7 | "github.com/astaxie/beego"
8 | )
9 |
10 | type ProjectSettingController struct {
11 | beego.Controller
12 | }
13 |
14 | func (c *ProjectSettingController) Get() {
15 | id := c.Ctx.Input.Param(":id")
16 |
17 | c.Data["id"] = id
18 |
19 | fakeURL := "https://github.com/Darkone0/weatherForcast"
20 |
21 | // starNum := models.GetStarNum(fakeURL)
22 | // contributorsNum := models.GetContributorNum(fakeURL)
23 | starNum := c.GetSession(id + "starNum")
24 | if starNum == nil {
25 | starNum = service.GetStarNum(fakeURL)
26 | c.SetSession(id+"starNum", starNum)
27 | }
28 |
29 | contributorsNum := c.GetSession(id + "contributorsNum")
30 | if contributorsNum == nil {
31 | contributorsNum = service.GetContributorNum(fakeURL)
32 | c.SetSession(id+"contributorsNum", contributorsNum)
33 | }
34 |
35 | c.Data["starNum"] = starNum
36 | c.Data["contributorsNum"] = contributorsNum
37 | c.TplName = "projectSetting.html" //该controller对应的页面
38 |
39 | //session获取textfiled
40 | textfield := c.GetSession("TextField")
41 | if textfield != nil {
42 | c.Data["TextField"] = textfield
43 | } else {
44 | c.Data["TextField"] = "不超过200字符"
45 | }
46 |
47 | }
48 |
--------------------------------------------------------------------------------
/src/views/leftNav.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | 个人中心
5 |
6 |
7 |
8 |
14 |
19 |
30 |
31 |
--------------------------------------------------------------------------------
/src/views/platformInformation.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | 平台信息
6 |
7 |
8 |
9 |
10 | {{template "./platformAdminTopNav.html" .}}
11 |
14 |
15 |
16 |
17 |
18 |
平台拥有的CC数
19 |
CC记录
20 |
21 |
日期
变化
总数
22 |
11.23
+1000
1000
23 |
11.25
+2000
3000
24 |
25 |
26 |
27 |
30 |
项目记录
31 |
32 |
日期
变化
总数
33 |
11.23
+2
2
34 |
11.25
+1
3
35 |
36 |
37 | {{template "./footer.html" .}}
38 |
39 |
--------------------------------------------------------------------------------
/src/models/searchCcAndCs.go:
--------------------------------------------------------------------------------
1 | package models
2 |
3 | import (
4 | // "encoding/json"
5 | _ "encoding/json"
6 | "fmt"
7 |
8 | "github.com/astaxie/beego/orm"
9 | )
10 |
11 | func GetCcAndCsQuery(userId int, projectId int) ([]orm.Params, error) {
12 | o := orm.NewOrm()
13 | _ = o.Using("default")
14 | SQLQuery := getQuery()
15 | var maps []orm.Params
16 | if _, err := o.Raw(SQLQuery, userId, projectId).Values(&maps); err != nil {
17 | fmt.Println(err.Error())
18 | return nil, err
19 | }
20 |
21 | if len(maps) == 0 {
22 | return nil, new(noResultErr)
23 | }
24 | return maps, nil
25 | }
26 |
27 | func getQuery() string {
28 | return `select user_cs, b.user_cc from "k_user_in_project" a, "k_user" b where a.user_id=? and a.project_id=? and a.user_id = b.user_id`
29 | }
30 |
31 | // 实现personalPage控制器中的查询CC余额
32 | func GetPersonalRemainingCc(userName string) (float64, error) {
33 | o := orm.NewOrm()
34 | _ = o.Using("default")
35 |
36 | type UsrCC struct {
37 | User_name string
38 | User_cc float64
39 | }
40 | var userCc UsrCC
41 |
42 | /**将取回的用户名和CC余额赋值给结构体userCc; 如有错误,则赋值给err1
43 | ***结构体中属性名需要与数据库中对应字段相同,且首字母大写*/
44 | ccQuery := `SELECT user_name, user_cc FROM "k_user" WHERE user_name=?`
45 | err1 := o.Raw(ccQuery, userName).QueryRow(&userCc)
46 | if err1 != nil {
47 | fmt.Println(err1.Error())
48 | return -1.0, err1
49 | }
50 |
51 | return userCc.User_cc, nil
52 |
53 | }
--------------------------------------------------------------------------------
/src/views/projectInfo.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | 项目信息
6 |
7 |
8 |
9 |
10 |
11 | {{template "./projectTopNav.html" .}}
12 |
15 |
16 |
17 |
18 |
19 |
KCoin 总值
20 |
{{.projectCC}}
21 |
22 |
发放记录
23 |
24 |
25 |
26 |
Token 总值
27 |
0
28 |
29 |
发放记录
30 |
31 |
36 |
37 |
38 | {{template "./footer.html" .}}
39 |
40 |
--------------------------------------------------------------------------------
/src/models/getGithubRepos.go:
--------------------------------------------------------------------------------
1 | // TODO 该文件并入service层的github_helper.go中, 并删除main函数, 改为测试覆盖.
2 | package models
3 |
4 | import (
5 | "encoding/json"
6 | "fmt"
7 | "io/ioutil"
8 | "net/http"
9 | )
10 |
11 | type GithubRepos []struct {
12 | Name string `json:"name"`
13 | Url string `json:"html_url"`
14 | }
15 |
16 | //type ReposInfo struct {
17 | // ErrorCode string `json:"error_code"`
18 | // Data GithubRepos `json:"data"`
19 | //}
20 | //获取一个用户在github上所有公开的repository,返回json
21 | func GetGithubRepos(user string) (string, error) {
22 | //var reposInfo ReposInfo
23 | //reposInfo.ErrorCode = "default Error"
24 | var url string = "https://api.github.com/users/" + user + "/repos"
25 |
26 | client := &http.Client{}
27 | response, _ := client.Get(url)
28 | defer response.Body.Close()
29 | body, err := ioutil.ReadAll(response.Body)
30 | if err != nil {
31 | panic(err)
32 | }
33 | var repos GithubRepos
34 | var projects ProjectInfo
35 | err1 := json.Unmarshal([]byte(body), &repos)
36 | if err1 != nil {
37 | panic(err1)
38 | }
39 | for i := range repos {
40 | p := &Project{}
41 | p.ProjectUrl = repos[i].Url
42 | p.ProjectName = repos[i].Name
43 | projects.Data = append(projects.Data, p)
44 | }
45 | //reposInfo.ErrorCode = "0"
46 | //reposInfo.Data = repos
47 | //res,err2 := json.Marshal(&reposInfo)
48 | res, err2 := json.Marshal(&projects)
49 | if err2 != nil {
50 | panic(err2)
51 | }
52 | return string(res), nil
53 | }
54 |
55 | //测试输出
56 | func main() {
57 | fmt.Println(GetGithubRepos("Darkone0"))
58 | }
59 |
--------------------------------------------------------------------------------
/src/routers/router.go:
--------------------------------------------------------------------------------
1 | package routers
2 |
3 | import (
4 | "Kcoin-Golang/src/controllers"
5 |
6 | "github.com/astaxie/beego"
7 | )
8 |
9 | func init() {
10 | beego.Router("/", &controllers.MainController{})
11 | beego.Router("/homepage", &controllers.HomePageController{})
12 | beego.Router("/logout", &controllers.LogOutController{})
13 | beego.Router("/personalpage", &controllers.PersonalPageController{})
14 | beego.Router("/login", &controllers.LoginController{})
15 | beego.Router("/join", &controllers.JoinController{})
16 | beego.Router("/autho", &controllers.AuthoController{})
17 | beego.Router("/import", &controllers.ImportController{})
18 | beego.Router("/personalprojects", &controllers.PersonalProjectsController{})
19 | beego.Router("/project/?:id/info", &controllers.ProjectInfoController{})
20 | beego.Router("/project/?:id/memberList", &controllers.ProjectMemberListController{})
21 | beego.Router("/project/?:id/memberWork", &controllers.ProjectMemberWorkController{})
22 | beego.Router("/project/?:id/notice", &controllers.ProjectNoticeController{})
23 | beego.Router("/project/?:id/setting", &controllers.ProjectSettingController{})
24 | beego.Router("/ccsearchpage", &controllers.CcSearchPageController{})
25 | beego.Router("/capitalInjection", &controllers.CapitalInjectionController{})
26 | beego.Router("/projectfunding", &controllers.ProjectFundingController{})
27 | beego.Router("/platformInformation", &controllers.PlatformInformationController{})
28 | beego.Router("/webhooks",&controllers.WebhooksController{})
29 | }
30 |
--------------------------------------------------------------------------------
/src/models/getAllJoinedProjects.go:
--------------------------------------------------------------------------------
1 | // TODO 该文件并入k_user.go中
2 | package models
3 |
4 | import (
5 | "fmt"
6 |
7 | "github.com/astaxie/beego/orm"
8 | )
9 |
10 | func GetAllJoinedProjects(userId string) (joinedProjects []*Project, err error) {
11 | var jp []*Project
12 | //var maps []orm.Params
13 | o := orm.NewOrm()
14 | _ = o.Using("default")
15 | SQLQuery := getAllJoinedProjectsQuery()
16 | if _, err := o.Raw(SQLQuery, userId).QueryRows(&jp); err != nil {
17 | fmt.Print(err.Error())
18 | return nil, err
19 | }
20 |
21 | SQLQuery = getMemberListQuery()
22 | for _, proj := range jp {
23 | var memberlist []*UserData
24 | if _, err = o.Raw(SQLQuery, proj.ProjectId).QueryRows(&memberlist); err != nil {
25 | fmt.Print(err.Error())
26 | return nil, err
27 | }
28 |
29 | proj.MemberList = memberlist
30 | fmt.Println(proj.MemberList)
31 | }
32 | return jp, nil
33 | }
34 |
35 | func getAllJoinedProjectsQuery() string {
36 | return "select * from \"k_project\" where project_id in " +
37 | "(select project_id from \"k_user_in_project\" where user_id = ?)"
38 | }
39 |
40 | func getMemberListQuery() string {
41 | return `SELECT u.k_user_id, u.user_name, u.head_shot_url
42 | FROM "k_user" u LEFT JOIN "k_user_in_project" up on u.k_user_id = up.user_id
43 | WHERE up.project_id = ?`
44 | //return "SELECT user_id, user_name, head_shot_url FROM \"k_user\" WHERE user_id in " +
45 | // "(SELECT user_id FROM \"k_user_in_Project\" WHERE project_id = ?)"
46 |
47 | }
48 |
49 | //测试
50 | //func main() {
51 | // fmt.Print(GetAllJoinedProjects("1" ))
52 | //}
53 |
--------------------------------------------------------------------------------
/src/controllers/personalPage.go:
--------------------------------------------------------------------------------
1 | package controllers
2 |
3 | import (
4 | "Kcoin-Golang/src/models"
5 | _ "Kcoin-Golang/src/models"
6 | // "encoding/json"
7 | "fmt"
8 |
9 | "github.com/astaxie/beego"
10 | )
11 |
12 | type PersonalPageController struct {
13 | beego.Controller
14 | }
15 |
16 | func (c *PersonalPageController) Get() {
17 | //jsonBuf是一个用于调试的静态json,之后会调用webserver的接口,动态获取。
18 | //jsonBuf :=
19 | // `{
20 | // "errorCode": "0",
21 | // "data":{
22 | // "userName": "DoubleJ",
23 | // "headShotUrl": "../static/img/tx2.png"
24 | // }
25 | //}`
26 | status := c.Ctx.GetCookie("status")
27 | c.Ctx.SetCookie("lastUri", c.Ctx.Request.RequestURI)
28 | if status == "0" || status == "" {
29 | defer c.Redirect("/login.html", 302)
30 | }
31 |
32 | //获取GitHubId
33 | //gitId := c.GetSession("GitHubId").(string)
34 | githubId := c.Ctx.GetCookie("githubId")
35 | //通过gitHubId查询cs数
36 | csNum := models.GetCsNum(githubId)
37 |
38 | user := models.UserInfo{Data: &models.UserData{}} //user中存放着json解析后获得的数据。
39 | user.Data.UserName = c.Ctx.GetCookie("userName")
40 | user.Data.HeadShotUrl = c.Ctx.GetCookie("headShotUrl")
41 | user.Data.CsNum = csNum
42 |
43 | c.Data["user"] = user
44 | c.TplName = "personalPage.html" //该controller对应的页面
45 |
46 | // 函数定义在models目录下的searchCcAndCs.go中,根据用户名查询CC余额
47 | remainingCc, err := models.GetPersonalRemainingCc(user.Data.UserName)
48 | if err != nil {
49 | fmt.Println("you r in personalPage controller, something got wrong "+
50 | "while querying the database: ", err.Error())
51 | }
52 |
53 | c.Data["remainingCc"] = remainingCc
54 | }
55 |
--------------------------------------------------------------------------------
/src/controllers/homepage.go:
--------------------------------------------------------------------------------
1 | package controllers
2 |
3 | import (
4 | "Kcoin-Golang/src/models"
5 | "encoding/json"
6 | "fmt"
7 | "github.com/astaxie/beego"
8 | )
9 |
10 | type HomePageController struct {
11 | beego.Controller
12 | }
13 |
14 | func (c *HomePageController) Get() {
15 | //从cookie中取出状态
16 | isLogin :=c.Ctx.GetCookie("status")
17 |
18 |
19 | //把Json字符串中的数据解析到结构体中
20 | var proj models.ProjectInfo
21 | projectBuf , _ := models.GetAllProjectsInfo()
22 | err := json.Unmarshal([]byte(projectBuf),&proj)
23 | if err != nil {
24 | fmt.Println("err=", err)
25 | //return
26 | }
27 |
28 | //把结构体传到模板当中
29 | c.Data["Projects"] = proj
30 |
31 |
32 | isPlatformAdmin := false
33 | //判断当前登录状态
34 | if isLogin == "1"{
35 | c.Data["isLogin"] = true
36 | user := models.UserInfo{Data:&models.UserData{}}//user中存放着json解析后获得的数据。
37 | user.Data.UserName = c.Ctx.GetCookie("userName")
38 | user.Data.UserId = c.Ctx.GetCookie("userId")
39 | user.Data.HeadShotUrl = c.Ctx.GetCookie("headShotUrl")
40 | c.Data["user"] = user
41 | //判断当前用户是不是平台管理员
42 | isPlatformAdmin = models.IsSupervisor(user.Data.UserId)
43 | } else {
44 | c.Data["isLogin"] = false
45 | c.Ctx.SetCookie("userName","",100)
46 | c.Ctx.SetCookie("headShotUrl","",100)
47 | c.Ctx.SetCookie("status", string('0'),100)
48 | c.Ctx.SetCookie("lastUri",c.Ctx.Request.RequestURI)
49 |
50 | }
51 | c.Data["isPlatformAdmin"] = isPlatformAdmin
52 |
53 | //设置Get方法对应展示的模板
54 | c.TplName = "homePage.tpl"
55 | }
56 |
--------------------------------------------------------------------------------
/src/models/models.go:
--------------------------------------------------------------------------------
1 | package models
2 |
3 | import (
4 | "fmt"
5 | "github.com/astaxie/beego/orm"
6 | _ "github.com/lib/pq"
7 | )
8 |
9 | //定义结构体,用来对接前后端json
10 | //homepage
11 | type Project struct {
12 | ProjectId string `json:"projectId"`
13 | ProjectName string `json:"projectName"`
14 | ProjectCoverUrl string `json:"projectCoverUrl"`
15 | ProjectUrl string `json:"projectUrl"`
16 | MemberList []*UserData `json:"memberList"`
17 | }
18 |
19 | type ProjectInfo struct {
20 | ErrorCode string `json:"errorCode"`
21 | Data []*Project `json:"data"`
22 | }
23 |
24 | //ccSearchPage
25 | /*UserCcData:为ccSearchPage的主要结构体,包括kcoin记录中的cc操作日期,操作类型和cc的数量
26 | */
27 | type UserCcOpe struct{
28 | OpeCcDate string `json:"opeCcDate"`
29 | OpeCcType string `json:"opeCcType"`
30 | OpeCcNumber string `json:"opeCcNumber"`
31 | }
32 |
33 | //homepage import
34 | /*UserData:为personalpage和projectpage的主要结构体,定义了用户姓名、用户头像url、项目列表
35 | */
36 | type UserData struct {
37 | UserId string `json:"userId"`
38 | UserName string `json:"userName"`
39 | HeadShotUrl string `json:"headshotUrl"`
40 | ProjectList []*Project `json:"projectList"`
41 | UserCcOpeList []*UserCcOpe `json:"userCcOpeList"`
42 | CsNum int `json:"csNum"`
43 | }
44 |
45 | //import personPage
46 | /*UserInfo:包括UserData和另外一个errorCode,errorCode主要用于调试
47 | */
48 | type UserInfo struct {
49 | ErrorCode string `json:"errorCode"`
50 | Data *UserData `json:"data"`
51 | }
52 |
53 | func init() {
54 | _ = orm.RegisterDriver("postgres", orm.DRPostgres)
55 | err := orm.RegisterDataBase("default", "postgres", "user=sspkukcoin password=kcoin2019 dbname=postgres host=114.115.133.140 port=5432")
56 | if err != nil {
57 | fmt.Println(err.Error())
58 | }
59 | }
60 |
--------------------------------------------------------------------------------
/src/views/ccSearchPage.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | 个人中心
5 |
10 |
11 |
12 |
13 |
14 |
15 |
16 | {{template "./leftNav.html" .}}
17 |
18 |
21 |
22 |
23 |
24 | Kcoin记录
25 |
26 |
27 |
28 | | 日期 |
29 | 操作类型 |
30 | cc数量 |
31 |
32 |
33 | {{with .user.Data}}
34 | {{range .UserCcOpeList}}
35 | | {{.OpeCcDate}} |
36 | {{.OpeCcType}} |
37 | {{.OpeCcNumber}} |
38 |
39 | {{end}}
40 | {{end}}
41 |
42 |
43 |
48 |
49 |
50 |
51 |
52 |
--------------------------------------------------------------------------------
/src/controllers/authorize.go:
--------------------------------------------------------------------------------
1 | package controllers
2 |
3 | import (
4 | "Kcoin-Golang/src/models"
5 | "Kcoin-Golang/src/service"
6 | "fmt"
7 | "github.com/astaxie/beego"
8 | "github.com/astaxie/beego/orm"
9 | "time"
10 | )
11 |
12 | type AuthoController struct {
13 | beego.Controller
14 | }
15 |
16 | func (c *AuthoController) Get() {
17 | var code string = c.GetString("code")
18 | accessToken, _ := service.GetAccessToken(code)
19 | text := service.GetUserJson(accessToken)
20 |
21 | name := text.Data.Name
22 | id := text.Data.Id
23 | // 修改参数
24 | //service.GithubUser.SetGithubUserAccessToken(id, name, accessToken)
25 | uri := text.Data.Uri
26 |
27 | o := orm.NewOrm()
28 | o.Using("default")
29 | // 移到model 改成GitID查询
30 | res, _ := models.FinduserByGitId(id)
31 |
32 | if res.UserId == "" {
33 | err := models.InsertUser(name, uri, id)
34 | if err != nil {
35 | panic(err)
36 | }
37 | } else {
38 | time := time.Now().Format("2006-01-02 15:04:05.000000")
39 | updateSql := `update "k_user" set register_time = ? where github_id = ?`
40 | _, err := o.Raw(updateSql, time, id).Exec()
41 | if err != nil {
42 | panic(err)
43 | }
44 | }
45 |
46 | //存储用户名到cooike中,获取语法:c.Ctx.GetCookie("userName")
47 | c.Ctx.SetCookie("userName", text.Data.Name, 3600)
48 | //存储用户名到cooike中,获取语法:c.Ctx.GetCookie("userId")
49 | c.Ctx.SetCookie("userId", res.UserId, 3600)
50 | //存储用户头像url到cooike中,获取语法:c.Ctx.GetCookie("headShotUrl")
51 | c.Ctx.SetCookie("headShotUrl", text.Data.Uri, 3600)
52 | //存储用户登录状态到cooike中,其中1表示已登录,获取语法:c.Ctx.GetCookie("status")
53 | c.Ctx.SetCookie("status", string('1'), 3600)
54 |
55 | c.Ctx.SetCookie("githubId", id, 3600)
56 | c.Ctx.SetCookie("githubName", name, 3600)
57 | c.Ctx.SetCookie("githubToken", accessToken, 3600)
58 |
59 | if redirectUrl := c.Ctx.GetCookie("lastUri"); redirectUrl != "" {
60 | fmt.Printf(redirectUrl)
61 | c.Redirect(c.Ctx.GetCookie("lastUri"), 302)
62 | } else {
63 | c.Redirect("homepage", 302)
64 | }
65 | }
66 |
--------------------------------------------------------------------------------
/src/controllers/import.go:
--------------------------------------------------------------------------------
1 | package controllers
2 |
3 | import (
4 | "Kcoin-Golang/src/models"
5 | "encoding/json"
6 | "fmt"
7 | "strconv"
8 |
9 | "github.com/astaxie/beego"
10 | )
11 |
12 | type ImportController struct {
13 | beego.Controller
14 | }
15 |
16 | func (c *ImportController) Get() {
17 | jsonBuf :=
18 | `{
19 | "errorCode": "0",
20 | "data": {
21 | "userName": "anaana",
22 | "headshotUrl": "../static/img/tx2.png",
23 | "projectList":
24 | [
25 | {
26 | "projectName": "天气预报1",
27 | "projectCoverUrl": "../static/img/projectbg.png",
28 | "projectUrl": "",
29 | "memberList": [
30 | {
31 | "userName": "Tony",
32 | "headshotUrl": "../static/img/tx2.png"
33 | },
34 | {
35 | "userName": "Tony",
36 | "headshotUrl": "../static/img/tx1.png"
37 | }
38 | ]
39 | },
40 | {
41 | "projectName": "天气预报2",
42 | "projectCoverUrl": "../static/img/projectbg.png",
43 | "projectUrl": "",
44 | "memberList": [
45 | {
46 | "userName": "Joy",
47 | "headshotUrl": "../static/img/tx1.png"
48 | },
49 | {
50 | "userName": "Tony",
51 | "headshotUrl": "../static/img/tx2.png"
52 | }
53 | ]
54 | }
55 | ]
56 | }
57 | }`
58 | var user models.UserInfo
59 | errorCode := json.Unmarshal([]byte(jsonBuf), &user)
60 | if errorCode != nil {
61 | fmt.Println("there is an error ,sorry ,please continue debug,haha", errorCode.Error())
62 | }
63 | c.Data["user"] = user //json数据解包
64 | c.Data["memberList_len"] = strconv.Itoa(len(user.Data.ProjectList)) //个人项目数量
65 | c.TplName = "import.tpl"
66 | }
67 |
--------------------------------------------------------------------------------
/src/views/import.tpl:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | 我的项目
8 |
9 |
10 |
11 |
导入项目
12 |
13 | - 选择项目
14 | - 初始信息
15 | - 初始分配
16 |
17 |
18 |
19 |
23 |
24 |
25 |
 
26 | {{.user.Data.UserName}} 
27 | ({{.memberList_len}}个项目)
28 |
29 |
30 |
31 | {{with .user.Data}}
32 | {{range .ProjectList}}
33 | - {{.ProjectName}}
34 | {{end}}
35 | {{end}}
36 |
37 |
38 |
39 |
42 |
43 |
 
44 |
1. 填写项目名称
45 |
48 |
2. 上传项目封面(选填,但只能添加不大于2M的图片)
49 |
选择文件
50 |
51 |
52 |
53 |
54 |
55 |
59 |
60 |
61 |
62 |
--------------------------------------------------------------------------------
/src/views/homePage.tpl:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | HomePage
6 |
7 |
8 |
9 |
10 |
39 |
40 |
61 |
62 | {{template "./footer.html" .}}
63 |
64 |
65 |
--------------------------------------------------------------------------------
/src/views/projectMemberWork.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | 工作列表
5 |
6 |
7 |
8 |
9 |
10 | {{template "./projectTopNav.html" .}}
11 |
12 |
15 |
16 |
17 |
18 | DoubleJ的工作信息
19 |
20 |
21 |
22 | | 日期 |
23 | 贡献类型 |
24 | 获得cs数量 |
25 |
26 |
27 | | 10.23 |
28 | 提交pr |
29 | 500 |
30 |
31 |
32 | | 10.23 |
33 | 提交issue |
34 | 200 |
35 |
36 |
37 | | 10.24 |
38 | 提交pr |
39 | 500 |
40 |
41 |
42 | | 10.24 |
43 | 提交issue |
44 | 200 |
45 |
46 |
47 | | 10.25 |
48 | 提交pr |
49 | 500 |
50 |
51 |
52 | | 10.27 |
53 | 提交pr |
54 | 500 |
55 |
56 |
57 |
58 |
63 |
64 | {{template "./footer.html" .}}
65 |
--------------------------------------------------------------------------------
/src/controllers/ccSearchPage.go:
--------------------------------------------------------------------------------
1 | package controllers
2 |
3 | import (
4 | "Kcoin-Golang/src/models"
5 | _ "Kcoin-Golang/src/models"
6 | "encoding/json"
7 | "fmt"
8 |
9 | "github.com/astaxie/beego"
10 | )
11 |
12 | type CcSearchPageController struct {
13 | beego.Controller
14 | }
15 |
16 | func (c *CcSearchPageController) Get() {
17 | //jsonBuf是一个用于调试的静态json,之后从数据库中读取数据
18 | jsonBuf :=
19 | `{
20 | "errorCode": "0",
21 | "data": {
22 | "userName": "Sonorous ",
23 | "headshotUrl": "../static/img/tx2.png",
24 | "userCcOpeList":
25 | [
26 | {
27 | "opeCcDate":"11.18",
28 | "opeCcType":"sell",
29 | "opeCcNumber":"-2000"
30 | },
31 | {
32 | "opeCcDate":"11.18",
33 | "opeCcType":"buy",
34 | "opeCcNumber":"5000"
35 | },
36 | {
37 | "opeCcDate":"11.19",
38 | "opeCcType":"sell",
39 | "opeCcNumber":"-1000"
40 | },
41 | {
42 | "opeCcDate":"11.18",
43 | "opeCcType":"sell",
44 | "opeCcNumber":"-1000"
45 | },
46 | {
47 | "opeCcDate":"11.18",
48 | "opeCcType":"buy",
49 | "opeCcNumber":"1000"
50 | },
51 | {
52 | "opeCcDate":"11.19",
53 | "opeCcType":"sell",
54 | "opeCcNumber":"-500"
55 | },
56 | {
57 | "opeCcDate":"11.18",
58 | "opeCcType":"sell",
59 | "opeCcNumber":"-3000"
60 | },
61 | {
62 | "opeCcDate":"11.18",
63 | "opeCcType":"buy",
64 | "opeCcNumber":"2000"
65 | },
66 | {
67 | "opeCcDate":"11.19",
68 | "opeCcType":"sell",
69 | "opeCcNumber":"-800"
70 | },
71 | {
72 | "opeCcDate":"11.18",
73 | "opeCcType":"sell",
74 | "opeCcNumber":"-1000"
75 | }
76 | ]
77 | }
78 | }`
79 |
80 | status:=c.Ctx.GetCookie("status")
81 | {
82 | c.Ctx.SetCookie("lastUri",c.Ctx.Request.RequestURI)
83 | if status =="0"||status ==""{
84 | defer c.Redirect("/login.html",302)
85 | }
86 | }
87 | var user models.UserInfo
88 | errorCode := json.Unmarshal([]byte(jsonBuf), &user)
89 | user.Data.UserName = c.Ctx.GetCookie("userName")
90 | user.Data.HeadShotUrl = c.Ctx.GetCookie("headShotUrl")
91 | if errorCode != nil {
92 | fmt.Println("Oops, there is an error:( please keep debugging.", errorCode.Error())
93 | }
94 |
95 | c.Data["user"] = user
96 | c.TplName = "ccSearchPage.html"//该controller对应的页面
97 | }
98 |
--------------------------------------------------------------------------------
/src/models/k_project.go:
--------------------------------------------------------------------------------
1 | package models
2 |
3 | import (
4 | "database/sql"
5 | "encoding/json"
6 | _ "encoding/json"
7 | "fmt"
8 | "log"
9 |
10 | "github.com/astaxie/beego/orm"
11 | )
12 |
13 | //查询并以json形式返回所有的项目信息
14 | func GetAllProjectsInfo() (string, error) {
15 | o := orm.NewOrm()
16 | o.Using("default")
17 |
18 | var projectsInfo ProjectInfo
19 | projectsInfo.ErrorCode = "default Error"
20 |
21 | /******************************************query all projects************************************************/
22 | queryProjectSql := `SELECT project_id , project_name , project_url , project_cover_url FROM "k_project" `
23 | /***********************************************************************************************************/
24 |
25 | _, err := o.Raw(queryProjectSql).QueryRows(&projectsInfo.Data)
26 |
27 | /******************************************query menberList in one project**********************************/
28 | queryUsersInProjectSql := `select u.k_user_id,u.user_name,u.head_shot_url
29 | from "k_user" u left join "k_user_in_project" up on u.k_user_id=up.user_id
30 | where up.project_id=?`
31 | /**********************************************************************************************************/
32 | for _, v := range projectsInfo.Data {
33 | var memberList []*UserData
34 | _, err := o.Raw(queryUsersInProjectSql, v.ProjectId).QueryRows(&memberList)
35 | if err != nil {
36 | fmt.Println(err.Error())
37 | return fmt.Sprint(projectsInfo), err
38 | }
39 | v.MemberList = memberList
40 | }
41 | projectsInfo.ErrorCode = "0"
42 | res, err := json.Marshal(&projectsInfo)
43 | if err != nil {
44 | fmt.Println(err.Error())
45 | return fmt.Sprint(projectsInfo), err
46 | }
47 | return string(res), nil
48 | }
49 |
50 | func GetProjectsCC(projectName string) (float64, error) {
51 | o := orm.NewOrm()
52 | o.Using("default")
53 |
54 | queryProjectSql := `SELECT project_cc FROM "k_project" WHERE project_name=? `
55 | var num float64
56 | err := o.Raw(queryProjectSql, projectName).QueryRow(&num)
57 | if err != nil {
58 | fmt.Println(err.Error())
59 | }
60 | return num, nil
61 | }
62 |
63 | func GetProjectidByRepoName(reponame string) (int, error) {
64 | o := orm.NewOrm()
65 | _ = o.Using("default")
66 | var project_id int
67 | querySql := `select project_id from "k_project" where project_name=?`
68 | err := o.Raw(querySql, reponame).QueryRow(&project_id)
69 | return project_id, err
70 |
71 | }
72 |
73 | func InsertProject(reponame string, url string, project_cover_url string) (sql.Result, error) {
74 | o := orm.NewOrm()
75 | _ = o.Using("default")
76 |
77 | querySql := `insert into "k_project"(project_name,project_url,project_cover_url)values(?,?,?)`
78 |
79 | res, err := o.Raw(querySql, reponame, url, project_cover_url).Exec()
80 | if err != nil {
81 | log.Fatal("error when insert project,", err)
82 | }
83 | return res, err
84 | }
85 |
--------------------------------------------------------------------------------
/src/controllers/personalProjects.go:
--------------------------------------------------------------------------------
1 | package controllers
2 |
3 | import (
4 | "Kcoin-Golang/src/models"
5 | "Kcoin-Golang/src/service"
6 | "encoding/json"
7 | "fmt"
8 | "log"
9 | "strconv"
10 |
11 | "github.com/astaxie/beego"
12 | )
13 |
14 | type PersonalProjectsController struct {
15 | beego.Controller
16 | }
17 |
18 | func (c *PersonalProjectsController) GetPersonalInfo() {
19 | name := c.Ctx.GetCookie("userName")
20 | userBuf, _ := models.GetUserInfo(name)
21 | projectBuf, _ := models.GetGithubRepos(name)
22 |
23 | status := c.Ctx.GetCookie("status")
24 | //判断是否登录,如果未登录,登录后跳转到原页面
25 | c.Ctx.SetCookie("lastUri", c.Ctx.Request.RequestURI)
26 | if status == "0" || status == "" {
27 | defer c.Redirect("/login.html", 302)
28 | }
29 |
30 | user := models.UserInfo{Data: &models.UserData{}}
31 | user.Data.UserName = name
32 | user.Data.HeadShotUrl = c.Ctx.GetCookie("headShotUrl")
33 | var projects models.ProjectInfo
34 | errorCode := json.Unmarshal([]byte(userBuf), &user)
35 | errorCode2 := json.Unmarshal([]byte(projectBuf), &projects)
36 |
37 | if errorCode != nil {
38 | fmt.Println("Oops, there is an error:( please keep debugging.", errorCode.Error())
39 | }
40 | if errorCode2 != nil {
41 | fmt.Println("Oops, there is an error:( please keep debugging.", errorCode2.Error())
42 | }
43 |
44 | c.Data["user"] = user
45 | c.Data["repos"] = projects
46 | c.Data["memberList_len"] = strconv.Itoa(len(projects.Data)) //个人项目数量
47 |
48 | //获取已加入项目
49 | //使用testid=95
50 | testid := c.Ctx.GetCookie("userId")
51 | joinedprojects, _ := models.GetAllJoinedProjects(testid)
52 | fmt.Print(models.GetAllJoinedProjects("95"))
53 | c.Data["joinedProjects"] = joinedprojects
54 | c.Data["joinedprojects_len"] = strconv.Itoa(len(joinedprojects))
55 | }
56 |
57 | func (c *PersonalProjectsController) Post() {
58 | //var U models.Project
59 | pUrl := c.GetString("ProjectUrl") //项目地址
60 | pName := c.GetString("ProjectName") //项目名称
61 | pIntro := c.GetString("ProjectIntro") //项目介绍
62 | //uploadname := c.GetString("uploadname") //项目封面
63 | fmt.Println(pUrl, pName, pIntro)
64 |
65 | //提交图片
66 | f, h, err := c.GetFile("uploadname")
67 | if err != nil {
68 | log.Fatal("getfile err ", err)
69 | }
70 | defer f.Close()
71 | fmt.Println(f, h, err)
72 | githubId := c.Ctx.GetCookie("githubId")
73 | githubName := c.Ctx.GetCookie("githubName")
74 | githubToken := c.Ctx.GetCookie("githubToken")
75 | githubInfo := service.GithubInfo{
76 | GithubId: githubId,
77 | GithubName: githubName,
78 | AccessToken: githubToken,
79 | }
80 |
81 | if err = ImportProject(pUrl, "../static/img/projectbg.png", githubInfo); err != nil {
82 | fmt.Println("Oops, there is an error:( please keep debugging.", err.Error())
83 | // 需要返回错误页面
84 | return
85 | }
86 |
87 | c.TplName = "personalProjects.html"
88 | c.Redirect("personalprojects", 302)
89 | }
90 |
91 | func (c *PersonalProjectsController) Get() {
92 | c.GetPersonalInfo()
93 |
94 | c.TplName = "personalProjects.html"
95 | }
96 |
--------------------------------------------------------------------------------
/src/views/capitalInjection.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | 资金注入页面
6 |
7 |
8 |
11 |
12 |
13 |
14 |
15 | {{template "./platformAdminTopNav.html" .}}
16 |
17 |
20 |
21 | {{with .Projects}}
22 | {{range .Data}}
23 |
24 |

25 |
{{.ProjectName}}
26 |
introduction
27 |
CC:12138
28 |
29 | {{range .MemberList}}
30 |

31 |
32 |
33 |
34 | {{end}}
35 |
36 |
37 |
38 |
39 | {{end}}
40 | {{end}}
41 |
42 |
43 |
44 |
45 |
46 |
注资信息
47 |
49 |
50 |
51 | 金额
52 |
53 |
54 | 期限
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
--------------------------------------------------------------------------------
/src/tests/models_test.go:
--------------------------------------------------------------------------------
1 | package test
2 |
3 | import (
4 | "Kcoin-Golang/src/models"
5 | "Kcoin-Golang/src/service"
6 | "testing"
7 | )
8 |
9 | func Test_getContributors(t *testing.T) {
10 | type args struct {
11 | userName string
12 | programName string
13 | }
14 | tests := []struct {
15 | name string
16 | args args
17 | want string
18 | }{
19 | //测试用例
20 | {args: args{userName: "rjkris", programName: "fluffy-robot"}, want: "rjkris "}, //PASS
21 | }
22 | for _, tt := range tests {
23 | t.Run(tt.name, func(t *testing.T) {
24 | if got := service.GetContributors(tt.args.userName, tt.args.programName); got != tt.want {
25 | t.Errorf("getContributors() = %v, want %v", got, tt.want)
26 | }
27 | })
28 | }
29 | }
30 |
31 | func TestGetContributorNum(t *testing.T) {
32 | type args struct {
33 | url string
34 | }
35 | tests := []struct {
36 | name string
37 | args args
38 | want int
39 | }{
40 | //测试用例
41 | {args: args{url: "https://github.com/OS-ABC/HelloWorld"}, want: 115}, //FAIL 通过该API获得的contributors可能不全
42 | {args: args{url: "https://github.com/OS-ABC/Kcoin-Golang"}, want: 17}, //PASS
43 | }
44 | for _, tt := range tests {
45 | t.Run(tt.name, func(t *testing.T) {
46 | if got := service.GetContributorNum(tt.args.url); got != tt.want {
47 | t.Errorf("GetContributorNum() = %v, want %v", got, tt.want)
48 | }
49 | })
50 | }
51 | }
52 |
53 | func TestGetStarNum(t *testing.T) {
54 | type args struct {
55 | url string
56 | }
57 | tests := []struct {
58 | name string
59 | args args
60 | want int
61 | }{
62 | //测试用例
63 | {args: args{url: "https://github.com/OS-ABC/Kcoin-Golang"}, want: 16}, //PASS
64 | {args: args{url: "https://github.com/OS-ABC/HelloWorld"}, want: 86}, //PASS
65 | }
66 | for _, tt := range tests {
67 | t.Run(tt.name, func(t *testing.T) {
68 | if got := service.GetStarNum(tt.args.url); got != tt.want {
69 | t.Errorf("GetStarNum() = %v, want %v", got, tt.want)
70 | }
71 | })
72 | }
73 | }
74 |
75 | func TestParseGithubHTTPSUrl(t *testing.T) {
76 | type args struct {
77 | url string
78 | }
79 | tests := []struct {
80 | name string
81 | args args
82 | wantUserName string
83 | wantUserRepo string
84 | }{
85 | //测试用例
86 | {args: args{url: "https://github.com/OS-ABC/Kcoin-Golang"}, wantUserName: "OS-ABC", wantUserRepo: "Kcoin-Golang"}, //PASS
87 | {args: args{url: "https://github.com/zhang2j/HelloWorld.git"}, wantUserName: "zhang2j", wantUserRepo: "HelloWorld"}, //PASS
88 | }
89 | for _, tt := range tests {
90 | t.Run(tt.name, func(t *testing.T) {
91 | if gotName, gotRepo, _ := service.ParseGithubHTTPSUrl(tt.args.url); gotName != tt.wantUserName || gotRepo != tt.wantUserRepo {
92 | t.Errorf("userName = %v, want %v; userRepo = %v; want %v", gotName, tt.wantUserName, gotRepo, tt.wantUserRepo)
93 | }
94 | })
95 | }
96 | }
97 |
98 | func TestGetProjectsCC(t *testing.T) {
99 | type args struct {
100 | projectName string
101 | }
102 | tests := []struct {
103 | name string
104 | args args
105 | want float64
106 | }{
107 | //测试用例
108 | {args: args{projectName: "baidu"}, want: 1}, //PASS
109 | {args: args{projectName: "i_love_Kcoin"}, want: 3}, //PASS
110 | }
111 | for _, tt := range tests {
112 | t.Run(tt.name, func(t *testing.T) {
113 | if got, _ := models.GetProjectsCC(tt.args.projectName); got != tt.want {
114 | t.Errorf("CCNum = %v, want %v", got, tt.want)
115 | }
116 | })
117 | }
118 | }
119 |
--------------------------------------------------------------------------------
/src/static/js/paging.js:
--------------------------------------------------------------------------------
1 |
2 | /**
3 | * 分页函数
4 | * pno--页数
5 | * psize--每页显示记录数
6 | * 分页部分是从真实数据行开始,因而存在加减某个常数,以确定真正的记录数
7 | * 纯js分页实质是数据行全部加载,通过是否显示属性完成分页功能
8 | **/
9 | function goPage1(pno,psize){
10 |
11 | var itable = document.getElementById("idData1");
12 | var num = itable.rows.length;//表格所有行数(所有记录数)
13 | console.log(num);
14 | var totalPage = 0;//总页数
15 | var pageSize = psize;//每页显示行数
16 | //总共分几页
17 | if(num/pageSize > parseInt(num/pageSize)){ //判断是否为小数
18 | totalPage=parseInt(num/pageSize)+1; }
19 | else{
20 | totalPage=parseInt(num/pageSize);
21 | }
22 | var currentPage = pno;//当前页数
23 | var startRow = (currentPage - 1) * pageSize+1;//开始显示的行 31
24 | var endRow = currentPage * pageSize;//结束显示的行 40
25 | endRow = (endRow > num)? num : endRow; //40
26 | console.log(endRow);
27 | //遍历显示数据实现分页
28 | for(var i=1;i<(num+1);i++){
29 | var irow = itable.rows[i-1];
30 | if(i>=startRow && i<=endRow){
31 | irow.style.display = "block";
32 | }else{
33 | irow.style.display = "none";
34 | }
35 | }
36 | var tempStr = "共"+num+"条记录 分"+totalPage+"页 当前第"+currentPage+"页";
37 | if(currentPage>1){
38 | tempStr += "首页";
39 | tempStr += "<上一页"
40 | }else{
41 | tempStr += "首页";
42 | tempStr += "<上一页";
43 | }
44 | if(currentPage下一页>";
46 | tempStr += "尾页";
47 | }else{
48 | tempStr += "下一页>";
49 | tempStr += "尾页";
50 | }
51 | document.getElementById("barcon1").innerHTML = tempStr;
52 |
53 |
54 | }
55 |
56 |
57 |
58 | function goPage2(pno,psize){
59 |
60 | var itable = document.getElementById("idData2");
61 | var num = itable.rows.length;//表格所有行数(所有记录数)
62 | console.log(num);
63 | var totalPage = 0;//总页数
64 | var pageSize = psize;//每页显示行数
65 | //总共分几页
66 | if(num/pageSize > parseInt(num/pageSize)){ //判断是否为小数
67 | totalPage=parseInt(num/pageSize)+1;
68 | }else{
69 | totalPage=parseInt(num/pageSize);
70 | }
71 | var currentPage = pno;//当前页数
72 | var startRow = (currentPage - 1) * pageSize+1;//开始显示的行 31
73 | var endRow = currentPage * pageSize;//结束显示的行 40
74 | endRow = (endRow > num)? num : endRow; //40
75 | console.log(endRow);
76 | //遍历显示数据实现分页
77 | for(var i=1;i<(num+1);i++){
78 | var irow = itable.rows[i-1];
79 | if(i>=startRow && i<=endRow){
80 | irow.style.display = "block";
81 | }else{
82 | irow.style.display = "none";
83 | }
84 | }
85 | var tempStr = "共"+num+"条记录 分"+totalPage+"页 当前第"+currentPage+"页";
86 | if(currentPage>1){
87 | tempStr += "首页";
88 | tempStr += "<上一页"
89 | }else{
90 | tempStr += "首页";
91 | tempStr += "<上一页";
92 | }
93 | if(currentPage下一页>";
95 | tempStr += "尾页";
96 | }else{
97 | tempStr += "下一页>";
98 | tempStr += "尾页";
99 | }
100 | document.getElementById("barcon2").innerHTML = tempStr;
101 | }
102 |
--------------------------------------------------------------------------------
/src/static/css/homepage.css:
--------------------------------------------------------------------------------
1 | @charset "utf-8";
2 | /* CSS Document */
3 |
4 | body {
5 | margin: 0;
6 | }
7 |
8 | a:link,a:visited,a:active
9 | {
10 | color: #1B1B1B;
11 | text-decoration:none;
12 | }
13 |
14 | a:hover{
15 | color: #1B1B1B;
16 | text-decoration:none;
17 | border: 2px;
18 | border-color: blue;
19 | }
20 |
21 | .header {
22 | background-size: cover;
23 | background-image: url("../img/bg2.png");
24 | background-repeat: no-repeat;
25 | padding-bottom: 16vw;
26 | }
27 |
28 | .title > .kcoin{
29 | color: aliceblue;
30 | font-size: 5vw;
31 | font-weight: 500;
32 | padding-top: 17vw;
33 | margin-left: 10vw;
34 | }
35 | .title h2{
36 | color: aliceblue;
37 | font-size: 2vw;
38 | font-weight: 500;
39 | margin-left: 10vw;
40 | }
41 | .title p{
42 | color:#B1B1B1;
43 | font-size: 15px;
44 | margin-left: 10vw;
45 | }
46 |
47 | .search {
48 | width: 25vw;
49 | height: 40px;
50 | border-radius: 18px;
51 | margin-left: 9.5vw;
52 | outline: none;
53 | border: 1px solid #ccc;
54 | padding-left: 20px;
55 | position: absolute;
56 | }
57 |
58 | .search-btn {
59 | height: 35px;
60 | width: 35px;
61 | position: absolute;
62 | background: url("../img/search.png") no-repeat;
63 | margin-top: 5px;
64 | margin-left: 32.5vw;
65 | border: none;
66 | outline: none;
67 | cursor: pointer;
68 | }
69 | .head {
70 | padding-top: 20px;
71 | padding-bottom: 20px;
72 | position: fixed;
73 | height: 40px;
74 | width: 100%;
75 | background-image: url("../img/head.png");
76 | background-size: cover;
77 | }
78 | .head > .head-bt {
79 | position: relative;
80 | float: right;
81 | color: aliceblue;
82 | height: 40px;
83 | width: 120px;
84 | font-size: 28px;
85 | text-decoration: none;
86 | text-align: right;
87 | padding-right: 20px;
88 | }
89 | .head > .login-bt {
90 | position: relative;
91 | float: right;
92 | color: aliceblue;
93 | font-size: 28px;
94 | display:block;
95 | margin-left: 15px;
96 | margin-right: 15px;
97 | width:100px;
98 | height:40px;
99 | border-radius: 20px 20px 20px 20px;
100 | background: #00CCFF;
101 | text-decoration: none;
102 | text-align: center;
103 | }
104 | .head > .login-bt:hover {
105 | background: #04e7ff;
106 | }
107 | .head > a > .login-headshot {
108 | position: relative;
109 | float: right;
110 | margin-right: 15px;
111 | margin-left: 15px;
112 | width: 50px;
113 | }
114 | .container {
115 | width: 100%;
116 | font-size: 0;
117 | }
118 | .container-child {
119 | margin: auto;
120 | width: 1250px;
121 | }
122 | .project {
123 | display: inline-block;
124 | margin-top: 40px;
125 | margin-left: 15px;
126 | margin-right: 15px;
127 | width: 220px;
128 | background: #F8F8FD;
129 | }
130 | .project > .project-cover {
131 | width: 100%;
132 | height: auto;
133 | }
134 | .project > .project-name {
135 | text-align: left;
136 | font-weight: 1000;
137 | font-size: 30px;
138 | padding-left: 10px;
139 | }
140 | .project > .introduction {
141 | text-align: left;
142 | font-size: 20px;
143 | padding-left: 20px;
144 | }
145 | .project > .CC {
146 | color: #FFCC33;
147 | font-size: 20px;
148 | text-align: left;
149 | padding-left: 20px;
150 | }
151 | .head_shot {
152 | padding-left: 15px;
153 | height: 50px;
154 | float: left;
155 | }
156 | .footer {
157 | position: relative;
158 | background: #1B1B1B;
159 | height: 100px;
160 | margin-top: 2vw;
161 | }
162 | .footer p {
163 | color: aliceblue;
164 | text-align: center;
165 | padding-top: 40px;
166 | font-family: "华文行楷";
167 | }
--------------------------------------------------------------------------------
/src/service/get_issue_info.go:
--------------------------------------------------------------------------------
1 | package service
2 |
3 | import (
4 | "encoding/json"
5 | "fmt"
6 | "io/ioutil"
7 | "net/http"
8 | "strconv"
9 | "strings"
10 | "time"
11 | )
12 |
13 | //解析api获取到的信息,需要的是labels中的name
14 | type IssueData struct {
15 | URL string `json:"url"`
16 | RepositoryURL string `json:"repository_url"`
17 | LabelsURL string `json:"labels_url"`
18 | CommentsURL string `json:"comments_url"`
19 | EventsURL string `json:"events_url"`
20 | HTMLURL string `json:"html_url"`
21 | ID int `json:"id"`
22 | NodeID string `json:"node_id"`
23 | Number int `json:"number"`
24 | Title string `json:"title"`
25 | User struct {
26 | Login string `json:"login"`
27 | ID int `json:"id"`
28 | NodeID string `json:"node_id"`
29 | AvatarURL string `json:"avatar_url"`
30 | GravatarID string `json:"gravatar_id"`
31 | URL string `json:"url"`
32 | HTMLURL string `json:"html_url"`
33 | FollowersURL string `json:"followers_url"`
34 | FollowingURL string `json:"following_url"`
35 | GistsURL string `json:"gists_url"`
36 | StarredURL string `json:"starred_url"`
37 | SubscriptionsURL string `json:"subscriptions_url"`
38 | OrganizationsURL string `json:"organizations_url"`
39 | ReposURL string `json:"repos_url"`
40 | EventsURL string `json:"events_url"`
41 | ReceivedEventsURL string `json:"received_events_url"`
42 | Type string `json:"type"`
43 | SiteAdmin bool `json:"site_admin"`
44 | } `json:"user"`
45 | Labels []struct {
46 | ID int `json:"id"`
47 | NodeID string `json:"node_id"`
48 | URL string `json:"url"`
49 | Name string `json:"name"`
50 | Color string `json:"color"`
51 | Default bool `json:"default"`
52 | Description string `json:"description"`
53 | } `json:"labels"`
54 | State string `json:"state"`
55 | Locked bool `json:"locked"`
56 | Assignee interface{} `json:"assignee"`
57 | Assignees []interface{} `json:"assignees"`
58 | Milestone interface{} `json:"milestone"`
59 | Comments int `json:"comments"`
60 | CreatedAt time.Time `json:"created_at"`
61 | UpdatedAt time.Time `json:"updated_at"`
62 | ClosedAt interface{} `json:"closed_at"`
63 | AuthorAssociation string `json:"author_association"`
64 | Body string `json:"body"`
65 | ClosedBy interface{} `json:"closed_by"`
66 | }
67 |
68 | //获取项目贡献者信息的接口
69 | // 函数名:Get_issue_info
70 | // 函数参数:userName string, programName string,issueName int
71 | // 返回值:string 包含所有的labels信息
72 |
73 | func Get_issue_info(userName string, programName string, issueNum int) int {
74 | Num := strconv.Itoa(issueNum)
75 | var url_1 string = "https://api.github.com/repos/" + userName + "/" + programName + "/" + "issues" + "/" + Num
76 | fmt.Println(url_1)
77 | client := &http.Client{}
78 | response, _ := client.Get(url_1)
79 | defer response.Body.Close()
80 | body, err_1 := ioutil.ReadAll(response.Body)
81 | if err_1 != nil {
82 | panic(err_1)
83 | }
84 |
85 | var ib IssueData
86 | json.Unmarshal(body, &ib)
87 | issues := []string{}
88 | for i := 0; i < len(ib.Labels); i++ {
89 | var labelsName string = ib.Labels[i].Name
90 | kcoin := "Kcoin"
91 | if strings.HasPrefix(labelsName, kcoin) == true {
92 | issues = append(issues, strings.Split(labelsName, "Kcoin#")[1])
93 | }
94 | }
95 | res, _ := strconv.Atoi(issues[0])
96 | return res
97 | }
98 |
99 | //使用实例:
100 | //func main() {
101 | // var info int= Get_issue_info("OS-ABC", "Kcoin-Golang", 288)
102 | // fmt.Println(info)
103 | //}
104 |
--------------------------------------------------------------------------------
/src/views/join.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | KCoin-join
8 |
9 |
10 |
11 |
12 |
13 |
67 |
68 |
69 |
70 |
71 |
--------------------------------------------------------------------------------
/src/controllers/importHelper.go:
--------------------------------------------------------------------------------
1 | // TODO 把该文件与github_helper.go移动到service文件夹下, 并保证可以运行
2 | package controllers
3 |
4 | import (
5 | "Kcoin-Golang/src/models"
6 | "Kcoin-Golang/src/service"
7 | "fmt"
8 | "log"
9 | "strings"
10 | )
11 |
12 | func ImportProject(url, cover_url string, githubInfo service.GithubInfo) error {
13 | fmt.Println("进入ImportProject")
14 | //首先将string类型的currentUserId转成Int型
15 | //currentUserId_int,err:=strconv.Atoi(currentUserId)
16 | //检查地址是否合法
17 | err := service.CheckGithubRepoUrl(githubInfo.GithubName, url)
18 | if err != nil {
19 | log.Fatal("url is illegal", err)
20 | return err
21 | } else {
22 | fmt.Println("url合法")
23 | }
24 | //解析已经合法的地址中的用户名和仓库名
25 | userName, repoName, _ := service.ParseGithubHTTPSUrl(url)
26 | //使用用户名和仓库名获取项目全部contributor
27 | userslist_string := service.GetContributors(userName, repoName)
28 | users := strings.Split(userslist_string, " ")
29 | //将当前登录用户注册到webhook中
30 | service.RegisterGithubWebhooks(githubInfo.GithubName, repoName, githubInfo.AccessToken)
31 | host_id, _ := models.GetUseridByUsername(userName)
32 | fmt.Println("当前登陆用户id为", host_id, "当前username为", userName)
33 | fmt.Println("项目中的全部contributors", users)
34 | //查询数据库,看看所有的contributor哪个已经加入到数据库了,如果已经加入数据库,就把这些人放到k_user_in_project这个表里
35 | var alreadyIn []string //已经加入kcoin的contributor
36 | var notIn []string //还没加入kcoin的contributor
37 | var project_id int
38 |
39 | //插入项目到数据库
40 | _, _ = models.InsertProject(repoName, url, cover_url)
41 | //根据根据项目名查k_project表获取project_id
42 | project_id, err = models.GetProjectidByRepoName(repoName)
43 | if err != nil {
44 | log.Fatal("when query project_id in k_project ,error occured:", err)
45 | }
46 | //基金会注入原始cc100.00,捐献种类dtype设为0.
47 | err = models.CCInject(0, project_id, 100.00, 0)
48 | if err != nil {
49 | log.Fatal("when initialize cc injection, error occured: ", err)
50 | }
51 |
52 | for _, singleUser := range users {
53 | fmt.Println("开始for循环")
54 | if singleUser == "" {
55 | break
56 | }
57 | //遍历全部contributor列表
58 | var k_user_id int
59 |
60 | fmt.Println("正在找当前contributor:", singleUser)
61 | res, err := models.FindUserByUsername(singleUser)
62 | if err != nil {
63 | log.Fatal("when query a single user in k_user table,an error occured,", err)
64 | } else {
65 | num, _ := res.RowsAffected()
66 | if num == 0 { //如果没查到
67 | notIn = append(notIn, singleUser)
68 | //通过github API获取这个用户的git id
69 | singleUser_git_id := service.GetGithubId(singleUser)
70 | //插入到临时用户表
71 | res, err := models.InsertIntoKTemporaryUser(host_id, singleUser_git_id, singleUser, project_id)
72 | if err == nil {
73 | num, _ := res.RowsAffected()
74 | fmt.Println(num)
75 | } else {
76 | log.Fatal("when insert into k_temporary_user,error occured,", err)
77 | }
78 | } else { //查到了,这个用户已经在项目了
79 | alreadyIn = append(alreadyIn, singleUser)
80 | //然后把这个用户加到k_user_in_project中
81 | //首先根据user_name获取k_user_id
82 | k_user_id, err = models.GetUseridByUsername(singleUser)
83 | if err != nil {
84 | log.Fatal("when query k_user_id in k_user,error occured:", err)
85 | }
86 | //然后根据根据项目名查k_project表获取project_id
87 | project_id, err = models.GetProjectidByRepoName(repoName)
88 | if err != nil {
89 | log.Fatal("when query project_id in k_project ,error occured:", err)
90 | }
91 | //最后两个id都有了,插入k_user_in_project
92 | res, err = models.InsertIntoKUserInProject(project_id, k_user_id)
93 | if err == nil {
94 | nums, _ := res.RowsAffected()
95 | fmt.Println("affected rows has", nums)
96 | id, _ := res.LastInsertId()
97 | fmt.Println("last insert id is ", id)
98 | } else {
99 | log.Fatal("when insert to k_user_in_project,error occured,", err)
100 | }
101 | }
102 | }
103 | }
104 | //最后判断一下项目拥有者在不在k_user_in_Projet里,不在就插入
105 | var IfOwnerIn int
106 | IfOwnerIn, err = models.FindUserInKUserInProject(host_id)
107 | if IfOwnerIn == 0 {
108 | fmt.Println("拥有者还不在数据库,插入")
109 |
110 | _, err = models.InsertIntoKUserInProject(project_id, host_id)
111 | }
112 | //对所有没有加入的人给他们发个邮件
113 | _, err = models.SendEMailToPotentialUsers(notIn, githubInfo.AccessToken)
114 | return err
115 | }
116 |
--------------------------------------------------------------------------------
/user-story.md:
--------------------------------------------------------------------------------
1 | # 用户故事集
2 | ## V1.0 Milestone
3 | ### 1. 作为一个平台管理者,我希望登陆时能够识别我的管理员身份,以便于进行相应的管理操作
4 |
5 | - [ ] 平台管理者登录后能在个人中心看到他是管理者身份。
6 | - [ ] 平台管理员登录后能看到外部发起的捐赠、注资信息。
7 | - [ ] 平台管理员能够参与有关向项目注资的讨论和决策。
8 | ### 2. 作为一个普通用户,我希望直接通过github、gitee登陆,以便于将账号与我的github相关联,进行导入项目、参与项目等操作
9 | - [ ] 用户可以通过github账号登录平台
10 | - [ ] 用户可以通过gitee账号登录平台
11 | - [ ] 一个用github或gitee登录过的用户再用另一种方式登录平台时,平台能关联这名用户的两种账号
12 |
13 | ### 3. 作为一个项目管理者,我希望通过项目url导入项目
14 |
15 | - [ ] 平台能通过URL获取git仓库的管理员、contributor等信息
16 | - [ ] 项目管理者可以通过项目URL导入项目
17 |
18 | ### 4. 作为一个项目管理者,我希望通过点击获取到的github仓库列表item,导入项目
19 |
20 | - [ ] 个人页面中可查看个人github仓库列表
21 | - [ ] 点击仓库列表项可导入github项目
22 | - [ ] 导入后提示是否成功,失败说明原因
23 |
24 | ### 5. 作为一个项目管理者,我希望我在导入项目时,可以制定自己的初始贡献量评定规则
25 |
26 | - [ ] 导入项目时以填表的方式设置简单的分配规则
27 | - [ ] 导入项目时可以上传自己定制的较为复杂的智能合约,并给出描述
28 |
29 | ### 6. 作为一个独裁制项目管理者,我希望我在导入项目后,可以更改贡献量评定规则
30 | - [ ] 项目在被导入后,管理者可以访问项目设置页面,更改项目规则。
31 | - [ ] 更改项目规则,可以查看到当前所有规则列表,管理者可以增加新的规则,或者改变某一规则赋予用户的CS,也可以删除一种规则。
32 | - [ ] 规则更改完成后,管理者可以点击确定保存。
33 | - [ ] 保存后应当判断规则制定合法性,如果合法提示更改成功;否则标红列表中不合法的规则,并注明原因。
34 | - [ ] 用户可以取消更改,当用户点击取消时,应当提示是否确定取消,以防止误操作。
35 | ### 7. 作为一个项目管理者,我希望可以设置项目封面,以便更好的展示给其他用户
36 | - [ ] 项目被导入后,在项目栏目中有设置封面按钮,点击后允许上传图片作为封面
37 | ### 8. 我是一名想在开源项目中做贡献的用户,我希望Kcoin能展示项目在Github上的star和committer数量等信息,以便我判断一个项目是否活跃且值得加入。
38 | - [ ] 项目详情页面会显示github中的star数量
39 | - [ ] 项目详情页面会显示github中的committer数量
40 | - [ ] kcoin的首页会展示按star数和committer数加权得到的排行榜
41 | ### 9. 作为一名投资者,我希望看到项目被哪些公司或机构使用,这样可以让我更好地决策,到底要不要给这个项目投资、要投资多少。
42 | - [ ] 项目详情页底部会展示所有使用该项目的公司/机构的图标
43 | - [ ] 项目管理者可以通过手动添加系统中预设的公司/机构
44 | - [ ] 项目管理者应该在添加公司/机构时提供相应的凭证,以供后台审核。
45 | - [ ] 系统中没有预设所选公司/机构的时候,可以通过向github中kcoin项目提交pr的方式来增加。
46 | ### 10. 我是一名项目管理者,我希望查看项目总体CC(市值cs*股价)和项目公共CC
47 |
48 | + [ ] 用户有项目管理页面
49 | + [ ] 项目管理者在项目管理页面中可看到项目总cs数, 项目cs与cc兑换比。
50 | + [ ] 项目管理者在项目管理页面中可看到项目总体CC和项目公共CC
51 |
52 | ### 11. 作为一个普通用户,我希望快速查看我参与的项目中我的CS和分配得到的CC
53 | - [ ] 普通用户可在我的项目列表中的每个项目名片上看到我的CS和CC
54 | - [ ] 若无法获取数据,则默认初始值为“--”
55 | ### 12. 作为一名项目管理者,我想要关注贡献者列表与具体工作列表,以便于增强对项目掌控。
56 | - [ ] 当用户选择访问一个项目详情时,应当判断他是否是管理员,若是则展示全体成员的贡献度列表,包括工作内容、贡献度、贡献时间。
57 | - [ ] 当信息读取失败时,要给出明确的提示。
58 | - [ ] 当列表内容过多时应当可以分页展示。
59 | ### 13. 作为一个普通用户,我想要查看目前项目所有成员的CS排行榜
60 | - [ ] 普通用户在我的项目列表中的每个项目名片上点击查看该项目的CS排行榜
61 | - [ ] 普通用户能正确读取所参与的各个项目的所有成员的CS排行榜
62 | - [ ] 信息读取失败时,应给出明确的提示信息
63 | - [ ] 普通用户通过点击刷新按钮获取最新的CS排名信息
64 | ### 14. 作为一个普通用户,我想要查看目前项目所有动态,包括项目规则的变化和公共CC变化
65 | - [ ] 普通用户在我的项目列表中,可以点击查看该项目的历史动态
66 | - [ ] 项目的历史动态中包含项目规则的变化和公共CC变化
67 | - [ ] 每次项目规则的变化都以“时间:项目规则的变化”的形式展示出来,最终形成项目规则变化的时间轴
68 | - [ ] 每次公共CC变化都以“时间:公共CC变化”的形式展示出来,最终形成公共CC变化的时间轴
69 | ### 15. 作为一个普通用户,我想要查看目前项目的贡献度评定规则,以便了解游戏规则
70 | - [ ] 普通用户在我的项目列表中的每个项目名片上点击查看该项目的贡献度评定规则
71 | - [ ] 当项目贡献度评定规则发生变化时,普通用户应收到变更通知
72 | - [ ] 贡献度评定规则变更后会保存历史版本,普通用户可以查阅
73 | ### 16. 作为一个普通用户,我希望我所在的项目在被管理员导入后,接收到邮件通知,提醒我加入kcoin平台,以便获取CS
74 | - [ ] 普通用户能通过项目所在平台的个人主要邮箱接收项目已被导入kcoin的邮件通知
75 | - [ ] 普通用户能在接收到通知后方便地跳转至kcoin网站,进行注册活动
76 | - [ ] 普通用户接收的邮件通知应包含:项目已被导入kcoin的通知、kcoin简介、kcoin主页链接、kcoin注册链接
77 | ### 17. 作为一个普通用户,我在给一个已托管的项目贡献成为一个新contributor时,希望收到邮件通知提醒我加入kcoin平台,以便获取CS
78 |
79 | - [ ] 普通用户在GitHub上做出贡献时,如果此项目已经在Kcoin平台上托管,则用户会收到该项目在Kcoin上的通知
80 | - [ ] 普通用户能在邮件中跳转到Kcoin网站
81 | - [ ] 普通用户能在Kcoin网站注册,并关联自己的GitHub账户,以便获取CS
82 |
83 | ### 18. 作为一个普通用户,我希望收到我参与的项目动态消息,包括项目规则的变化、决议投票和公共CC变化等,以便及时了解情况。
84 |
85 | - [ ] 普通用户可以在Kcoin平台看到他参与项目的动态信息
86 | - [ ] 普通用户可以选择是否通过邮件接收项目动态信息
87 |
88 | ### 19. 我是一名普通用户,我希望通过向开源社区提交代码,按照该项目贡献度规则获得相应的贡献度和CS
89 |
90 | - [ ] 普通用户能在GitHub上提交了PR或者作出其他贡献时,在Kcoin平台获取CS
91 | - [ ] 普通用户能在Kcoin平台上查看贡献度规则
92 |
93 | ### 20. 我是kcoin基金会,我希望用CC按股价比例收购某个项目的CS,以便支持项目发展
94 |
95 | - [ ] 有一个网页专门显示当前每个项目CS和CC的市场兑换比例
96 |
97 | ### 21. 我是一名投资者,我希望用法币向基金会购买CC,以便于收购某个项目的股权、投资项目。
98 |
99 | - [ ] CC购买页面有法币CC互换比例,微信/支付宝/银行卡支付功能。
100 | - [ ] 由项目页面点击购买,则CC购买页面有法币与项目CS互换比例
101 | - [ ] 未登录时,也可进行项目搜索,查看信息,购买选项
102 | - [ ] 点击购买时若未登录跳转至登录/注册页面,登录环节完毕检查CC是否足够,分别跳转
103 |
104 | ### 22. 我是一名投资者,我希望用CC按股价比例收购某个项目的CS,这些CS由全体成员按比例缴出,以便获得该项目的CS,进而控制投票权
105 | - [ ] 投资者能够在项目名片中看到cc与cs的股价比例
106 | - [ ] 投资者能够在投资时看到投资后自己的cs在项目中的占比以及投票权情况
107 | - [ ] 投资者能够收到活跃项目的推荐信息
108 |
109 | ### 23. 我是一名投资者,我希望用CC按股价比例向某个项目成员购买他手中的CS,从而拥有项目的投票权
110 | - [ ] 项目详情页面显示“买入cs”按钮
111 | - [ ] 点击“买入cs”按钮,会让用户在文本框输入买入多少cc的cs,文本框中的内容只能是实数
112 | - [ ] 有确定买入和取消按钮,供用户选择
113 | - [ ] 当用户点击确定买入,会跳转到输入密码页面
114 | - [ ] 当用户输入正确的密码,买入成功,个人持有的该项目cs增加相应数量,个人cc减少相应数量
115 |
116 |
--------------------------------------------------------------------------------
/src/views/login.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | KCoin
8 |
9 |
10 |
11 |
12 |
13 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
--------------------------------------------------------------------------------
/src/static/css/loginJoin.css:
--------------------------------------------------------------------------------
1 | /*以下是login和join页面的css*/
2 | .logo-join {
3 | display:block;
4 | margin-top:50px;
5 | position: relative;
6 | width:100%;
7 | height: auto;
8 | text-align: center;
9 | }
10 |
11 | .title-join {
12 | display: block;
13 | font-family: PingFangHK-Semibold;
14 | font-size: 20px;
15 | color: #ffffff;
16 | position: relative;
17 | margin-top: 20px;
18 | width:100%;
19 | height:auto;
20 | text-align:center;
21 | }
22 |
23 | .join-label {
24 | padding-left: 32px;
25 | text-align: left;
26 | color:#ffffff;
27 | }
28 |
29 | .grid-join {
30 | display: block;
31 | position: relative;
32 | width: 376px;
33 | left:35%;
34 | height: 700px;
35 | z-index: 1001;
36 | }
37 |
38 | .father-div {
39 | display: block;
40 | width: 100%;
41 | position: relative;
42 | text-align: center;
43 | }
44 |
45 | .form-submit {
46 | display: block;
47 | position: relative;
48 | width: 376px;
49 | height: 95px;
50 | }
51 |
52 | .content {
53 | position: relative;
54 | width: 100%;
55 | top: 10%;
56 | }
57 |
58 | .left-subcontent {
59 | position: relative;
60 | width:40%;
61 | left:150px;
62 | margin-top: 35px;
63 | margin-bottom: 50px;
64 | left:150px;
65 | }
66 |
67 | .right-subcontent {
68 | width:40%;
69 | margin-top: 120px;
70 | margin-left: 20px;
71 | margin-bottom: 50px;
72 | float:right
73 | }
74 |
75 | .login-subtitle {
76 | text-align:center;
77 | margin-top: 20px;
78 | margin-bottom: 10px;
79 | font-family: PingFangHK-Semibold;
80 | font-size: 28px;
81 | color: #323a45;
82 | }
83 |
84 | .grid {
85 | position: absolute;
86 | background: #ffffff;
87 | border-radius: 5px;
88 | width: 310px;
89 | height: 420px;
90 | padding-left: 20px;
91 | padding-right: 20px;
92 | }
93 |
94 | .row {
95 | position: relative;
96 | display: flex;
97 | flex-wrap: wrap;
98 | }
99 |
100 | .cell {
101 | -webkit-box-flex: 1;
102 | flex: 1 0 0;
103 | max-width: 100%;
104 | padding: 0 12px
105 | }
106 |
107 | .form-group {
108 | display: block;
109 | position: relative
110 | }
111 |
112 | .form-group > label {
113 | margin-top: 20px;
114 | display: block;
115 | font-family: PingFangHK-Semibold;
116 | font-size: 13px;
117 | margin-bottom: 5px;
118 | }
119 |
120 | .required {
121 | border: 1px #1ba1e2 dashed !important;
122 | width: 310px !important;
123 | height: 40px;
124 | }
125 |
126 | .link {
127 | color: #60a8f0 !important;
128 | font-family: PingFangHK-Semibold;
129 | font-size: 13px;
130 | float: right;
131 | bottom:20px;
132 | position:relative;
133 | text-decoration: none;
134 | }
135 |
136 | .bottom-login {
137 | background: #60A8F0;
138 | border-radius: 5px;
139 | font-size: 16px;
140 | margin-bottom: 5px;
141 | text-align: center;
142 | width: 320px;
143 | height: 40px;
144 | box-shadow: none;
145 | text-decoration: none;
146 | max-width: 400px;
147 | height: 40px;
148 | font-weight: 400;
149 | text-align: center;
150 | white-space: nowrap;
151 | vertical-align: middle;
152 | }
153 |
154 | .link-underBotton {
155 | display: block;
156 | outline-color: #9d9d9d;
157 | font-family: PingFangHK-Semibold;
158 | font-size: 13px;
159 | float: right;
160 | position: relative;
161 | float: right;
162 | width: 25%;
163 | }
164 |
165 | .cell {
166 | display: block;
167 | background-color: lime;
168 | }
169 |
170 | .block-dark {
171 | display: block;
172 | position: relative;
173 | border-radius: 5px;
174 | font-size: 16px;
175 | margin-bottom: 5px;
176 | text-align: center;
177 | width: 320px;
178 | height: 40px;
179 | box-shadow: none;
180 | background-color: #666666;
181 | }
182 |
183 | .buttom-dark {
184 | color: #ffffff;
185 | width: 100% !important;
186 | text-decoration: none;
187 | text-align: center;
188 | margin-top: 10px;
189 | }
190 |
191 | .github-icon {
192 | width: 25px !important;
193 | height: 25px !important;
194 | position: relative;
195 | }
196 |
197 | .gitee-icon {
198 | width: 36px !important;
199 | height: 36px !important;
200 | position: relative;
201 | }
202 |
203 | .form-login {
204 | width: 100%;
205 | }
206 |
207 | .form-login-buttom {
208 | display: block;
209 | position: relative;
210 | height:65px;
211 | }
212 |
--------------------------------------------------------------------------------
/database/create.sql:
--------------------------------------------------------------------------------
1 | --创建用户表
2 | CREATE TABLE "public"."K_User" (
3 | "user_id" int4 DEFAULT nextval('test_c_id_seq'::regclass) NOT NULL,
4 | "user_name" varchar(255) COLLATE "default" NOT NULL,
5 | "user_cc" float8 DEFAULT 0,
6 | "register_time" timestamp(6) NOT NULL,
7 | "head_shot_url" varchar(255) COLLATE "default" NOT NULL,
8 | "is_delete" bool DEFAULT false,
9 | CONSTRAINT "K_User_pkey" PRIMARY KEY ("user_id")
10 | )
11 | WITH (OIDS=FALSE)
12 |
13 |
14 | --创建项目表
15 | CREATE TABLE "public"."K_Project" (
16 | "project_id" int4 DEFAULT nextval('"K_Project1_project_id_seq"'::regclass) NOT NULL,
17 | "project_name" varchar(255) COLLATE "default" NOT NULL,
18 | "project_url" varchar(255) COLLATE "default" NOT NULL,
19 | "project_cover_url" varchar(255) COLLATE "default" NOT NULL,
20 | "project_institution" int4,
21 | "project_description" text COLLATE "default",
22 | CONSTRAINT "k_project_pkey" PRIMARY KEY ("project_id")
23 | )
24 | WITH (OIDS=FALSE)
25 | ;
26 |
27 | ALTER TABLE "public"."K_Project" OWNER TO "sspkukcoin";
28 |
29 | COMMENT ON TABLE "public"."K_Project" IS '项目表';
30 |
31 | COMMENT ON COLUMN "public"."K_Project"."project_id" IS '项目id(主键)';
32 |
33 | COMMENT ON COLUMN "public"."K_Project"."project_name" IS '项目名称';
34 |
35 | COMMENT ON COLUMN "public"."K_Project"."project_url" IS '项目url';
36 |
37 | COMMENT ON COLUMN "public"."K_Project"."project_cover_url" IS '项目封面urll';
38 |
39 | COMMENT ON COLUMN "public"."K_Project"."project_institution" IS '项目制度(1是独裁制,2是委员会占比制,3是委员会单票制,4是全体占比制,5是全体单票制)';
40 |
41 | --创建用户 in项目表
42 | CREATE TABLE "public"."K_User_in_Project" (
43 | "item_id" int4 DEFAULT nextval('"K_User_in_Project1_item_id_seq"'::regclass) NOT NULL,
44 | "project_id" int4 NOT NULL,
45 | "user_id" int4 NOT NULL,
46 | "user_cs" float8 DEFAULT 0 NOT NULL,
47 | "user_cc" float8 DEFAULT 0 NOT NULL,
48 | CONSTRAINT "k_user_in_project_pkey" PRIMARY KEY ("user_id", "project_id"),
49 | CONSTRAINT "K_User_in_Project_user_id_fkey" FOREIGN KEY ("user_id") REFERENCES "public"."K_User" ("user_id") ON DELETE NO ACTION ON UPDATE NO ACTION,
50 | CONSTRAINT "K_User_in_Project_project_id_fkey" FOREIGN KEY ("project_id") REFERENCES "public"."K_Project" ("project_id") ON DELETE NO ACTION ON UPDATE NO ACTION
51 | )
52 | WITH (OIDS=FALSE)
53 | ;
54 |
55 | --创建触发器
56 | CREATE TRIGGER "cc_trigger" AFTER UPDATE ON "public"."K_User_in_Project"
57 | FOR EACH ROW
58 | EXECUTE PROCEDURE "sumcc"();
59 |
60 |
61 | --创建权限表
62 | CREATE TABLE "public"."K_Permission" (
63 | "id" int4 DEFAULT nextval('"K_Permission_id_seq"'::regclass) NOT NULL,
64 | "Permission_id" int4 NOT NULL,
65 | "Permission" varchar(100) COLLATE "default" NOT NULL,
66 | CONSTRAINT "K_Permission_pkey" PRIMARY KEY ("id")
67 | )
68 | WITH (OIDS=FALSE)
69 | ;
70 |
71 | ALTER TABLE "public"."K_Permission" OWNER TO "sspkukcoin";
72 |
73 | COMMENT ON TABLE "public"."K_Permission" IS '权限表';
74 |
75 | COMMENT ON COLUMN "public"."K_Permission"."id" IS '主键ID';
76 |
77 | COMMENT ON COLUMN "public"."K_Permission"."Permission_id" IS '权限ID';
78 |
79 | COMMENT ON COLUMN "public"."K_Permission"."Permission" IS '权限名';
80 |
81 | --创建角色表
82 | CREATE TABLE "public"."k_role" (
83 | "id" int4 DEFAULT nextval('k_role_id_seq'::regclass) NOT NULL,
84 | "role_id" int4 NOT NULL,
85 | "role_name" varchar(100) COLLATE "default" NOT NULL,
86 | "role_permissions" int4 NOT NULL,
87 | "is_able" bool DEFAULT false NOT NULL,
88 | CONSTRAINT "k_role_pkey" PRIMARY KEY ("id"),
89 | CONSTRAINT "k_role_role_permissions_fkey" FOREIGN KEY ("role_permissions") REFERENCES "public"."K_Permission" ("id") ON DELETE NO ACTION ON UPDATE NO ACTION
90 | )
91 | WITH (OIDS=FALSE)
92 | ;
93 |
94 | ALTER TABLE "public"."k_role" OWNER TO "sspkukcoin";
95 |
96 | COMMENT ON TABLE "public"."k_role" IS '角色表';
97 |
98 | COMMENT ON COLUMN "public"."k_role"."id" IS '主键ID';
99 |
100 | COMMENT ON COLUMN "public"."k_role"."role_id" IS '用户ID';
101 |
102 | COMMENT ON COLUMN "public"."k_role"."role_name" IS '用户名';
103 |
104 | COMMENT ON COLUMN "public"."k_role"."role_permissions" IS '用户权限';
105 |
106 | COMMENT ON COLUMN "public"."k_role"."is_able" IS '用户是否使用';
107 |
108 | --创建项目中,用户的角色表
109 | CREATE TABLE "public"."k_user_role_in_project" (
110 | "id" int4 DEFAULT nextval('k_user_role_in_project_id_seq'::regclass) NOT NULL,
111 | "project_id" int4 NOT NULL,
112 | "user_id" int4 NOT NULL,
113 | "role_id" int4 NOT NULL,
114 | CONSTRAINT "k_user_role_in_project_pkey" PRIMARY KEY ("id"),
115 | CONSTRAINT "k_user_role_in_project_project_id_fkey" FOREIGN KEY ("project_id") REFERENCES "public"."K_Project" ("project_id") ON DELETE NO ACTION ON UPDATE NO ACTION,
116 | CONSTRAINT "k_user_role_in_project_user_id_fkey" FOREIGN KEY ("user_id") REFERENCES "public"."K_User" ("user_id") ON DELETE NO ACTION ON UPDATE NO ACTION
117 | )
118 | WITH (OIDS=FALSE)
119 | ;
120 |
121 |
--------------------------------------------------------------------------------
/src/static/js/EasePack.min.js:
--------------------------------------------------------------------------------
1 | /*!
2 | * VERSION: beta 1.9.4
3 | * DATE: 2014-07-17
4 | * UPDATES AND DOCS AT: http://www.greensock.com
5 | *
6 | * @license Copyright (c) 2008-2014, GreenSock. All rights reserved.
7 | * This work is subject to the terms at http://www.greensock.com/terms_of_use.html or for
8 | * Club GreenSock members, the software agreement that was issued with your membership.
9 | *
10 | * @author: Jack Doyle, jack@greensock.com
11 | **/
12 | var _gsScope="undefined"!=typeof module&&module.exports&&"undefined"!=typeof global?global:this||window;(_gsScope._gsQueue||(_gsScope._gsQueue=[])).push(function(){"use strict";_gsScope._gsDefine("easing.Back",["easing.Ease"],function(t){var e,i,s,r=_gsScope.GreenSockGlobals||_gsScope,n=r.com.greensock,a=2*Math.PI,o=Math.PI/2,h=n._class,l=function(e,i){var s=h("easing."+e,function(){},!0),r=s.prototype=new t;return r.constructor=s,r.getRatio=i,s},_=t.register||function(){},u=function(t,e,i,s){var r=h("easing."+t,{easeOut:new e,easeIn:new i,easeInOut:new s},!0);return _(r,t),r},c=function(t,e,i){this.t=t,this.v=e,i&&(this.next=i,i.prev=this,this.c=i.v-e,this.gap=i.t-t)},p=function(e,i){var s=h("easing."+e,function(t){this._p1=t||0===t?t:1.70158,this._p2=1.525*this._p1},!0),r=s.prototype=new t;return r.constructor=s,r.getRatio=i,r.config=function(t){return new s(t)},s},f=u("Back",p("BackOut",function(t){return(t-=1)*t*((this._p1+1)*t+this._p1)+1}),p("BackIn",function(t){return t*t*((this._p1+1)*t-this._p1)}),p("BackInOut",function(t){return 1>(t*=2)?.5*t*t*((this._p2+1)*t-this._p2):.5*((t-=2)*t*((this._p2+1)*t+this._p2)+2)})),m=h("easing.SlowMo",function(t,e,i){e=e||0===e?e:.7,null==t?t=.7:t>1&&(t=1),this._p=1!==t?e:0,this._p1=(1-t)/2,this._p2=t,this._p3=this._p1+this._p2,this._calcEnd=i===!0},!0),d=m.prototype=new t;return d.constructor=m,d.getRatio=function(t){var e=t+(.5-t)*this._p;return this._p1>t?this._calcEnd?1-(t=1-t/this._p1)*t:e-(t=1-t/this._p1)*t*t*t*e:t>this._p3?this._calcEnd?1-(t=(t-this._p3)/this._p1)*t:e+(t-e)*(t=(t-this._p3)/this._p1)*t*t*t:this._calcEnd?1:e},m.ease=new m(.7,.7),d.config=m.config=function(t,e,i){return new m(t,e,i)},e=h("easing.SteppedEase",function(t){t=t||1,this._p1=1/t,this._p2=t+1},!0),d=e.prototype=new t,d.constructor=e,d.getRatio=function(t){return 0>t?t=0:t>=1&&(t=.999999999),(this._p2*t>>0)*this._p1},d.config=e.config=function(t){return new e(t)},i=h("easing.RoughEase",function(e){e=e||{};for(var i,s,r,n,a,o,h=e.taper||"none",l=[],_=0,u=0|(e.points||20),p=u,f=e.randomize!==!1,m=e.clamp===!0,d=e.template instanceof t?e.template:null,g="number"==typeof e.strength?.4*e.strength:.4;--p>-1;)i=f?Math.random():1/u*p,s=d?d.getRatio(i):i,"none"===h?r=g:"out"===h?(n=1-i,r=n*n*g):"in"===h?r=i*i*g:.5>i?(n=2*i,r=.5*n*n*g):(n=2*(1-i),r=.5*n*n*g),f?s+=Math.random()*r-.5*r:p%2?s+=.5*r:s-=.5*r,m&&(s>1?s=1:0>s&&(s=0)),l[_++]={x:i,y:s};for(l.sort(function(t,e){return t.x-e.x}),o=new c(1,1,null),p=u;--p>-1;)a=l[p],o=new c(a.x,a.y,o);this._prev=new c(0,0,0!==o.t?o:o.next)},!0),d=i.prototype=new t,d.constructor=i,d.getRatio=function(t){var e=this._prev;if(t>e.t){for(;e.next&&t>=e.t;)e=e.next;e=e.prev}else for(;e.prev&&e.t>=t;)e=e.prev;return this._prev=e,e.v+(t-e.t)/e.gap*e.c},d.config=function(t){return new i(t)},i.ease=new i,u("Bounce",l("BounceOut",function(t){return 1/2.75>t?7.5625*t*t:2/2.75>t?7.5625*(t-=1.5/2.75)*t+.75:2.5/2.75>t?7.5625*(t-=2.25/2.75)*t+.9375:7.5625*(t-=2.625/2.75)*t+.984375}),l("BounceIn",function(t){return 1/2.75>(t=1-t)?1-7.5625*t*t:2/2.75>t?1-(7.5625*(t-=1.5/2.75)*t+.75):2.5/2.75>t?1-(7.5625*(t-=2.25/2.75)*t+.9375):1-(7.5625*(t-=2.625/2.75)*t+.984375)}),l("BounceInOut",function(t){var e=.5>t;return t=e?1-2*t:2*t-1,t=1/2.75>t?7.5625*t*t:2/2.75>t?7.5625*(t-=1.5/2.75)*t+.75:2.5/2.75>t?7.5625*(t-=2.25/2.75)*t+.9375:7.5625*(t-=2.625/2.75)*t+.984375,e?.5*(1-t):.5*t+.5})),u("Circ",l("CircOut",function(t){return Math.sqrt(1-(t-=1)*t)}),l("CircIn",function(t){return-(Math.sqrt(1-t*t)-1)}),l("CircInOut",function(t){return 1>(t*=2)?-.5*(Math.sqrt(1-t*t)-1):.5*(Math.sqrt(1-(t-=2)*t)+1)})),s=function(e,i,s){var r=h("easing."+e,function(t,e){this._p1=t||1,this._p2=e||s,this._p3=this._p2/a*(Math.asin(1/this._p1)||0)},!0),n=r.prototype=new t;return n.constructor=r,n.getRatio=i,n.config=function(t,e){return new r(t,e)},r},u("Elastic",s("ElasticOut",function(t){return this._p1*Math.pow(2,-10*t)*Math.sin((t-this._p3)*a/this._p2)+1},.3),s("ElasticIn",function(t){return-(this._p1*Math.pow(2,10*(t-=1))*Math.sin((t-this._p3)*a/this._p2))},.3),s("ElasticInOut",function(t){return 1>(t*=2)?-.5*this._p1*Math.pow(2,10*(t-=1))*Math.sin((t-this._p3)*a/this._p2):.5*this._p1*Math.pow(2,-10*(t-=1))*Math.sin((t-this._p3)*a/this._p2)+1},.45)),u("Expo",l("ExpoOut",function(t){return 1-Math.pow(2,-10*t)}),l("ExpoIn",function(t){return Math.pow(2,10*(t-1))-.001}),l("ExpoInOut",function(t){return 1>(t*=2)?.5*Math.pow(2,10*(t-1)):.5*(2-Math.pow(2,-10*(t-1)))})),u("Sine",l("SineOut",function(t){return Math.sin(t*o)}),l("SineIn",function(t){return-Math.cos(t*o)+1}),l("SineInOut",function(t){return-.5*(Math.cos(Math.PI*t)-1)})),h("easing.EaseLookup",{find:function(e){return t.map[e]}},!0),_(r.SlowMo,"SlowMo","ease,"),_(i,"RoughEase","ease,"),_(e,"SteppedEase","ease,"),f},!0)}),_gsScope._gsDefine&&_gsScope._gsQueue.pop()();
--------------------------------------------------------------------------------
/src/views/projectFunding.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | 项目信息
5 |
6 |
7 |
8 |
9 |
10 |
11 | {{template "./platformAdminTopNav.html" .}}
12 |
13 |
16 |
17 |
18 |
19 |
20 |
21 | | 日期 |
22 | 注资项目 |
23 | cc数量 |
24 |
25 |
26 | | 11.22 |
27 | Sonorous77/Robot |
28 | 2000 |
29 |
30 |
31 | | 11.22 |
32 | Sonorous77/Weather forecast |
33 | 3000 |
34 |
35 |
36 | | 11.23 |
37 | OS-ABC/HelloWorld |
38 | 5000 |
39 |
40 |
41 | | 11.24 |
42 | Sonorous77/Robot |
43 | 5000 |
44 |
45 |
46 | | 11.24 |
47 | OS-ABC/HelloWorld |
48 | 2000 |
49 |
50 |
51 | | 11.25 |
52 | OS-ABC/HelloWorld |
53 | 6000 |
54 |
55 |
56 | | 11.25 |
57 | Sonorous77/Robot |
58 | 2000 |
59 |
60 |
61 | | 11.26 |
62 | Sonorous77/Weather forecast |
63 | 3000 |
64 |
65 |
66 | | 日期 |
67 | 注资项目 |
68 | cc数量 |
69 |
70 |
71 |
72 | | 11.27 |
73 | OS-ABC/HelloWorld |
74 | 1000 |
75 |
76 |
77 | | 11.27 |
78 | Sonorous77/Weather forecast |
79 | 3000 |
80 |
81 |
82 | | 11.28 |
83 | Sonorous77/Robot |
84 | 3000 |
85 |
86 |
87 | | 11.28 |
88 | OS-ABC/HelloWorld |
89 | 5000 |
90 |
91 |
92 | | 11.29 |
93 | Sonorous77/Robot |
94 | 4000 |
95 |
96 |
97 | | 11.29 |
98 | OS-ABC/HelloWorld |
99 | 6000 |
100 |
101 |
102 | | 11.30 |
103 | Sonorous77/Weather forecast |
104 | 2000 |
105 |
106 |
107 | | 11.30 |
108 | Sonorous77/Robot |
109 | 3000 |
110 |
111 |
112 | | 日期 |
113 | 注资项目 |
114 | cc数量 |
115 |
116 |
117 | | 12.01 |
118 | Sonorous77/Weather forecast |
119 | 2000 |
120 |
121 |
122 | | 12.01 |
123 | Sonorous77/Robot |
124 | 3000 |
125 |
126 |
127 | | 12.02 |
128 | Sonorous77/Robot |
129 | 5000 |
130 |
131 |
132 | | 12.02 |
133 | OS-ABC/HelloWorld |
134 | 5000 |
135 |
136 |
137 | | 12.03 |
138 | OS-ABC/HelloWorld |
139 | 2000 |
140 |
141 |
142 | | 12.03 |
143 | OS-ABC/HelloWorld |
144 | 6000 |
145 |
146 |
147 | | 12.04 |
148 | Sonorous77/Robot |
149 | 2000 |
150 |
151 |
152 | | 12.04 |
153 | Sonorous77/Weather forecast |
154 | 3000 |
155 |
156 |
157 |
162 |
163 |
164 |
165 |
166 | {{template "./footer.html" .}}
167 |
--------------------------------------------------------------------------------
/src/views/personalProjects.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | 我的项目
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 | {{template "./leftNav.html" .}}
13 |
14 |
17 |
18 |
19 |
22 |
23 |
24 |
31 |
32 |
33 |
51 |
52 |
53 |
test
54 |
{{.test_projectUrl}}
55 |
{{.test_projectName}}
56 |
{{.test_filename}}
57 |
{{.test_ProjectIntro}}
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
导入项目
66 |
68 |
69 |
70 | - 选择项目
71 | - 初始信息
72 | - 初始分配
73 |
74 |
75 |
113 |
114 |
115 |
116 |
--------------------------------------------------------------------------------
/src/static/js/import.js:
--------------------------------------------------------------------------------
1 | var step_num = 1;
2 |
3 | function showPopup(){
4 | step_num = 1;
5 | var step = document.getElementById("step2");
6 | step.className = "";
7 | step = document.getElementById("step3");
8 | step.className = "";
9 | var page = document.getElementById("myprojects");
10 | page.style.display="block";
11 | page = document.getElementById("init_message");
12 | page.style.display="none";
13 | page = document.getElementById("config_project");
14 | page.style.display="none";
15 | var button = document.getElementById("btnNextStep");
16 | button.style.display="block";
17 | button = document.getElementById("btnconfirm");
18 | button.style.display="none";
19 |
20 | var popUp = document.getElementById("import");
21 | popUp.style.position= "absolute";
22 | popUp.style.zIndex="100";
23 | popUp.style.width = "100%";
24 | popUp.style.height = "100%";
25 | popUp.style.visibility = "visible";
26 | }
27 |
28 | function hidePopup(){
29 | var popUp = document.getElementById("import");
30 | popUp.style.visibility = "hidden";
31 | }
32 |
33 | function next_step(){
34 | if(step_num === 1) { //在第一步输入url后,点击下一步时,进行判断,验证其权限
35 | var isProjOwner = false; //表示仓库是否属于此用户,默认为false
36 | var orgMember = false; //表示仓库是否属于用户所在的组织,暂且默认为false,待后端写好再实现
37 | var projUrl = document.getElementById("projectUrl").value; //获取用户输入的URL
38 | var temp = projUrl.split('/');
39 |
40 | //用cookie获取用户的用户名
41 | var userName = getCookie("userName");
42 | if (userName==null) {
43 | //此时浏览器中cookie已经到期,需要重新登录
44 | }
45 | //用斜杠‘/’分割项目url,则倒数第二项为用户名。两个用户名相等,则项目属于该用户
46 | if(userName === temp[temp.length-2] ||
47 | userName === temp[temp.length-2].replace("git@github.com:", "")) //使用SSH
48 | isProjOwner = true;
49 | //如果两个条件都不满足,则提示错误并返回
50 | if(!isProjOwner && !orgMember) {
51 | alert('请检查输入的URL:您不是此项目的所有者,且不属于此项目的组织。(当前仅支持https)');
52 | return;
53 | }
54 | }
55 |
56 | if(step_num >= 1 && step_num < 3)
57 | step_num += 1;
58 | switch(step_num){
59 | case 2:
60 | var step = document.getElementById("step2");
61 | step.className = "active";
62 | var page = document.getElementById("myprojects");
63 | page.style.display="none";
64 | page = document.getElementById("init_message");
65 | page.style.display="block";
66 | break;
67 | case 3:
68 | var step = document.getElementById("step3");
69 | step.className = "active";
70 | var page = document.getElementById("init_message");
71 | page.style.display="none";
72 | page = document.getElementById("config_project");
73 | page.style.display="block";
74 | var button = document.getElementById("btnNextStep");
75 | button.style.display="none";
76 | button = document.getElementById("btnconfirm");
77 | button.style.display="block";
78 | break;
79 | default:
80 | break;
81 | }
82 | }
83 |
84 | function back_step(){
85 | if(step_num >1 && step_num <= 3)
86 | step_num -= 1;
87 | switch(step_num){
88 | case 1:
89 | var step = document.getElementById("step2");
90 | step.className = "";
91 | var page = document.getElementById("myprojects");
92 | page.style.display="block";
93 | page = document.getElementById("init_message");
94 | page.style.display="none";
95 | break;
96 | case 2:
97 | var step = document.getElementById("step3");
98 | step.className = "";
99 | var page = document.getElementById("init_message");
100 | page.style.display="block";
101 | page = document.getElementById("config_project");
102 | page.style.display="none";
103 | var button = document.getElementById("btnNextStep");
104 | button.style.display="block";
105 | button = document.getElementById("btnconfirm");
106 | button.style.display="none";
107 |
108 | break;
109 | default:
110 | break;
111 | }
112 | }
113 |
114 | function showImg(input) {
115 | var file = input.files[0];
116 | var url = window.URL.createObjectURL(file);
117 | document.getElemtById('upload_image').src=url;
118 | }
119 |
120 | function show_joined(){
121 | var popUp = document.getElementById("joined_projects");
122 | popUp.style.display = "block";
123 | popUp = document.getElementById("managed_projects");
124 | popUp.style.display = "none";
125 | document.getElementById("join").style.backgroundColor = 'white';
126 | document.getElementById("manage").style.backgroundColor = '#bfbfbf';
127 | }
128 |
129 | function show_managed(){
130 | var popUp = document.getElementById("managed_projects");
131 | popUp.style.display = "block";
132 | popUp = document.getElementById("joined_projects");
133 | popUp.style.display = "none";
134 | document.getElementById("join").style.backgroundColor = '#bfbfbf';
135 | document.getElementById("manage").style.backgroundColor = 'white';
136 | }
137 |
138 | function setUrl(url) {
139 | var projectUrl = document.getElementById("projectUrl");
140 | projectUrl.value = url;
141 | next_step();
142 | }
143 |
144 | function getCookie(cookieKey){
145 | var arrcookie = document.cookie.split("; ");
146 | //遍历匹配
147 | for ( var i = 0; i < arrcookie.length; i++) {
148 | var arr = arrcookie[i].split("=");
149 | if (arr[0] == cookieKey){
150 | return arr[1];
151 | }
152 | }
153 | return null;
154 | }
155 |
156 | //JS获取url中项目名称
157 | function getProjectNameByUrl(){
158 | var projUrl = document.getElementById("projectUrl").value; //获取用户输入的URL
159 | var index = projUrl.lastIndexOf("\/");
160 | projUrl = projUrl.substring(index + 1, projUrl.length);
161 | document.getElementById("projUrl").value = projUrl;
162 | }
--------------------------------------------------------------------------------
/src/static/js/helloweb.js:
--------------------------------------------------------------------------------
1 | (function() {
2 |
3 | var width, height, largeHeader, canvas, ctx, points, target, animateHeader = true;
4 |
5 | // Main
6 | initHeader();
7 | initAnimation();
8 | addListeners();
9 |
10 | function initHeader() {
11 | width = window.innerWidth;
12 | height = window.innerHeight;
13 | target = {x: width/2, y: height/2};
14 |
15 | largeHeader = document.getElementById('large-header');
16 | largeHeader.style.height = height+'px';
17 |
18 | canvas = document.getElementById('demo-canvas');
19 | canvas.width = width;
20 | canvas.height = height;
21 | ctx = canvas.getContext('2d');
22 |
23 | // create points
24 | points = [];
25 | for(var x = 0; x < width; x = x + width/20) {
26 | for(var y = 0; y < height; y = y + height/20) {
27 | var px = x + Math.random()*width/20;
28 | var py = y + Math.random()*height/20;
29 | var p = {x: px, originX: px, y: py, originY: py };
30 | points.push(p);
31 | }
32 | }
33 |
34 | // for each point find the 5 closest points
35 | for(var i = 0; i < points.length; i++) {
36 | var closest = [];
37 | var p1 = points[i];
38 | for(var j = 0; j < points.length; j++) {
39 | var p2 = points[j]
40 | if(!(p1 == p2)) {
41 | var placed = false;
42 | for(var k = 0; k < 5; k++) {
43 | if(!placed) {
44 | if(closest[k] == undefined) {
45 | closest[k] = p2;
46 | placed = true;
47 | }
48 | }
49 | }
50 |
51 | for(var k = 0; k < 5; k++) {
52 | if(!placed) {
53 | if(getDistance(p1, p2) < getDistance(p1, closest[k])) {
54 | closest[k] = p2;
55 | placed = true;
56 | }
57 | }
58 | }
59 | }
60 | }
61 | p1.closest = closest;
62 | }
63 |
64 | // assign a circle to each point
65 | for(var i in points) {
66 | var c = new Circle(points[i], 2+Math.random()*2, 'rgba(255,255,255,0.3)');
67 | points[i].circle = c;
68 | }
69 | }
70 |
71 | // Event handling
72 | function addListeners() {
73 | if(!('ontouchstart' in window)) {
74 | window.addEventListener('mousemove', mouseMove);
75 | }
76 | window.addEventListener('scroll', scrollCheck);
77 | window.addEventListener('resize', resize);
78 | }
79 |
80 | function mouseMove(e) {
81 | var posx = posy = 0;
82 | if (e.pageX || e.pageY) {
83 | posx = e.pageX;
84 | posy = e.pageY;
85 | }
86 | else if (e.clientX || e.clientY) {
87 | posx = e.clientX + document.body.scrollLeft + document.documentElement.scrollLeft;
88 | posy = e.clientY + document.body.scrollTop + document.documentElement.scrollTop;
89 | }
90 | target.x = posx;
91 | target.y = posy;
92 | }
93 |
94 | function scrollCheck() {
95 | if(document.body.scrollTop > height) animateHeader = false;
96 | else animateHeader = true;
97 | }
98 |
99 | function resize() {
100 | width = window.innerWidth;
101 | height = window.innerHeight;
102 | largeHeader.style.height = height+'px';
103 | canvas.width = width;
104 | canvas.height = height;
105 | }
106 |
107 | // animation
108 | function initAnimation() {
109 | animate();
110 | for(var i in points) {
111 | shiftPoint(points[i]);
112 | }
113 | }
114 |
115 | function animate() {
116 | if(animateHeader) {
117 | ctx.clearRect(0,0,width,height);
118 | for(var i in points) {
119 | // detect points in range
120 | if(Math.abs(getDistance(target, points[i])) < 4000) {
121 | points[i].active = 0.3;
122 | points[i].circle.active = 0.6;
123 | } else if(Math.abs(getDistance(target, points[i])) < 20000) {
124 | points[i].active = 0.1;
125 | points[i].circle.active = 0.3;
126 | } else if(Math.abs(getDistance(target, points[i])) < 40000) {
127 | points[i].active = 0.02;
128 | points[i].circle.active = 0.1;
129 | } else {
130 | points[i].active = 0;
131 | points[i].circle.active = 0;
132 | }
133 |
134 | drawLines(points[i]);
135 | points[i].circle.draw();
136 | }
137 | }
138 | requestAnimationFrame(animate);
139 | }
140 |
141 | function shiftPoint(p) {
142 | TweenLite.to(p, 1+1*Math.random(), {x:p.originX-50+Math.random()*100,
143 | y: p.originY-50+Math.random()*100, ease:Circ.easeInOut,
144 | onComplete: function() {
145 | shiftPoint(p);
146 | }});
147 | }
148 |
149 | // Canvas manipulation
150 | function drawLines(p) {
151 | if(!p.active) return;
152 | for(var i in p.closest) {
153 | ctx.beginPath();
154 | ctx.moveTo(p.x, p.y);
155 | ctx.lineTo(p.closest[i].x, p.closest[i].y);
156 | ctx.strokeStyle = 'rgba(156,217,249,'+ p.active+')';
157 | ctx.stroke();
158 | }
159 | }
160 |
161 | function Circle(pos,rad,color) {
162 | var _this = this;
163 |
164 | // constructor
165 | (function() {
166 | _this.pos = pos || null;
167 | _this.radius = rad || null;
168 | _this.color = color || null;
169 | })();
170 |
171 | this.draw = function() {
172 | if(!_this.active) return;
173 | ctx.beginPath();
174 | ctx.arc(_this.pos.x, _this.pos.y, _this.radius, 0, 2 * Math.PI, false);
175 | ctx.fillStyle = 'rgba(156,217,249,'+ _this.active+')';
176 | ctx.fill();
177 | };
178 | }
179 |
180 | // Util
181 | function getDistance(p1, p2) {
182 | return Math.pow(p1.x - p2.x, 2) + Math.pow(p1.y - p2.y, 2);
183 | }
184 |
185 | })();
--------------------------------------------------------------------------------
/go.sum:
--------------------------------------------------------------------------------
1 | github.com/Knetic/govaluate v3.0.0+incompatible/go.mod h1:r7JcOSlj0wfOMncg0iLm8Leh48TZaKVeNIfJntJ2wa0=
2 | github.com/OwnLocal/goes v1.0.0/go.mod h1:8rIFjBGTue3lCU0wplczcUgt9Gxgrkkrw7etMIcn8TM=
3 | github.com/PuerkitoBio/goquery v1.5.1 h1:PSPBGne8NIUWw+/7vFBV+kG2J/5MOjbzc7154OaKCSE=
4 | github.com/PuerkitoBio/goquery v1.5.1/go.mod h1:GsLWisAFVj4WgDibEWF4pvYnkVQBpKBKeU+7zCJoLcc=
5 | github.com/andybalholm/cascadia v1.1.0 h1:BuuO6sSfQNFRu1LppgbD25Hr2vLYW25JvxHs5zzsLTo=
6 | github.com/andybalholm/cascadia v1.1.0/go.mod h1:GsXiBklL0woXo1j/WYWtSYYC4ouU9PqHO0sqidkEA4Y=
7 | github.com/astaxie/beego v1.12.0 h1:MRhVoeeye5N+Flul5PoVfD9CslfdoH+xqC/xvSQ5u2Y=
8 | github.com/astaxie/beego v1.12.0/go.mod h1:fysx+LZNZKnvh4GED/xND7jWtjCR6HzydR2Hh2Im57o=
9 | github.com/beego/goyaml2 v0.0.0-20130207012346-5545475820dd/go.mod h1:1b+Y/CofkYwXMUU0OhQqGvsY2Bvgr4j6jfT699wyZKQ=
10 | github.com/beego/x2j v0.0.0-20131220205130-a0352aadc542/go.mod h1:kSeGC/p1AbBiEp5kat81+DSQrZenVBZXklMLaELspWU=
11 | github.com/bradfitz/gomemcache v0.0.0-20180710155616-bc664df96737/go.mod h1:PmM6Mmwb0LSuEubjR8N7PtNe1KxZLtOUHtbeikc5h60=
12 | github.com/casbin/casbin v1.7.0/go.mod h1:c67qKN6Oum3UF5Q1+BByfFxkwKvhwW57ITjqwtzR1KE=
13 | github.com/cloudflare/golz4 v0.0.0-20150217214814-ef862a3cdc58/go.mod h1:EOBUe0h4xcZ5GoxqC5SDxFQ8gwyZPKQoEzownBlhI80=
14 | github.com/couchbase/go-couchbase v0.0.0-20181122212707-3e9b6e1258bb/go.mod h1:TWI8EKQMs5u5jLKW/tsb9VwauIrMIxQG1r5fMsswK5U=
15 | github.com/couchbase/gomemcached v0.0.0-20181122193126-5125a94a666c/go.mod h1:srVSlQLB8iXBVXHgnqemxUXqN6FCvClgCMPCsjBDR7c=
16 | github.com/couchbase/goutils v0.0.0-20180530154633-e865a1461c8a/go.mod h1:BQwMFlJzDjFDG3DJUdU0KORxn88UlsOULuxLExMh3Hs=
17 | github.com/cupcake/rdb v0.0.0-20161107195141-43ba34106c76/go.mod h1:vYwsqCOLxGiisLwp9rITslkFNpZD5rz43tf41QFkTWY=
18 | github.com/edsrzf/mmap-go v0.0.0-20170320065105-0bce6a688712/go.mod h1:YO35OhQPt3KJa3ryjFM5Bs14WD66h8eGKpfaBNrHW5M=
19 | github.com/elazarl/go-bindata-assetfs v1.0.0 h1:G/bYguwHIzWq9ZoyUQqrjTmJbbYn3j3CKKpKinvZLFk=
20 | github.com/elazarl/go-bindata-assetfs v1.0.0/go.mod h1:v+YaWX3bdea5J/mo8dSETolEo7R71Vk1u8bnjau5yw4=
21 | github.com/go-redis/redis v6.14.2+incompatible/go.mod h1:NAIEuMOZ/fxfXJIrKDQDz8wamY7mA7PouImQ2Jvg6kA=
22 | github.com/go-sql-driver/mysql v1.4.1 h1:g24URVg0OFbNUTx9qqY1IRZ9D9z3iPyi5zKhQZpNwpA=
23 | github.com/go-sql-driver/mysql v1.4.1/go.mod h1:zAC/RDZ24gD3HViQzih4MyKcchzm+sOG5ZlKdlhCg5w=
24 | github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ=
25 | github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
26 | github.com/golang/snappy v0.0.0-20180518054509-2e65f85255db/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
27 | github.com/gomodule/redigo v2.0.0+incompatible/go.mod h1:B4C85qUVwatsJoIUNIfCRsp7qO0iAmpGFZ4EELWSbC4=
28 | github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1 h1:EGx4pi6eqNxGaHF6qqu48+N2wcFQ5qg5FXgOdqsJ5d8=
29 | github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY=
30 | github.com/jtolds/gls v4.20.0+incompatible h1:xdiiI2gbIgH/gLH7ADydsJ1uDOEzR8yvV7C0MuV77Wo=
31 | github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU=
32 | github.com/lib/pq v1.0.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo=
33 | github.com/lib/pq v1.2.0 h1:LXpIM/LZ5xGFhOpXAQUIMM1HdyqzVYM13zNdjCEEcA0=
34 | github.com/lib/pq v1.2.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo=
35 | github.com/mattn/go-sqlite3 v1.10.0 h1:jbhqpg7tQe4SupckyijYiy0mJJ/pRyHvXf7JdWK860o=
36 | github.com/mattn/go-sqlite3 v1.10.0/go.mod h1:FPy6KqzDD04eiIsT53CuJW3U88zkxoIYsOqkbpncsNc=
37 | github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic=
38 | github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
39 | github.com/shiena/ansicolor v0.0.0-20151119151921-a422bbe96644 h1:X+yvsM2yrEktyI+b2qND5gpH8YhURn0k8OCaeRnkINo=
40 | github.com/shiena/ansicolor v0.0.0-20151119151921-a422bbe96644/go.mod h1:nkxAfR/5quYxwPZhyDxgasBMnRtBZd0FCEpawpjMUFg=
41 | github.com/siddontang/go v0.0.0-20180604090527-bdc77568d726/go.mod h1:3yhqj7WBBfRhbBlzyOC3gUxftwsU0u8gqevxwIHQpMw=
42 | github.com/siddontang/ledisdb v0.0.0-20181029004158-becf5f38d373/go.mod h1:mF1DpOSOUiJRMR+FDqaqu3EBqrybQtrDDszLUZ6oxPg=
43 | github.com/siddontang/rdb v0.0.0-20150307021120-fc89ed2e418d/go.mod h1:AMEsy7v5z92TR1JKMkLLoaOQk++LVnOKL3ScbJ8GNGA=
44 | github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d h1:zE9ykElWQ6/NYmHa3jpm/yHnI4xSofP+UP6SpjHcSeM=
45 | github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc=
46 | github.com/smartystreets/goconvey v1.6.4 h1:fv0U8FUIMPNf1L9lnHLvLhgicrIVChEkdzIKYqbNC9s=
47 | github.com/smartystreets/goconvey v1.6.4/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA=
48 | github.com/ssdb/gossdb v0.0.0-20180723034631-88f6b59b84ec/go.mod h1:QBvMkMya+gXctz3kmljlUCu/yB3GZ6oee+dUozsezQE=
49 | github.com/syndtr/goleveldb v0.0.0-20181127023241-353a9fca669c/go.mod h1:Z4AUp2Km+PwemOoO/VB5AOx9XSsIItzFjoJlOSiYmn0=
50 | github.com/wendal/errors v0.0.0-20130201093226-f66c77a7882b/go.mod h1:Q12BUT7DqIlHRmgv3RskH+UCM/4eqVMgI0EMmlSpAXc=
51 | golang.org/x/crypto v0.0.0-20181127143415-eb0de9b17e85/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
52 | golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2 h1:VklqNMn3ovrHsnt90PveolxSbWFaJdECFbxSq0Mqo2M=
53 | golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
54 | golang.org/x/net v0.0.0-20180218175443-cbe0f9307d01/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
55 | golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
56 | golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
57 | golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks=
58 | golang.org/x/net v0.0.0-20200202094626-16171245cfb2 h1:CCH4IOTTfewWjGOlSp+zGcjutRKlBEZQ6wTn8ozI/nI=
59 | golang.org/x/net v0.0.0-20200202094626-16171245cfb2/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
60 | golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
61 | golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
62 | golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
63 | golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
64 | golang.org/x/tools v0.0.0-20190328211700-ab21143f2384/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
65 | google.golang.org/appengine v1.6.5 h1:tycE03LOZYQNhDpS27tcQdAzLCVMaj7QT2SXxebnpCM=
66 | google.golang.org/appengine v1.6.5/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc=
67 | gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
68 | gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
69 | gopkg.in/yaml.v2 v2.2.1 h1:mUhvW9EsL+naU5Q3cakzfE91YhliOondGd6ZrsDBHQE=
70 | gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
71 |
--------------------------------------------------------------------------------
/src/static/css/platformAdmin.css:
--------------------------------------------------------------------------------
1 | /*以下页面共有的css*/
2 | body{
3 | margin: 0;
4 |
5 | }
6 |
7 | /*以下是platformAdminTopNav页面的css*/
8 |
9 | a:link,a:visited,a:hover,a:active
10 | {
11 | color: #1B1B1B;
12 | text-decoration:none;
13 | }
14 |
15 | .head {
16 | position: relative;
17 | height: 70px;
18 | background-color: #333333;
19 | }
20 |
21 | .topNavLogo{
22 | float: left;
23 | width: 60px;
24 | height: 60px;
25 | margin-top: 5px;
26 | margin-left: 5px;
27 | margin-right: 10px;
28 | }
29 |
30 | .topNavName{
31 | float: left;
32 | line-height: 70px;
33 | font-size: 28px;
34 | color: aliceblue;
35 | }
36 |
37 | .navigation {
38 | position: relative;
39 | height: 160px;
40 | padding-left: 100px;
41 | background-color: #bfbfbf;
42 | }
43 |
44 | .navigation > img {
45 | position: absolute;
46 | width: 150px;
47 | height: 100%;
48 | border-style: solid;
49 | border-width: 6px;
50 | border-color: #FFFFFF;
51 | border-radius: 5px;
52 | margin-left: 50px;
53 | margin-top: 20px;
54 | }
55 |
56 | .navigation > .platform-admin {
57 | position: absolute;
58 | font-size: 60px;
59 | margin-left: 250px;
60 | margin-top: 30px;
61 | color: #323a45;
62 | }
63 |
64 | .navigation > .first {
65 | margin-left: 250px;
66 |
67 | }
68 |
69 | .navigation > a {
70 | float: left;
71 | margin-top: 110px;
72 | margin-left: 40px;
73 | padding-left: 10px;
74 | padding-right: 10px;
75 | padding-top: 5px;
76 | border-radius: 10px;
77 | font-size: 30px;
78 | height: 60px;
79 | }
80 |
81 |
82 | /*以下是platformInformation.html页面的css*/
83 | .pltinfo-container {
84 | margin: auto;
85 | width: 1200px;
86 | font-size: 0;
87 | }
88 | .pltinfo-card {
89 | display: inline-block;
90 | vertical-align: top;
91 | border: 2px solid #52B1EC;
92 | border-radius: 10px;
93 | width: 500px;
94 | height: 500px;
95 | margin-top: 70px;
96 | margin-left: 46px;
97 | margin-right: 46px;
98 | }
99 | .card-head {
100 | height: 70px;
101 | background-color: #ACDCFA;
102 | }
103 | .card-title {
104 | display: inline-block;
105 | vertical-align: bottom;
106 | font-size: 25px;
107 | color: #3B43F4;
108 | height: 70px;
109 | line-height: 70px;
110 | text-align: center;
111 | margin-left: 20px;
112 | }
113 | .pltinfo-card-value {
114 | display: inline-block;
115 | vertical-align: bottom;
116 | font-size: 25px;
117 | font-weight: bold;
118 | color: #5DCBED;
119 | height: 370px;
120 | width: 500px;
121 | line-height: 70px;
122 | text-align: center;
123 |
124 | }
125 | .pltinfo-card-value p{
126 | display: inline-block;
127 | vertical-align: bottom;
128 | font-size: 25px;
129 | font-weight: bold;
130 | color: #5DCBED;
131 | height: 70px;
132 | width: 100px;
133 | line-height: 70px;
134 | text-align: center;
135 | margin-left: 30px;
136 | }
137 | .record-label {
138 | font-size: 15px;
139 | text-align: center;
140 | color: #1B82EB;
141 | width: 100px;
142 | height: 30px;
143 | line-height: 30px;
144 | margin: -15px auto;
145 | background-color: #41F2FD;
146 | border-radius: 15px;
147 | }
148 |
149 | /*以下是projectFunding页面的css*/
150 | .record{
151 | position: relative;
152 | margin: 50px;
153 | width: 900px;
154 | height: 350px;
155 | padding-left: 50px;
156 | padding-bottom: 30px;
157 | margin-bottom: 120px;
158 | }
159 |
160 | .customers{
161 | font-family:"Trebuchet MS", Arial, Helvetica, sans-serif;
162 | border-collapse:collapse;
163 | position: relative;
164 | width: 900px;
165 | margin-top: 40px;
166 | font-size: 19px;
167 | }
168 |
169 | .customers th
170 | { display: inline-block;
171 | font-size:1em;
172 | border:1px solid #ffffff;
173 | margin:5px 10px 15px 10px;
174 | text-align: left;
175 | width: 270px;
176 | }
177 |
178 | .customers td
179 | { display: inline-block;
180 | width: 270px;
181 | white-space: nowrap;
182 | text-overflow: ellipsis;
183 | overflow: hidden;
184 | font-size:1em;
185 | border:1px solid #ffffff;
186 | margin:5px 10px 15px 10px;
187 | }
188 |
189 | /*以下是capitalInjection页面的css*/
190 | .topNavLogo{
191 | float: left;
192 | width: 60px;
193 | height: 60px;
194 | margin-top: 5px;
195 | margin-left: 5px;
196 | margin-right: 10px;
197 | }
198 | .topNavName{
199 | float: left;
200 | line-height: 70px;
201 | font-size: 28px;
202 | color: aliceblue;
203 | }
204 | .container {
205 | width: 100%;
206 | font-size: 0;
207 | }
208 | .container-child {
209 | margin: auto;
210 | width: 1250px;
211 | }
212 | .project {
213 | display: inline-block;
214 | margin-top: 40px;
215 | margin-left: 15px;
216 | margin-right: 15px;
217 | width: 220px;
218 | background: #F8F8FD;
219 | }
220 | .project > .project-cover {
221 | width: 100%;
222 | height: auto;
223 | }
224 | .project > .project-name {
225 | text-align: left;
226 | font-weight: 1000;
227 | font-size: 30px;
228 | padding-left: 10px;
229 | }
230 | .project > .introduction {
231 | text-align: left;
232 | font-size: 20px;
233 | padding-left: 20px;
234 | }
235 | .project > .CC {
236 | color: #FFCC33;
237 | font-size: 20px;
238 | text-align: left;
239 | padding-left: 20px;
240 | }
241 | .head_shot {
242 | padding-left: 15px;
243 | height: 50px;
244 | float: left;
245 | }
246 |
247 | .main{
248 | width:500px;
249 | margin: auto;
250 | position: relative;
251 | top: 50%;
252 | transform: translateY(-50%);
253 | }
254 | .content{
255 | padding-left: 20px;
256 | padding-right: 20px;
257 | }
258 |
259 | #injection{
260 | position:absolute;
261 | left:0px;
262 | top:0px;
263 | /*width:300px; */
264 | min-height:700px;
265 | }
266 | input[type="text"]{
267 | border: 2px solid #ccc;
268 | padding: 6px 0px;
269 | border-radius: 10px;
270 | padding-left:20px;
271 | -webkit-box-shadow: inset 0 1px 1px rgba(0,0,0,.075);
272 | box-shadow: inset 0 1px 1px rgba(0,0,0,.075);
273 | -webkit-transition: border-color ease-in-out .15s,-webkit-box-shadow ease-in-out .15s;
274 | -o-transition: border-color ease-in-out .15s,box-shadow ease-in-out .15s;
275 | transition: border-color ease-in-out .15s,box-shadow ease-in-out .15s
276 | }
277 | input:focus{
278 | border-color: #3052e9;
279 | outline: 0;
280 | -webkit-box-shadow: inset 0 1px 1px rgba(0,0,0,.075),0 0 8px rgba(102,175,233,.6);
281 | box-shadow: inset 0 1px 1px rgba(0,0,0,.075),0 0 8px rgba(102,175,233,.6)
282 | }
283 |
284 | input[type="button"] {
285 | position: relative;
286 | display: inline-block;
287 | background: #D0EEFF;
288 | border: 1px solid #99D3F5;
289 | border-radius: 4px;
290 | padding: 4px 12px;
291 | overflow: hidden;
292 | color: #3052e9;
293 | text-decoration: none;
294 | text-indent: 0;
295 | line-height: 20px;
296 | }
297 | #commit{
298 | border-style: ridge;
299 | border-radius: 5px;
300 | font-size: 110%;
301 | padding-top: 2px;
302 | padding-bottom: 2px;
303 | margin-left: 15px;
304 | background-color: #ff5b5d;
305 | color: white;
306 |
307 | }
308 | #cancel{
309 | border-style: ridge;
310 | border-radius: 5px;
311 | font-size: 110%;
312 | padding-top: 2px;
313 | padding-bottom: 2px;
314 | margin-left: 15px;
315 | background-color: white;
316 | color:#ff5b5d;
317 |
318 | }
319 |
320 |
321 |
322 |
--------------------------------------------------------------------------------
/src/models/sendEmailToPotentialUsers.go:
--------------------------------------------------------------------------------
1 | // TODO 该文件不应该放在model层, 应该放在service层
2 | package models
3 |
4 | import (
5 | "encoding/json"
6 | "fmt"
7 | "github.com/PuerkitoBio/goquery"
8 | "github.com/astaxie/beego/utils"
9 | "io/ioutil"
10 | "log"
11 | "net/http"
12 | "net/http/cookiejar"
13 | "net/url"
14 | "time"
15 | )
16 |
17 | //用于登录时验证
18 | type AuthenticityToken struct {
19 | Token string
20 | }
21 |
22 | //同样用于登录时验证
23 | type TimeStamp struct {
24 | Time string
25 | Secret string
26 | }
27 |
28 | //http请求
29 | type App struct {
30 | Client *http.Client
31 | }
32 |
33 | const (
34 | baseURL = "https://github.com"
35 | githubUserApi = "https://api.github.com/users/"
36 | )
37 |
38 | var ( //用于模拟登录,个人账号,请勿登录
39 | username = "kcoinTest"
40 | password = "Kcoin123456."
41 | )
42 |
43 | //用于接收爬取到的邮箱
44 | type Email struct {
45 | Email string
46 | }
47 |
48 | type UsersApiJson struct {
49 | Login string `json:"login"`
50 | ID int `json:"id"`
51 | NodeID string `json:"node_id"`
52 | AvatarURL string `json:"avatar_url"`
53 | GravatarID string `json:"gravatar_id"`
54 | URL string `json:"url"`
55 | HTMLURL string `json:"html_url"`
56 | FollowersURL string `json:"followers_url"`
57 | FollowingURL string `json:"following_url"`
58 | GistsURL string `json:"gists_url"`
59 | StarredURL string `json:"starred_url"`
60 | SubscriptionsURL string `json:"subscriptions_url"`
61 | OrganizationsURL string `json:"organizations_url"`
62 | ReposURL string `json:"repos_url"`
63 | EventsURL string `json:"events_url"`
64 | ReceivedEventsURL string `json:"received_events_url"`
65 | Type string `json:"type"`
66 | SiteAdmin bool `json:"site_admin"`
67 | Name string `json:"name"`
68 | Company interface{} `json:"company"`
69 | Blog string `json:"blog"`
70 | Location string `json:"location"`
71 | Email string `json:"email"`
72 | Hireable interface{} `json:"hireable"`
73 | Bio interface{} `json:"bio"`
74 | PublicRepos int `json:"public_repos"`
75 | PublicGists int `json:"public_gists"`
76 | Followers int `json:"followers"`
77 | Following int `json:"following"`
78 | CreatedAt time.Time `json:"created_at"`
79 | UpdatedAt time.Time `json:"updated_at"`
80 | }
81 |
82 | /*
83 | func (app *App) GetToken() AuthenticityToken
84 | 该函数用于获取github的登录时的authenticity_token,是一个隐藏的值,相当于验证码
85 | */
86 | func (app *App) GetToken() (AuthenticityToken, TimeStamp) {
87 | var authenticityToken AuthenticityToken
88 | var timeAndsecret TimeStamp
89 | loginURL := baseURL + "/login"
90 | client := app.Client
91 | response, err := client.Get(loginURL)
92 | if err != nil {
93 | log.Fatalln("Error fetching response. ", err)
94 | return authenticityToken, timeAndsecret
95 | }
96 | defer response.Body.Close()
97 |
98 | document, err := goquery.NewDocumentFromReader(response.Body)
99 | if err != nil {
100 | log.Fatal("Error loading HTTP response body. ", err)
101 | }
102 |
103 | token, exist := document.Find("input[name='authenticity_token']").Attr("value")
104 | if exist != true {
105 | log.Fatal("Error finding authenticity_token,does not exist", exist)
106 | exist = true
107 | }
108 |
109 | fmt.Println("token is", token)
110 | authenticityToken.Token = token
111 | time, exist := document.Find("input[name='timestamp']").Attr("value")
112 | if exist != true {
113 | log.Fatal("Error finding timestamp,does not exist", exist)
114 | exist = true
115 | }
116 | secret, exist := document.Find("input[name='timestamp_secret']").Attr("value")
117 | if exist != true {
118 | log.Fatal("Error finding timestamp,does not exist", exist)
119 | exist = true
120 | }
121 | fmt.Println("timestamp is ", time)
122 | fmt.Println("timestamp_secret is ", secret)
123 | timeAndsecret.Secret = secret
124 | timeAndsecret.Time = time
125 | return authenticityToken, timeAndsecret
126 | }
127 |
128 | /*
129 | func (app *App) Login()
130 | 该函数用于模拟登录,如果不登录,爬取到的内容是“sign up to view email”
131 | */
132 | func (app *App) Login() {
133 | client := app.Client
134 | //通过GetToken()获得登录所需的动态信息
135 | authenticityToken, timeAndsecret := app.GetToken()
136 | loginURL := baseURL + "/session"
137 | //模拟登录的文件header中的Form data,详情请看github登录时候的发包
138 | data := url.Values{
139 | "utf8": {"✓"},
140 | "commit": {"Sign in"},
141 | "ga_id": {"76806099.1573434977"},
142 | "login": {username},
143 | "password": {password},
144 | "webauthn-support": {"supported"},
145 | "webauthn-iuvpaa-support": {"unsupported"},
146 |
147 | "required_field_440e": {},
148 | "timestamp": {timeAndsecret.Time},
149 | "timestamp_secret": {timeAndsecret.Secret},
150 | "authenticity_token": {authenticityToken.Token},
151 | }
152 | //模拟post请求,发送header
153 | response, err := client.PostForm(loginURL, data)
154 | if err != nil {
155 | fmt.Println(err)
156 | log.Fatalln(err)
157 | }
158 | defer response.Body.Close()
159 | _, err = ioutil.ReadAll(response.Body)
160 | if err != nil {
161 | log.Fatalln(err)
162 | }
163 | fmt.Println("status code is ", response.StatusCode)
164 | fmt.Println("login done")
165 | }
166 |
167 | /*
168 | func (app *App) getEmail(user,githubToken string) Email
169 | 功能:获得用户user的邮箱
170 | 参数:user github用户名
171 | githubToken 此时登录系统的github账号的githubToken
172 | 返回:user对应的邮箱(用户未公布邮箱,未测试)
173 | */
174 | func (app *App) getEmail(user, githubToken string) Email {
175 | //个人主页,如果邮箱公开,那么会显示在主页
176 | personalURL := githubUserApi + user + "?access_token=" + githubToken
177 |
178 | client := &http.Client{}
179 | response, _ := client.Get(personalURL)
180 | defer response.Body.Close()
181 | body, err := ioutil.ReadAll(response.Body)
182 | if err != nil {
183 | panic(err)
184 | }
185 | var userApiJson UsersApiJson
186 | err = json.Unmarshal(body, &userApiJson)
187 | if err != nil {
188 | log.Fatal("Error Unmarshaling json response body from githubUserApi. ", err)
189 | panic(err)
190 | }
191 | return Email{Email: userApiJson.Email}
192 | }
193 |
194 | /*
195 | func SendEMailToPotentialUsers(users []string)([]string ,error)
196 | 功能:将邮件发送给users中的每一个人
197 | 参数:users 用户列表,github用户名的切片,待发送邮件的名单
198 | githubToken 此时登录系统的github账号的githubToken
199 | 返回:邮箱不对外显示,因此无法发送邮件的成员用户名集合
200 | */
201 | func SendEMailToPotentialUsers(users []string, githubToken string) ([]string, error) {
202 | jar, _ := cookiejar.New(nil)
203 | app := App{
204 | Client: &http.Client{Jar: jar},
205 | }
206 | app.Login()
207 |
208 | //未能成功发送邮件的用户名单
209 | var UsersNotSend []string
210 | for i := 0; i < len(users); i++ {
211 | email := app.getEmail(users[i], githubToken)
212 | if email.Email == "" {
213 | //如果得到邮箱,给他加到列表里,最后返回
214 | UsersNotSend = append(UsersNotSend, users[i])
215 | } else {
216 | //如果得到了邮箱
217 | config :=
218 | `{"username":"kcoin_golang@163.com","password":"kcoin163","host":"smtp.163.com","port":25}`
219 | // 通过存放配置信息的字符串,创建Email对象
220 | temail := utils.NewEMail(config)
221 | // 指定邮件的基本信息
222 | temail.To = []string{email.Email} //指定收件人邮箱地址
223 | temail.From = "kcoin_golang@163.com" //指定发件人的邮箱地址,这是我注册的kcoin项目邮箱,账号kcoin_golang@163.com 密码kcoingolang
224 | temail.Subject = "Kcoin:Welcome to join us" //指定邮件的标题
225 | //这是邮件的内容
226 | temail.HTML = `
227 |
228 |
229 |
230 | 你好,我们是开原激励社区Kcoin,现在你所在的github项目已经加入Kcoin,我们同样欢迎您的加入
231 |
232 | `
233 | // 发送邮件
234 | err := temail.Send()
235 | if err != nil {
236 | return UsersNotSend, err
237 | }
238 | }
239 | }
240 | return UsersNotSend, nil
241 | }
242 |
--------------------------------------------------------------------------------
/src/models/k_user.go:
--------------------------------------------------------------------------------
1 | package models
2 |
3 | import (
4 | "database/sql"
5 | "encoding/json"
6 | "fmt"
7 | "time"
8 |
9 | "github.com/astaxie/beego/orm"
10 | )
11 |
12 | type noResultErr int
13 |
14 | func (err noResultErr) Error() string {
15 | return "There is no result."
16 | }
17 |
18 | func GetUserInfo(userName string) (string, error) {
19 | userInfo := UserInfo{}
20 | userInfo.ErrorCode = "default Error"
21 |
22 | maps, err := getSQLQueryResult(userName)
23 | if err != nil {
24 | return fmt.Sprint(userInfo), err
25 | }
26 |
27 | userData := buildProjectsDataFrom(maps)
28 |
29 | // complete userInfo building
30 | userInfo.ErrorCode = "0"
31 | userData.UserName = userName
32 | for i := range maps {
33 | if name := maps[i]["user_name"].(string); name == userName {
34 | userData.HeadShotUrl = maps[i]["head_shot_url"].(string)
35 | }
36 | }
37 | userInfo.Data = userData
38 |
39 | return jsonize(userInfo)
40 | }
41 |
42 | func getSQLQueryResult(userName string) ([]orm.Params, error) {
43 | o := orm.NewOrm()
44 | _ = o.Using("default")
45 | SQLQuery := getUserInfoSQLQuery()
46 | var maps []orm.Params
47 |
48 | if _, err := o.Raw(SQLQuery, userName).Values(&maps); err != nil {
49 | fmt.Println(err.Error())
50 | return nil, err
51 | }
52 |
53 | if len(maps) == 0 {
54 | return nil, new(noResultErr)
55 | }
56 | return maps, nil
57 | }
58 |
59 | func getUserInfoSQLQuery() string {
60 | return `WITH attend_project AS
61 | (
62 | SELECT DISTINCT(project_id) AS attended_pro_id from "k_user_in_project"
63 | where user_id in(
64 | SELECT user_id from "k_user"
65 | where user_name=?
66 | )
67 | )
68 |
69 | SELECT a.project_name,a.project_url,a.project_cover_url,b.user_name,b.head_shot_url FROM
70 |
71 | (SELECT project_id, project_name,project_url,project_cover_url FROM "k_project" kpro
72 | where kpro.project_id in
73 | (SELECT attended_pro_id FROM attend_project)
74 | ) a
75 |
76 | LEFT JOIN
77 |
78 | (SELECT kuip.project_id,ku.user_name,ku.head_shot_url FROM "k_user_in_project" kuip INNER JOIN "k_user" ku ON kuip.user_id=ku.user_id
79 | where kuip.project_id in
80 | (SELECT attended_pro_id FROM attend_project)
81 | ) b
82 |
83 | ON a.project_id=b.project_id`
84 | }
85 |
86 | func buildProjectsDataFrom(maps []orm.Params) *UserData {
87 | userData := &UserData{}
88 | projectToIndex := make(map[string]int)
89 | index := 0
90 | for i := range maps {
91 | projectName := maps[i]["project_name"].(string)
92 | if _, ok := projectToIndex[projectName]; !ok {
93 | // 如果project name不存在, 那么添加这个projectName, 并且新建这个Project的信息
94 | projectToIndex[projectName] = index
95 | index++
96 | projectInfo := &Project{}
97 | projectInfo.ProjectName = projectName
98 | projectInfo.ProjectUrl = maps[i]["project_url"].(string)
99 | projectInfo.ProjectCoverUrl = maps[i]["project_cover_url"].(string)
100 | userData.ProjectList = append(userData.ProjectList, projectInfo)
101 | }
102 | member := &UserData{}
103 | member.UserName = maps[i]["user_name"].(string)
104 | member.HeadShotUrl = maps[i]["head_shot_url"].(string)
105 | projectIndex := projectToIndex[projectName]
106 | userData.ProjectList[projectIndex].MemberList = append(userData.ProjectList[projectIndex].MemberList, member)
107 | }
108 | return userData
109 | }
110 |
111 | func jsonize(info UserInfo) (string, error) {
112 | if res, err := json.Marshal(&info); err != nil {
113 | fmt.Println(err.Error())
114 | return fmt.Sprint(info), err
115 | } else {
116 | return string(res), nil
117 | }
118 | }
119 |
120 | func FinduserByGitId(id string) (UserData, error) {
121 | o := orm.NewOrm()
122 | _ = o.Using("default")
123 | querySql := `select * from "k_user" where github_id = ?`
124 | var maps []orm.Params
125 | var u = UserData{}
126 | _, err := o.Raw(querySql, id).Values(&maps)
127 | if err != nil {
128 | fmt.Println(err.Error())
129 | }
130 | for i := range maps {
131 | u.UserId = maps[i]["k_user_id"].(string)
132 | u.UserName = maps[i]["user_name"].(string)
133 | }
134 | return u, err
135 | }
136 | func FindUserByUsername(username string) (sql.Result, error) {
137 | o := orm.NewOrm()
138 | _ = o.Using("default")
139 | querySql := `select k_user_id from "k_user" where user_name = ?`
140 | res, err := o.Raw(querySql, username).Exec()
141 | return res, err
142 | }
143 | func GetUseridByUsername(username string) (int, error) {
144 | var k_user_id int
145 | o := orm.NewOrm()
146 | _ = o.Using("default")
147 | querySql := `select k_user_id from "k_user" where user_name = ?`
148 | err := o.Raw(querySql, username).QueryRow(&k_user_id)
149 | return k_user_id, err
150 | }
151 | func InsertIntoKUserInProject(projectId int, userId int) (sql.Result, error) {
152 | o := orm.NewOrm()
153 | _ = o.Using("default")
154 | insertSql := `insert into "k_user_in_project" (project_id,user_id)values(?,?)`
155 | res, err := o.Raw(insertSql, projectId, userId).Exec()
156 | return res, err
157 | }
158 | func InsertIntoKTemporaryUser(inviterId, gitId int, gitName string, projectId int) (sql.Result, error) {
159 | o := orm.NewOrm()
160 | _ = o.Using("default")
161 | insertSql := `insert into "k_temporary_user" (inviter_id,git_id,git_name,project_id,invite_time)values(?,?,?,?,?)`
162 | currentTime := time.Now()
163 | currentTime.Format("2006-01-02 15:04:05:000000")
164 | res, err := o.Raw(insertSql, inviterId, gitId, gitName, projectId, currentTime).Exec()
165 | return res, err
166 | }
167 | func InsertUser(name string, uri string, id string) error {
168 | o := orm.NewOrm()
169 | _ = o.Using("default")
170 | time := time.Now().Format("2006-01-02 15:04:05.000000")
171 |
172 | insertSql := `INSERT INTO "k_user" (USER_NAME,REGISTER_TIME,HEAD_SHOT_URL,GITHUB_ID) VALUES (?,?,?,?);`
173 | _, err := o.Raw(insertSql, name, time, uri, id).Exec()
174 |
175 | return err
176 | }
177 | func IsSupervisor(id string) bool {
178 | o := orm.NewOrm()
179 | _ = o.Using("default")
180 | findSql := `select * from "k_supervisor" where k_user_id= ?`
181 | res, _ := o.Raw(findSql, id).Exec()
182 | if res == nil {
183 | return false
184 | } else if n, _ := res.RowsAffected(); n == 0 {
185 | return false
186 | }
187 | return true
188 | }
189 | func FindUserInKUserInProject(userid int) (int, error) {
190 | o := orm.NewOrm()
191 | _ = o.Using("default")
192 | querySql := `select project_id from "k_user_in_project" where user_id = ?`
193 | res, err := o.Raw(querySql, userid).Exec()
194 | num, err := res.RowsAffected()
195 | return int(num), err
196 | }
197 |
198 | func InsertKCsChangeRecord(projectId int, projectName string, acceptUserId int, acceptUserName string, csAmount int) (sql.Result, error) {
199 | o := orm.NewOrm()
200 | insertSql := `insert into "k_cs_change_record"(distribute_project_id,distribute_project_name,accept_user_id,accept_user_name,cs_amount,distribute_time)values(?,?,?,?,?,?)`
201 | currentTime := time.Now()
202 | currentTime.Format("2006-01-02 15:04:05:000000")
203 | res, err := o.Raw(insertSql, projectId, projectName, acceptUserId, acceptUserName, csAmount, currentTime).Exec()
204 | return res, err
205 |
206 | }
207 |
208 | //该函数通过项目id获取该项目的所有成员信息
209 | func GetMembersInfoByProjectName(projectName string) (membersInfo []*UserData, err error) {
210 | var memberlist []*UserData
211 | var projectid int
212 | o := orm.NewOrm()
213 | o.Using("default")
214 | queryProjectIDSql := getProjectIDQuery()
215 | if err = o.Raw(queryProjectIDSql, projectName).QueryRow(&projectid); err != nil {
216 | fmt.Print(err.Error())
217 | return nil, err
218 | }
219 |
220 | queryMembersInProjectSql := getAllMemberQuery()
221 | if _, err = o.Raw(queryMembersInProjectSql, projectid).QueryRows(&memberlist); err != nil {
222 | fmt.Print(err.Error())
223 | return nil, err
224 | }
225 |
226 | return memberlist, nil
227 | }
228 |
229 | //通过连接k_user表和k_user_in_project表查询用户信息
230 | func getAllMemberQuery() string {
231 | return `SELECT u.k_user_id, u.user_name, u.head_shot_url
232 | FROM "k_user" u LEFT JOIN "k_user_in_project" up on u.k_user_id = up.user_id
233 | WHERE up.project_id = ?`
234 | }
235 |
236 | //ProjectId只能通过查询K_project表获取,所以getProjectId函数通过函数名查询ProjectId后返回
237 | func getProjectIDQuery() string {
238 | return `SELECT project_id FROM "k_project" WHERE project_name = ?`
239 | }
240 |
--------------------------------------------------------------------------------
/src/static/css/project.css:
--------------------------------------------------------------------------------
1 | @charset "utf-8";
2 | /* CSS Document */
3 |
4 | /*以下是projectTopNav页面用到的css*/
5 | body {
6 | margin: 0;
7 | }
8 |
9 | a:link,a:visited,a:hover,a:active
10 | {
11 | color: #1B1B1B;
12 | text-decoration:none;
13 | }
14 |
15 | .head {
16 | position: relative;
17 | height: 70px;
18 | background-color: #333333;
19 | }
20 | .navigation {
21 | position: relative;
22 | height: 160px;
23 | padding-left: 100px;
24 | background-color: #bfbfbf;
25 | }
26 | .navigation > img {
27 | position: absolute;
28 | width: 150px;
29 | height: 100%;
30 | border-style: solid;
31 | border-width: 6px;
32 | border-color: #FFFFFF;
33 | border-radius: 5px;
34 | margin-left: 50px;
35 | margin-top: 20px;
36 | }
37 | .navigation > .prj-name {
38 | position: absolute;
39 | font-size: 60px;
40 | margin-left: 250px;
41 | margin-top: 30px;
42 | color: #323a45;
43 | }
44 |
45 | .navigation > .invest{
46 | position: absolute;
47 | right: 150px;
48 | top: 50px;
49 | width: 100px;
50 | height: 50px;
51 | text-align: center;
52 | background-color: rgb(56, 212, 69);
53 | border-radius: 20px;
54 | font-size: 25px;
55 | cursor: pointer;
56 | border: none;
57 | outline: none;
58 | }
59 |
60 |
61 | .navigation > .starNum{
62 | position:absolute;
63 | right: 300px;
64 | top: 60px;
65 | font-size: 20px;
66 |
67 | }
68 |
69 |
70 | .navigation > .first {
71 | margin-left: 250px;
72 |
73 | }
74 | .navigation > a {
75 | float: left;
76 | margin-top: 110px;
77 | margin-left: 40px;
78 | padding-left: 10px;
79 | padding-right: 10px;
80 | padding-top: 5px;
81 | border-radius: 10px;
82 | font-size: 30px;
83 | height: 60px;
84 | }
85 |
86 | .topNavLogo{
87 | float: left;
88 | width: 60px;
89 | height: 60px;
90 | margin-top: 5px;
91 | margin-left: 5px;
92 | margin-right: 10px;
93 | }
94 |
95 | .topNavName{
96 | float: left;
97 | line-height: 70px;
98 | font-size: 28px;
99 | color: aliceblue;
100 | }
101 |
102 | /*以下是projectInfo页面的css*/
103 | .projectInfo-container {
104 | margin: auto;
105 | width: 1200px;
106 | font-size: 0;
107 | }
108 | .projectInfo-card {
109 | display: inline-block;
110 | vertical-align: top;
111 | border-style: solid;
112 | border-width: 4px;
113 | border-radius: 10px;
114 | border-color: #bfbfbf;
115 | width: 500px;
116 | height: 500px;
117 | margin-top: 70px;
118 | margin-left: 46px;
119 | margin-right: 46px;
120 | }
121 | .projectInfo-card-head {
122 | height: 70px;
123 | background-color: #bfbfbf;
124 | }
125 | .projectInfo-card-title {
126 | display: inline-block;
127 | vertical-align: bottom;
128 | font-size: 25px;
129 | height: 70px;
130 | line-height: 70px;
131 | text-align: center;
132 | margin-left: 20px;
133 | }
134 | .projectInfo-card-value {
135 | display: inline-block;
136 | vertical-align: bottom;
137 | font-size: 35px;
138 | font-weight: bold;
139 | color: #ff3600;
140 | height: 70px;
141 | line-height: 70px;
142 | text-align: center;
143 | margin-left: 300px;
144 | }
145 | .projectInfo-record-label {
146 | font-size: 15px;
147 | text-align: center;
148 | width: 100px;
149 | height: 30px;
150 | line-height: 30px;
151 | margin: -15px auto;
152 | background-color: #FFFFFF;
153 | border-radius: 15px;
154 | }
155 |
156 | .projectInfo-card-rule {
157 | display: inline-block;
158 | vertical-align: top;
159 | border-style: solid;
160 | border-width: 4px;
161 | border-radius: 10px;
162 | border-color: #bfbfbf;
163 | width: 1100px;
164 | height: 350px;
165 | margin-top: 70px;
166 | margin-left: 46px;
167 | margin-right: 46px;
168 | }
169 |
170 | /*以下是projectNotice页面的css*/
171 | .container {
172 | width: 1200px;
173 | padding-left: 150px;
174 | padding-top: 150px;
175 | font-size: 20px;
176 |
177 | }
178 |
179 | .yearNode { /*表示年份的结点*/
180 | width: 80px;
181 | height: 30px;
182 | border-radius: 15px; /*给矩形增加圆角*/
183 | background-color: #ff7070;
184 | position: relative;
185 | left: -45px;
186 | top: 30px;
187 | text-align: center;
188 | margin-bottom: 100px;
189 | }
190 |
191 |
192 | .time-vertical {
193 | list-style-type: none;
194 | border-left: 10px solid #ff7070;/*左侧边界,显示效果为纵向的时间线*/
195 | margin-left: 10px;
196 | padding: 0px;
197 | }
198 |
199 | .time-vertical div {
200 | height: 100px;
201 | position: relative;
202 | }
203 |
204 | .time-vertical div a {
205 | display: inline-block;
206 | margin-left: 20px;
207 | margin-top: 15px;
208 | text-decoration: none;
209 | color: #000;
210 | }
211 |
212 | .time-vertical div b:before {
213 | content: '';
214 | position: absolute;
215 | top: 15px;
216 | left: -16px;
217 | width: 18px;
218 | height: 18px;
219 | border: 2px solid #ff7070;
220 | border-radius: 10px;
221 | background: #fff;
222 | vertical-align: middle;
223 | }
224 |
225 | .time-vertical div span {
226 | position: absolute;
227 | color: #ff5050;
228 | top: 18px;
229 | left: -65px;
230 | }
231 |
232 | /*以下是projectMemberList页面的css*/
233 | .memberListContainer{
234 | background-color: white;
235 | margin: auto;
236 | margin-top: 80px;
237 | width: 1200px;
238 | height: 300px;
239 | }
240 | .memberItem{
241 | float:left;
242 | width: 600px;
243 | height: 125px;
244 | background-color: white;
245 | display: flex;
246 | }
247 | .pageList{
248 | position: relative;
249 | width: 100%;
250 | height: 50px;
251 | background-color: white;
252 | }
253 | .lookMore{
254 | line-height: 50px;
255 | }
256 | .lookMore > a{
257 | position: relative;
258 | left: 92%;
259 | color:cadetblue;
260 | }
261 | .memberItem > .headShot{
262 | float:left;
263 | width: 125px;
264 | height: 125px;
265 | }
266 | .memberItem > .memberInfo{
267 | float: left;
268 | width: 175px;
269 | height: 125px;
270 | }
271 |
272 | /*以下是projectSetting.html页面的css*/
273 | .projectsetting{
274 | margin-top: 60px;
275 | height: 282px;
276 | }
277 | .projectsetting p1{
278 | display:block;
279 | color: #A9AFB5;
280 | margin-top: 110px;
281 | margin-left: 20px;
282 | font-size: 16px;
283 | }
284 | .projectsetting p2{
285 | display:block;
286 | margin-left: 20px;
287 | color: #A9AFB5;
288 | font-size: 16px;
289 | }
290 | .projectsetting p3{
291 | display:block;
292 | margin-left: 20px;
293 | color: #A9AFB5;
294 | font-size: 16px;
295 | }
296 | .upload-pjname {
297 | display:block;
298 | font-size: 16px;
299 | width: 1150px;
300 | height: 35px;
301 | border-radius: 5px;
302 | outline: none;
303 | border: 1px solid #B5B3B3;
304 | margin-top: 10px;
305 | margin-left: 20px;
306 | }
307 | .upload-button {
308 | display:block;
309 | width: 70px;
310 | margin-top: 10px;
311 | margin-left:20px;
312 | border:2px solid #27D5F5;
313 | padding:10px;
314 | border-radius: 10px;
315 | color: #27D5F5;
316 | }
317 |
318 | textarea.projectintro{
319 | border-style: ridge;
320 | border-radius: 5px;
321 | padding: 5px;
322 | color:gray;
323 | font-size: 110%;
324 | margin-left: 20px;
325 | width: 1140px;
326 | height:100px;
327 | }
328 |
329 | /*以下是projectMemberWork.html页面的css*/
330 | .work-mainInterface{
331 | background-color: #FFFFFF;
332 | position: relative;
333 | min-height: 70vh;
334 | width: 100%;
335 | font-size: 20px;
336 | }
337 |
338 | .work-record{
339 | position: relative;
340 | margin: 50px;
341 | width: 900px;
342 | height: 150px;
343 | top:60px
344 | }
345 |
346 | .work-customers{
347 | font-family:"Trebuchet MS", Arial, Helvetica, sans-serif;
348 | width:100%;
349 | border-collapse:collapse;
350 | margin-top: 20px;
351 | }
352 |
353 | .work-customers th {
354 | font-size:1em;
355 | border:0px solid #ffffff;
356 | padding:3px 7px 15px 7px;
357 |
358 | }
359 |
360 | .work-customers td{
361 | font-size:1em;
362 | border:0px solid #ffffff;
363 | padding:3px 7px 2px 7px;
364 | text-align: center;
365 | }
366 |
367 | .work-back{
368 | position: absolute;
369 | font-size: 15px;
370 | left: 25px;
371 | top: 15px;
372 | color: rgb(75, 192, 238);
373 | }
374 |
--------------------------------------------------------------------------------
/src/static/css/personal.css:
--------------------------------------------------------------------------------
1 | @charset "utf-8";
2 |
3 |
4 | /*以下是personalPage页面的css*/
5 | *{
6 | border: 0;
7 | margin: 0;
8 | }
9 |
10 | body{
11 | font:19px/1.5 Microsoft YaHei;
12 | position:relative;
13 | margin:0 auto;
14 | background-color:#ece9ecfd;
15 | }
16 | a:link,a:visited,a:hover,a:active
17 | {
18 | color: #1B1B1B;
19 | text-decoration:none;
20 | }
21 | ul {
22 | list-style-type:none;
23 | margin:0;
24 | padding:0;
25 | }
26 |
27 | #container{
28 | position: relative;
29 | width: 100%;
30 | height: 1200px;
31 | }
32 |
33 | .left-nav{
34 | background-color: #ece9ecfd;
35 | position: relative;
36 | float: left;
37 | width: 20%;
38 | }
39 |
40 | .mainInterface{
41 | background-color: #FFFFFF;
42 | position: relative;
43 | min-height: 100vh;
44 | float: left;
45 | width: 80%;
46 | height: 100%;
47 | }
48 |
49 | .banner{
50 | background-color: #8a818afd;
51 | position:relative;
52 | padding-top: 10px;
53 | padding-left: 10px;
54 | vertical-align: middle;
55 | width: 100%;
56 | height: 40px;
57 | }
58 |
59 | .information{
60 | position: relative;
61 | width: 100%;
62 | height: 250px;
63 | text-align: center;
64 | padding-top: 30px;
65 | padding-top: 50px;
66 | }
67 |
68 | .list{
69 | position: relative;
70 | padding-top: 30px;
71 | width: 100%;
72 | height: 100%;
73 | text-align: center;
74 | }
75 |
76 | .money{
77 | position: relative;
78 | box-shadow: 0px 3px 7px #000000;
79 | margin: 50px;
80 | width: 900px;
81 | height: 150px;
82 | border: 0px;
83 | border-radius: 15px;
84 | border-style: solid;
85 | border-color:#4da5b4fd;
86 | padding: 2px;
87 | }
88 |
89 | .record{
90 | position: relative;
91 | margin: 50px;
92 | width: 900px;
93 | height: 150px;
94 | }
95 |
96 | .token{
97 | position: absolute;
98 | margin-top: 200px;
99 | width: 900px;
100 | height: 150px;
101 | }
102 |
103 | .list a{
104 | display:block;
105 | font-weight:bold;
106 | width:100%;
107 | height: 60px;
108 | text-align: center;
109 | }
110 |
111 | .sermore{
112 | margin-left: 550px;
113 | font-weight: 500;
114 | font-size: 18px;
115 | color: #c00;
116 | }
117 |
118 | .customers
119 | {
120 | font-family:"Trebuchet MS", Arial, Helvetica, sans-serif;
121 | width:120%;
122 | border-collapse:collapse;
123 | margin-top: 20px;
124 | }
125 | .customers th
126 | { display: inline-block;
127 | border:0px solid #ffffff;
128 | font-size:1em;
129 | text-align:left;
130 | margin-top:30px;
131 | margin-right:80px;
132 | background-color:#FFFFFF;
133 | width: 200px;
134 | }
135 | .customers td
136 | { display: inline-block;
137 | border:0px solid #ffffff;
138 | font-size:1em;
139 | text-align:left;
140 | margin-top:30px;
141 | margin-right:80px;
142 | background-color:#FFFFFF;
143 | width: 200px;
144 | }
145 | .customers tr.alt td
146 | {
147 | color:#000000;
148 | background-color:#e2e0e0;
149 | }
150 |
151 | ul.pagination {
152 | position: absolute;
153 | display: inline-block;
154 | padding: 0;
155 | margin: 10px;
156 | margin-top: 80px;
157 |
158 | }
159 |
160 | ul.pagination li {display: inline;}
161 |
162 | ul.pagination li a {
163 | color: black;
164 | float: left;
165 | padding: 3px 6px;
166 | text-decoration: none;
167 | transition: background-color .3s;
168 | border: 1px solid #ddd;
169 | margin: 0 4px;
170 | }
171 |
172 | ul.pagination li a.active {
173 | background-color: rgb(176, 225, 248);
174 | color: white;
175 | border: 1px solid rgb(176, 225, 248);
176 | }
177 |
178 | ul.pagination li a:hover:not(.active) {background-color: #ddd;}
179 |
180 |
181 |
182 | /*以下是personalProjects页面的css*/
183 | .container {
184 | width: 100%;
185 | text-align: center;
186 | float: left;
187 | }
188 |
189 | .addprojbar {
190 | width: 100%;
191 | height: 60px;
192 | float: left;
193 | font-size: 25px;
194 | border: 1px;
195 | }
196 |
197 | .project {
198 | display: inline-block;
199 | margin-top: 40px;
200 | margin-left: 10px;
201 | margin-right: 10px;
202 | width: 300px;
203 | background: #F8F8FD;
204 | }
205 | .project > .project-cover {
206 | width: 100%;
207 | height: auto;
208 | }
209 | .project > .project-name {
210 | text-align: left;
211 | font-weight: 1000;
212 | font-size: 30px;
213 | padding-left: 10px;
214 | }
215 | .project > .introduction {
216 | text-align: left;
217 | padding-left: 20px;
218 | }
219 | .project > .CC {
220 | color: #FFCC33;
221 | font-size: 20px;
222 | text-align: left;
223 | padding-left: 20px;
224 | }
225 | .head_shot {
226 | padding-left: 15px;
227 | height: 50px;
228 | float: left;
229 | }
230 |
231 |
232 |
233 | /*表示点击按钮后,其他区域阴影*/
234 | .black_overlay{
235 | display: none;
236 | position: absolute;
237 | top: 0%;
238 | left: 0%;
239 | width: 100%;
240 | height: 100%;
241 | background-color: black;
242 | z-index:1001;
243 | -moz-opacity: 0.8;
244 | opacity:.80;
245 | filter: alpha(opacity=88);
246 | }
247 |
248 | /*以下为点击按钮后高亮的图层*/
249 |
250 | .main{
251 | width:800px;
252 | margin: auto;
253 | position: relative;
254 | top: 50%;
255 | transform: translateY(-50%);
256 | }
257 | .content{
258 | padding-left: 20px;
259 | padding-right: 20px;
260 | }
261 |
262 | .steps {
263 | position: relative;
264 | counter-reset: step; /*创建步骤数字计数器*/
265 | margin:0;
266 | padding:0;
267 | }
268 |
269 | /*步骤描述*/
270 | .steps li {
271 | list-style-type: none;
272 | font-size: 12px;
273 | color:black;
274 | text-align: center;
275 | width: 33.3%;
276 | position: relative;
277 | float: left;
278 | padding-bottom: 5px;
279 | }
280 | /*步骤数字*/
281 | .steps li:before {
282 | display: block;
283 | content: counter(step); /*设定计数器内容*/
284 | counter-increment: step; /*计数器值递增*/
285 | width: 32px;
286 | height: 32px;
287 | background-color: #ffd7d8;
288 | line-height: 32px;
289 | border-radius: 32px;
290 | font-size: 16px;
291 | color: white;
292 | text-align: center;
293 | font-weight: 700;
294 | margin: 0 auto 8px auto;
295 | }
296 |
297 | /*连接线*/
298 | .steps li ~ li:after {
299 | content: '';
300 | width: 100%;
301 | height: 2px;
302 | background-color: #ffd7d8;
303 | position: absolute;
304 | left: -50%;
305 | top: 15px;
306 | z-index: -1; /*放置在数字后面*/
307 | }
308 |
309 | .steps li.active:before,
310 | .steps li.active:after {
311 | background-color: #ff5b5d;
312 | }
313 |
314 | img.profile{
315 | height: 25px;
316 | }
317 | #username{
318 | font-weight:bold;
319 | }
320 | #userprojects{
321 | color:gray;
322 | }
323 | ul.projects{
324 | list-style-position: outside;
325 | font-size:130%;
326 | padding: 0px;
327 | }
328 | .projects li{
329 | margin-top:5px;
330 | list-style-type: none;
331 | border-radius: 5px;
332 | background-color:#edf0f5;
333 | padding: 5px;
334 | }
335 |
336 | #managed_projects{
337 | display: none;
338 | }
339 |
340 | /* 参加项目和管理项目头部 */
341 | a:link,a:visited,a:hover,a:active
342 | {
343 | color: #1B1B1B;
344 | text-decoration:none;
345 | }
346 |
347 | .navigation > .first {
348 | margin-left: 40px;
349 | background-color:#bfbfbf;
350 | }
351 | .navigation > a {
352 | float: left;
353 | margin-top: 20px;
354 | margin-left: 40px;
355 | padding-left: 10px;
356 | padding-right: 10px;
357 | padding-top: 5px;
358 | border-radius: 10px;
359 | font-size: 30px;
360 | height: 60px;
361 | }
362 |
363 | textarea.projectintro{
364 | border-style: ridge;
365 | border-radius: 5px;
366 | padding: 5px;
367 | color:gray;
368 | font-size: 110%;
369 | width:98%;
370 | height:100px;
371 | }
372 |
373 | /*以下是import.tpl页面用到的css*/
374 | html, body {
375 | width: 100%;
376 | height: 100%;
377 | margin: 0;
378 | padding: 0;
379 | }
380 |
381 | .main{
382 | width:800px;
383 | margin: auto;
384 | position: relative;
385 | top: 50%;
386 | transform: translateY(-50%);
387 | }
388 | .content{
389 | padding-left: 20px;
390 | padding-right: 20px;
391 | }
392 |
393 | .steps {
394 | position: relative;
395 | counter-reset: step; /*创建步骤数字计数器*/
396 | margin:0;
397 | padding:0;
398 | }
399 |
400 | /*步骤描述*/
401 | .steps li {
402 | list-style-type: none;
403 | font-size: 12px;
404 | color:black;
405 | text-align: center;
406 | width: 33.3%;
407 | position: relative;
408 | float: left;
409 | padding-bottom: 5px;
410 | }
411 | /*步骤数字*/
412 | .steps li:before {
413 | display: block;
414 | content: counter(step); /*设定计数器内容*/
415 | counter-increment: step; /*计数器值递增*/
416 | width: 32px;
417 | height: 32px;
418 | background-color: #ffd7d8;
419 | line-height: 32px;
420 | border-radius: 32px;
421 | font-size: 16px;
422 | color: white;
423 | text-align: center;
424 | font-weight: 700;
425 | margin: 0 auto 8px auto;
426 | }
427 |
428 | /*连接线*/
429 | .steps li ~ li:after {
430 | content: '';
431 | width: 100%;
432 | height: 2px;
433 | background-color: #ffd7d8;
434 | position: absolute;
435 | left: -50%;
436 | top: 15px;
437 | z-index: -1; /*放置在数字后面*/
438 | }
439 |
440 | .steps li.active:before,
441 | .steps li.active:after {
442 | background-color: #ff5b5d;
443 | }
444 |
445 | /*主体*/
446 | input.url_input{
447 | border-style: ridge;
448 | border-radius: 5px;
449 | margin-top: 5px;
450 | padding-left: 5px;
451 | padding-top: 5px;
452 | padding-bottom: 5px;
453 | color:gray;
454 | font-size: 110%;
455 | width:90%;
456 | }
457 |
458 | input.submit{
459 | border-style: ridge;
460 | border-radius: 5px;
461 | background-color:white;
462 | color:#ff5b5d;
463 | font-size: 110%;
464 | padding-top: 2px;
465 | padding-bottom: 2px;
466 | margin-left: 5px;
467 | }
468 |
469 | h1 {
470 | background-color: #434343;
471 | padding-top: 5px;
472 | padding-bottom: 5px;
473 | padding-left: 20px;
474 | color:white;
475 | font-weight:normal;
476 | font-size: 160%;
477 | }
478 |
479 | img.profile{
480 | height: 25px;
481 | }
482 |
483 | #username{
484 | font-weight:bold;
485 | }
486 |
487 | #userprojects{
488 | color:gray;
489 | }
490 |
491 | ul.projects{
492 | list-style-position: outside;
493 | font-size:130%;
494 | padding: 0px;
495 | }
496 |
497 | .projects li{
498 | margin-top:5px;
499 | list-style-type: none;
500 | border-radius: 5px;
501 | background-color:#edf0f5;
502 | padding: 5px;
503 | }
504 |
505 | #next_back{
506 | margin-top: 20px;
507 | }
508 |
509 | button.back{
510 | border-style: ridge;
511 | border-radius: 5px;
512 | color:#ff5b5d;
513 | background-color: white;
514 | font-size: 110%;
515 | padding-top: 2px;
516 | padding-bottom: 2px;
517 | /* float:right; */
518 | margin-left: 590px;
519 | margin-bottom: 20px;
520 | }
521 |
522 | button.next{
523 | border-style: ridge;
524 | border-radius: 5px;
525 | font-size: 110%;
526 | padding-top: 2px;
527 | padding-bottom: 2px;
528 | margin-left: 15px;
529 | background-color: #ff5b5d;
530 | color:white;
531 | float:right;
532 | }
533 | button.confirm{
534 | border-style: ridge;
535 | border-radius: 5px;
536 | font-size: 110%;
537 | padding-top: 2px;
538 | padding-bottom: 2px;
539 | margin-left: 15px;
540 | background-color: #ff5b5d;
541 | color:white;
542 | float:right;
543 | display: none;
544 | }
545 |
546 | #myprojects{
547 | display: block;
548 | }
549 |
550 | #init_message{
551 | display: none;
552 | }
553 | #config_project{
554 | display: none;
555 | }
556 |
557 | #config_project p{
558 | color:gray;
559 | }
560 |
561 | input.projectname{
562 | border-style: ridge;
563 | border-radius: 5px;
564 | padding: 5px;
565 | color:gray;
566 | font-size: 110%;
567 | width:98%;
568 | }
569 |
570 | .upload{
571 | padding: 4px 10px;
572 | border-style: ridge;
573 | border-radius: 5px;
574 | border: 1px solid #999;
575 | text-decoration: none;
576 | color: #ff5b5d;
577 | }
578 |
579 | .change{
580 | border-style: ridge;
581 | border-radius: 5px;
582 | color:#ff5b5d;
583 | font-size: 25px;
584 | overflow: hidden;
585 | position: absolute;
586 | left:20px;
587 | bottom: 65px;
588 | opacity:0;
589 | width:90px;
590 | }
591 |
592 |
--------------------------------------------------------------------------------
/src/views/personalPage.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | 个人中心
5 |
10 |
11 |
12 |
13 |
14 |
15 |
16 | {{template "./leftNav.html" .}}
17 |
18 |
21 |
22 |
23 |
24 |

25 | Kcoin
26 | {{.remainingCc}}
27 |
28 |
29 | Kcoin记录
30 |
查看更多
31 |
32 |
33 | | 日期 |
34 | 操作类型 |
35 | cc数量 |
36 |
37 |
38 |
39 | | 11.19 |
40 | sell |
41 | -1000 |
42 |
43 |
44 | | 11.20 |
45 | buy |
46 | +5000 |
47 |
48 |
49 | | 11.21 |
50 | sell |
51 | -1500 |
52 |
53 |
54 | | 11.22 |
55 | sell |
56 | -1000 |
57 |
58 |
59 | | 日期 |
60 | 操作类型 |
61 | cc数量 |
62 |
63 |
64 | | 11.23 |
65 | sell |
66 | -1500 |
67 |
68 |
69 | | 11.24 |
70 | sell |
71 | -2000 |
72 |
73 |
74 | | 11.25 |
75 | buy |
76 | +3000 |
77 |
78 |
79 | | 11.26 |
80 | sell |
81 | -2500 |
82 |
83 |
84 | | 日期 |
85 | 操作类型 |
86 | cc数量 |
87 |
88 |
89 | | 11.27 |
90 | buy |
91 | +1000 |
92 |
93 |
94 | | 11.28 |
95 | sell |
96 | -1500 |
97 |
98 | 11.29 |
99 | sell |
100 | -1000 |
101 |
102 |
103 |
104 | | 11.30 |
105 | sell |
106 | -2000 |
107 |
108 |
109 | | 日期 |
110 | 操作类型 |
111 | cc数量 |
112 |
113 |
114 | | 12.01 |
115 | buy |
116 | +4000 |
117 |
118 |
119 | | 12.02 |
120 | sell |
121 | -1000 |
122 |
123 |
124 | | 12.03 |
125 | buy |
126 | +6000 |
127 |
128 |
129 | | 12.04 |
130 | sell |
131 | -1500 |
132 |
133 |
134 | | 日期 |
135 | 操作类型 |
136 | cc数量 |
137 |
138 |
139 | | 12.05 |
140 | sell |
141 | -1000 |
142 |
143 |
144 | | 12.06 |
145 | sell |
146 | -1500 |
147 |
148 |
149 | | 12.07 |
150 | sell |
151 | -1000 |
152 |
153 |
154 | | 12.08 |
155 | buy |
156 | +1000 |
157 |
158 |
159 |
160 |
161 |
171 |
178 |
179 |
180 | 项目token记录
181 |
cs数
182 |
{{.user.Data.CsNum}}
183 |
184 |
185 |
186 |
187 | | 日期 |
188 | 操作类型 |
189 | cc数量 |
190 |
191 |
192 |
193 | | 11.19 |
194 | sell |
195 | -1000 |
196 |
197 |
198 | | 11.20 |
199 | buy |
200 | +5000 |
201 |
202 |
203 | | 11.21 |
204 | sell |
205 | -1500 |
206 |
207 |
208 | | 11.22 |
209 | sell |
210 | -1000 |
211 |
212 |
213 | | 日期 |
214 | 操作类型 |
215 | cc数量 |
216 |
217 |
218 | | 11.23 |
219 | sell |
220 | -1500 |
221 |
222 |
223 | | 11.24 |
224 | sell |
225 | -2000 |
226 |
227 |
228 | | 11.25 |
229 | buy |
230 | +3000 |
231 |
232 |
233 | | 11.26 |
234 | sell |
235 | -2500 |
236 |
237 |
238 | | 日期 |
239 | 操作类型 |
240 | cc数量 |
241 |
242 |
243 | | 11.27 |
244 | buy |
245 | +1000 |
246 |
247 |
248 | | 11.28 |
249 | sell |
250 | -1500 |
251 |
252 | 11.29 |
253 | sell |
254 | -1000 |
255 |
256 |
257 |
258 | | 11.30 |
259 | sell |
260 | -2000 |
261 |
262 |
263 | | 日期 |
264 | 操作类型 |
265 | cc数量 |
266 |
267 |
268 | | 12.01 |
269 | buy |
270 | +4000 |
271 |
272 |
273 | | 12.02 |
274 | sell |
275 | -1000 |
276 |
277 |
278 | | 12.03 |
279 | buy |
280 | +6000 |
281 |
282 |
283 | | 12.04 |
284 | sell |
285 | -1500 |
286 |
287 |
288 | | 日期 |
289 | 操作类型 |
290 | cc数量 |
291 |
292 |
293 | | 12.05 |
294 | sell |
295 | -1000 |
296 |
297 |
298 | | 12.06 |
299 | sell |
300 | -1500 |
301 |
302 |
303 | | 12.07 |
304 | sell |
305 | -1000 |
306 |
307 |
308 | | 12.08 |
309 | buy |
310 | +1000 |
311 |
312 |
313 |
314 |
315 |
325 |
330 |
331 |
332 |
333 |
334 |
--------------------------------------------------------------------------------
/src/service/github_helper.go:
--------------------------------------------------------------------------------
1 | package service
2 |
3 | import (
4 | "bytes"
5 | "context"
6 | "encoding/json"
7 | "fmt"
8 | "github.com/astaxie/beego"
9 | "io/ioutil"
10 | "net/http"
11 | "strings"
12 | "time"
13 | )
14 |
15 | /**
16 | * 这是一个全局数据结构,目前只有三个字段,用来保存GithubID, Github Name和对应access_token
17 | */
18 | type GithubInfo struct {
19 | GithubId string
20 | GithubName string
21 | AccessToken string
22 | }
23 |
24 | // TODO 妥善使用该数据结构, 用户信息应该用session保存, 可以建立一个sessionID->session的映射, 但是不太清楚session如何使用, 这里需要会的人来修改这个丑陋的数据结构
25 | //Github UserID -> GithubInfo
26 | //type GithubUserMap map[string]*GithubInfo
27 |
28 | //var GithubUser GithubUserMap
29 |
30 | // struct for github api: "https://api.github.com/repos/"+userName+"/"+programName发送请求后的返回值
31 | type JsonData struct {
32 | ID int `json:"id"`
33 | NodeID string `json:"node_id"`
34 | Name string `json:"name"`
35 | FullName string `json:"full_name"`
36 | Private bool `json:"private"`
37 | Owner struct {
38 | Login string `json:"login"`
39 | ID int `json:"id"`
40 | NodeID string `json:"node_id"`
41 | AvatarURL string `json:"avatar_url"`
42 | GravatarID string `json:"gravatar_id"`
43 | URL string `json:"url"`
44 | HTMLURL string `json:"html_url"`
45 | FollowersURL string `json:"followers_url"`
46 | FollowingURL string `json:"following_url"`
47 | GistsURL string `json:"gists_url"`
48 | StarredURL string `json:"starred_url"`
49 | SubscriptionsURL string `json:"subscriptions_url"`
50 | OrganizationsURL string `json:"organizations_url"`
51 | ReposURL string `json:"repos_url"`
52 | EventsURL string `json:"events_url"`
53 | ReceivedEventsURL string `json:"received_events_url"`
54 | Type string `json:"type"`
55 | SiteAdmin bool `json:"site_admin"`
56 | } `json:"owner"`
57 | HTMLURL string `json:"html_url"`
58 | Description interface{} `json:"description"`
59 | Fork bool `json:"fork"`
60 | URL string `json:"url"`
61 | ForksURL string `json:"forks_url"`
62 | KeysURL string `json:"keys_url"`
63 | CollaboratorsURL string `json:"collaborators_url"`
64 | TeamsURL string `json:"teams_url"`
65 | HooksURL string `json:"hooks_url"`
66 | IssueEventsURL string `json:"issue_events_url"`
67 | EventsURL string `json:"events_url"`
68 | AssigneesURL string `json:"assignees_url"`
69 | BranchesURL string `json:"branches_url"`
70 | TagsURL string `json:"tags_url"`
71 | BlobsURL string `json:"blobs_url"`
72 | GitTagsURL string `json:"git_tags_url"`
73 | GitRefsURL string `json:"git_refs_url"`
74 | TreesURL string `json:"trees_url"`
75 | StatusesURL string `json:"statuses_url"`
76 | LanguagesURL string `json:"languages_url"`
77 | StargazersURL string `json:"stargazers_url"`
78 | ContributorsURL string `json:"contributors_url"`
79 | SubscribersURL string `json:"subscribers_url"`
80 | SubscriptionURL string `json:"subscription_url"`
81 | CommitsURL string `json:"commits_url"`
82 | GitCommitsURL string `json:"git_commits_url"`
83 | CommentsURL string `json:"comments_url"`
84 | IssueCommentURL string `json:"issue_comment_url"`
85 | ContentsURL string `json:"contents_url"`
86 | CompareURL string `json:"compare_url"`
87 | MergesURL string `json:"merges_url"`
88 | ArchiveURL string `json:"archive_url"`
89 | DownloadsURL string `json:"downloads_url"`
90 | IssuesURL string `json:"issues_url"`
91 | PullsURL string `json:"pulls_url"`
92 | MilestonesURL string `json:"milestones_url"`
93 | NotificationsURL string `json:"notifications_url"`
94 | LabelsURL string `json:"labels_url"`
95 | ReleasesURL string `json:"releases_url"`
96 | DeploymentsURL string `json:"deployments_url"`
97 | CreatedAt time.Time `json:"created_at"`
98 | UpdatedAt time.Time `json:"updated_at"`
99 | PushedAt time.Time `json:"pushed_at"`
100 | GitURL string `json:"git_url"`
101 | SSHURL string `json:"ssh_url"`
102 | CloneURL string `json:"clone_url"`
103 | SvnURL string `json:"svn_url"`
104 | Homepage interface{} `json:"homepage"`
105 | Size int `json:"size"`
106 | StargazersCount int `json:"stargazers_count"`
107 | WatchersCount int `json:"watchers_count"`
108 | Language string `json:"language"`
109 | HasIssues bool `json:"has_issues"`
110 | HasProjects bool `json:"has_projects"`
111 | HasDownloads bool `json:"has_downloads"`
112 | HasWiki bool `json:"has_wiki"`
113 | HasPages bool `json:"has_pages"`
114 | ForksCount int `json:"forks_count"`
115 | MirrorURL interface{} `json:"mirror_url"`
116 | Archived bool `json:"archived"`
117 | Disabled bool `json:"disabled"`
118 | OpenIssuesCount int `json:"open_issues_count"`
119 | License interface{} `json:"license"`
120 | Forks int `json:"forks"`
121 | OpenIssues int `json:"open_issues"`
122 | Watchers int `json:"watchers"`
123 | DefaultBranch string `json:"default_branch"`
124 | Organization struct {
125 | Login string `json:"login"`
126 | ID int `json:"id"`
127 | NodeID string `json:"node_id"`
128 | AvatarURL string `json:"avatar_url"`
129 | GravatarID string `json:"gravatar_id"`
130 | URL string `json:"url"`
131 | HTMLURL string `json:"html_url"`
132 | FollowersURL string `json:"followers_url"`
133 | FollowingURL string `json:"following_url"`
134 | GistsURL string `json:"gists_url"`
135 | StarredURL string `json:"starred_url"`
136 | SubscriptionsURL string `json:"subscriptions_url"`
137 | OrganizationsURL string `json:"organizations_url"`
138 | ReposURL string `json:"repos_url"`
139 | EventsURL string `json:"events_url"`
140 | ReceivedEventsURL string `json:"received_events_url"`
141 | Type string `json:"type"`
142 | SiteAdmin bool `json:"site_admin"`
143 | } `json:"organization"`
144 | NetworkCount int `json:"network_count"`
145 | SubscribersCount int `json:"subscribers_count"`
146 | }
147 |
148 | // struct for github api: "https://api.github.com/repos/" + userName + "/" + programName + "/" + "contributors"
149 | type ContributorData []struct {
150 | Login string `json:"login"`
151 | ID int `json:"id"`
152 | NodeID string `json:"node_id"`
153 | AvatarURL string `json:"avatar_url"`
154 | GravatarID string `json:"gravatar_id"`
155 | URL string `json:"url"`
156 | HTMLURL string `json:"html_url"`
157 | FollowersURL string `json:"followers_url"`
158 | FollowingURL string `json:"following_url"`
159 | GistsURL string `json:"gists_url"`
160 | StarredURL string `json:"starred_url"`
161 | SubscriptionsURL string `json:"subscriptions_url"`
162 | OrganizationsURL string `json:"organizations_url"`
163 | ReposURL string `json:"repos_url"`
164 | EventsURL string `json:"events_url"`
165 | ReceivedEventsURL string `json:"received_events_url"`
166 | Type string `json:"type"`
167 | SiteAdmin bool `json:"site_admin"`
168 | Contributions int `json:"contributions"`
169 | }
170 |
171 | // struct for github api: "https://api.github.com/users/" + username
172 | type API_User struct {
173 | Login string `json:"login"`
174 | Id int `json:"id"`
175 | Node_id string `json:"node_id"`
176 | Avatar_url string `json:"avatar_url"`
177 | Gravatar_id string `json:"gravatar_id"`
178 | Url string `json:"url"`
179 | Html_url string `json:"html_url"`
180 | Followers_url string `json:"followers_url"`
181 | Following_url string `json:"following_url"`
182 | Gists_url string `json:"gists_url"`
183 | Starred_url string `json:"starred_url"`
184 | Subscriptions_url string `json:"subscriptions_url"`
185 | Organizations_url string `json:"organizations_url"`
186 | Repos_url string `json:"repos_url"`
187 | Events_url string `json:"events_url"`
188 | Received_events_url string `json:"received_events_url"`
189 | Type string `json:"type"`
190 | Site_admin bool `json:"site_admin"`
191 | Name string `json:"name"`
192 | Company string `json:"company"`
193 | Blog string `json:"blog"`
194 | Location string `json:"location"`
195 | Email string `json:"email"`
196 | Hireable bool `json:"hireable"`
197 | Bio string `json:"bio"`
198 | Public_repos int `json:"public_repos"`
199 | Public_gists int `json:"public_gists"`
200 | Followers int `json:"followers"`
201 | Following int `json:"following"`
202 | Created_at string `json:"created_at"`
203 | Updated_at string `json:"updated_at"`
204 | }
205 |
206 | func init() {
207 | fmt.Println("Controller initialized!")
208 | //GithubUser = make(GithubUserMap)
209 | }
210 |
211 | /**
212 | * 获取项目star数量的接口
213 | * 函数名:GetStarNum
214 | * 函数参数:url string
215 | * 返回值:starNum int 返回url对应项目的star数目
216 | */
217 | func GetStarNum(url string) int {
218 | var starNum = 0
219 | //从url中获取到用户名和项目名
220 | userName, programName, _ := ParseGithubHTTPSUrl(url)
221 |
222 | var Api = "https://api.github.com/repos/" + userName + "/" + programName
223 | client := &http.Client{}
224 | response, _ := client.Get(Api)
225 | defer response.Body.Close()
226 | body, err := ioutil.ReadAll(response.Body)
227 | if err != nil {
228 | panic(err)
229 | }
230 |
231 | var jd JsonData
232 | json.Unmarshal(body, &jd)
233 | starNum = jd.StargazersCount
234 | return starNum
235 | }
236 |
237 | //获取项目贡献者信息的接口
238 | // 函数名:getContributors
239 | // 函数参数:userName string programName string
240 | // 返回值:string 包含所有的contributor信息,不同的contributor用" "分割
241 |
242 | func GetContributors(userName string, programName string) string {
243 | var url_1 string = "https://api.github.com/repos/" + userName + "/" + programName + "/" + "contributors"
244 |
245 | client := &http.Client{}
246 | response, _ := client.Get(url_1)
247 | defer response.Body.Close()
248 | body, err_1 := ioutil.ReadAll(response.Body)
249 | if err_1 != nil {
250 | panic(err_1)
251 | }
252 |
253 | var cb ContributorData
254 | json.Unmarshal(body, &cb)
255 | var cl string = ""
256 | for i := 0; i < len(cb); i++ {
257 | var Name = cb[i].Login
258 | cl = cl + Name + " "
259 | }
260 | fmt.Println(cl)
261 | return cl
262 | }
263 |
264 | //获取贡献者的人数
265 | // 函数名:GetContributorNum
266 | // 函数参数:url string
267 | // 返回值:int 返回对应项目的贡献者人数
268 | func GetContributorNum(url string) int {
269 |
270 | user_Name, program_Name, _ := ParseGithubHTTPSUrl(url)
271 |
272 | info := GetContributors(user_Name, program_Name)
273 | res := strings.TrimSpace(info)
274 | str_arr := strings.Split(res, " ")
275 | count := len(str_arr)
276 | return count
277 | }
278 |
279 | type Data struct {
280 | Id string `json:userId`
281 | Name string `json:"userName"`
282 | Uri string `json:"headShotUrl"`
283 | }
284 |
285 | type UserJson struct {
286 | ErrorCode int
287 | Data Data
288 | }
289 |
290 | func GetUserJson(access_token string) UserJson {
291 | var url_2 = "https://api.github.com/user?" + "access_token=" + access_token
292 |
293 | client_2 := &http.Client{}
294 | response_2, _ := client_2.Get(url_2)
295 | defer response_2.Body.Close()
296 | body_2, err_2 := ioutil.ReadAll(response_2.Body)
297 | if err_2 != nil {
298 | panic(err_2)
299 | }
300 |
301 | // 获取ID
302 | var name = strings.Split(strings.Split(string(body_2), ",")[0], "\"")[3]
303 | var uri = strings.Split(strings.Split(string(body_2), ",")[3], "\"")[3]
304 | var id = strings.Split(strings.Split(string(body_2), ",")[1], ":")[1]
305 |
306 | //select id according to name
307 | data := Data{
308 | Name: name,
309 | Uri: uri,
310 | Id: id,
311 | }
312 | userJson := UserJson{
313 | ErrorCode: 0,
314 | Data: data,
315 | }
316 |
317 | return userJson
318 | }
319 |
320 | func GetAccessToken(code string) (accessToken string, err error) {
321 | client_id := beego.AppConfig.String("client_id")
322 | client_secret := beego.AppConfig.String("client_secret")
323 | url_1 := "https://github.com/login/oauth/access_token?code=" + code + "&client_id=" + client_id + "&client_secret=" + client_secret
324 |
325 | client := &http.Client{}
326 | response, err := client.Get(url_1)
327 | if err != nil {
328 | return "", err
329 | } else {
330 | defer response.Body.Close()
331 | }
332 | body, err1 := ioutil.ReadAll(response.Body)
333 | if err1 != nil {
334 | panic(err1)
335 | }
336 | accessToken = strings.Split(strings.Split(string(body), "&")[0], "=")[1]
337 | return accessToken, err
338 | }
339 |
340 | /**
341 | * 设置Github User这个map的Access Token字段.
342 | */
343 | /*func (this GithubUserMap) SetGithubUserAccessToken(id string, name string, accessToken string) {
344 | if _, ok := this[id]; !ok {
345 | this[id] = new(GithubInfo)
346 | }
347 | this[id].AccessToken = accessToken
348 | this[id].GithubId = id
349 | this[id].GithubName = name
350 | }*/
351 |
352 | /*func (this GithubUserMap) GetGithubUserAccessToken(userId string) (string, error) {
353 | if userInfo, ok := this[userId]; ok {
354 | return userInfo.AccessToken, nil
355 | } else {
356 | return "", fmt.Errorf("user id %s is not valid", userId)
357 | }
358 | }*/
359 |
360 | //getWebhooksUrl 可以通过
361 | func RegisterGithubWebhooks(githubName, repoName, accessToken string) {
362 | //accessToken, _ := GithubUser.GetGithubUserAccessToken(userId)
363 | postPayload := getPayloadOfRegisterGithubWebhooks()
364 | //userName := c.Ctx.GetCookie("gethubName")
365 | api_url := getWebhooksUrlBy(githubName, repoName)
366 | bytePostPayload := []byte(postPayload)
367 | buffer := bytes.NewBuffer(bytePostPayload)
368 | request, err := http.NewRequest("POST", api_url, buffer)
369 | if err != nil {
370 | fmt.Printf("http.NewRequest%v", err)
371 | }
372 | request.Header.Set("Content-Type", "application/json")
373 | request.Header.Set("Authorization", "token "+accessToken)
374 | client := &http.Client{}
375 | resp, err := client.Do(request.WithContext(context.TODO()))
376 | if err != nil {
377 | fmt.Printf("client.Do%v", err)
378 | }
379 | respBytes, err := ioutil.ReadAll(resp.Body)
380 | defer resp.Body.Close()
381 | if err != nil {
382 | fmt.Printf("ioutil.ReadAll%v", err)
383 | }
384 |
385 | fmt.Println(string(respBytes))
386 | }
387 |
388 | /**
389 | * TODO 在config中设置secret, 与github_webhooks中的Post函数一起完成
390 | */
391 | func getPayloadOfRegisterGithubWebhooks() string {
392 | return `{
393 | "name": "web",
394 | "active": true,
395 | "events": [
396 | "push",
397 | "pull_request"
398 | ],
399 | "config": {
400 | "url": "http://114.115.206.8:8080/webhooks",
401 | "content_type": "json",
402 | "insecure_ssl": "0"
403 | }
404 | }`
405 | }
406 |
407 | func getWebhooksUrlBy(userName string, repoName string) string {
408 | return "https://api.github.com/repos/" + userName + "/" + repoName + "/hooks"
409 | }
410 |
411 | func GetGithubId(username string) int {
412 | api := "https://api.github.com/users/" + username
413 | client := &http.Client{}
414 | response, _ := client.Get(api)
415 | defer response.Body.Close()
416 | body, err_1 := ioutil.ReadAll(response.Body)
417 | if err_1 != nil {
418 | panic(err_1)
419 | }
420 | var res API_User
421 | json.Unmarshal(body, &res)
422 | fmt.Println(res.Id)
423 | return res.Id
424 | }
425 |
--------------------------------------------------------------------------------