updatepull/948/head
@@ -17,6 +17,7 @@ require ( | |||||
gitea.com/macaron/macaron v1.4.0 | gitea.com/macaron/macaron v1.4.0 | ||||
gitea.com/macaron/session v0.0.0-20191207215012-613cebf0674d | gitea.com/macaron/session v0.0.0-20191207215012-613cebf0674d | ||||
gitea.com/macaron/toolbox v0.0.0-20190822013122-05ff0fc766b7 | gitea.com/macaron/toolbox v0.0.0-20190822013122-05ff0fc766b7 | ||||
github.com/360EntSecGroup-Skylar/excelize/v2 v2.0.2 | |||||
github.com/BurntSushi/toml v0.3.1 | github.com/BurntSushi/toml v0.3.1 | ||||
github.com/PuerkitoBio/goquery v1.5.0 | github.com/PuerkitoBio/goquery v1.5.0 | ||||
github.com/RichardKnop/machinery v1.6.9 | github.com/RichardKnop/machinery v1.6.9 | ||||
@@ -107,7 +108,6 @@ require ( | |||||
github.com/unknwon/paginater v0.0.0-20151104151617-7748a72e0141 | github.com/unknwon/paginater v0.0.0-20151104151617-7748a72e0141 | ||||
github.com/urfave/cli v1.22.1 | github.com/urfave/cli v1.22.1 | ||||
github.com/xanzy/go-gitlab v0.31.0 | github.com/xanzy/go-gitlab v0.31.0 | ||||
github.com/360EntSecGroup-Skylar/excelize/v2 v2.0.2 | |||||
github.com/yohcop/openid-go v1.0.0 | github.com/yohcop/openid-go v1.0.0 | ||||
github.com/yuin/goldmark v1.1.27 | github.com/yuin/goldmark v1.1.27 | ||||
github.com/yuin/goldmark-meta v0.0.0-20191126180153-f0638e958b60 | github.com/yuin/goldmark-meta v0.0.0-20191126180153-f0638e958b60 | ||||
@@ -22,7 +22,6 @@ var customMigrations = []CustomMigration{ | |||||
} | } | ||||
var customMigrationsStatic = []CustomMigrationStatic{ | var customMigrationsStatic = []CustomMigrationStatic{ | ||||
{"Alter user static table field type ", alterUserStaticTable}, | |||||
{"Delete organization user history data ", deleteNotDisplayUser}, | {"Delete organization user history data ", deleteNotDisplayUser}, | ||||
{"update issue_fixed_rate to 1 if num_issues is 0 ", updateIssueFixedRate}, | {"update issue_fixed_rate to 1 if num_issues is 0 ", updateIssueFixedRate}, | ||||
} | } | ||||
@@ -59,14 +58,6 @@ func syncTopicStruct(x *xorm.Engine) error { | |||||
return err | return err | ||||
} | } | ||||
func alterUserStaticTable(x *xorm.Engine, static *xorm.Engine) error { | |||||
alterSql := "alter table public.user_business_analysis alter column open_i_index type double precision" | |||||
_, err := static.Exec(alterSql) | |||||
return err | |||||
} | |||||
func deleteNotDisplayUser(x *xorm.Engine, static *xorm.Engine) error { | func deleteNotDisplayUser(x *xorm.Engine, static *xorm.Engine) error { | ||||
querySQL := "select id,name from public.user where type=1" | querySQL := "select id,name from public.user where type=1" | ||||
@@ -172,3 +172,10 @@ func UpdateRepoStat(repoStat *RepoStatistic) error { | |||||
_, err := xStatistic.Exec(sql, repoStat.Impact, repoStat.Completeness, repoStat.Liveness, repoStat.ProjectHealth, repoStat.TeamHealth, repoStat.Growth, repoStat.RadarTotal, repoStat.RepoID, repoStat.Date) | _, err := xStatistic.Exec(sql, repoStat.Impact, repoStat.Completeness, repoStat.Liveness, repoStat.ProjectHealth, repoStat.TeamHealth, repoStat.Growth, repoStat.RadarTotal, repoStat.RepoID, repoStat.Date) | ||||
return err | return err | ||||
} | } | ||||
func UpdateRepoStatVisits(repoStat *RepoStatistic) error { | |||||
sql := "update repo_statistic set num_visits=? where repo_id=? and date=?" | |||||
_, err := xStatistic.Exec(sql, repoStat.NumVisits, repoStat.RepoID, repoStat.Date) | |||||
return err | |||||
} |
@@ -153,6 +153,76 @@ func getLastCountDate() int64 { | |||||
return pageStartTime.Unix() | return pageStartTime.Unix() | ||||
} | } | ||||
func QueryUserStaticDataAll(opts *UserBusinessAnalysisQueryOptions) ([]*UserBusinessAnalysis, int64) { | |||||
log.Info("query startTime =" + fmt.Sprint(opts.StartTime) + " endTime=" + fmt.Sprint(opts.EndTime) + " isAll=" + fmt.Sprint(opts.IsAll)) | |||||
statictisSess := xStatistic.NewSession() | |||||
defer statictisSess.Close() | |||||
resultMap := make(map[int64]*UserBusinessAnalysis) | |||||
var newAndCond = builder.NewCond() | |||||
if len(opts.UserName) > 0 { | |||||
newAndCond = newAndCond.And( | |||||
builder.Like{"name", opts.UserName}, | |||||
) | |||||
} | |||||
if !opts.IsAll { | |||||
newAndCond = newAndCond.And( | |||||
builder.Gte{"count_date": opts.StartTime}, | |||||
) | |||||
newAndCond = newAndCond.And( | |||||
builder.Lte{"count_date": opts.EndTime}, | |||||
) | |||||
} | |||||
allCount, err := statictisSess.Where(newAndCond).Count(new(UserBusinessAnalysis)) | |||||
if err != nil { | |||||
log.Info("query error." + err.Error()) | |||||
return nil, 0 | |||||
} | |||||
log.Info("query return total:" + fmt.Sprint(allCount)) | |||||
pageSize := 200 | |||||
totalPage := int(allCount) / pageSize | |||||
for i := 0; i <= int(totalPage); i++ { | |||||
userBusinessAnalysisList := make([]*UserBusinessAnalysis, 0) | |||||
if err := statictisSess.Table("user_business_analysis").Where(newAndCond).OrderBy("count_date desc").Limit(pageSize, i*pageSize). | |||||
Find(&userBusinessAnalysisList); err != nil { | |||||
return nil, 0 | |||||
} | |||||
log.Info("query " + fmt.Sprint(i+1) + " result size=" + fmt.Sprint(len(userBusinessAnalysisList))) | |||||
for _, userRecord := range userBusinessAnalysisList { | |||||
if _, ok := resultMap[userRecord.ID]; !ok { | |||||
resultMap[userRecord.ID] = userRecord | |||||
} else { | |||||
resultMap[userRecord.ID].CodeMergeCount += userRecord.CodeMergeCount | |||||
resultMap[userRecord.ID].CommitCount += userRecord.CommitCount | |||||
resultMap[userRecord.ID].IssueCount += userRecord.IssueCount | |||||
resultMap[userRecord.ID].CommentCount += userRecord.CommentCount | |||||
resultMap[userRecord.ID].FocusRepoCount += userRecord.FocusRepoCount | |||||
resultMap[userRecord.ID].StarRepoCount += userRecord.StarRepoCount | |||||
resultMap[userRecord.ID].WatchedCount += userRecord.WatchedCount | |||||
resultMap[userRecord.ID].CommitCodeSize += userRecord.CommitCodeSize | |||||
resultMap[userRecord.ID].CommitDatasetSize += userRecord.CommitDatasetSize | |||||
resultMap[userRecord.ID].CommitModelCount += userRecord.CommitModelCount | |||||
resultMap[userRecord.ID].SolveIssueCount += userRecord.SolveIssueCount | |||||
resultMap[userRecord.ID].EncyclopediasCount += userRecord.EncyclopediasCount | |||||
resultMap[userRecord.ID].CreateRepoCount += userRecord.CreateRepoCount | |||||
resultMap[userRecord.ID].LoginCount += userRecord.LoginCount | |||||
} | |||||
} | |||||
} | |||||
userBusinessAnalysisReturnList := UserBusinessAnalysisList{} | |||||
for _, v := range resultMap { | |||||
userBusinessAnalysisReturnList = append(userBusinessAnalysisReturnList, v) | |||||
} | |||||
sort.Sort(userBusinessAnalysisReturnList) | |||||
log.Info("return size=" + fmt.Sprint(len(userBusinessAnalysisReturnList))) | |||||
return userBusinessAnalysisReturnList, allCount | |||||
} | |||||
func QueryUserStaticDataPage(opts *UserBusinessAnalysisQueryOptions) ([]*UserBusinessAnalysis, int64) { | func QueryUserStaticDataPage(opts *UserBusinessAnalysisQueryOptions) ([]*UserBusinessAnalysis, int64) { | ||||
log.Info("query startTime =" + fmt.Sprint(opts.StartTime) + " endTime=" + fmt.Sprint(opts.EndTime) + " isAll=" + fmt.Sprint(opts.IsAll)) | log.Info("query startTime =" + fmt.Sprint(opts.StartTime) + " endTime=" + fmt.Sprint(opts.EndTime) + " isAll=" + fmt.Sprint(opts.IsAll)) | ||||
@@ -219,32 +289,43 @@ func QueryUserStaticDataPage(opts *UserBusinessAnalysisQueryOptions) ([]*UserBus | |||||
builder.Lte{"count_date": opts.EndTime}, | builder.Lte{"count_date": opts.EndTime}, | ||||
) | ) | ||||
} | } | ||||
userBusinessAnalysisList = make([]*UserBusinessAnalysis, 0) | |||||
if err := statictisSess.Table("user_business_analysis").Where(newAndCond).OrderBy("count_date desc"). | |||||
Find(&userBusinessAnalysisList); err != nil { | |||||
allCount, err := statictisSess.Where(newAndCond).Count(new(UserBusinessAnalysis)) | |||||
if err != nil { | |||||
log.Info("query error." + err.Error()) | |||||
return nil, 0 | return nil, 0 | ||||
} | } | ||||
} | |||||
log.Info("query result size=" + fmt.Sprint(len(userBusinessAnalysisList))) | |||||
for _, userRecord := range userBusinessAnalysisList { | |||||
if _, ok := resultMap[userRecord.ID]; !ok { | |||||
resultMap[userRecord.ID] = userRecord | |||||
} else { | |||||
resultMap[userRecord.ID].CodeMergeCount += userRecord.CodeMergeCount | |||||
resultMap[userRecord.ID].CommitCount += userRecord.CommitCount | |||||
resultMap[userRecord.ID].IssueCount += userRecord.IssueCount | |||||
resultMap[userRecord.ID].CommentCount += userRecord.CommentCount | |||||
resultMap[userRecord.ID].FocusRepoCount += userRecord.FocusRepoCount | |||||
resultMap[userRecord.ID].StarRepoCount += userRecord.StarRepoCount | |||||
resultMap[userRecord.ID].WatchedCount += userRecord.WatchedCount | |||||
resultMap[userRecord.ID].CommitCodeSize += userRecord.CommitCodeSize | |||||
resultMap[userRecord.ID].CommitDatasetSize += userRecord.CommitDatasetSize | |||||
resultMap[userRecord.ID].CommitModelCount += userRecord.CommitModelCount | |||||
resultMap[userRecord.ID].SolveIssueCount += userRecord.SolveIssueCount | |||||
resultMap[userRecord.ID].EncyclopediasCount += userRecord.EncyclopediasCount | |||||
resultMap[userRecord.ID].CreateRepoCount += userRecord.CreateRepoCount | |||||
resultMap[userRecord.ID].LoginCount += userRecord.LoginCount | |||||
pageSize := 1000 | |||||
totalPage := int(allCount) / pageSize | |||||
for i := 0; i <= int(totalPage); i++ { | |||||
userBusinessAnalysisList = make([]*UserBusinessAnalysis, 0) | |||||
if err := statictisSess.Table("user_business_analysis").Where(newAndCond).OrderBy("count_date desc").Limit(pageSize, i*pageSize). | |||||
Find(&userBusinessAnalysisList); err != nil { | |||||
return nil, 0 | |||||
} | |||||
log.Info("query result size=" + fmt.Sprint(len(userBusinessAnalysisList))) | |||||
for _, userRecord := range userBusinessAnalysisList { | |||||
if _, ok := resultMap[userRecord.ID]; !ok { | |||||
resultMap[userRecord.ID] = userRecord | |||||
} else { | |||||
resultMap[userRecord.ID].CodeMergeCount += userRecord.CodeMergeCount | |||||
resultMap[userRecord.ID].CommitCount += userRecord.CommitCount | |||||
resultMap[userRecord.ID].IssueCount += userRecord.IssueCount | |||||
resultMap[userRecord.ID].CommentCount += userRecord.CommentCount | |||||
resultMap[userRecord.ID].FocusRepoCount += userRecord.FocusRepoCount | |||||
resultMap[userRecord.ID].StarRepoCount += userRecord.StarRepoCount | |||||
resultMap[userRecord.ID].WatchedCount += userRecord.WatchedCount | |||||
resultMap[userRecord.ID].CommitCodeSize += userRecord.CommitCodeSize | |||||
resultMap[userRecord.ID].CommitDatasetSize += userRecord.CommitDatasetSize | |||||
resultMap[userRecord.ID].CommitModelCount += userRecord.CommitModelCount | |||||
resultMap[userRecord.ID].SolveIssueCount += userRecord.SolveIssueCount | |||||
resultMap[userRecord.ID].EncyclopediasCount += userRecord.EncyclopediasCount | |||||
resultMap[userRecord.ID].CreateRepoCount += userRecord.CreateRepoCount | |||||
resultMap[userRecord.ID].LoginCount += userRecord.LoginCount | |||||
} | |||||
} | |||||
} | } | ||||
} | } | ||||
@@ -4,6 +4,7 @@ import ( | |||||
"bytes" | "bytes" | ||||
"encoding/base64" | "encoding/base64" | ||||
"encoding/json" | "encoding/json" | ||||
"fmt" | |||||
"io/ioutil" | "io/ioutil" | ||||
"net/http" | "net/http" | ||||
@@ -113,13 +114,23 @@ func GetResultFromElk(resultInfo ResultInfo, jsonStr []byte) (loaded int, totalV | |||||
client := &http.Client{} | client := &http.Client{} | ||||
resp, err := client.Do(req) | resp, err := client.Do(req) | ||||
if err != nil { | if err != nil { | ||||
panic(err) | |||||
// panic(err) | |||||
return 0, 0, err | |||||
} | } | ||||
defer resp.Body.Close() | defer resp.Body.Close() | ||||
body, _ := ioutil.ReadAll(resp.Body) | |||||
errs := json.Unmarshal([]byte(string(body)), &resultInfo) | |||||
log.Info("Get resultJson failed", errs) | |||||
if resp.StatusCode != 200 { | |||||
log.Error("ConnectToElk failed:%s", resp.Status) | |||||
return 0, 0, fmt.Errorf("ConnectToElk failed:%s", resp.Status) | |||||
} | |||||
body, err := ioutil.ReadAll(resp.Body) | |||||
if err != nil { | |||||
return 0, 0, err | |||||
} | |||||
err = json.Unmarshal([]byte(string(body)), &resultInfo) | |||||
if err != nil { | |||||
log.Error("Get resultJson failed", err) | |||||
return 0, 0, err | |||||
} | |||||
return resultInfo.Result.Loaded, resultInfo.Result.RawResponse.Hits.Total, err | return resultInfo.Result.Loaded, resultInfo.Result.RawResponse.Hits.Total, err | ||||
} | } | ||||
@@ -138,6 +149,7 @@ func ProjectViewInit(User string, Project string, Gte string, Lte string) (proje | |||||
var timeRange Range | var timeRange Range | ||||
timeRange.Timestamptest.Gte = Gte | timeRange.Timestamptest.Gte = Gte | ||||
timeRange.Timestamptest.Lte = Lte | timeRange.Timestamptest.Lte = Lte | ||||
timeRange.Timestamptest.Format = "strict_date_optional_time" | |||||
inputStruct.Batch[0].Request.Params.Body.Query.BoolIn.Filter[0].Range = &timeRange | inputStruct.Batch[0].Request.Params.Body.Query.BoolIn.Filter[0].Range = &timeRange | ||||
//限定用户 | //限定用户 | ||||
var userName FilterMatchPhrase | var userName FilterMatchPhrase | ||||
@@ -208,9 +220,10 @@ func TagNameInit(MessageInfo string, Tagname string, Gte string, Lte string) (pr | |||||
//向elk发送请求,将获取的结果只保留访问量,输入是初始化后的数据结构,返回访问量 | //向elk发送请求,将获取的结果只保留访问量,输入是初始化后的数据结构,返回访问量 | ||||
func ViewInfo(viewInfo InputInfo) (totalView int, err error) { | func ViewInfo(viewInfo InputInfo) (totalView int, err error) { | ||||
jsons, errs := json.Marshal(viewInfo) | |||||
if errs != nil { | |||||
log.Info("errs:", errs) | |||||
jsons, err := json.Marshal(viewInfo) | |||||
if err != nil { | |||||
log.Error("jsons failed", err) | |||||
return 0, err | |||||
} | } | ||||
var jsonStr = []byte(jsons) | var jsonStr = []byte(jsons) | ||||
var resultInfo ResultInfo | var resultInfo ResultInfo | ||||
@@ -221,7 +234,6 @@ func ViewInfo(viewInfo InputInfo) (totalView int, err error) { | |||||
if loaded == 0 { | if loaded == 0 { | ||||
loaded_next, totalView, err := GetResultFromElk(resultInfo, jsonStr) | loaded_next, totalView, err := GetResultFromElk(resultInfo, jsonStr) | ||||
time++ | time++ | ||||
log.Info("time:", time) | |||||
if loaded_next != 0 && time < 100 { | if loaded_next != 0 && time < 100 { | ||||
return totalView, err | return totalView, err | ||||
} | } | ||||
@@ -816,6 +816,9 @@ total_count_get_error=查询总页数失败。 | |||||
last_update_time_error=查询最新更新时间失败。 | last_update_time_error=查询最新更新时间失败。 | ||||
get_repo_stat_error=查询当前仓库的统计信息失败。 | get_repo_stat_error=查询当前仓库的统计信息失败。 | ||||
get_repo_info_error=查询当前仓库信息失败。 | get_repo_info_error=查询当前仓库信息失败。 | ||||
generate_statistic_file_error=生成文件失败。 | |||||
repo_stat_inspect=项目分析 | |||||
all=所有 | |||||
modelarts.status=状态 | modelarts.status=状态 | ||||
modelarts.createtime=创建时间 | modelarts.createtime=创建时间 | ||||
@@ -529,6 +529,7 @@ func RegisterRoutes(m *macaron.Macaron) { | |||||
m.Get("/restoreFork", adminReq, repo.RestoreForkNumber) | m.Get("/restoreFork", adminReq, repo.RestoreForkNumber) | ||||
m.Get("/downloadAll", adminReq, repo.ServeAllProjectsPeriodStatisticsFile) | m.Get("/downloadAll", adminReq, repo.ServeAllProjectsPeriodStatisticsFile) | ||||
m.Get("/downloadAllOpenI", adminReq, repo.ServeAllProjectsOpenIStatisticsFile) | |||||
m.Group("/project", func() { | m.Group("/project", func() { | ||||
m.Get("", adminReq, repo.GetAllProjectsPeriodStatistics) | m.Get("", adminReq, repo.GetAllProjectsPeriodStatistics) | ||||
@@ -207,6 +207,71 @@ func ServeAllProjectsPeriodStatisticsFile(ctx *context.Context) { | |||||
} | } | ||||
func ServeAllProjectsOpenIStatisticsFile(ctx *context.Context) { | |||||
page := ctx.QueryInt("page") | |||||
if page <= 0 { | |||||
page = 1 | |||||
} | |||||
pageSize := 1000 | |||||
_, latestDate, err := models.GetRepoStatLastUpdatedTime() | |||||
if err != nil { | |||||
log.Error("Can not query the last updated time.", err) | |||||
ctx.Error(http.StatusBadRequest, ctx.Tr("repo.last_update_time_error")) | |||||
return | |||||
} | |||||
date := ctx.QueryTrim("date") | |||||
if date == "" { | |||||
date = latestDate | |||||
} | |||||
countSql := generateOpenICountSql(date) | |||||
total, err := models.CountRepoStatByRawSql(countSql) | |||||
if err != nil { | |||||
log.Error("Can not query total count.", err) | |||||
ctx.Error(http.StatusBadRequest, ctx.Tr("repo.total_count_get_error")) | |||||
return | |||||
} | |||||
var projectAnalysis = ctx.Tr("repo.repo_stat_inspect") | |||||
fileName := "项目分析_OPENI_" + date + ".xlsx" | |||||
totalPage := getTotalPage(total, pageSize) | |||||
f := excelize.NewFile() | |||||
index := f.NewSheet(projectAnalysis) | |||||
f.DeleteSheet("Sheet1") | |||||
for k, v := range allProjectsOpenIHeader() { | |||||
f.SetCellValue(projectAnalysis, k, v) | |||||
} | |||||
var row = 2 | |||||
for i := 0; i <= totalPage; i++ { | |||||
pageRecords := models.GetRepoStatisticByRawSql(generateTypeAllOpenISql(date, i+1, pageSize)) | |||||
for _, record := range pageRecords { | |||||
for k, v := range allProjectsOpenIValues(row, record, ctx) { | |||||
f.SetCellValue(projectAnalysis, k, v) | |||||
} | |||||
row++ | |||||
} | |||||
} | |||||
f.SetActiveSheet(index) | |||||
ctx.Resp.Header().Set("Content-Disposition", "attachment; filename="+url.QueryEscape(fileName)) | |||||
ctx.Resp.Header().Set("Content-Type", "application/octet-stream") | |||||
f.WriteTo(ctx.Resp) | |||||
} | |||||
func getFileName(ctx *context.Context, beginTime time.Time, endTime time.Time, projectAnalysis string) string { | func getFileName(ctx *context.Context, beginTime time.Time, endTime time.Time, projectAnalysis string) string { | ||||
baseName := projectAnalysis + "_" | baseName := projectAnalysis + "_" | ||||
@@ -237,6 +302,32 @@ func allProjectsPeroidValues(row int, rs *models.RepoStatistic, ctx *context.Con | |||||
} | } | ||||
} | } | ||||
func allProjectsOpenIHeader() map[string]string { | |||||
return map[string]string{"A1": "ID", "B1": "项目名称", "C1": "拥有者", "D1": "是否私有", "E1": "OpenI指数", | |||||
"F1": "影响力", "G1": "成熟度", "H1": "活跃度", "I1": "项目健康度", "J1": "团队健康度", "K1": "项目发展趋势", | |||||
"L1": "关注数", "M1": "点赞数", "N1": "派生数", "O1": "代码下载量", "P1": "评论数", "Q1": "浏览量", "R1": "已解决任务数", "S1": "版本发布数量", "T1": "有效开发年龄", | |||||
"U1": "数据集", "V1": "模型数", "W1": "百科页面数量", "X1": "提交数", "Y1": "任务数", "Z1": "PR数", "AA1": "版本发布数量", "AB1": "任务完成比例", "AC1": "贡献者数", "AD1": "关键贡献者数", | |||||
"AE1": "新人增长量", "AF1": "代码规模增长量", "AG1": "任务增长量", "AH1": "新人增长量", "AI1": "提交增长量", "AJ1": "评论增长量", | |||||
} | |||||
} | |||||
func allProjectsOpenIValues(row int, rs *models.RepoStatistic, ctx *context.Context) map[string]string { | |||||
return map[string]string{getCellName("A", row): strconv.FormatInt(rs.RepoID, 10), getCellName("B", row): rs.Name, getCellName("C", row): rs.OwnerName, getCellName("D", row): getIsPrivateDisplay(rs.IsPrivate, ctx), getCellName("E", row): strconv.FormatFloat(rs.RadarTotal, 'f', 2, 64), | |||||
getCellName("F", row): strconv.FormatFloat(rs.Impact, 'f', 2, 64), getCellName("G", row): strconv.FormatFloat(rs.Completeness, 'f', 2, 64), getCellName("H", row): strconv.FormatFloat(rs.Liveness, 'f', 2, 64), getCellName("I", row): strconv.FormatFloat(rs.ProjectHealth, 'f', 2, 64), getCellName("J", row): strconv.FormatFloat(rs.TeamHealth, 'f', 2, 64), getCellName("K", row): strconv.FormatFloat(rs.Growth, 'f', 2, 64), | |||||
getCellName("L", row): strconv.FormatInt(rs.NumWatches, 10), getCellName("M", row): strconv.FormatInt(rs.NumStars, 10), getCellName("N", row): strconv.FormatInt(rs.NumForks, 10), getCellName("O", row): strconv.FormatInt(rs.NumDownloads, 10), | |||||
getCellName("P", row): strconv.FormatInt(rs.NumComments, 10), getCellName("Q", row): strconv.FormatInt(rs.NumVisits, 10), getCellName("R", row): strconv.FormatInt(rs.NumClosedIssues, 10), getCellName("S", row): strconv.FormatInt(rs.NumVersions, 10), | |||||
getCellName("T", row): strconv.FormatInt(rs.NumDevMonths, 10), getCellName("U", row): strconv.FormatInt(rs.DatasetSize, 10), getCellName("V", row): strconv.FormatInt(rs.NumModels, 10), getCellName("W", row): strconv.FormatInt(rs.NumWikiViews, 10), | |||||
getCellName("X", row): strconv.FormatInt(rs.NumCommits, 10), getCellName("Y", row): strconv.FormatInt(rs.NumIssues, 10), getCellName("Z", row): strconv.FormatInt(rs.NumPulls, 10), getCellName("AA", row): strconv.FormatInt(rs.NumVersions, 10), | |||||
getCellName("AB", row): strconv.FormatFloat(float64(rs.IssueFixedRate), 'f', 2, 64), getCellName("AC", row): strconv.FormatInt(rs.NumContributor, 10), getCellName("AD", row): strconv.FormatInt(rs.NumKeyContributor, 10), getCellName("AE", row): strconv.FormatInt(rs.NumContributorsGrowth, 10), | |||||
getCellName("AF", row): strconv.FormatInt(rs.NumCommitLinesGrowth, 10), getCellName("AG", row): strconv.FormatInt(rs.NumIssuesGrowth, 10), getCellName("AH", row): strconv.FormatInt(rs.NumContributorsGrowth, 10), getCellName("AI", row): strconv.FormatInt(rs.NumCommitsGrowth, 10), getCellName("AJ", row): strconv.FormatInt(rs.NumCommentsGrowth, 10), | |||||
} | |||||
} | |||||
func getCellName(col string, row int) string { | func getCellName(col string, row int) string { | ||||
return col + strconv.Itoa(row) | return col + strconv.Itoa(row) | ||||
} | } | ||||
@@ -381,6 +472,13 @@ func generateCountSql(beginTime time.Time, endTime time.Time, latestDate string, | |||||
return countSql | return countSql | ||||
} | } | ||||
func generateOpenICountSql(latestDate string) string { | |||||
countSql := "SELECT count(*) FROM " + | |||||
"public.repo_statistic where date='" + latestDate + "'" | |||||
return countSql | |||||
} | |||||
func generateTypeAllSql(beginTime time.Time, endTime time.Time, latestDate string, q string, orderBy string, page int, pageSize int) string { | func generateTypeAllSql(beginTime time.Time, endTime time.Time, latestDate string, q string, orderBy string, page int, pageSize int) string { | ||||
sql := "SELECT A.repo_id,name,owner_name,is_private,radar_total,num_watches,num_visits,num_downloads,num_pulls,num_commits,num_stars,num_forks,num_issues,num_closed_issues,num_contributor FROM " + | sql := "SELECT A.repo_id,name,owner_name,is_private,radar_total,num_watches,num_visits,num_downloads,num_pulls,num_commits,num_stars,num_forks,num_issues,num_closed_issues,num_contributor FROM " + | ||||
"(SELECT repo_id,sum(num_visits) as num_visits " + | "(SELECT repo_id,sum(num_visits) as num_visits " + | ||||
@@ -396,6 +494,14 @@ func generateTypeAllSql(beginTime time.Time, endTime time.Time, latestDate strin | |||||
return sql | return sql | ||||
} | } | ||||
func generateTypeAllOpenISql(latestDate string, page int, pageSize int) string { | |||||
sql := "SELECT id, repo_id, date, num_watches, num_stars, num_forks, num_downloads, num_comments, num_visits, num_closed_issues, num_versions, num_dev_months, repo_size, dataset_size, num_models, num_wiki_views, num_commits, num_issues, num_pulls, issue_fixed_rate, num_contributor, num_key_contributor, num_contributors_growth, num_commits_growth, num_commit_lines_growth, num_issues_growth, num_comments_growth, impact, completeness, liveness, project_health, team_health, growth, radar_total, name, is_private, owner_name FROM " + | |||||
" public.repo_statistic where date='" + latestDate + "'" | |||||
sql = sql + " order by radar_total desc,repo_id" + " limit " + strconv.Itoa(pageSize) + " offset " + strconv.Itoa((page-1)*pageSize) | |||||
return sql | |||||
} | |||||
func generatePageSql(beginTime time.Time, endTime time.Time, latestDate string, q string, orderBy string, page int, pageSize int) string { | func generatePageSql(beginTime time.Time, endTime time.Time, latestDate string, q string, orderBy string, page int, pageSize int) string { | ||||
sql := "SELECT A.repo_id,name,owner_name,is_private,radar_total,num_watches,num_visits,num_downloads,num_pulls,num_commits,num_stars,num_forks,num_issues,num_closed_issues,num_contributor FROM " + | sql := "SELECT A.repo_id,name,owner_name,is_private,radar_total,num_watches,num_visits,num_downloads,num_pulls,num_commits,num_stars,num_forks,num_issues,num_closed_issues,num_contributor FROM " + | ||||
@@ -43,7 +43,8 @@ func RegisterRoutes(m *macaron.Macaron) { | |||||
m.Post("/manager/restart", Restart) | m.Post("/manager/restart", Restart) | ||||
m.Post("/manager/flush-queues", bind(private.FlushOptions{}), FlushQueues) | m.Post("/manager/flush-queues", bind(private.FlushOptions{}), FlushQueues) | ||||
m.Post("/tool/update_all_repo_commit_cnt", UpdateAllRepoCommitCnt) | m.Post("/tool/update_all_repo_commit_cnt", UpdateAllRepoCommitCnt) | ||||
m.Post("/tool/repo_stat", RepoStatisticManually) | |||||
m.Post("/tool/repo_stat/:date", RepoStatisticManually) | |||||
m.Post("/tool/update_repo_visit/:date", UpdateRepoVisit) | |||||
}, CheckInternalToken) | }, CheckInternalToken) | ||||
} | } |
@@ -39,8 +39,35 @@ func UpdateAllRepoCommitCnt(ctx *macaron.Context) { | |||||
} | } | ||||
func RepoStatisticManually(ctx *macaron.Context) { | func RepoStatisticManually(ctx *macaron.Context) { | ||||
date := ctx.Query("date") | |||||
date := ctx.Params("date") | |||||
repo.RepoStatisticDaily(date) | repo.RepoStatisticDaily(date) | ||||
repo.SummaryStatisticDaily(date) | repo.SummaryStatisticDaily(date) | ||||
repo.TimingCountDataByDate(date) | repo.TimingCountDataByDate(date) | ||||
} | } | ||||
func UpdateRepoVisit(ctx *macaron.Context) { | |||||
date := ctx.Params("date") | |||||
log.Info("date(%s)", date) | |||||
repos, err := models.GetAllRepositories() | |||||
if err != nil { | |||||
log.Error("GetAllRepositories failed:%v", err.Error(), ctx.Data["MsgID"]) | |||||
ctx.JSON(http.StatusInternalServerError, map[string]string{ | |||||
"error_msg": "GetAllRepositories failed", | |||||
}) | |||||
return | |||||
} | |||||
for i, repoStat := range repos { | |||||
log.Info("%d:begin UpdateRepoVisits(id = %d, name = %s)", i, repoStat.ID, repoStat.Name) | |||||
if err = repo.UpdateRepoVisits(ctx, repoStat, date); err != nil { | |||||
log.Error("UpdateRepoVisits(id = %d, name = %s) failed:%v", repoStat.ID, repoStat.Name, err.Error()) | |||||
continue | |||||
} | |||||
log.Info("%d:finish UpdateRepoVisits(id = %d, name = %s)", i, repoStat.ID, repoStat.Name) | |||||
} | |||||
ctx.JSON(http.StatusOK, map[string]string{ | |||||
"error_msg": "", | |||||
}) | |||||
} |
@@ -1,15 +1,17 @@ | |||||
package repo | package repo | ||||
import ( | import ( | ||||
"errors" | |||||
"time" | "time" | ||||
"code.gitea.io/gitea/services/mailer" | |||||
"code.gitea.io/gitea/models" | "code.gitea.io/gitea/models" | ||||
"code.gitea.io/gitea/modules/log" | "code.gitea.io/gitea/modules/log" | ||||
"code.gitea.io/gitea/modules/normalization" | "code.gitea.io/gitea/modules/normalization" | ||||
"code.gitea.io/gitea/modules/repository" | "code.gitea.io/gitea/modules/repository" | ||||
"code.gitea.io/gitea/modules/setting" | "code.gitea.io/gitea/modules/setting" | ||||
"code.gitea.io/gitea/services/mailer" | |||||
"gitea.com/macaron/macaron" | |||||
) | ) | ||||
func StatisticAuto() { | func StatisticAuto() { | ||||
@@ -48,7 +50,7 @@ func RepoStatisticDaily(date string) { | |||||
var maxRepoRadar models.RepoStatistic | var maxRepoRadar models.RepoStatistic | ||||
for i, repo := range repos { | for i, repo := range repos { | ||||
log.Info("start statistic: %s", repo.Name) | |||||
log.Info("start statistic: %s", getDistinctProjectName(repo)) | |||||
var numDevMonths, numWikiViews, numContributor, numKeyContributor, numCommitsGrowth, numCommitLinesGrowth, numContributorsGrowth int64 | var numDevMonths, numWikiViews, numContributor, numKeyContributor, numCommitsGrowth, numCommitLinesGrowth, numContributorsGrowth int64 | ||||
repoGitStat, err := models.GetRepoKPIStats(repo) | repoGitStat, err := models.GetRepoKPIStats(repo) | ||||
if err != nil { | if err != nil { | ||||
@@ -230,7 +232,7 @@ func RepoStatisticDaily(date string) { | |||||
} | } | ||||
log.Info("finish statistic: %s", repo.Name) | |||||
log.Info("finish statistic: %s", getDistinctProjectName(repo)) | |||||
} | } | ||||
//radar map | //radar map | ||||
@@ -274,3 +276,29 @@ func getStatTime(timeStr string) (string, string) { | |||||
return beginTime, endTime | return beginTime, endTime | ||||
} | } | ||||
func UpdateRepoVisits(ctx *macaron.Context, repo *models.Repository, date string) error { | |||||
beginTime, endTime := getStatTime(date) | |||||
var numVisits int | |||||
numVisits, err := repository.AppointProjectView(repo.OwnerName, repo.Name, beginTime, endTime) | |||||
if err != nil { | |||||
log.Error("AppointProjectView failed(%s): %v", getDistinctProjectName(repo), err) | |||||
return err | |||||
} | |||||
repoStat, err := models.GetRepoStatisticByDate(date, repo.ID) | |||||
if err != nil { | |||||
log.Error("GetRepoStatisticByDate failed(%s): %v", getDistinctProjectName(repo), err) | |||||
return err | |||||
} else if len(repoStat) != 1 { | |||||
log.Error("GetRepoStatisticByDate failed(%s): %v", getDistinctProjectName(repo), err) | |||||
return errors.New("not find repo") | |||||
} | |||||
repoStat[0].NumVisits = int64(numVisits) | |||||
if err = models.UpdateRepoStatVisits(repoStat[0]); err != nil { | |||||
log.Error("UpdateRepoStatVisits failed(%s): %v", getDistinctProjectName(repo), err) | |||||
return err | |||||
} | |||||
return nil | |||||
} |
@@ -49,13 +49,13 @@ func QueryUserStaticDataPage(ctx *context.Context) { | |||||
startTime = time.Now() | startTime = time.Now() | ||||
endTime = time.Now() | endTime = time.Now() | ||||
} else { | } else { | ||||
startTime, _ = time.Parse("2006-01-02", startDate) | |||||
startTime, _ = time.ParseInLocation("2006-01-02", startDate, time.Local) | |||||
settingStartTime, _ := time.Parse("2006-01-02", setting.RadarMap.RecordBeginTime) | settingStartTime, _ := time.Parse("2006-01-02", setting.RadarMap.RecordBeginTime) | ||||
if startTime.Unix() < settingStartTime.Unix() { | if startTime.Unix() < settingStartTime.Unix() { | ||||
startTime = settingStartTime | startTime = settingStartTime | ||||
startDate = settingStartTime.Format("2006-01-02") | startDate = settingStartTime.Format("2006-01-02") | ||||
} | } | ||||
endTime, _ = time.Parse("2006-01-02", endDate) | |||||
endTime, _ = time.ParseInLocation("2006-01-02", endDate, time.Local) | |||||
endTime = endTime.AddDate(0, 0, 1) | endTime = endTime.AddDate(0, 0, 1) | ||||
isAll = false | isAll = false | ||||
log.Info("startTime=" + fmt.Sprint(startTime.Unix()) + " endDate=" + fmt.Sprint(endTime.Unix())) | log.Info("startTime=" + fmt.Sprint(startTime.Unix()) + " endDate=" + fmt.Sprint(endTime.Unix())) | ||||
@@ -76,17 +76,15 @@ func QueryUserStaticDataPage(ctx *context.Context) { | |||||
EndTime: endTime.Unix(), | EndTime: endTime.Unix(), | ||||
IsAll: isAll, | IsAll: isAll, | ||||
} | } | ||||
mapInterface := make(map[string]interface{}) | |||||
re, count := models.QueryUserStaticDataPage(pageOpts) | |||||
mapInterface["data"] = re | |||||
mapInterface["count"] = count | |||||
if IsReturnFile { | if IsReturnFile { | ||||
re, count := models.QueryUserStaticDataAll(pageOpts) | |||||
log.Info("return count=" + fmt.Sprint(count)) | |||||
//writer exec file. | //writer exec file. | ||||
xlsx := excelize.NewFile() | xlsx := excelize.NewFile() | ||||
xlsx.DeleteSheet("Sheet1") | |||||
sheetName := ctx.Tr("user.static.sheetname") | sheetName := ctx.Tr("user.static.sheetname") | ||||
index := xlsx.NewSheet(sheetName) | index := xlsx.NewSheet(sheetName) | ||||
xlsx.DeleteSheet("Sheet1") | |||||
dataHeader := map[string]string{ | dataHeader := map[string]string{ | ||||
"A1": ctx.Tr("user.static.id"), | "A1": ctx.Tr("user.static.id"), | ||||
"B1": ctx.Tr("user.static.name"), | "B1": ctx.Tr("user.static.name"), | ||||
@@ -129,8 +127,12 @@ func QueryUserStaticDataPage(ctx *context.Context) { | |||||
xlsx.SetCellValue(sheetName, "M"+rows, userRecord.EncyclopediasCount) | xlsx.SetCellValue(sheetName, "M"+rows, userRecord.EncyclopediasCount) | ||||
xlsx.SetCellValue(sheetName, "N"+rows, userRecord.CreateRepoCount) | xlsx.SetCellValue(sheetName, "N"+rows, userRecord.CreateRepoCount) | ||||
xlsx.SetCellValue(sheetName, "O"+rows, fmt.Sprintf("%.2f", userRecord.OpenIIndex)) | xlsx.SetCellValue(sheetName, "O"+rows, fmt.Sprintf("%.2f", userRecord.OpenIIndex)) | ||||
xlsx.SetCellValue(sheetName, "P"+rows, userRecord.RegistDate.Format("2006-01-02")) | |||||
xlsx.SetCellValue(sheetName, "Q"+rows, time.Unix(userRecord.CountDate, 0).Format("2006-01-02")) | |||||
formatTime := userRecord.RegistDate.Format("2006-01-02 15:04:05") | |||||
xlsx.SetCellValue(sheetName, "P"+rows, formatTime[0:len(formatTime)-3]) | |||||
formatTime = time.Unix(userRecord.CountDate, 0).Format("2006-01-02 15:04:05") | |||||
xlsx.SetCellValue(sheetName, "Q"+rows, formatTime[0:len(formatTime)-3]) | |||||
} | } | ||||
//设置默认打开的表单 | //设置默认打开的表单 | ||||
@@ -160,6 +162,10 @@ func QueryUserStaticDataPage(ctx *context.Context) { | |||||
} | } | ||||
} else { | } else { | ||||
mapInterface := make(map[string]interface{}) | |||||
re, count := models.QueryUserStaticDataPage(pageOpts) | |||||
mapInterface["data"] = re | |||||
mapInterface["count"] = count | |||||
ctx.JSON(http.StatusOK, mapInterface) | ctx.JSON(http.StatusOK, mapInterface) | ||||
} | } | ||||
} | } | ||||
@@ -0,0 +1,42 @@ | |||||
<footer> | |||||
<div class="ui fluid container" style="padding: 0px 10px;"> | |||||
<div class="ui grid"> | |||||
<div class="sixteen wide mobile eight wide tablet eight wide computer column"> | |||||
<div class="ui three column grid"> | |||||
<div class="column ui vertical text menu"> | |||||
<div class="header item">{{.i18n.Tr "custom.head.community"}}</div> | |||||
<a href="https://openi.org.cn/html/Club/2019/0227/14.html" class="item">{{.i18n.Tr "custom.foot.council"}}</a> | |||||
<a href="https://openi.org.cn/html/Club/2019/0227/14.html" class="item">{{.i18n.Tr "custom.foot.technical_committee"}}</a> | |||||
<a href="https://openi.org.cn/html/Club/2019/0228/17.html" class="item">{{.i18n.Tr "custom.foot.join"}}</a> | |||||
</div> | |||||
<div class="column ui vertical text menu"> | |||||
<div class="header item">{{.i18n.Tr "custom.foot.news"}}</div> | |||||
<a href="https://openi.org.cn/html/news/dongtai/" class="item">{{.i18n.Tr "custom.foot.community_news"}}</a> | |||||
<a href="https://openi.org.cn/html/news/huodong/" class="item">{{.i18n.Tr "custom.foot.member_news"}}</a> | |||||
<a href="https://openi.org.cn/html/news/zixun/" class="item">{{.i18n.Tr "custom.foot.industry_advisory"}}</a> | |||||
</div> | |||||
<div class="column ui vertical text menu"> | |||||
<div class="header item">{{.i18n.Tr "custom.foot.help"}}</div> | |||||
<div class="ui language bottom floating slide up dropdown link item"> | |||||
<i class="world icon"></i> | |||||
<div class="text">{{.LangName}}</div> | |||||
<div class="menu"> | |||||
{{range .AllLangs}} | |||||
<a lang="{{.Lang}}" class="item {{if eq $.Lang .Lang}}active selected{{end}}" href="{{if eq $.Lang .Lang}}#{{else}}{{$.Link}}?lang={{.Lang}}{{end}}">{{.Name}}</a> | |||||
{{end}} | |||||
</div> | |||||
</div> | |||||
{{if .EnableSwagger}}<a href="/api/swagger" class="ui item">API</a>{{end}} | |||||
{{template "custom/extra_links_footer" .}} | |||||
</div> | |||||
</div> | |||||
</div> | |||||
<div class="sixteen wide mobile eight wide tablet eight wide computer column" style=" margin:2.0rem 0"> | |||||
{{.i18n.Tr "custom.foot.copyright"}} <a href="http://beian.miit.gov.cn/" target="_blank">京ICP备18004880号</a> | |||||
<br> | |||||
{{.i18n.Tr "Powered_by 鹏城实验室云脑、"}}<a href="https://www.trustie.net/" target="_blank">Trustie确实</a>{{.i18n.Tr "、gitea"}} | |||||
<br> | |||||
</div> | |||||
</div> | |||||
</div> | |||||
</footer> |
@@ -0,0 +1,48 @@ | |||||
{{/* | |||||
<html> | |||||
<body> | |||||
<div> | |||||
*/}} | |||||
{{template "custom/body_inner_post" .}} | |||||
</div> | |||||
{{template "custom/body_outer_post" .}} | |||||
{{template "base/footer_content_fluid" .}} | |||||
<script src="{{StaticUrlPrefix}}/js/jquery.js?v={{MD5 AppVer}}"></script> | |||||
{{if .RequireSimpleMDE}} | |||||
<script src="{{StaticUrlPrefix}}/vendor/plugins/simplemde/simplemde.min.js"></script> | |||||
<script src="{{StaticUrlPrefix}}/vendor/plugins/codemirror/addon/mode/loadmode.js"></script> | |||||
<script src="{{StaticUrlPrefix}}/vendor/plugins/codemirror/mode/meta.js"></script> | |||||
<script> | |||||
CodeMirror.modeURL = "{{StaticUrlPrefix}}/vendor/plugins/codemirror/mode/%N/%N.js"; | |||||
</script> | |||||
{{end}} | |||||
<!-- Third-party libraries --> | |||||
{{if .RequireMinicolors}} | |||||
<script src="{{StaticUrlPrefix}}/vendor/plugins/jquery.minicolors/jquery.minicolors.min.js"></script> | |||||
{{end}} | |||||
{{if .RequireU2F}} | |||||
<script src="{{StaticUrlPrefix}}/vendor/plugins/u2f/index.js"></script> | |||||
{{end}} | |||||
{{if .EnableCaptcha}} | |||||
{{if eq .CaptchaType "recaptcha"}} | |||||
<script src='{{ URLJoin .RecaptchaURL "api.js"}}' async></script> | |||||
{{end}} | |||||
{{end}} | |||||
{{if .RequireTribute}} | |||||
<script src="{{StaticUrlPrefix}}/vendor/plugins/tribute/tribute.min.js"></script> | |||||
{{end}} | |||||
{{if .PageIsHome}} | |||||
<script rel="stylesheet" src="{{StaticUrlPrefix}}/vendor/plugins/jquery.particleground/jquery.particleground.min.js"></script> | |||||
{{end}} | |||||
<script src="{{StaticUrlPrefix}}/fomantic/semantic.min.js?v={{MD5 AppVer}}"></script> | |||||
<script src="{{StaticUrlPrefix}}/js/index.js?v={{MD5 AppVer}}"></script> | |||||
{{template "custom/footer" .}} | |||||
</body> | |||||
</html> | |||||
@@ -0,0 +1,208 @@ | |||||
<!DOCTYPE html> | |||||
<html lang="{{.Language}}"> | |||||
<head data-suburl="{{AppSubUrl}}"> | |||||
<meta charset="utf-8"> | |||||
<meta name="viewport" content="width=device-width, initial-scale=1"> | |||||
<meta http-equiv="x-ua-compatible" content="ie=edge"> | |||||
<title>{{if .Title}}{{.Title}} - {{end}} {{if .Repository.Name}}{{.Repository.Name}} - {{end}}{{AppName}}</title> | |||||
<link rel="manifest" href="{{AppSubUrl}}/manifest.json" crossorigin="use-credentials"> | |||||
{{if UseServiceWorker}} | |||||
<script> | |||||
if ('serviceWorker' in navigator) { | |||||
navigator.serviceWorker.register('{{AppSubUrl}}/serviceworker.js').then(function(registration) { | |||||
// Registration was successful | |||||
console.info('ServiceWorker registration successful with scope: ', registration.scope); | |||||
}, function(err) { | |||||
// registration failed :( | |||||
console.info('ServiceWorker registration failed: ', err); | |||||
}); | |||||
} | |||||
</script> | |||||
{{else}} | |||||
<script> | |||||
if ('serviceWorker' in navigator) { | |||||
navigator.serviceWorker.getRegistrations().then(function(registrations) { | |||||
registrations.forEach(function(registration) { | |||||
registration.unregister(); | |||||
console.info('ServiceWorker unregistered'); | |||||
}); | |||||
}); | |||||
} | |||||
</script> | |||||
{{end}} | |||||
<meta name="theme-color" content="{{ThemeColorMetaTag}}"> | |||||
<meta name="author" content="{{if .Repository}}{{.Owner.Name}}{{else}}{{MetaAuthor}}{{end}}" /> | |||||
<meta name="description" content="{{if .Repository}}{{.Repository.Name}}{{if .Repository.Description}} - {{.Repository.Description}}{{end}}{{else}}{{MetaDescription}}{{end}}" /> | |||||
<meta name="keywords" content="{{MetaKeywords}}"> | |||||
<meta name="referrer" content="no-referrer" /> | |||||
<meta name="_csrf" content="{{.CsrfToken}}" /> | |||||
{{if .IsSigned}} | |||||
<meta name="_uid" content="{{.SignedUser.ID}}" /> | |||||
{{end}} | |||||
{{if .ContextUser}} | |||||
<meta name="_context_uid" content="{{.ContextUser.ID}}" /> | |||||
{{end}} | |||||
{{if .SearchLimit}} | |||||
<meta name="_search_limit" content="{{.SearchLimit}}" /> | |||||
{{end}} | |||||
{{if .GoGetImport}} | |||||
<meta name="go-import" content="{{.GoGetImport}} git {{.CloneLink.HTTPS}}"> | |||||
<meta name="go-source" content="{{.GoGetImport}} _ {{.GoDocDirectory}} {{.GoDocFile}}"> | |||||
{{end}} | |||||
<script> | |||||
{{SafeJS `/* | |||||
@licstart The following is the entire license notice for the | |||||
JavaScript code in this page. | |||||
Copyright (c) 2016 The Gitea Authors | |||||
Copyright (c) 2015 The Gogs Authors | |||||
Permission is hereby granted, free of charge, to any person obtaining a copy | |||||
of this software and associated documentation files (the "Software"), to deal | |||||
in the Software without restriction, including without limitation the rights | |||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | |||||
copies of the Software, and to permit persons to whom the Software is | |||||
furnished to do so, subject to the following conditions: | |||||
The above copyright notice and this permission notice shall be included in | |||||
all copies or substantial portions of the Software. | |||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | |||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | |||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | |||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | |||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | |||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN | |||||
THE SOFTWARE. | |||||
--- | |||||
Licensing information for additional javascript libraries can be found at: | |||||
{{StaticUrlPrefix}}/vendor/librejs.html | |||||
@licend The above is the entire license notice | |||||
for the JavaScript code in this page. | |||||
*/`}} | |||||
</script> | |||||
<script> | |||||
window.config = { | |||||
AppSubUrl: '{{AppSubUrl}}', | |||||
StaticUrlPrefix: '{{StaticUrlPrefix}}', | |||||
csrf: '{{.CsrfToken}}', | |||||
HighlightJS: {{if .RequireHighlightJS}}true{{else}}false{{end}}, | |||||
Minicolors: {{if .RequireMinicolors}}true{{else}}false{{end}}, | |||||
SimpleMDE: {{if .RequireSimpleMDE}}true{{else}}false{{end}}, | |||||
Tribute: {{if .RequireTribute}}true{{else}}false{{end}}, | |||||
U2F: {{if .RequireU2F}}true{{else}}false{{end}}, | |||||
Heatmap: {{if .EnableHeatmap}}true{{else}}false{{end}}, | |||||
heatmapUser: {{if .HeatmapUser}}'{{.HeatmapUser}}'{{else}}null{{end}}, | |||||
NotificationSettings: { | |||||
MinTimeout: {{NotificationSettings.MinTimeout}}, | |||||
TimeoutStep: {{NotificationSettings.TimeoutStep}}, | |||||
MaxTimeout: {{NotificationSettings.MaxTimeout}}, | |||||
EventSourceUpdateTime: {{NotificationSettings.EventSourceUpdateTime}}, | |||||
}, | |||||
{{if .RequireTribute}} | |||||
tributeValues: [ | |||||
{{ range .Assignees }} | |||||
{key: '{{.Name}} {{.FullName}}', value: '{{.Name}}', | |||||
name: '{{.Name}}', fullname: '{{.FullName}}', avatar: '{{.RelAvatarLink}}'}, | |||||
{{ end }} | |||||
], | |||||
{{end}} | |||||
}; | |||||
</script> | |||||
<link rel="shortcut icon" href="{{StaticUrlPrefix}}/img/favicon.png"> | |||||
<link rel="mask-icon" href="{{StaticUrlPrefix}}/img/openi-safari.svg" color="#609926"> | |||||
<link rel="fluid-icon" href="{{StaticUrlPrefix}}/img/gitea-lg.png" title="{{AppName}}"> | |||||
<link rel="stylesheet" href="{{StaticUrlPrefix}}/vendor/assets/font-awesome/css/font-awesome.min.css"> | |||||
<link rel="preload" as="font" href="{{StaticUrlPrefix}}/fomantic/themes/default/assets/fonts/icons.woff2" type="font/woff2" crossorigin="anonymous"> | |||||
<link rel="preload" as="font" href="{{StaticUrlPrefix}}/fomantic/themes/default/assets/fonts/outline-icons.woff2" type="font/woff2" crossorigin="anonymous"> | |||||
{{if .RequireSimpleMDE}} | |||||
<link rel="stylesheet" href="{{StaticUrlPrefix}}/vendor/plugins/simplemde/simplemde.min.css"> | |||||
{{end}} | |||||
{{if .RequireTribute}} | |||||
<link rel="stylesheet" href="{{StaticUrlPrefix}}/vendor/plugins/tribute/tribute.css"> | |||||
{{end}} | |||||
<link rel="stylesheet" href="{{StaticUrlPrefix}}/fomantic/semantic.min.css?v={{MD5 AppVer}}"> | |||||
<link rel="stylesheet" href="{{StaticUrlPrefix}}/css/index.css?v={{MD5 AppVer}}"> | |||||
<noscript> | |||||
<style> | |||||
.dropdown:hover > .menu { display: block; } | |||||
.ui.secondary.menu .dropdown.item > .menu { margin-top: 0; } | |||||
</style> | |||||
</noscript> | |||||
{{if .RequireMinicolors}} | |||||
<link rel="stylesheet" href="{{StaticUrlPrefix}}/vendor/plugins/jquery.minicolors/jquery.minicolors.css"> | |||||
{{end}} | |||||
<style class="list-search-style"></style> | |||||
{{if .PageIsUserProfile}} | |||||
<meta property="og:title" content="{{.Owner.Name}}" /> | |||||
<meta property="og:type" content="profile" /> | |||||
<meta property="og:image" content="{{.Owner.AvatarLink}}" /> | |||||
<meta property="og:url" content="{{.Owner.HTMLURL}}" /> | |||||
{{if .Owner.Description}} | |||||
<meta property="og:description" content="{{.Owner.Description}}"> | |||||
{{end}} | |||||
{{else if .Repository}} | |||||
{{if .Issue}} | |||||
<meta property="og:title" content="{{.Issue.Title}}" /> | |||||
<meta property="og:url" content="{{.Issue.HTMLURL}}" /> | |||||
{{if .Issue.Content}} | |||||
<meta property="og:description" content="{{.Issue.Content}}" /> | |||||
{{end}} | |||||
{{else}} | |||||
<meta property="og:title" content="{{.Repository.Name}}" /> | |||||
<meta property="og:url" content="{{.Repository.HTMLURL}}" /> | |||||
{{if .Repository.Description}} | |||||
<meta property="og:description" content="{{.Repository.Description}}" /> | |||||
{{end}} | |||||
{{end}} | |||||
<meta property="og:type" content="object" /> | |||||
<meta property="og:image" content="{{.Repository.Owner.AvatarLink}}" /> | |||||
{{else}} | |||||
<meta property="og:title" content="{{AppName}}"> | |||||
<meta property="og:type" content="website" /> | |||||
<meta property="og:image" content="{{StaticUrlPrefix}}/img/gitea-lg.png" /> | |||||
<meta property="og:url" content="{{AppUrl}}" /> | |||||
<meta property="og:description" content="{{MetaDescription}}"> | |||||
{{end}} | |||||
<meta property="og:site_name" content="{{AppName}}" /> | |||||
{{if .IsSigned }} | |||||
{{ if ne .SignedUser.Theme "gitea" }} | |||||
<link rel="stylesheet" href="{{StaticUrlPrefix}}/css/theme-{{.SignedUser.Theme}}.css?v={{MD5 AppVer}}"> | |||||
{{end}} | |||||
{{else if ne DefaultTheme "gitea"}} | |||||
<link rel="stylesheet" href="{{StaticUrlPrefix}}/css/theme-{{DefaultTheme}}.css?v={{MD5 AppVer}}"> | |||||
{{end}} | |||||
{{template "custom/header" .}} | |||||
<script> | |||||
var _hmt = _hmt || []; | |||||
(function() { | |||||
var hm = document.createElement("script"); | |||||
hm.src = "https://hm.baidu.com/hm.js?46149a0b61fdeddfe427ff4de63794ba"; | |||||
var s = document.getElementsByTagName("script")[0]; | |||||
s.parentNode.insertBefore(hm, s); | |||||
})(); | |||||
</script> | |||||
<script src="/self/func.js" type="text/javascript"></script> | |||||
</head> | |||||
<body> | |||||
{{template "custom/body_outer_pre" .}} | |||||
<div class="full height"> | |||||
<noscript>{{.i18n.Tr "enable_javascript"}}</noscript> | |||||
{{template "custom/body_inner_pre" .}} | |||||
{{if not .PageIsInstall}} | |||||
<div class="ui top secondary stackable main menu following bar dark"> | |||||
{{template "base/head_navbar_fluid" .}} | |||||
</div><!-- end bar --> | |||||
{{end}} | |||||
{{/* | |||||
</div> | |||||
</body> | |||||
</html> | |||||
*/}} |
@@ -0,0 +1,177 @@ | |||||
<div class="ui fluid container" style = "padding: 0px 20px;" id="navbar"> | |||||
<div class="item brand" style="justify-content: space-between;"> | |||||
<a href="https://openi.org.cn/"> | |||||
<img class="ui mini image" src="{{StaticUrlPrefix}}/img/logo-w.svg"> | |||||
</a> | |||||
<div class="ui basic icon button mobile-only" id="navbar-expand-toggle"> | |||||
<i class="sidebar icon"></i> | |||||
</div> | |||||
</div> | |||||
<div style="width:1px;background:#606266;height:80%;margin:auto 0.5rem"></div> | |||||
<div class="item brand" style="margin-left: 0.9rem;"> | |||||
<a href="/"> | |||||
<img class="ui mini image" style="height: 1.3rem;" src="{{StaticUrlPrefix}}/img/git-logo.svg"> | |||||
</a> | |||||
</div> | |||||
{{if .IsSigned}} | |||||
<a class="item {{if .PageIsDashboard}}active{{end}}" href="/dashboard">{{.i18n.Tr "index"}}</a> | |||||
<a class="item" href="{{AppSubUrl}}/OpenI">{{.i18n.Tr "custom.head.openi"}}</a> | |||||
{{if not .UnitIssuesGlobalDisabled}} | |||||
<a class="item {{if .PageIsIssues}}active{{end}}" href="{{AppSubUrl}}/issues">{{.i18n.Tr "issues"}}</a> | |||||
{{end}} | |||||
{{if not .UnitPullsGlobalDisabled}} | |||||
<a class="item {{if .PageIsPulls}}active{{end}}" href="{{AppSubUrl}}/pulls">{{.i18n.Tr "pull_requests"}}</a> | |||||
{{end}} | |||||
{{if not (and .UnitIssuesGlobalDisabled .UnitPullsGlobalDisabled)}} | |||||
{{if .ShowMilestonesDashboardPage}}<a class="item {{if .PageIsMilestonesDashboard}}active{{end}}" href="{{AppSubUrl}}/milestones">{{.i18n.Tr "milestones"}}</a>{{end}} | |||||
{{end}} | |||||
<div class="ui dropdown item"> | |||||
{{.i18n.Tr "explore"}} | |||||
<i class="dropdown icon"></i> | |||||
<div class="menu"> | |||||
<a class="item" href="{{AppSubUrl}}/explore/repos">{{.i18n.Tr "custom.head.project"}}</a> | |||||
<a class="item" href="{{AppSubUrl}}/explore/datasets">{{.i18n.Tr "custom.head.dataset"}}</a> | |||||
<a class="item" href="{{AppSubUrl}}/explore/users">{{.i18n.Tr "explore.users"}}</a> | |||||
<a class="item" href="{{AppSubUrl}}/explore/organizations">{{.i18n.Tr "explore.organizations"}}</a> | |||||
<a class="item" href="{{AppSubUrl}}/explore/images">{{.i18n.Tr "explore.images"}}</a> | |||||
{{if .IsAdmin}} | |||||
<a class="item" href="{{AppSubUrl}}/explore/data_analysis">{{.i18n.Tr "explore.data_analysis"}}</a> | |||||
{{end}} | |||||
</div> | |||||
</div> | |||||
{{else if .IsLandingPageHome}} | |||||
<a class="item {{if .PageIsHome}}active{{end}}" href="{{AppSubUrl}}/dashboard">{{.i18n.Tr "home"}}</a> | |||||
<a class="item" href="{{AppSubUrl}}/OpenI">{{.i18n.Tr "custom.head.openi"}}</a> | |||||
<div class="ui dropdown item"> | |||||
{{.i18n.Tr "explore"}} | |||||
<i class="dropdown icon"></i> | |||||
<div class="menu"> | |||||
<a class="item" href="{{AppSubUrl}}/explore/repos">{{.i18n.Tr "custom.head.project"}}</a> | |||||
<a class="item" href="{{AppSubUrl}}/explore/datasets">{{.i18n.Tr "datasets"}}</a> | |||||
<a class="item" href="{{AppSubUrl}}/explore/users">{{.i18n.Tr "explore.users"}}</a> | |||||
<a class="item" href="{{AppSubUrl}}/explore/organizations">{{.i18n.Tr "explore.organizations"}}</a> | |||||
<a class="item" href="{{AppSubUrl}}/explore/images">{{.i18n.Tr "explore.images"}}</a> | |||||
{{if .IsAdmin}} | |||||
<a class="item" href="{{AppSubUrl}}/explore/data_analysis">{{.i18n.Tr "explore.data_analysis"}}</a> | |||||
{{end}} | |||||
</div> | |||||
</div> | |||||
{{else if .IsLandingPageExplore}} | |||||
<a class="item {{if .PageIsExplore}}active{{end}}" href="{{AppSubUrl}}/explore/repos">{{.i18n.Tr "home"}}</a> | |||||
{{else if .IsLandingPageOrganizations}} | |||||
<a class="item {{if .PageIsExplore}}active{{end}}" href="{{AppSubUrl}}/explore/organizations">{{.i18n.Tr "home"}}</a> | |||||
{{end}} | |||||
{{template "custom/extra_links" .}} | |||||
{{/* | |||||
<div class="item"> | |||||
<div class="ui icon input"> | |||||
<input class="searchbox" type="text" placeholder="{{.i18n.Tr "search_project"}}"> | |||||
<i class="search icon"></i> | |||||
</div> | |||||
</div> | |||||
*/}} | |||||
{{if .IsSigned}} | |||||
<div class="right stackable menu"> | |||||
<a href="{{AppSubUrl}}/notifications" class="item poping up" data-content='{{.i18n.Tr "notifications"}}' data-variation="tiny inverted"> | |||||
<span class="text"> | |||||
<span class="fitted">{{svg "octicon-bell" 16}}</span> | |||||
<span class="sr-mobile-only">{{.i18n.Tr "notifications"}}</span> | |||||
{{$notificationUnreadCount := 0}} | |||||
{{if .NotificationUnreadCount}}{{$notificationUnreadCount = call .NotificationUnreadCount}}{{end}} | |||||
<span class="ui red label {{if not $notificationUnreadCount}}hidden{{end}} notification_count"> | |||||
{{$notificationUnreadCount}} | |||||
</span> | |||||
</span> | |||||
</a> | |||||
<div class="ui dropdown jump item poping up" data-content="{{.i18n.Tr "create_new"}}" data-variation="tiny inverted"> | |||||
<span class="text"> | |||||
<span class="fitted">{{svg "octicon-plus" 16}}</span> | |||||
<span class="sr-mobile-only">{{.i18n.Tr "create_new"}}</span> | |||||
<span class="fitted not-mobile">{{svg "octicon-triangle-down" 16}}</span> | |||||
</span> | |||||
<div class="menu"> | |||||
<a class="item" href="{{AppSubUrl}}/repo/create"> | |||||
<span class="fitted">{{svg "octicon-plus" 16}}</span> {{.i18n.Tr "new_repo"}} | |||||
</a> | |||||
<a class="item" href="{{AppSubUrl}}/repo/migrate"> | |||||
<span class="fitted">{{svg "octicon-repo-clone" 16}}</span> {{.i18n.Tr "new_migrate"}} | |||||
</a> | |||||
{{if .SignedUser.CanCreateOrganization}} | |||||
<a class="item" href="{{AppSubUrl}}/org/create"> | |||||
<span class="fitted">{{svg "octicon-organization" 16}}</span> {{.i18n.Tr "new_org"}} | |||||
</a> | |||||
{{end}} | |||||
</div><!-- end content create new menu --> | |||||
</div><!-- end dropdown menu create new --> | |||||
<div class="ui dropdown jump item poping up" tabindex="-1" data-content="{{.i18n.Tr "user_profile_and_more"}}" data-variation="tiny inverted"> | |||||
<span class="text"> | |||||
<img class="ui tiny avatar image" width="24" height="24" src="{{.SignedUser.RelAvatarLink}}"> | |||||
<span class="sr-only">{{.i18n.Tr "user_profile_and_more"}}</span> | |||||
<span class="mobile-only">{{.SignedUser.Name}}</span> | |||||
<span class="fitted not-mobile" tabindex="-1">{{svg "octicon-triangle-down" 16}}</span> | |||||
</span> | |||||
<div class="menu user-menu" tabindex="-1"> | |||||
<div class="ui header"> | |||||
{{.i18n.Tr "signed_in_as"}} <strong>{{.SignedUser.Name}}</strong> | |||||
</div> | |||||
<div class="divider"></div> | |||||
<a class="item" href="{{AppSubUrl}}/{{.SignedUser.Name}}"> | |||||
{{svg "octicon-person" 16}} | |||||
{{.i18n.Tr "your_profile"}}<!-- Your profile --> | |||||
</a> | |||||
<a class="item" href="{{AppSubUrl}}/{{.SignedUser.Name}}?tab=stars"> | |||||
{{svg "octicon-star" 16}} | |||||
{{.i18n.Tr "your_starred"}} | |||||
</a> | |||||
<a class="{{if .PageIsUserSettings}}active{{end}} item" href="{{AppSubUrl}}/user/settings"> | |||||
{{svg "octicon-settings" 16}} | |||||
{{.i18n.Tr "your_settings"}}<!-- Your settings --> | |||||
</a> | |||||
<!--a class="item" target="_blank" rel="noopener noreferrer" href="https://docs.gitea.io"> | |||||
{{svg "octicon-question" 16}} | |||||
{{.i18n.Tr "help"}}<!-- Help --> | |||||
</a--> | |||||
{{if .IsAdmin}} | |||||
<div class="divider"></div> | |||||
<a class="{{if .PageIsAdmin}}active{{end}} item" href="{{AppSubUrl}}/admin"> | |||||
<i class="icon settings"></i> | |||||
{{.i18n.Tr "admin_panel"}}<!-- Admin Panel --> | |||||
</a> | |||||
{{end}} | |||||
<div class="divider"></div> | |||||
<a class="item link-action" href data-url="{{AppSubUrl}}/user/logout" data-redirect="{{AppSubUrl}}/"> | |||||
{{svg "octicon-sign-out" 16}} | |||||
{{.i18n.Tr "sign_out"}}<!-- Sign Out --> | |||||
</a> | |||||
</div><!-- end content avatar menu --> | |||||
</div><!-- end dropdown avatar menu --> | |||||
</div><!-- end signed user right menu --> | |||||
{{else}} | |||||
<!--a class="item" target="_blank" rel="noopener noreferrer" href="https://docs.gitea.io">{{.i18n.Tr "help"}}</a--> | |||||
<div class="right stackable menu"> | |||||
{{if .ShowRegistrationButton}} | |||||
<a class="item{{if .PageIsSignUp}} active{{end}}" href="{{AppSubUrl}}/user/sign_up"> | |||||
{{svg "octicon-person" 16}} {{.i18n.Tr "register"}} | |||||
</a> | |||||
{{end}} | |||||
<a class="item{{if .PageIsSignIn}} active{{end}}" rel="nofollow" href="{{AppSubUrl}}/user/login"> | |||||
{{svg "octicon-sign-in" 16}} {{.i18n.Tr "sign_in"}} | |||||
</a> | |||||
</div><!-- end anonymous right menu --> | |||||
{{end}} | |||||
</div> |
@@ -1,14 +1,15 @@ | |||||
{{template "base/head" .}} | |||||
{{template "base/head_fluid" .}} | |||||
<div id="data_analysis" style="height: 100%;"> | <div id="data_analysis" style="height: 100%;"> | ||||
</div> | </div> | ||||
{{template "base/footer" .}} | |||||
{{template "base/footer_fluid" .}} | |||||
<style> | <style> | ||||
.full.height { | .full.height { | ||||
flex-grow: 1; | |||||
/* flex-grow: 1; */ | |||||
padding-bottom: 53px; | padding-bottom: 53px; | ||||
} | } | ||||
</style> | |||||
</style> |
@@ -11,7 +11,7 @@ | |||||
{{.i18n.Tr "repo.cloudbrain"}} | {{.i18n.Tr "repo.cloudbrain"}} | ||||
</a> | </a> | ||||
<div class="divider"> / </div> | <div class="divider"> / </div> | ||||
<a class="section" href="{{.RepoLink}}/cloudbrain"> | |||||
<a class="section" href="{{.RepoLink}}/modelarts/notebook"> | |||||
{{$.i18n.Tr "repo.modelarts.notebook"}} | {{$.i18n.Tr "repo.modelarts.notebook"}} | ||||
</a> | </a> | ||||
<div class="divider"> / </div> | <div class="divider"> / </div> | ||||
@@ -328,7 +328,7 @@ | |||||
</div> | </div> | ||||
<!-- 版本数量 --> | <!-- 版本数量 --> | ||||
<div class="one wide column text center padding0"> | <div class="one wide column text center padding0"> | ||||
<span>{{.VersionCount}} </span> | |||||
<span style="font-size: 12px;">{{.VersionCount}} </span> | |||||
</div> | </div> | ||||
<!-- 任务状态 --> | <!-- 任务状态 --> | ||||
<div class="two wide column padding0" style="padding-left: 2.2rem !important;"> | <div class="two wide column padding0" style="padding-left: 2.2rem !important;"> | ||||
@@ -8,13 +8,13 @@ | |||||
<bar-label :width="'95%'" :height="'500px'"></bar-label> | <bar-label :width="'95%'" :height="'500px'"></bar-label> | ||||
<div style="margin-top: 20px;"> | <div style="margin-top: 20px;"> | ||||
<span class="sta_iterm">统计周期:</span> | <span class="sta_iterm">统计周期:</span> | ||||
<button type="button" class='btn' id ="yesterday" v-bind:class="{colorChange:1==dynamic}" @click="resetPage(),getAllProList('yesterday',1)">昨天</button> | |||||
<button type="button" class='btnFirst' id ="yesterday" v-bind:class="{colorChange:1==dynamic}" @click="resetPage(),getAllProList('yesterday',1)">昨天</button> | |||||
<button type="button" class='btn' id = "current_week" v-bind:class="{colorChange:2==dynamic}" @click="resetPage(),getAllProList('current_week',2)">本周</button> | <button type="button" class='btn' id = "current_week" v-bind:class="{colorChange:2==dynamic}" @click="resetPage(),getAllProList('current_week',2)">本周</button> | ||||
<button type="button" class='btn' id = "current_month" v-bind:class="{colorChange:3==dynamic}" @click="resetPage(),getAllProList('current_month',3)">本月</button> | <button type="button" class='btn' id = "current_month" v-bind:class="{colorChange:3==dynamic}" @click="resetPage(),getAllProList('current_month',3)">本月</button> | ||||
<button type="button" class='btn' id = "last_month" v-bind:class="{colorChange:4==dynamic}" @click="resetPage(),getAllProList('last_month',4)">上月</button> | <button type="button" class='btn' id = "last_month" v-bind:class="{colorChange:4==dynamic}" @click="resetPage(),getAllProList('last_month',4)">上月</button> | ||||
<button type="button" class='btn' id = "monthly" v-bind:class="{colorChange:5==dynamic}" @click="resetPage(),getAllProList('monthly',5)">近30天</button> | <button type="button" class='btn' id = "monthly" v-bind:class="{colorChange:5==dynamic}" @click="resetPage(),getAllProList('monthly',5)">近30天</button> | ||||
<button type="button" class='btn' id = "current_year" v-bind:class="{colorChange:6==dynamic}" @click="resetPage(),getAllProList('current_year',6)">今年</button> | <button type="button" class='btn' id = "current_year" v-bind:class="{colorChange:6==dynamic}" @click="resetPage(),getAllProList('current_year',6)">今年</button> | ||||
<button type="button" class='btn' id = "all" v-bind:class="{colorChange:7==dynamic}" @click="resetPage(),getAllProList('all',7)">所有</button> | |||||
<button type="button" class='btnLast' id = "all" v-bind:class="{colorChange:7==dynamic}" @click="resetPage(),getAllProList('all',7)">所有</button> | |||||
<span style="margin-left: 20px;"> | <span style="margin-left: 20px;"> | ||||
<el-date-picker | <el-date-picker | ||||
v-model="value_time" | v-model="value_time" | ||||
@@ -160,7 +160,7 @@ | |||||
</div> | </div> | ||||
<div id ="pro_detail" style="display:none;width: 100%;"> | <div id ="pro_detail" style="display:none;width: 100%;"> | ||||
<div style="margin-top: 10px;"> | <div style="margin-top: 10px;"> | ||||
<b class="pro_item">{{this.ownerName}} / {{this.pro_name}}</b> <span class="update_time">数据更新时间:</span><span style="font-size: 12px;">{{tableDataIDTotal.lastUpdatedTime}} / 从{{tableDataIDTotal.recordBeginTime}}开始统计</span> | |||||
<a class="pro_item" :href="'../../../'+this.ownerName+'/'+this.pro_name">{{this.ownerName}} / {{this.pro_name}}</a> <span class="update_time">数据更新时间:</span><span style="font-size: 12px;">{{tableDataIDTotal.lastUpdatedTime}} / 从{{tableDataIDTotal.recordBeginTime}}开始统计</span> | |||||
</div> | </div> | ||||
<div style="margin-top: 10px;"> | <div style="margin-top: 10px;"> | ||||
项目描述:{{tableDataIDTotal.description | discriptionFun}} | 项目描述:{{tableDataIDTotal.description | discriptionFun}} | ||||
@@ -207,44 +207,46 @@ | |||||
</el-col> | </el-col> | ||||
<el-col :span=6 > | <el-col :span=6 > | ||||
<div class="item_r"> | <div class="item_r"> | ||||
<div style="font-size:14px;color:rgb(0,0,0);margin:20px 5px;">贡献者TOP10</div> | |||||
<div> | |||||
<el-table | |||||
:data="tableDataContTop10" | |||||
style="width: 100%" | |||||
stripe | |||||
:header-cell-style="tableHeaderStyle" | |||||
> | |||||
<el-table-column | |||||
label="用户名" | |||||
align="left" | |||||
prop="user"> | |||||
<template slot-scope="scope"> | |||||
<a v-if="scope.row.mode!=-1" :href="AppSubUrl +'../../../'+ scope.row.user"><img class="ui avatar s16 image js-popover-card" :src="scope.row.relAvatarLink">{{scope.row.user}} </a> | |||||
<a v-else :href="'mailto:'+ scope.row.email "> <img class="ui avatar s16 image js-popover-card" :avatar="scope.row.email"> {{scope.row.user}}</a> | |||||
</template> | |||||
</el-table-column> | |||||
<el-table-column | |||||
label="身份" | |||||
align="center" | |||||
prop="mode" | |||||
v-if='0'> | |||||
<template slot-scope="scope"> | |||||
{{scope.row.mode | showMode}} | |||||
</template> | |||||
</el-table-column> | |||||
<el-table-column | |||||
prop="pr" | |||||
label="PR" | |||||
align="center"> | |||||
</el-table-column> | |||||
<el-table-column | |||||
prop="commit" | |||||
label="commit" | |||||
align="center"> | |||||
</el-table-column> | |||||
</el-table> | |||||
<div style="margin:0 5px;"> | |||||
<div style="font-size:14px;color:rgb(0,0,0);margin:10px 0px">贡献者TOP10</div> | |||||
<div> | |||||
<el-table | |||||
:data="tableDataContTop10" | |||||
style="width: 100%" | |||||
stripe | |||||
:header-cell-style="tableHeaderStyle" | |||||
> | |||||
<el-table-column | |||||
label="用户名" | |||||
align="left" | |||||
prop="user"> | |||||
<template slot-scope="scope"> | |||||
<a v-if="scope.row.relAvatarLink!=''" :href="AppSubUrl +'../../../'+ scope.row.user"><img class="ui avatar s16 image js-popover-card" :src="scope.row.relAvatarLink">{{scope.row.user}} </a> | |||||
<a v-else :href="'mailto:'+ scope.row.email "> <img class="ui avatar s16 image js-popover-card" :avatar="scope.row.email"> {{scope.row.user}}</a> | |||||
</template> | |||||
</el-table-column> | |||||
<el-table-column | |||||
label="身份" | |||||
align="center" | |||||
prop="mode" | |||||
v-if='0'> | |||||
<template slot-scope="scope"> | |||||
{{scope.row.mode | showMode}} | |||||
</template> | |||||
</el-table-column> | |||||
<el-table-column | |||||
prop="pr" | |||||
label="PR" | |||||
align="center"> | |||||
</el-table-column> | |||||
<el-table-column | |||||
prop="commit" | |||||
label="commit" | |||||
align="center"> | |||||
</el-table-column> | |||||
</el-table> | |||||
</div> | |||||
</div> | </div> | ||||
</div> | </div> | ||||
</el-col> | </el-col> | ||||
@@ -252,13 +254,13 @@ | |||||
</div> | </div> | ||||
<div style="margin-top: 20px;"> | <div style="margin-top: 20px;"> | ||||
<span class="sta_iterm">统计周期:</span> | <span class="sta_iterm">统计周期:</span> | ||||
<button type="button" class='btn' id ="yesterday_pro" v-bind:class="{colorChange:1==dynamic_pro}" @click="resetCurrentPage(),getOneProList(pro_id,'yesterday',false,1)">昨天</button> | |||||
<button type="button" class='btnFirst' id ="yesterday_pro" v-bind:class="{colorChange:1==dynamic_pro}" @click="resetCurrentPage(),getOneProList(pro_id,'yesterday',false,1)">昨天</button> | |||||
<button type="button" class='btn' id = "current_week_pro" v-bind:class="{colorChange:2==dynamic_pro}" @click="resetCurrentPage(),getOneProList(pro_id,'current_week',false,2)">本周</button> | <button type="button" class='btn' id = "current_week_pro" v-bind:class="{colorChange:2==dynamic_pro}" @click="resetCurrentPage(),getOneProList(pro_id,'current_week',false,2)">本周</button> | ||||
<button type="button" class='btn' id = "current_month_pro" v-bind:class="{colorChange:3==dynamic_pro}" @click="resetCurrentPage(),getOneProList(pro_id,'current_month',false,3)">本月</button> | <button type="button" class='btn' id = "current_month_pro" v-bind:class="{colorChange:3==dynamic_pro}" @click="resetCurrentPage(),getOneProList(pro_id,'current_month',false,3)">本月</button> | ||||
<button type="button" class='btn' id = "last_month_pro" v-bind:class="{colorChange:4==dynamic_pro}" @click="resetCurrentPage(),getOneProList(pro_id,'last_month',false,4)">上月</button> | <button type="button" class='btn' id = "last_month_pro" v-bind:class="{colorChange:4==dynamic_pro}" @click="resetCurrentPage(),getOneProList(pro_id,'last_month',false,4)">上月</button> | ||||
<button type="button" class='btn' id = "monthly_pro" v-bind:class="{colorChange:5==dynamic_pro}" @click="resetCurrentPage(),getOneProList(pro_id,'monthly',false,5)">近30天</button> | <button type="button" class='btn' id = "monthly_pro" v-bind:class="{colorChange:5==dynamic_pro}" @click="resetCurrentPage(),getOneProList(pro_id,'monthly',false,5)">近30天</button> | ||||
<button type="button" class='btn' id = "current_year_pro" v-bind:class="{colorChange:6==dynamic_pro}" @click="resetCurrentPage(),getOneProList(pro_id,'current_year',false,6)">今年</button> | <button type="button" class='btn' id = "current_year_pro" v-bind:class="{colorChange:6==dynamic_pro}" @click="resetCurrentPage(),getOneProList(pro_id,'current_year',false,6)">今年</button> | ||||
<button type="button" class='btn' id = "all_pro" v-bind:class="{colorChange:7==dynamic_pro}" @click="resetCurrentPage(),getOneProList(pro_id,'all',false,7)">所有</button> | |||||
<button type="button" class='btnLast' id = "all_pro" v-bind:class="{colorChange:7==dynamic_pro}" @click="resetCurrentPage(),getOneProList(pro_id,'all',false,7)">所有</button> | |||||
<span style="margin-left: 20px;"> | <span style="margin-left: 20px;"> | ||||
<el-date-picker | <el-date-picker | ||||
v-model="create_time_pro" | v-model="create_time_pro" | ||||
@@ -788,6 +790,10 @@ | |||||
}, | }, | ||||
slpitNumber:5, | slpitNumber:5, | ||||
center: ['50%', '50%'], | center: ['50%', '50%'], | ||||
splitArea: { // 坐标轴在 grid 区域中的分隔区域 | |||||
show: false, | |||||
}, | |||||
indicator: [{ | indicator: [{ | ||||
name: '社区影响力', | name: '社区影响力', | ||||
max: 100 | max: 100 | ||||
@@ -1170,16 +1176,43 @@ | |||||
color:rgba(187, 187, 187, 100); | color:rgba(187, 187, 187, 100); | ||||
margin-left: 10px; | margin-left: 10px; | ||||
} | } | ||||
.btnFirst{ | |||||
line-height: 1.5; | |||||
margin: -3.5px; | |||||
border: 1px solid #409eff; | |||||
border-right: none; | |||||
background: #FFFF; | |||||
color: #409eff; | |||||
width: 60px; | |||||
height: 30px; | |||||
border-radius:4px 0px 0px 4px; | |||||
} | |||||
.btn{ | .btn{ | ||||
line-height: 1.5; | line-height: 1.5; | ||||
margin: -3px; | |||||
margin: -3.5px; | |||||
border: 1px solid #409eff; | |||||
border-right: none; | |||||
background: #FFFF; | |||||
color: #409eff; | |||||
width: 60px; | |||||
height: 30px; | |||||
} | |||||
.btnLast{ | |||||
line-height: 1.5; | |||||
margin: -3.5px; | |||||
border: 1px solid #409eff; | border: 1px solid #409eff; | ||||
/* border-right: none; */ | |||||
background: #FFFF; | background: #FFFF; | ||||
color: #409eff; | color: #409eff; | ||||
width: 60px; | width: 60px; | ||||
height: 30px; | height: 30px; | ||||
border-radius:4px ; | |||||
border-radius:0px 4px 4px 0px; | |||||
} | } | ||||
.btnFirst, .btn, .btnLast { | |||||
cursor: pointer; | |||||
} | |||||
/* | /* | ||||
.btn:focus, | .btn:focus, | ||||
.btn:active{ | .btn:active{ | ||||
@@ -1203,6 +1236,7 @@ | |||||
.colorChange { | .colorChange { | ||||
background-color: #409effd6; | background-color: #409effd6; | ||||
color: #FFFF; | color: #FFFF; | ||||
cursor: default; | |||||
} | } | ||||
.items{ | .items{ | ||||
text-align: center; | text-align: center; | ||||
@@ -5,13 +5,13 @@ | |||||
</div> | </div> | ||||
<div style="margin-top: 20px;"> | <div style="margin-top: 20px;"> | ||||
<span class="sta_iterm">统计周期:</span> | <span class="sta_iterm">统计周期:</span> | ||||
<button type="button" class='btn' id ="yesterday_usr" v-bind:class="{colorChange:1==dynamic}" @click="resetPage(),getUserList('yesterday_usr',1)">昨天</button> | |||||
<button type="button" class='btnFirst' id ="yesterday_usr" v-bind:class="{colorChange:1==dynamic}" @click="resetPage(),getUserList('yesterday_usr',1)">昨天</button> | |||||
<button type="button" class='btn' id = "current_week_usr" v-bind:class="{colorChange:2==dynamic}" @click="resetPage(),getUserList('current_week_usr',2)">本周</button> | <button type="button" class='btn' id = "current_week_usr" v-bind:class="{colorChange:2==dynamic}" @click="resetPage(),getUserList('current_week_usr',2)">本周</button> | ||||
<button type="button" class='btn' id = "current_month_usr" v-bind:class="{colorChange:3==dynamic}" @click="resetPage(),getUserList('current_month_usr',3)">本月</button> | <button type="button" class='btn' id = "current_month_usr" v-bind:class="{colorChange:3==dynamic}" @click="resetPage(),getUserList('current_month_usr',3)">本月</button> | ||||
<button type="button" class='btn' id = "last_month_usr" v-bind:class="{colorChange:4==dynamic}" @click="resetPage(),getUserList('last_month_usr',4)">上月</button> | <button type="button" class='btn' id = "last_month_usr" v-bind:class="{colorChange:4==dynamic}" @click="resetPage(),getUserList('last_month_usr',4)">上月</button> | ||||
<button type="button" class='btn' id = "monthly_usr" v-bind:class="{colorChange:5==dynamic}" @click="resetPage(),getUserList('monthly_usr',5)">近30天</button> | <button type="button" class='btn' id = "monthly_usr" v-bind:class="{colorChange:5==dynamic}" @click="resetPage(),getUserList('monthly_usr',5)">近30天</button> | ||||
<button type="button" class='btn' id = "current_year_usr" v-bind:class="{colorChange:6==dynamic}" @click="resetPage(),getUserList('current_year_usr',6)">今年</button> | <button type="button" class='btn' id = "current_year_usr" v-bind:class="{colorChange:6==dynamic}" @click="resetPage(),getUserList('current_year_usr',6)">今年</button> | ||||
<button type="button" class='btn' id = "all_usr" v-bind:class="{colorChange:7==dynamic}" @click="resetPage(),getUserList('all_usr',7)">所有</button> | |||||
<button type="button" class='btnLast' id = "all_usr" v-bind:class="{colorChange:7==dynamic}" @click="resetPage(),getUserList('all_usr',7)">所有</button> | |||||
<span style="margin-left: 20px;"> | <span style="margin-left: 20px;"> | ||||
<el-date-picker | <el-date-picker | ||||
v-model="value_time" | v-model="value_time" | ||||
@@ -462,7 +462,7 @@ | |||||
color:rgba(187, 187, 187, 100); | color:rgba(187, 187, 187, 100); | ||||
margin-left: 10px; | margin-left: 10px; | ||||
} | } | ||||
.btn{ | |||||
/* .btn{ | |||||
line-height: 1.5; | line-height: 1.5; | ||||
margin: -3px; | margin: -3px; | ||||
border: 1px solid #409effd6; | border: 1px solid #409effd6; | ||||
@@ -471,7 +471,43 @@ | |||||
width: 60px; | width: 60px; | ||||
height: 30px; | height: 30px; | ||||
border-radius:4px ; | border-radius:4px ; | ||||
} */ | |||||
.btnFirst{ | |||||
line-height: 1.5; | |||||
margin: -3.5px; | |||||
border: 1px solid #409eff; | |||||
border-right: none; | |||||
background: #FFFF; | |||||
color: #409eff; | |||||
width: 60px; | |||||
height: 30px; | |||||
border-radius:4px 0px 0px 4px; | |||||
} | |||||
.btn{ | |||||
line-height: 1.5; | |||||
margin: -3.5px; | |||||
border: 1px solid #409eff; | |||||
border-right: none; | |||||
background: #FFFF; | |||||
color: #409eff; | |||||
width: 60px; | |||||
height: 30px; | |||||
} | } | ||||
.btnLast{ | |||||
line-height: 1.5; | |||||
margin: -3.5px; | |||||
border: 1px solid #409eff; | |||||
/* border-right: none; */ | |||||
background: #FFFF; | |||||
color: #409eff; | |||||
width: 60px; | |||||
height: 30px; | |||||
border-radius:0px 4px 4px 0px; | |||||
} | |||||
.btnFirst,.btn,.btnLast { | |||||
cursor: pointer; | |||||
} | |||||
/* .btn:focus, | /* .btn:focus, | ||||
.btn:active{ | .btn:active{ | ||||
@@ -492,8 +528,9 @@ | |||||
} | } | ||||
.colorChange { | .colorChange { | ||||
background-color: #409effd6; | |||||
color: #FFFF; | |||||
background-color: #409effd6; | |||||
color: #FFFF; | |||||
cursor: default; | |||||
} | } | ||||
</style> | </style> |