Browse Source

Merge branch 'liuzx_trainjob' of https://git.openi.org.cn/OpenI/aiforge into liuzx_trainjob

update
pull/948/head
liuzx 3 years ago
parent
commit
2b54431a85
21 changed files with 924 additions and 114 deletions
  1. +1
    -1
      go.mod
  2. +0
    -9
      models/custom_migrations.go
  3. +7
    -0
      models/repo_statistic.go
  4. +104
    -23
      models/user_business_analysis.go
  5. +21
    -9
      modules/repository/elk_pagedata.go
  6. +3
    -0
      options/locale/locale_zh-CN.ini
  7. +1
    -0
      routers/api/v1/api.go
  8. +106
    -0
      routers/api/v1/repo/repo_dashbord.go
  9. +2
    -1
      routers/private/internal.go
  10. +28
    -1
      routers/private/tool.go
  11. +32
    -4
      routers/repo/repo_statistic.go
  12. +16
    -10
      routers/repo/user_data_analysis.go
  13. +42
    -0
      templates/base/footer_content_fluid.tmpl
  14. +48
    -0
      templates/base/footer_fluid.tmpl
  15. +208
    -0
      templates/base/head_fluid.tmpl
  16. +177
    -0
      templates/base/head_navbar_fluid.tmpl
  17. +5
    -4
      templates/explore/data_analysis.tmpl
  18. +1
    -1
      templates/repo/modelarts/notebook/show.tmpl
  19. +1
    -1
      templates/repo/modelarts/trainjob/index.tmpl
  20. +79
    -45
      web_src/js/components/ProAnalysis.vue
  21. +42
    -5
      web_src/js/components/UserAnalysis.vue

+ 1
- 1
go.mod View File

@@ -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


+ 0
- 9
models/custom_migrations.go View File

@@ -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"


+ 7
- 0
models/repo_statistic.go View File

@@ -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
}

+ 104
- 23
models/user_business_analysis.go View File

@@ -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
}
}
} }
} }




+ 21
- 9
modules/repository/elk_pagedata.go View File

@@ -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
} }


+ 3
- 0
options/locale/locale_zh-CN.ini View File

@@ -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=创建时间


+ 1
- 0
routers/api/v1/api.go View File

@@ -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)




+ 106
- 0
routers/api/v1/repo/repo_dashbord.go View File

@@ -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 " +


+ 2
- 1
routers/private/internal.go View File

@@ -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)
} }

+ 28
- 1
routers/private/tool.go View File

@@ -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": "",
})
}

+ 32
- 4
routers/repo/repo_statistic.go View File

@@ -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
}

+ 16
- 10
routers/repo/user_data_analysis.go View File

@@ -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)
} }
} }


+ 42
- 0
templates/base/footer_content_fluid.tmpl View File

@@ -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>

+ 48
- 0
templates/base/footer_fluid.tmpl View File

@@ -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>

+ 208
- 0
templates/base/head_fluid.tmpl View File

@@ -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>
*/}}

+ 177
- 0
templates/base/head_navbar_fluid.tmpl View File

@@ -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>

+ 5
- 4
templates/explore/data_analysis.tmpl View File

@@ -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>

+ 1
- 1
templates/repo/modelarts/notebook/show.tmpl View File

@@ -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>


+ 1
- 1
templates/repo/modelarts/trainjob/index.tmpl View File

@@ -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;">


+ 79
- 45
web_src/js/components/ProAnalysis.vue View File

@@ -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}}&nbsp/&nbsp{{this.pro_name}}</b> <span class="update_time">数据更新时间:</span><span style="font-size: 12px;">{{tableDataIDTotal.lastUpdatedTime}}&nbsp/&nbsp从{{tableDataIDTotal.recordBeginTime}}开始统计</span>
<a class="pro_item" :href="'../../../'+this.ownerName+'/'+this.pro_name">{{this.ownerName}}&nbsp/&nbsp{{this.pro_name}}</a> <span class="update_time">数据更新时间:</span><span style="font-size: 12px;">{{tableDataIDTotal.lastUpdatedTime}}&nbsp/&nbsp从{{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;


+ 42
- 5
web_src/js/components/UserAnalysis.vue View File

@@ -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>

Loading…
Cancel
Save