Browse Source

Merge pull request 'V20220519合入develop分支' (#2143) from V20220519 into develop

Reviewed-on: https://git.openi.org.cn/OpenI/aiforge/pulls/2143
tags/v1.22.5.1
lewis 3 years ago
parent
commit
0c9b0f7eea
81 changed files with 9167 additions and 4463 deletions
  1. +4
    -0
      .prettierignore
  2. +1
    -0
      .prettierrc.json
  3. +16
    -0
      cmd/serv.go
  4. +6
    -0
      models/cloudbrain.go
  5. +8
    -3
      models/cloudbrain_image.go
  6. +7
    -3
      models/dbsql/repo_foreigntable_for_es.sql
  7. +5
    -0
      models/repo.go
  8. +48
    -0
      models/summary_statistic.go
  9. +199
    -10
      models/user_business_analysis.go
  10. +15
    -6
      models/user_business_struct.go
  11. +6
    -0
      modules/auth/repo_form.go
  12. +9
    -3
      modules/cloudbrain/cloudbrain.go
  13. +19
    -20
      modules/cloudbrain/resty.go
  14. +30
    -0
      modules/private/hook.go
  15. +28
    -0
      modules/repofiles/temp_repo.go
  16. +207
    -0
      modules/repofiles/update.go
  17. +1
    -1
      modules/repository/hooks.go
  18. +9
    -5
      modules/setting/setting.go
  19. +2
    -1
      modules/ssh/ssh.go
  20. +42
    -6
      options/locale/locale_en-US.ini
  21. +40
    -4
      options/locale/locale_zh-CN.ini
  22. +10
    -4
      package-lock.json
  23. +2
    -1
      package.json
  24. +45
    -0
      public/home/home.js
  25. +2
    -2
      routers/admin/cloudbrains.go
  26. +12
    -1
      routers/api/v1/api.go
  27. +328
    -0
      routers/api/v1/repo/repo_dashbord.go
  28. +109
    -0
      routers/home.go
  29. +18
    -1
      routers/private/hook.go
  30. +4
    -2
      routers/private/internal.go
  31. +5
    -0
      routers/private/tool.go
  32. +172
    -34
      routers/repo/cloudbrain.go
  33. +101
    -0
      routers/repo/editor.go
  34. +1
    -1
      routers/repo/modelarts.go
  35. +7
    -0
      routers/repo/repo_summary_statistic.go
  36. +190
    -15
      routers/repo/user_data_analysis.go
  37. +5
    -0
      routers/repo/view.go
  38. +32
    -0
      routers/response/response.go
  39. +10
    -0
      routers/routes/routes.go
  40. +2
    -2
      routers/user/home.go
  41. +2
    -0
      services/repository/repository.go
  42. +128
    -74
      templates/admin/cloudbrain/list.tmpl
  43. +2
    -2
      templates/admin/cloudbrain/search.tmpl
  44. +3
    -3
      templates/admin/cloudbrain/search_dashboard.tmpl
  45. +8
    -4
      templates/custom/select_dataset_train.tmpl
  46. +9
    -3
      templates/explore/data_analysis.tmpl
  47. +1
    -1
      templates/explore/repo_right.tmpl
  48. +14
    -0
      templates/home.tmpl
  49. +2
    -2
      templates/org/create.tmpl
  50. +5
    -3
      templates/org/home.tmpl
  51. +2
    -2
      templates/org/settings/options.tmpl
  52. +26
    -22
      templates/repo/cloudbrain/benchmark/index.tmpl
  53. +280
    -166
      templates/repo/cloudbrain/benchmark/new.tmpl
  54. +396
    -261
      templates/repo/cloudbrain/benchmark/show.tmpl
  55. +2
    -1
      templates/repo/cloudbrain/models/dir_list.tmpl
  56. +84
    -68
      templates/repo/cloudbrain/new.tmpl
  57. +463
    -378
      templates/repo/cloudbrain/show.tmpl
  58. +482
    -404
      templates/repo/cloudbrain/trainjob/show.tmpl
  59. +259
    -215
      templates/repo/datasets/index.tmpl
  60. +161
    -114
      templates/repo/debugjob/index.tmpl
  61. +244
    -199
      templates/repo/home.tmpl
  62. +328
    -296
      templates/repo/modelarts/notebook/show.tmpl
  63. +1
    -1
      templates/repo/modelarts/trainjob/index.tmpl
  64. +569
    -536
      templates/repo/modelarts/trainjob/show.tmpl
  65. +146
    -81
      templates/repo/view_list.tmpl
  66. +135
    -99
      templates/user/dashboard/cloudbrains.tmpl
  67. +76
    -105
      web_src/js/components/DataAnalysis.vue
  68. +5
    -0
      web_src/js/components/Overview.vue
  69. +55
    -12
      web_src/js/components/ProAnalysis.vue
  70. +903
    -0
      web_src/js/components/ProTrend.vue
  71. +17
    -14
      web_src/js/components/UserAnalysis.vue
  72. +949
    -0
      web_src/js/components/UserTrend.vue
  73. +14
    -2
      web_src/js/components/images/Images.vue
  74. +355
    -363
      web_src/js/components/images/adminImages.vue
  75. +296
    -277
      web_src/js/components/images/selectImages.vue
  76. +1
    -1
      web_src/js/features/clipboard.js
  77. +200
    -113
      web_src/js/features/cloudrbanin.js
  78. +156
    -0
      web_src/js/features/contexmenu.js
  79. +537
    -515
      web_src/js/index.js
  80. +64
    -0
      web_src/js/router/index.js
  81. +30
    -1
      web_src/less/openi.less

+ 4
- 0
.prettierignore View File

@@ -0,0 +1,4 @@
# Ignore artifacts:
dist
build
coverage

+ 1
- 0
.prettierrc.json View File

@@ -0,0 +1 @@
{}

+ 16
- 0
cmd/serv.go View File

@@ -6,6 +6,7 @@
package cmd

import (
"code.gitea.io/gitea/services/repository"
"encoding/json"
"fmt"
"net/http"
@@ -208,6 +209,21 @@ func runServ(c *cli.Context) error {
os.Setenv(models.ProtectedBranchPRID, fmt.Sprintf("%d", 0))
os.Setenv(models.EnvIsDeployKey, fmt.Sprintf("%t", results.IsDeployKey))
os.Setenv(models.EnvKeyID, fmt.Sprintf("%d", results.KeyID))
//set environment for pre-receive hook script
if verb == "git-receive-pack" {
os.Setenv(models.EnvRepoMaxFileSize, fmt.Sprint(setting.Repository.Upload.FileMaxSize))
os.Setenv(models.EnvRepoMaxSize, fmt.Sprint(setting.Repository.RepoMaxSize))
os.Setenv(models.EnvPushSizeCheckFlag, fmt.Sprint(setting.Repository.Upload.ShellFlag))
if setting.Repository.Upload.ShellFlag == repository.SHELL_FLAG_ON {
env, _ := private.GetHookConfig(username, reponame)
if env != nil && len(env) > 0 {
repoSize := env[models.EnvRepoSize]
if repoSize != "" {
os.Setenv(models.EnvRepoSize, repoSize)
}
}
}
}

//LFS token authentication
if verb == lfsAuthenticateVerb {


+ 6
- 0
models/cloudbrain.go View File

@@ -160,6 +160,7 @@ type Cloudbrain struct {

User *User `xorm:"-"`
Repo *Repository `xorm:"-"`
BenchmarkType string `xorm:"-"` //算法评测,模型评测
BenchmarkTypeName string `xorm:"-"`
BenchmarkTypeRankLink string `xorm:"-"`
StartTime timeutil.TimeStamp
@@ -1565,6 +1566,11 @@ func GetCloudbrainCountByUserID(userID int64, jobType string) (int, error) {
return int(count), err
}

func GetBenchmarkCountByUserID(userID int64) (int, error) {
count, err := x.In("status", JobWaiting, JobRunning).And("(job_type = ? or job_type = ? or job_type = ?) and user_id = ? and type = ?", string(JobTypeBenchmark), string(JobTypeBrainScore), string(JobTypeSnn4imagenet), userID, TypeCloudBrainOne).Count(new(Cloudbrain))
return int(count), err
}

func GetCloudbrainNotebookCountByUserID(userID int64) (int, error) {
count, err := x.In("status", ModelArtsCreateQueue, ModelArtsCreating, ModelArtsStarting, ModelArtsReadyToStart, ModelArtsResizing, ModelArtsStartQueuing, ModelArtsRunning, ModelArtsRestarting).
And("job_type = ? and user_id = ? and type = ?", JobTypeDebug, userID, TypeCloudBrainTwo).Count(new(Cloudbrain))


+ 8
- 3
models/cloudbrain_image.go View File

@@ -45,7 +45,7 @@ type ImageStar struct {
}

type ImageTopic struct {
ID int64
ID int64 `xorm:"pk autoincr"`
Name string `xorm:"UNIQUE VARCHAR(105)"`
ImageCount int
CreatedUnix timeutil.TimeStamp `xorm:"INDEX created"`
@@ -468,8 +468,13 @@ func (images ImageList) loadAttributes(e Engine, uid int64) error {
}

for i := range images {
images[i].UserName = users[images[i].UID].Name
images[i].RelAvatarLink = users[images[i].UID].RelAvatarLink()
if users[images[i].UID] != nil {
images[i].UserName = users[images[i].UID].Name
images[i].RelAvatarLink = users[images[i].UID].RelAvatarLink()
} else {
images[i].UserName = ""
images[i].RelAvatarLink = ""
}
if uid == -1 {
images[i].IsStar = false
} else {


+ 7
- 3
models/dbsql/repo_foreigntable_for_es.sql View File

@@ -523,17 +523,21 @@ DROP TRIGGER IF EXISTS es_udpate_repository_lang on public.language_stat;

CREATE OR REPLACE FUNCTION public.udpate_repository_lang() RETURNS trigger AS
$def$
DECLARE
privateValue bigint;
BEGIN
if (TG_OP = 'UPDATE') then
update public.repository_es SET lang=(select array_to_string(array_agg(language order by percentage desc),',') from public.language_stat where repo_id=NEW.repo_id) where id=NEW.repo_id;
select into privateValue updated_unix from public.repository where id=NEW.repo_id;
update public.repository_es SET updated_unix=privateValue,lang=(select array_to_string(array_agg(language order by percentage desc),',') from public.language_stat where repo_id=NEW.repo_id) where id=NEW.repo_id;
elsif (TG_OP = 'INSERT') then
update public.repository_es SET lang=(select array_to_string(array_agg(language order by percentage desc),',') from public.language_stat where repo_id=NEW.repo_id) where id=NEW.repo_id;
select into privateValue updated_unix from public.repository where id=NEW.repo_id;
update public.repository_es SET updated_unix=privateValue,lang=(select array_to_string(array_agg(language order by percentage desc),',') from public.language_stat where repo_id=NEW.repo_id) where id=NEW.repo_id;
elsif (TG_OP = 'DELETE') then
if exists(select 1 from public.repository where id=OLD.repo_id) then
update public.repository_es SET lang=(select array_to_string(array_agg(language order by percentage desc),',') from public.language_stat where repo_id=OLD.repo_id) where id=OLD.repo_id;
end if;
end if;
return null;
return NEW;
END;
$def$
LANGUAGE plpgsql;


+ 5
- 0
models/repo.go View File

@@ -1554,6 +1554,11 @@ func GetAllMirrorRepositoriesCount() (int64, error) {
return x.Where("is_mirror = ?", true).Count(repo)
}

func GetAllOrgRepositoriesCount() (int64, error) {
repo := new(Repository)
return x.Table("repository").Join("INNER", []string{"\"user\"", "u"}, "repository.owner_id = u.id and u.type=1").Count(repo)
}

func GetAllForkRepositoriesCount() (int64, error) {
repo := new(Repository)
return x.Where("is_fork = ?", true).Count(repo)


+ 48
- 0
models/summary_statistic.go View File

@@ -2,6 +2,8 @@ package models

import (
"fmt"
"strconv"
"time"

"code.gitea.io/gitea/modules/timeutil"
)
@@ -45,6 +47,7 @@ type SummaryStatistic struct {
NumRepoFork int64 `xorm:"NOT NULL DEFAULT 0"`
NumRepoMirror int64 `xorm:"NOT NULL DEFAULT 0"`
NumRepoSelf int64 `xorm:"NOT NULL DEFAULT 0"`
NumRepoOrg int64 `xorm:"NOT NULL DEFAULT 0"`
CreatedUnix timeutil.TimeStamp `xorm:"INDEX created"`
UpdatedUnix timeutil.TimeStamp `xorm:"INDEX updated"`
}
@@ -69,6 +72,51 @@ func DeleteSummaryStatisticDaily(date string) error {
return nil
}

func GetLatest2SummaryStatistic() ([]*SummaryStatistic, error) {
summaryStatistics := make([]*SummaryStatistic, 0)
err := xStatistic.Desc("created_unix").Limit(2).Find(&summaryStatistics)
return summaryStatistics, err
}

func GetSummaryStatisticByTimeCount(beginTime time.Time, endTime time.Time) (int64, error) {
summaryStatistics := new(SummaryStatistic)
total, err := xStatistic.Asc("created_unix").Where("created_unix>=" + strconv.FormatInt(beginTime.Unix(), 10) + " and created_unix<" + strconv.FormatInt(endTime.Unix(), 10)).Count(summaryStatistics)
return total, err
}

func GetSummaryStatisticByDateCount(dates []string) (int64, error) {
summaryStatistics := new(SummaryStatistic)
total, err := xStatistic.Asc("created_unix").In("date", dates).Count(summaryStatistics)
return total, err
}


func GetAllSummaryStatisticByTime(beginTime time.Time, endTime time.Time) ([]*SummaryStatistic, error) {
summaryStatistics := make([]*SummaryStatistic, 0)
err := xStatistic.Asc("created_unix").Where("created_unix>=" + strconv.FormatInt(beginTime.Unix(), 10) + " and created_unix<" + strconv.FormatInt(endTime.Unix(), 10)).Find(&summaryStatistics)

return summaryStatistics, err
}

func GetSummaryStatisticByTime(beginTime time.Time, endTime time.Time, page int, pageSize int) ([]*SummaryStatistic, error) {
summaryStatistics := make([]*SummaryStatistic, 0)
err := xStatistic.Asc("created_unix").Limit(pageSize+1, (page-1)*pageSize).Where("created_unix>=" + strconv.FormatInt(beginTime.Unix(), 10) + " and created_unix<" + strconv.FormatInt(endTime.Unix(), 10)).Find(&summaryStatistics)

return summaryStatistics, err
}

func GetAllSummaryStatisticByDates(dates []string) ([]*SummaryStatistic, error) {
summaryStatistics := make([]*SummaryStatistic, 0)
err := xStatistic.Asc("created_unix").In("date", dates).Find(&summaryStatistics)
return summaryStatistics, err
}

func GetSummaryStatisticByDates(dates []string, page int, pageSize int) ([]*SummaryStatistic, error) {
summaryStatistics := make([]*SummaryStatistic, 0)
err := xStatistic.Asc("created_unix").In("date", dates).Limit(pageSize+1, (page-1)*pageSize).Find(&summaryStatistics)
return summaryStatistics, err
}

func InsertSummaryStatistic(summaryStatistic *SummaryStatistic) (int64, error) {
return xStatistic.Insert(summaryStatistic)
}

+ 199
- 10
models/user_business_analysis.go View File

@@ -1,9 +1,11 @@
package models

import (
"encoding/json"
"fmt"
"sort"
"strconv"
"strings"
"time"

"code.gitea.io/gitea/modules/log"
@@ -227,7 +229,23 @@ func getLastCountDate() int64 {
return pageStartTime.Unix()
}

func QueryMetrics(start int64, end int64) ([]*UserMetrics, int64) {
func QueryMetricsPage(start int64, end int64) ([]*UserMetrics, int64) {

statictisSess := xStatistic.NewSession()
defer statictisSess.Close()
cond := "count_date >" + fmt.Sprint(start) + " and count_date<" + fmt.Sprint(end)

userMetricsList := make([]*UserMetrics, 0)
//.Limit(pageSize, page*pageSize)
if err := statictisSess.Table(new(UserMetrics)).Where(cond).OrderBy("count_date desc").
Find(&userMetricsList); err != nil {
return nil, 0
}
postUserMetricsList := postDeal(userMetricsList)
return postUserMetricsList, int64(len(postUserMetricsList))
}

func QueryMetrics(start int64, end int64) ([]*UserMetrics, int) {
statictisSess := xStatistic.NewSession()
defer statictisSess.Close()
userMetricsList := make([]*UserMetrics, 0)
@@ -235,7 +253,91 @@ func QueryMetrics(start int64, end int64) ([]*UserMetrics, int64) {
Find(&userMetricsList); err != nil {
return nil, 0
}
return userMetricsList, int64(len(userMetricsList))
postUserMetricsList := postDeal(userMetricsList)
return postUserMetricsList, int(len(postUserMetricsList))
}

func duplicateRemoval(userMetricsList []*UserMetrics) []*UserMetrics {
userMetricsResult := make([]*UserMetrics, 0)
for i := 0; i < len(userMetricsList); i++ {
if i > 0 {
if userMetricsList[i].DataDate == userMetricsList[i-1].DataDate {
continue
}
}
userMetricsResult = append(userMetricsResult, userMetricsList[i])
}
return userMetricsResult
}

func postDeal(userMetricsList []*UserMetrics) []*UserMetrics {
duplicateRemovalUserMetricsList := duplicateRemoval(userMetricsList)
for _, userMetrics := range duplicateRemovalUserMetricsList {
userMetrics.DisplayDate = userMetrics.DataDate
userMetrics.TotalRegistUser = userMetrics.ActivateRegistUser + userMetrics.NotActivateRegistUser
userMetrics.TotalNotActivateRegistUser = userMetrics.TotalUser - userMetrics.TotalActivateRegistUser
}
return duplicateRemovalUserMetricsList
}

func QueryMetricsForAll(start int64, end int64) []*UserMetrics {
statictisSess := xStatistic.NewSession()
defer statictisSess.Close()
userMetricsList := make([]*UserMetrics, 0)
if err := statictisSess.Table(new(UserMetrics)).Where("count_date >" + fmt.Sprint(start) + " and count_date<" + fmt.Sprint(end)).OrderBy("count_date desc").
Find(&userMetricsList); err != nil {
return nil
}
duplicateRemovalUserMetricsList := duplicateRemoval(userMetricsList)
return makeResultForMonth(duplicateRemovalUserMetricsList, len(duplicateRemovalUserMetricsList))
}

func QueryMetricsForYear(start int64, end int64) []*UserMetrics {

allUserInfo, count := QueryMetrics(start, end)

return makeResultForMonth(allUserInfo, count)
}

func makeResultForMonth(allUserInfo []*UserMetrics, count int) []*UserMetrics {
monthMap := make(map[string]*UserMetrics)
if count > 0 {
for _, userMetrics := range allUserInfo {
dateTime := time.Unix(userMetrics.CountDate, 0)
month := fmt.Sprint(dateTime.Year()) + "-" + fmt.Sprint(int(dateTime.Month()))
if _, ok := monthMap[month]; !ok {
monthUserMetrics := &UserMetrics{
DisplayDate: month,
ActivateRegistUser: userMetrics.ActivateRegistUser,
NotActivateRegistUser: userMetrics.NotActivateRegistUser,
TotalUser: userMetrics.TotalUser,
TotalNotActivateRegistUser: userMetrics.TotalUser - userMetrics.TotalActivateRegistUser,
TotalActivateRegistUser: userMetrics.TotalActivateRegistUser,
TotalHasActivityUser: userMetrics.TotalHasActivityUser,
HasActivityUser: userMetrics.HasActivityUser,
DaysForMonth: 1,
TotalRegistUser: userMetrics.ActivateRegistUser + userMetrics.NotActivateRegistUser,
}
monthMap[month] = monthUserMetrics
} else {
value := monthMap[month]
value.ActivateRegistUser += userMetrics.ActivateRegistUser
value.NotActivateRegistUser += userMetrics.NotActivateRegistUser
value.HasActivityUser += userMetrics.HasActivityUser
value.TotalRegistUser += userMetrics.ActivateRegistUser + userMetrics.NotActivateRegistUser
value.ActivateIndex = float64(value.ActivateRegistUser) / float64(value.TotalRegistUser)
value.DaysForMonth += 1
}
}
}
result := make([]*UserMetrics, 0)
for _, value := range monthMap {
result = append(result, value)
}
sort.Slice(result, func(i, j int) bool {
return strings.Compare(result[i].DisplayDate, result[j].DisplayDate) > 0
})
return result
}

func QueryRankList(key string, tableName string, limit int) ([]*UserBusinessAnalysisAll, int64) {
@@ -540,6 +642,7 @@ func refreshUserStaticTable(wikiCountMap map[string]int, tableName string, pageS
if minUserIndex > dateRecordAll.UserIndexPrimitive {
minUserIndex = dateRecordAll.UserIndexPrimitive
}

dateRecordBatch = append(dateRecordBatch, dateRecordAll)
if len(dateRecordBatch) >= BATCH_INSERT_SIZE {
insertTable(dateRecordBatch, tableName, statictisSess)
@@ -550,7 +653,9 @@ func refreshUserStaticTable(wikiCountMap map[string]int, tableName string, pageS
dateRecordBatch = make([]UserBusinessAnalysisAll, 0)
}
if tableName == "user_business_analysis_all" {
if dateRecordAll.UserIndex > 0 || dateRecordAll.LoginCount > 0 {
tValue := getUserActivateAll(dateRecordAll)
if tValue > 0 {
log.Info("dateRecordAll name=" + dateRecordAll.Name + " value=" + fmt.Sprint(tValue))
userMetrics["TotalHasActivityUser"] = getMapKeyStringValue("TotalHasActivityUser", userMetrics) + 1
}
}
@@ -567,7 +672,9 @@ func refreshUserStaticTable(wikiCountMap map[string]int, tableName string, pageS
log.Info("insert all data failed." + err.Error())
}
}

if tableName == "user_business_analysis_all" {
log.Info("TotalHasActivityUser=" + fmt.Sprint(userMetrics["TotalHasActivityUser"]))
}
//normalization
for k, v := range userIndexMap {
tmpResult := (v - minUserIndex) / (maxUserIndex - minUserIndex)
@@ -672,6 +779,8 @@ func CounDataByDateAndReCount(wikiCountMap map[string]int, startTime time.Time,
log.Info("query commit code errr.")
} else {
log.Info("query commit code size, len=" + fmt.Sprint(len(CommitCodeSizeMap)))
CommitCodeSizeMapJson, _ := json.Marshal(CommitCodeSizeMap)
log.Info("CommitCodeSizeMapJson=" + string(CommitCodeSizeMapJson))
}
CommitDatasetSizeMap, CommitDatasetNumMap := queryDatasetSize(start_unix, end_unix)
SolveIssueCountMap := querySolveIssue(start_unix, end_unix)
@@ -689,13 +798,13 @@ func CounDataByDateAndReCount(wikiCountMap map[string]int, startTime time.Time,
statictisSess := xStatistic.NewSession()
defer statictisSess.Close()

cond := "type != 1 and is_active=true"
cond := "type != 1"
count, err := sess.Where(cond).Count(new(User))
if err != nil {
log.Info("query user error. return.")
return err
}
userNewAddActivity := make(map[int64]map[int64]int64)
ParaWeight := getParaWeight()
userMetrics := make(map[string]int)
var indexTotal int64
@@ -711,8 +820,6 @@ func CounDataByDateAndReCount(wikiCountMap map[string]int, startTime time.Time,
log.Info("i=" + fmt.Sprint(i) + " userName=" + userRecord.Name)
dateRecord.CountDate = CountDate.Unix()

statictisSess.Delete(&dateRecord)

dateRecord.Email = userRecord.Email
dateRecord.RegistDate = userRecord.CreatedUnix
dateRecord.Name = userRecord.Name
@@ -767,6 +874,14 @@ func CounDataByDateAndReCount(wikiCountMap map[string]int, startTime time.Time,

dateRecord.UserIndexPrimitive = getUserIndex(dateRecord, ParaWeight)
setUserMetrics(userMetrics, userRecord, start_unix, end_unix, dateRecord)
if getUserActivate(dateRecord) > 0 {
log.Info("has activity." + userRecord.Name)
addUserToMap(userNewAddActivity, userRecord.CreatedUnix, dateRecord.ID)
}
if userRecord.IsActive {
continue
}
statictisSess.Delete(&dateRecord)
_, err = statictisSess.Insert(&dateRecord)
if err != nil {
log.Info("insert daterecord failed." + err.Error())
@@ -781,22 +896,75 @@ func CounDataByDateAndReCount(wikiCountMap map[string]int, startTime time.Time,
}

RefreshUserStaticAllTabel(wikiCountMap, userMetrics)
log.Info("start to update UserMetrics")
//insert userMetrics table
var useMetrics UserMetrics
useMetrics.CountDate = CountDate.Unix()
statictisSess.Delete(&useMetrics)

useMetrics.DataDate = DataDate
useMetrics.ActivateRegistUser = getMapKeyStringValue("ActivateRegistUser", userMetrics)
useMetrics.HasActivityUser = getMapKeyStringValue("HasActivityUser", userMetrics)
useMetrics.RegistActivityUser = 0
useMetrics.NotActivateRegistUser = getMapKeyStringValue("NotActivateRegistUser", userMetrics)
useMetrics.TotalActivateRegistUser = getMapKeyStringValue("TotalActivateRegistUser", userMetrics)
useMetrics.TotalHasActivityUser = getMapKeyStringValue("TotalHasActivityUser", userMetrics)
statictisSess.Insert(&useMetrics)

count, err = sess.Where("type=0").Count(new(User))
if err != nil {
log.Info("query user error. return.")
}
useMetrics.TotalUser = int(count)
if useMetrics.ActivateRegistUser+useMetrics.NotActivateRegistUser == 0 {
useMetrics.ActivateIndex = 0
} else {
useMetrics.ActivateIndex = float64(useMetrics.ActivateRegistUser) / float64(useMetrics.ActivateRegistUser+useMetrics.NotActivateRegistUser)
}
statictisSess.Insert(&useMetrics)
//update new user activity
updateNewUserAcitivity(userNewAddActivity, statictisSess)
return nil
}

func updateNewUserAcitivity(currentUserActivity map[int64]map[int64]int64, statictisSess *xorm.Session) {
for key, value := range currentUserActivity {
useMetrics := &UserMetrics{CountDate: key}
has, err := statictisSess.Get(useMetrics)
if err == nil && has {
userIdArrays := strings.Split(useMetrics.HasActivityUserJson, ",")
for _, userIdStr := range userIdArrays {
userIdInt, err := strconv.ParseInt(userIdStr, 10, 64)
if err == nil {
value[userIdInt] = userIdInt
}
}
userIdArray := ""
for _, tmpValue := range value {
userIdArray += fmt.Sprint(tmpValue) + ","
}
useMetrics.HasActivityUser = len(value)
if len(userIdArray) > 0 {
useMetrics.HasActivityUserJson = userIdArray[0 : len(userIdArray)-1]
}
updateSql := "update public.user_metrics set has_activity_user_json='" + useMetrics.HasActivityUserJson + "',regist_activity_user=" + fmt.Sprint(useMetrics.HasActivityUser) + " where count_date=" + fmt.Sprint(key)
statictisSess.Exec(updateSql)
}
}
}

func addUserToMap(currentUserActivity map[int64]map[int64]int64, registDate timeutil.TimeStamp, userId int64) {
CountDateTime := time.Date(registDate.Year(), registDate.AsTime().Month(), registDate.AsTime().Day(), 0, 1, 0, 0, registDate.AsTime().Location())
CountDate := CountDateTime.Unix()
if _, ok := currentUserActivity[CountDate]; !ok {
userIdMap := make(map[int64]int64, 0)
userIdMap[userId] = userId
currentUserActivity[CountDate] = userIdMap
} else {
currentUserActivity[CountDate][userId] = userId
}

}

func setUserMetrics(userMetrics map[string]int, user *User, start_time int64, end_time int64, dateRecord UserBusinessAnalysis) {
//ActivateRegistUser int `xorm:"NOT NULL DEFAULT 0"`
//NotActivateRegistUser int `xorm:"NOT NULL DEFAULT 0"`
@@ -875,6 +1043,27 @@ func getUserIndexFromAnalysisAll(dateRecord UserBusinessAnalysisAll, ParaWeight
return result
}

func getUserActivateAll(dateRecord UserBusinessAnalysisAll) int {
var result int
result += dateRecord.CodeMergeCount
result += dateRecord.CommitCount
result += dateRecord.IssueCount
result += dateRecord.CommentCount
result += dateRecord.FocusRepoCount
result += dateRecord.StarRepoCount
result += dateRecord.SolveIssueCount
result += dateRecord.EncyclopediasCount
result += dateRecord.CreateRepoCount
result += dateRecord.CloudBrainTaskNum
result += dateRecord.CommitModelCount
result += dateRecord.CommitDatasetNum
result += dateRecord.FocusOtherUser
result += dateRecord.CollectDataset
result += dateRecord.CollectImage
result += dateRecord.CommitCodeSize
return result
}

func getUserActivate(dateRecord UserBusinessAnalysis) int {
var result int
result += dateRecord.CodeMergeCount


+ 15
- 6
models/user_business_struct.go View File

@@ -400,10 +400,19 @@ type UserAnalysisPara struct {
}

type UserMetrics struct {
CountDate int64 `xorm:"pk"`
ActivateRegistUser int `xorm:"NOT NULL DEFAULT 0"`
NotActivateRegistUser int `xorm:"NOT NULL DEFAULT 0"`
HasActivityUser int `xorm:"NOT NULL DEFAULT 0"`
TotalActivateRegistUser int `xorm:"NOT NULL DEFAULT 0"`
TotalHasActivityUser int `xorm:"NOT NULL DEFAULT 0"`
CountDate int64 `xorm:"pk"`
ActivateRegistUser int `xorm:"NOT NULL DEFAULT 0"`
NotActivateRegistUser int `xorm:"NOT NULL DEFAULT 0"`
ActivateIndex float64 `xorm:"NOT NULL DEFAULT 0"`
RegistActivityUser int `xorm:"NOT NULL DEFAULT 0"`
HasActivityUser int `xorm:"NOT NULL DEFAULT 0"`
TotalUser int `xorm:"NOT NULL DEFAULT 0"`
TotalRegistUser int `xorm:"-"`
TotalActivateRegistUser int `xorm:"NOT NULL DEFAULT 0"`
TotalNotActivateRegistUser int `xorm:"-"`
TotalHasActivityUser int `xorm:"NOT NULL DEFAULT 0"`
DisplayDate string `xorm:"-"`
DataDate string `xorm:"NULL"`
DaysForMonth int `xorm:"NOT NULL DEFAULT 0"`
HasActivityUserJson string `xorm:"text NULL"`
}

+ 6
- 0
modules/auth/repo_form.go View File

@@ -740,3 +740,9 @@ type CreateCourseForm struct {
func (f *CreateCourseForm) Validate(ctx *macaron.Context, errs binding.Errors) binding.Errors {
return validate(errs, ctx.Data, f, ctx.Locale)
}

// RenameRepoFileForm form for renaming repository file
type RenameRepoFileForm struct {
TreePath string `binding:"Required;MaxSize(500)"`
LastCommit string
}

+ 9
- 3
modules/cloudbrain/cloudbrain.go View File

@@ -1,11 +1,12 @@
package cloudbrain

import (
"code.gitea.io/gitea/modules/timeutil"
"encoding/json"
"errors"
"strconv"

"code.gitea.io/gitea/modules/timeutil"

"code.gitea.io/gitea/modules/storage"

"code.gitea.io/gitea/models"
@@ -28,6 +29,8 @@ const (
Snn4imagenetMountPath = "/snn4imagenet"
BrainScoreMountPath = "/brainscore"
TaskInfoName = "/taskInfo"
Snn4imagenetCommand = `/opt/conda/bin/python /snn4imagenet/testSNN_script.py --modelname '%s' --modelpath '/dataset' --modeldescription '%s'`
BrainScoreCommand = `bash /brainscore/brainscore_test_par4shSrcipt.sh -b '%s' -n '%s' -p '/dataset' -d '%s'`

SubTaskName = "task1"

@@ -184,7 +187,6 @@ func AdminOrImageCreaterRight(ctx *context.Context) {

}


func GenerateTask(ctx *context.Context, displayJobName, jobName, image, command, uuid, codePath, modelPath, benchmarkPath, snn4imagenetPath, brainScorePath, jobType, gpuQueue, description, branchName, bootFile, params string, benchmarkTypeID, benchmarkChildTypeID, resourceSpecId int) error {

dataActualPath := setting.Attachment.Minio.RealPath +
@@ -347,7 +349,7 @@ func GenerateTask(ctx *context.Context, displayJobName, jobName, image, command,
}
stringId := strconv.FormatInt(task.ID, 10)

if string(models.JobTypeBenchmark) == jobType {
if IsBenchmarkJob(jobType) {
notification.NotifyOtherTask(ctx.User, ctx.Repo.Repository, stringId, displayJobName, models.ActionCreateBenchMarkTask)
} else if string(models.JobTypeTrain) == jobType {
notification.NotifyOtherTask(ctx.User, ctx.Repo.Repository, jobID, displayJobName, models.ActionCreateGPUTrainTask)
@@ -358,6 +360,10 @@ func GenerateTask(ctx *context.Context, displayJobName, jobName, image, command,
return nil
}

func IsBenchmarkJob(jobType string) bool {
return string(models.JobTypeBenchmark) == jobType || string(models.JobTypeBrainScore) == jobType || string(models.JobTypeSnn4imagenet) == jobType
}

func RestartTask(ctx *context.Context, task *models.Cloudbrain, newID *string) error {
dataActualPath := setting.Attachment.Minio.RealPath +
setting.Attachment.Minio.Bucket + "/" +


+ 19
- 20
modules/cloudbrain/resty.go View File

@@ -4,7 +4,6 @@ import (
"encoding/json"
"errors"
"fmt"
"math"
"net/http"
"strconv"
"strings"
@@ -213,8 +212,9 @@ func getQueryString(page int, size int, name string) string {
}

func CommitImage(jobID string, params models.CommitImageParams) error {
imageTag := strings.TrimSpace(params.ImageTag)

dbImage, err := models.GetImageByTag(params.ImageTag)
dbImage, err := models.GetImageByTag(imageTag)

if err != nil && !models.IsErrImageNotExist(err) {
return fmt.Errorf("resty CommitImage: %v", err)
@@ -224,12 +224,12 @@ func CommitImage(jobID string, params models.CommitImageParams) error {
if dbImage != nil {
if dbImage.UID != params.UID {
return models.ErrorImageTagExist{
Tag: params.ImageTag,
Tag: imageTag,
}
} else {
if dbImage.Status == models.IMAGE_STATUS_COMMIT {
return models.ErrorImageCommitting{
Tag: params.ImageTag,
Tag: imageTag,
}

} else { //覆盖提交
@@ -282,9 +282,9 @@ sendjob:
CloudbrainType: params.CloudBrainType,
UID: params.UID,
IsPrivate: params.IsPrivate,
Tag: params.ImageTag,
Tag: imageTag,
Description: params.ImageDescription,
Place: setting.Cloudbrain.ImageURLPrefix + params.ImageTag,
Place: setting.Cloudbrain.ImageURLPrefix + imageTag,
Status: models.IMAGE_STATUS_COMMIT,
}

@@ -318,15 +318,15 @@ sendjob:
}

func CommitAdminImage(params models.CommitImageParams) error {
exist, err := models.IsImageExist(params.ImageTag)
imageTag := strings.TrimSpace(params.ImageTag)
exist, err := models.IsImageExist(imageTag)

if err != nil {
return fmt.Errorf("resty CommitImage: %v", err)
}
if exist {
return models.ErrorImageTagExist{
Tag: params.ImageTag,
Tag: imageTag,
}
}

@@ -334,7 +334,7 @@ func CommitAdminImage(params models.CommitImageParams) error {
CloudbrainType: params.CloudBrainType,
UID: params.UID,
IsPrivate: params.IsPrivate,
Tag: params.ImageTag,
Tag: imageTag,
Description: params.ImageDescription,
Place: params.Place,
Status: models.IMAGE_STATUS_SUCCESS,
@@ -358,17 +358,16 @@ func CommitAdminImage(params models.CommitImageParams) error {
}

func updateImageStatus(image models.Image, isSetCreatedUnix bool, createTime time.Time) {
attemps := 5
attemps := 60
commitSuccess := false
time.Sleep(5 * time.Second)
for i := 0; i < attemps; i++ {

if commitSuccess {
break
}

for i := 0; i < attemps; i++ {
time.Sleep(20 * time.Second)
log.Info("the " + strconv.Itoa(i) + " times query cloudbrain images.Imagetag:" + image.Tag + "isSetCreate:" + strconv.FormatBool(isSetCreatedUnix))
result, err := GetImagesPageable(1, pageSize, Custom, "")
if err == nil && result.Code == "S000" {

log.Info("images count:" + strconv.Itoa(result.Payload.Count))
for _, v := range result.Payload.ImageInfo {
if v.Place == image.Place && (!isSetCreatedUnix || (isSetCreatedUnix && createTimeUpdated(v, createTime))) {
image.Status = models.IMAGE_STATUS_SUCCESS
@@ -380,10 +379,10 @@ func updateImageStatus(image models.Image, isSetCreatedUnix bool, createTime tim
}

}
//第一次循环等待4秒,第二次等待4的2次方16秒,...,第5次。。。 ,总共大概是20多分钟内进行5次重试
var sleepTime = time.Duration(int(math.Pow(4, (float64(i + 1)))))

time.Sleep(sleepTime * time.Second)
if commitSuccess {
break
}

}
if !commitSuccess {


+ 30
- 0
modules/private/hook.go View File

@@ -50,6 +50,11 @@ type HookPostReceiveBranchResult struct {
URL string
}

// HookEnvResult
type HookEnvResult struct {
Config map[string]string
}

// HookPreReceive check whether the provided commits are allowed
func HookPreReceive(ownerName, repoName string, opts HookOptions) (int, string) {
reqURL := setting.LocalURL + fmt.Sprintf("api/internal/hook/pre-receive/%s/%s",
@@ -122,3 +127,28 @@ func SetDefaultBranch(ownerName, repoName, branch string) error {
}
return nil
}

// GetHookConfig get hook config to set environment for hook script
func GetHookConfig(ownerName, repoName string) (map[string]string, string) {
reqURL := setting.LocalURL + fmt.Sprintf("api/internal/hook/env/%s/%s",
url.PathEscape(ownerName),
url.PathEscape(repoName),
)

req := newInternalRequest(reqURL, "GET")
req = req.Header("Content-Type", "application/json")
req.SetTimeout(60*time.Second, time.Duration(60)*time.Second)
resp, err := req.Response()
if err != nil {
return nil, fmt.Sprintf("Unable to contact gitea: %v", err.Error())
}
defer resp.Body.Close()

if resp.StatusCode != http.StatusOK {
return nil, decodeJSONError(resp).Err
}
res := &HookEnvResult{}
_ = json.NewDecoder(resp.Body).Decode(res)

return res.Config, ""
}

+ 28
- 0
modules/repofiles/temp_repo.go View File

@@ -109,6 +109,34 @@ func (t *TemporaryUploadRepository) LsFiles(filenames ...string) ([]string, erro
return filelist, nil
}

// LsFilesStage list all files with stage format in index for the given paths
// if the given path is directory ,then return all files under it
// if the given path is file ,then return the file
func (t *TemporaryUploadRepository) LsFilesStage(paths ...string) ([]string, error) {
stdOut := new(bytes.Buffer)
stdErr := new(bytes.Buffer)

cmdArgs := []string{"ls-files", "-z", "-s", "--"}
for _, arg := range paths {
if arg != "" {
cmdArgs = append(cmdArgs, arg)
}
}

if err := git.NewCommand(cmdArgs...).RunInDirPipeline(t.basePath, stdOut, stdErr); err != nil {
log.Error("Unable to run git ls-files for temporary repo: %s (%s) Error: %v\nstdout: %s\nstderr: %s", t.repo.FullName(), t.basePath, err, stdOut.String(), stdErr.String())
err = fmt.Errorf("Unable to run git ls-files for temporary repo of: %s Error: %v\nstdout: %s\nstderr: %s", t.repo.FullName(), err, stdOut.String(), stdErr.String())
return nil, err
}

filelist := make([]string, 0)
for _, line := range bytes.Split(stdOut.Bytes(), []byte{'\000'}) {
filelist = append(filelist, string(line))
}

return filelist, nil
}

// RemoveFilesFromIndex removes the given files from the index
func (t *TemporaryUploadRepository) RemoveFilesFromIndex(filenames ...string) error {
stdOut := new(bytes.Buffer)


+ 207
- 0
modules/repofiles/update.go View File

@@ -756,3 +756,210 @@ func createCommitRepoActions(repo *models.Repository, gitRepo *git.Repository, o
}
return actions, nil
}

// RenameRepoFileOptions
type RenameRepoFileOptions struct {
LastCommitID string
BranchName string
TreePath string
FromTreePath string
Message string
Author *IdentityOptions
Committer *IdentityOptions
}

// RenameRepoFile rename file in the given repository
func RenameRepoFile(repo *models.Repository, doer *models.User, opts *RenameRepoFileOptions) error {

// Branch must exist for this operation
if _, err := repo_module.GetBranch(repo, opts.BranchName); err != nil {
return err
}

//make sure user can commit to the given branch
if err := checkBranchProtection(doer, repo, opts.BranchName, opts.TreePath); err != nil {
return err
}

// Check that the path given in opts.treePath is valid (not a git path)
treePath := CleanUploadFileName(opts.TreePath)
if treePath == "" {
return models.ErrFilenameInvalid{
Path: opts.TreePath,
}
}
// If there is a fromTreePath (we are copying it), also clean it up
fromTreePath := CleanUploadFileName(opts.FromTreePath)
if fromTreePath == "" && opts.FromTreePath != "" {
return models.ErrFilenameInvalid{
Path: opts.FromTreePath,
}
}

author, committer := GetAuthorAndCommitterUsers(opts.Author, opts.Committer, doer)

t, err := NewTemporaryUploadRepository(repo)
if err != nil {
log.Error("%v", err)
}
defer t.Close()
if err := t.Clone(opts.BranchName); err != nil {
return err
}
if err := t.SetDefaultIndex(); err != nil {
return err
}

// Get the commit of the original branch
commit, err := t.GetBranchCommit(opts.BranchName)
if err != nil {
return err // Couldn't get a commit for the branch
}

lastCommitID, err := t.gitRepo.ConvertToSHA1(opts.LastCommitID)
if err != nil {
return fmt.Errorf("DeleteRepoFile: Invalid last commit ID: %v", err)
}
opts.LastCommitID = lastCommitID.String()

if opts.LastCommitID == "" {
// When updating a file, a lastCommitID needs to be given to make sure other commits
// haven't been made. We throw an error if one wasn't provided.
return models.ErrSHAOrCommitIDNotProvided{}
}

//if fromTreePath not exist,return error
_, err = commit.GetTreeEntryByPath(fromTreePath)
if err != nil {
return err
}

// If a lastCommitID was given and it doesn't match the commitID of the head of the branch throw
// an error.
if commit.ID.String() != opts.LastCommitID {
if changed, err := commit.FileChangedSinceCommit(fromTreePath, opts.LastCommitID); err != nil {
return err
} else if changed {
return models.ErrCommitIDDoesNotMatch{
GivenCommitID: opts.LastCommitID,
CurrentCommitID: opts.LastCommitID,
}
}
}

//if treePath has been exist,return error
_, err = commit.GetTreeEntryByPath(treePath)
if err == nil || !git.IsErrNotExist(err) {
// Means the file has been exist in new path
return models.ErrFilePathInvalid{
Message: fmt.Sprintf("a file exists where you’re trying to create a subdirectory [path: %s]", treePath),
Path: treePath,
Name: treePath,
Type: git.EntryModeBlob,
}
}

//move and add files to index
if err = moveAndAddFiles(fromTreePath, treePath, t); err != nil {
return err
}

// Now write the tree
treeHash, err := t.WriteTree()
if err != nil {
return err
}

// Now commit the tree
message := strings.TrimSpace(opts.Message)
commitHash, err := t.CommitTree(author, committer, treeHash, message)
if err != nil {
return err
}

// Then push this tree to NewBranch
if err := t.Push(doer, commitHash, opts.BranchName); err != nil {
log.Error("%T %v", err, err)
return err
}

return nil
}

func checkBranchProtection(doer *models.User, repo *models.Repository, branchName, treePath string) error {
//make sure user can commit to the given branch
protectedBranch, err := repo.GetBranchProtection(branchName)
if err != nil {
return err
}
if protectedBranch != nil {
if !protectedBranch.CanUserPush(doer.ID) {
return models.ErrUserCannotCommit{
UserName: doer.LowerName,
}
}
if protectedBranch.RequireSignedCommits {
_, _, err := repo.SignCRUDAction(doer, repo.RepoPath(), branchName)
if err != nil {
if !models.IsErrWontSign(err) {
return err
}
return models.ErrUserCannotCommit{
UserName: doer.LowerName,
}
}
}
patterns := protectedBranch.GetProtectedFilePatterns()
for _, pat := range patterns {
if pat.Match(strings.ToLower(treePath)) {
return models.ErrFilePathProtected{
Path: treePath,
}
}
}
}
return nil
}

func moveAndAddFiles(oldTreePath, newTreePath string, t *TemporaryUploadRepository) error {
array, err := t.LsFilesStage(oldTreePath)
if err != nil {
return err
}
if len(array) == 0 {
return git.ErrNotExist{RelPath: oldTreePath}
}
stdOut := new(bytes.Buffer)
stdErr := new(bytes.Buffer)
stdIn := new(bytes.Buffer)
//write all files in stage format to the stdin,
//for each file,remove old tree path and add new tree path
//see the update-index help document at https://git-scm.com/docs/git-update-index
//especially see the content of "USING --INDEX-INFO"
for _, v := range array {
if v == "" {
continue
}
//example for v(mode SHA-1 stage file)
//100755 d294c88235ac05d3dece028d8a65590f28ec46ac 0 custom/conf/app.ini
v = strings.ReplaceAll(v, "0\t", "")
tmpArray := strings.Split(v, " ")
oldPath := tmpArray[2]
newPath := newTreePath + strings.TrimPrefix(oldPath, oldTreePath)
// mode 0 means remove file
stdIn.WriteString("0 0000000000000000000000000000000000000000\t")
stdIn.WriteString(oldPath)
stdIn.WriteByte('\000')
stdIn.WriteString(tmpArray[0] + " ")
stdIn.WriteString(tmpArray[1] + "\t")
stdIn.WriteString(newPath)
stdIn.WriteByte('\000')
}

if err := git.NewCommand("update-index", "--replace", "-z", "--index-info").RunInDirFullPipeline(t.basePath, stdOut, stdErr, stdIn); err != nil {
log.Error("Unable to update-index for temporary repo: %s (%s) Error: %v\nstdout: %s\nstderr: %s", t.repo.FullName(), t.basePath, err, stdOut.String(), stdErr.String())
return fmt.Errorf("Unable to update-index for temporary repo: %s Error: %v\nstdout: %s\nstderr: %s", t.repo.FullName(), err, stdOut.String(), stdErr.String())
}

return nil
}

+ 1
- 1
modules/repository/hooks.go View File

@@ -36,7 +36,7 @@ func getHookTemplates() (hookNames, hookTpls, giteaHookTpls, sizeLimitTpls []str
fmt.Sprintf("#!/usr/bin/env %s\n\"%s\" hook --config='%s' post-receive\n", setting.ScriptType, setting.AppPath, setting.CustomConf),
}
sizeLimitTpls = []string{
fmt.Sprintf("#!/usr/bin/env %s\n\n\nset -o pipefail\n\nreadonly DEFAULT_FILE_MAXSIZE_MB=\"30\" \nreadonly CONFIG_NAME=\"hooks.maxfilesize\"\nreadonly NULLSHA=\"0000000000000000000000000000000000000000\"\nreadonly EXIT_SUCCESS=0\nreadonly EXIT_FAILURE=1\nreadonly DEFAULT_REPO_MAXSIZE_MB=\"1024\" \nreadonly CHECK_FLAG_ON=1\n\n\nstatus=\"$EXIT_SUCCESS\"\n\n# skip this hook entirely if shell check is not open\ncheck_flag=${PUSH_SIZE_CHECK_FLAG}\nif [[ $check_flag != $CHECK_FLAG_ON ]]; then\nexit $EXIT_SUCCESS\nfi\n\n\n#######################################\n# check the file max size limit\n#######################################\n\n# get maximum filesize (from repository-specific config)\nmaxsize_mb=\"${REPO_MAX_FILE_SIZE}\"\n\nif [[ \"$?\" != $EXIT_SUCCESS ]]; then\necho \"failed to get ${CONFIG_NAME} from config\"\nexit \"$EXIT_FAILURE\"\nfi\n\npush_size=\"0\"\n# read lines from stdin (format: \"<oldref> <newref> <refname>\\n\")\nwhile read oldref newref refname; do\n# skip branch deletions\nif [[ \"$newref\" == \"$NULLSHA\" ]]; then\n continue\nfi\n\n# find large objects\n# check all objects from $oldref (possible $NULLSHA) to $newref, but\n# skip all objects that have already been accepted (i.e. are referenced by\n# another branch or tag).\n\nif [[ \"$oldref\" == \"$NULLSHA\" ]]; then\n target=\"$newref\"\nelse\n target=\"${oldref}..${newref}\"\nfi\nmaxsize=`expr $maxsize_mb \\* 1048576` \n\n# find objects in this push_size\n# print like:\n# 08da8e2ab9ae4095bf94dd71ac913132b880b463 commit 214\n# 43e993b768ede5740e8c65de2ed6edec25053ea1 tree 185\n# 4476971d76569039df7569af1b8d03c288f6b193 blob 20167318 b0417e6593a1.zip\nfiles=\"$(git rev-list --objects \"$target\" --tags=\\* | \\\n git cat-file $'--batch-check=%%(objectname) %%(objecttype) %%(objectsize) %%(rest)')\"\n \nif [[ \"$?\" != $EXIT_SUCCESS ]]; then\n echo \"failed to check for large files in ref ${refname}\"\n continue\nfi\n\n# rewrite IFS to seperate line in $files\nIFS=$'\\n'\nfor file in $files; do\n # if don't unset IFS,temp_array=(${file}) will get error answer\n unset IFS\n temp_array=(${file})\n # add all commit files size\n push_size=`expr $push_size + ${temp_array[2]}`\n if [[ ${temp_array[2]} -gt $maxsize ]]; then\n\t if [[ \"$status\" == $EXIT_SUCCESS ]]; then\n\t\techo -e \"Error: Your push was rejected because it contains files larger than $(numfmt --to=iec \"$maxsize_mb\") Mb\"\n\t\techo \"oversize files:\"\n\t\tstatus=\"$EXIT_FAILURE\"\n\t fi\n\t echo -e \"\\033[31m- ${temp_array[3]} \\033[0m (ref: ${refname}) \"\n fi\ndone\n\nif [[ \"$status\" != $EXIT_SUCCESS ]]; then\n\texit \"$status\"\nfi\n\ndone\n\n#######################################\n# check the repo max size limit\n#######################################\nif [[ $push_size -eq \"0\" ]]; then\n\texit $EXIT_SUCCESS\nfi\n\n\nsizelimit_mb=\"${REPO_MAX_SIZE}\"\nlet sizelimit_b=$sizelimit_mb*1024*1024\n\n# repo size at here means the size of repo directory in server \nreposize_b=${REPO_CURRENT_SIZE}\n\ntotal=`expr $push_size + $reposize_b`\n\nif [ $total -gt $sizelimit_b ]; then\n echo \"Error: Your push was rejected because the repository size is large than $sizelimit_mb Mb\"\n exit $EXIT_FAILURE\nfi\n\n\nexit $EXIT_SUCCESS\n", setting.ScriptType, setting.CustomConf),
fmt.Sprintf("#!/usr/bin/env %s\n\n\nset -o pipefail\n\nreadonly DEFAULT_FILE_MAXSIZE_MB=\"30\" \nreadonly CONFIG_NAME=\"hooks.maxfilesize\"\nreadonly NULLSHA=\"0000000000000000000000000000000000000000\"\nreadonly EXIT_SUCCESS=0\nreadonly EXIT_FAILURE=1\nreadonly DEFAULT_REPO_MAXSIZE_MB=\"1024\" \nreadonly CHECK_FLAG_ON=1\n\n\nstatus=\"$EXIT_SUCCESS\"\n\n# skip this hook entirely if shell check is not open\ncheck_flag=${PUSH_SIZE_CHECK_FLAG}\nif [[ $check_flag != $CHECK_FLAG_ON ]]; then\nexit $EXIT_SUCCESS\nfi\n\n\n#######################################\n# check the file max size limit\n#######################################\n\n# get maximum filesize (from repository-specific config)\nmaxsize_mb=\"${REPO_MAX_FILE_SIZE}\"\n\nif [[ \"$?\" != $EXIT_SUCCESS ]]; then\necho \"failed to get ${CONFIG_NAME} from config\"\nexit \"$EXIT_FAILURE\"\nfi\n\npush_size=\"0\"\n# read lines from stdin (format: \"<oldref> <newref> <refname>\\n\")\nwhile read oldref newref refname; do\n# skip branch deletions\nif [[ \"$newref\" == \"$NULLSHA\" ]]; then\n continue\nfi\n\n# find large objects\n# check all objects from $oldref (possible $NULLSHA) to $newref, but\n# skip all objects that have already been accepted (i.e. are referenced by\n# another branch or tag).\n\nnew_branch_flag=0\nif [[ \"$oldref\" == \"$NULLSHA\" ]]; then\n target=\"$newref\"\n new_branch_flag=1\n echo \"You are creating a new remote branch,openI will check all files in commit history to find oversize files\"\nelse\n target=\"${oldref}..${newref}\"\nfi\nmaxsize=`expr $maxsize_mb \\* 1048576` \n\n# find objects in this push_size\n# print like:\n# 08da8e2ab9ae4095bf94dd71ac913132b880b463 commit 214\n# 43e993b768ede5740e8c65de2ed6edec25053ea1 tree 185\n# 4476971d76569039df7569af1b8d03c288f6b193 blob 20167318 b0417e6593a1.zip\nfiles=\"$(git rev-list --objects \"$target\" | \\\n git cat-file $'--batch-check=%%(objectname) %%(objecttype) %%(objectsize) %%(rest)' | \\\n awk -F ' ' -v maxbytes=\"$maxsize\" 'BEGIN {totalIn=0} {if( $3 > maxbytes && $2 == \"blob\") { totalIn+=$3; print $4} else { totalIn+=$3}} END { printf (\"totalIn=\\t%%s\",totalIn)}' )\"\n \nif [[ \"$?\" != $EXIT_SUCCESS ]]; then\n echo \"failed to check for large files in ref ${refname}\"\n continue\nfi\n\nIFS=$'\\n'\n# rewrite IFS to seperate line in $files\nfor file in $files; do\n # if don't unset IFS,temp_array=(${file}) will get error answer\n \n if [[ ${file} == totalIn=* ]]; then\n\tIFS=$'\\t'\n\ttemp_array=(${file})\n\tpush_size=${temp_array[1]}\n\tcontinue\n fi\n\tunset IFS\n if [[ \"$status\" == $EXIT_SUCCESS ]]; then\n\t\techo -e \"Error: Your push was rejected because it contains files larger than $(numfmt --to=iec \"$maxsize_mb\") Mb\"\n\t\techo \"help document -- https://git.openi.org.cn/zeizei/OpenI_Learning/src/branch/master/docs/git/repository_capacity_help.md\"\n\t\techo \"oversize files:\"\n\t\tstatus=\"$EXIT_FAILURE\"\t\n fi\n echo -e \"\\033[31m- ${file}\\033[0m \"\ndone\n\nif [[ \"$status\" != $EXIT_SUCCESS ]]; then\n\texit \"$status\"\nfi\n\ndone\n\n#######################################\n# check the repo max size limit\n#######################################\nif [[ $push_size -eq \"0\" ]]; then\n\texit $EXIT_SUCCESS\nfi\n\n# if create new branch or tag,use count-objects -v to get pack size\nif [[ $new_branch_flag -eq 1 ]]; then\n size_kb=`git count-objects -v | grep 'size-pack' | sed 's/.*\\(size-pack:\\).//'`\n size_pack_kb=`git count-objects -v | grep 'size:' | sed 's/.*\\(size:\\).//'`\n\ttotal_kb=`expr $size_kb + $size_pack_kb`\n\tlet push_size=$total_kb*1024\nfi\n\nsizelimit_mb=\"${REPO_MAX_SIZE}\"\nlet sizelimit_b=$sizelimit_mb*1024*1024\n\n# repo size at here means the size of repo directory in server \nreposize_b=${REPO_CURRENT_SIZE}\n\ntotal=`expr $push_size + $reposize_b`\n\nif [ $total -gt $sizelimit_b ]; then\n echo \"Error: Your push was rejected because the repository size is large than $sizelimit_mb Mb\"\n echo \"see the help document--https://git.openi.org.cn/zeizei/OpenI_Learning/src/branch/master/docs/git/repository_capacity_help.md\"\n exit $EXIT_FAILURE\nfi\n\n\nexit $EXIT_SUCCESS", setting.ScriptType),
fmt.Sprintf(""),
fmt.Sprintf(""),
}


+ 9
- 5
modules/setting/setting.go View File

@@ -478,10 +478,11 @@ var (
BenchmarkMaxDuration int64

//snn4imagenet config
IsSnn4imagenetEnabled bool
Snn4imagenetOwner string
Snn4imagenetName string
Snn4imagenetServerHost string
IsSnn4imagenetEnabled bool
Snn4imagenetOwner string
Snn4imagenetName string
Snn4imagenetServerHost string
ModelBenchmarkMaxDuration int64

//snn4imagenet config
IsBrainScoreEnabled bool
@@ -584,6 +585,7 @@ var (
GrowthCommit float64
GrowthComments float64
RecordBeginTime string
GrowthBeginTime string
IgnoreMirrorRepo bool
}{}

@@ -1309,6 +1311,7 @@ func NewContext() {
Snn4imagenetOwner = sec.Key("OWNER").MustString("")
Snn4imagenetName = sec.Key("NAME").MustString("")
Snn4imagenetServerHost = sec.Key("HOST").MustString("")
ModelBenchmarkMaxDuration = sec.Key("MAX_DURATION").MustInt64(28800)

sec = Cfg.Section("brainscore")
IsBrainScoreEnabled = sec.Key("ENABLED").MustBool(false)
@@ -1415,7 +1418,8 @@ func SetRadarMapConfig() {
RadarMap.GrowthContributors = sec.Key("growth_contributors").MustFloat64(0.2)
RadarMap.GrowthCommit = sec.Key("growth_commit").MustFloat64(0.2)
RadarMap.GrowthComments = sec.Key("growth_comments").MustFloat64(0.2)
RadarMap.RecordBeginTime = sec.Key("record_beigin_time").MustString("2021-11-05")
RadarMap.RecordBeginTime = sec.Key("record_begin_time").MustString("2021-11-05")
RadarMap.GrowthBeginTime = sec.Key("growth_begin_time").MustString("2022-05-20")
RadarMap.IgnoreMirrorRepo = sec.Key("ignore_mirror_repo").MustBool(true)

}


+ 2
- 1
modules/ssh/ssh.go View File

@@ -5,6 +5,7 @@
package ssh

import (
"code.gitea.io/gitea/services/repository"
"crypto/rand"
"crypto/rsa"
"crypto/x509"
@@ -74,7 +75,7 @@ func sessionHandler(session ssh.Session) {
models.EnvPushSizeCheckFlag+"="+fmt.Sprint(setting.Repository.Upload.ShellFlag),
)

if strings.HasPrefix(command, "git-receive-pack") {
if strings.HasPrefix(command, "git-receive-pack") && setting.Repository.Upload.ShellFlag == repository.SHELL_FLAG_ON {
repo := getRepoFromCommandStr(command)
if repo != nil {
cmd.Env = append(cmd.Env, models.EnvRepoSize+"="+fmt.Sprint(repo.Size))


+ 42
- 6
options/locale/locale_en-US.ini View File

@@ -237,6 +237,8 @@ page_recommend_repo_desc=Excellent AI projects recommendation. To show your proj
page_recommend_repo_commit=Click here to submit.
page_recommend_repo_go=Click here to
page_recommend_repo_more=explore more projects.
page_recommend_activity=Community Activities
page_recommend_activity_desc=The community has prepared a wealth of activities, waiting for you to participate!
page_dev_env=Collaborative Development Environment
page_dev_env_desc=Provide a collaborative development environment for AI development, which is the biggest highlight that distinguishes the OpenI AI Collaboration Platform from other traditional Git platforms.
page_dev_env_desc_title=Unified Management of Development Elements
@@ -261,7 +263,7 @@ search_issue=Issue
search_pr=Pull Request
search_user=User
search_org=Organization
search_finded=Find
search_finded=Find
search_related=related
search_maybe=maybe
search_ge=
@@ -274,7 +276,7 @@ use_plt__fuction = To use the AI collaboration functions provided by this platfo
provide_resoure = Computing resources of CPU/GPU/NPU are provided freely for various types of AI tasks.
activity = Activity
no_events = There are no events related
or_t = or
or_t = or

[explore]
repos = Repositories
@@ -525,6 +527,19 @@ static.public.user_business_analysis_last30_day=Last_30_day
static.public.user_business_analysis_last_month=Last_Month
static.public.user_business_analysis_yesterday=Yesterday
static.public.user_business_analysis_all=All

metrics.sheetname=User Trend Analysis
metrics.date=Count Date
metrics.newregistuser=New registered user
metrics.newregistandactiveuser=New activated
metrics.hasactivateuser=New contributing activities
metrics.newregistnotactiveuser=New inactive
metrics.averageuser=Average new users
metrics.newuseractiveindex=Activation rate of new users
metrics.totalregistuser=Cumulative registered users
metrics.totalactiveduser=Cumulative activated users
metrics.totalhasactivityuser=Cumulative active users

[settings]
profile = Profile
account = Account
@@ -945,6 +960,15 @@ model_manager = Model
model_noright=No right
model_rename=Duplicate model name, please modify model name.

date=Date
repo_add=Project Increment
repo_total=Project Total
repo_public_add=Public Project Increment
repo_private_add=Private Project Increment
repo_fork_add=Fork Project Increment
repo_mirror_add=Mirror Project Increment
repo_self_add=Custom Project Increment

debug=Debug
debug_again=Restart
stop=Stop
@@ -1009,7 +1033,9 @@ get_repo_stat_error=Can not get the statistics of the repository.
get_repo_info_error=Can not get the information of the repository.
generate_statistic_file_error=Failed to generate file.
repo_stat_inspect=ProjectAnalysis
repo_stat_develop=ProjectTrendAnalysis
all=All
current_year=Current_Year

computing.all = All
computing.Introduction=Introduction
@@ -1090,12 +1116,18 @@ modelarts.train_job_para.connfirm=train_job_para.connfirm

modelarts.evaluate_job=Model Evaluation
modelarts.evaluate_job.new_job=New Model Evaluation

cloudbrain.benchmark.evaluate_type=Evaluation Type
cloudbrain.benchmark.evaluate_scenes = Evaluation Scenes
cloudbrain.benchmark.algorithm=Algorithm Evaluation
cloudbrain.benchmark.model=Model Evaluation
cloudbrain.benchmark.evaluate_child_type=Child Type
cloudbrain.benchmark.evaluate_mirror=Mirror
cloudbrain.benchmark.evaluate_train=Train Script
cloudbrain.benchmark.evaluate_test=Test Script
cloudbrain.benchmark.types={"type":[{"id":1,"rank_link":"https://git.openi.org.cn/benchmark/?username=admin&algType=detection","first":"Target detection","second":[{"id":1,"value":"None","attachment":"84cf39c4-d8bc-41aa-aaa3-182ce289b105","owner":"yangzhx","repo_name":"detection_benchmark_script"}]},{"id":2,"rank_link":"https://git.openi.org.cn/benchmark/?username=admin&algType=reid","first":"Target re-identification","second":[{"id":1,"value":"Vehicle re-identification","attachment":"84cf39c4-d8bc-41aa-aaa3-182ce289b105","owner":"JiahongXu","repo_name":"benchmark_reID_script"},{"id":2,"value":"Image-based person re-identification","attachment":"84cf39c4-d8bc-41aa-aaa3-182ce289b105","owner":"JiahongXu","repo_name":"benchmark_reID_script"}]},{"id":3,"rank_link":"https://git.openi.org.cn/benchmark/?username=admin&algType=tracking","first":"Multi-target tracking","second":[{"id":1,"value":"None","attachment":"84cf39c4-d8bc-41aa-aaa3-182ce289b105","owner":"lix07","repo_name":"MOT_benchmark_script"}]}]}
cloudbrain.morethanonejob=You already have a running or waiting task, create it after that task is over.


modelarts.infer_job_model = Model
modelarts.infer_job_model_file = Model File
@@ -1279,6 +1311,7 @@ editor.directory_is_a_file = Directory name '%s' is already used as a filename i
editor.file_is_a_symlink = '%s' is a symbolic link. Symbolic links cannot be edited in the web editor
editor.filename_is_a_directory = Filename '%s' is already used as a directory name in this repository.
editor.file_editing_no_longer_exists = The file being edited, '%s', no longer exists in this repository.
editor.file_or_directory_editing_no_longer_exists = The file or directory being edited, '%s', no longer exists in this repository.
editor.file_deleting_no_longer_exists = The file being deleted, '%s', no longer exists in this repository.
editor.file_changed_while_editing = The file contents have changed since you started editing. <a target="_blank" rel="noopener noreferrer" href="%s">Click here</a> to see them or <strong>Commit Changes again</strong> to overwrite them.
editor.file_already_exists = A file named '%s' already exists in this repository.
@@ -1299,6 +1332,8 @@ editor.require_signed_commit = Branch requires a signed commit
editor.repo_too_large = Repository can not exceed %d MB
editor.repo_file_invalid = Upload files are invalid
editor.upload_file_too_much = Can not upload more than %d files at a time
editor.rename = rename "%s" to %s"
editor.file_changed_while_renaming=The version of the file or folder to be renamed has changed. Please refresh the page and try again


commits.desc = Browse source code change history.
@@ -1363,7 +1398,7 @@ issues.add_milestone_at = `added this to the <b>%s</b> milestone %s`
issues.change_milestone_at = `modified the milestone from <b>%s</b> to <b>%s</b> %s`
issues.remove_milestone_at = `removed this from the <b>%s</b> milestone %s`

issues.add_branch_at=`added this to the <b>%s</b> branch %s`
issues.add_branch_at=`added this to the <b>%s</b> branch %s`
issues.add_tag_at =`added this to the <b>%s</b> tag %s`
issues.change_branch_tag_at= `modified the branch/tag from <b>%s</b> to <b>%s</b> %s`
issues.remove_branch_at=`removed this from the <b>%s</b> branch %s`
@@ -3011,8 +3046,9 @@ shared_memory = Shared Memory


DEBUG = DEBUG
SNN4IMAGENET = SNN4IMAGENET
BRAINSCORE = BRAINSCORE
SNN4IMAGENET = BENCHMARK
BRAINSCORE = BENCHMARK
TRAIN = TRAIN
INFERENCE = INFERENCE
BENCHMARK = BENCHMARK
BENCHMARK = BENCHMARK
brain_area = Brain Area

+ 40
- 4
options/locale/locale_zh-CN.ini View File

@@ -239,6 +239,8 @@ page_recommend_repo_desc=优秀的AI项目推荐;你的项目也想展示到
page_recommend_repo_commit=点此提交
page_recommend_repo_go=。进入
page_recommend_repo_more=项目广场
page_recommend_activity=社区活动
page_recommend_activity_desc=社区准备了丰富的活动,等你来参加!
page_dev_env=协同开发环境
page_dev_env_desc=启智AI协作开发平台与传统git平台最大的不同就在于提供了面向AI开发的协同开发环境
page_dev_env_desc_title=开发要素统一管理
@@ -269,7 +271,7 @@ search_maybe=约为
search_ge=个

wecome_AI_plt=欢迎来到启智AI协作平台!
explore_AI = 探索更好的AI,来这里发现更有意思的
explore_AI = 探索更好的AI,来这里发现更有意思的
datasets = 数据集
repositories = 项目
use_plt__fuction = 使用本平台提供的AI协作功能,如:托管代码、共享数据、调试算法或训练模型,请先
@@ -277,7 +279,7 @@ provide_resoure = 平台目前免费提供CPU、GPU、NPU的算力资源,可
create_pro = 创建项目
activity = 活动
no_events = 还没有与您相关的活动
or_t = 或
or_t = 或


[explore]
@@ -530,6 +532,19 @@ static.public.user_business_analysis_last30_day=近30天
static.public.user_business_analysis_last_month=上月
static.public.user_business_analysis_yesterday=昨天
static.public.user_business_analysis_all=所有

metrics.sheetname=用户趋势分析
metrics.date=日期
metrics.newregistuser=新增注册用户
metrics.newregistandactiveuser=新增已激活
metrics.hasactivateuser=新增有贡献活动
metrics.newregistnotactiveuser=新增未激活
metrics.averageuser=平均新增用户
metrics.newuseractiveindex=新增用户激活率
metrics.totalregistuser=累计注册用户
metrics.totalactiveduser=累计已激活
metrics.totalhasactivityuser=累计有贡献活动

[settings]
profile=个人信息
account=账号
@@ -946,6 +961,16 @@ model_manager = 模型
model_noright=无权限操作
model_rename=模型名称重复,请修改模型名称


date=日期
repo_add=新增项目
repo_total=累计项目
repo_public_add=新增公开项目
repo_private_add=新增私有项目
repo_fork_add=新增派生项目
repo_mirror_add=新增镜像项目
repo_self_add=新增自建项目

debug=调试
debug_again=再次调试
stop=停止
@@ -1017,7 +1042,9 @@ get_repo_stat_error=查询当前仓库的统计信息失败。
get_repo_info_error=查询当前仓库信息失败。
generate_statistic_file_error=生成文件失败。
repo_stat_inspect=项目分析
repo_stat_develop=项目趋势分析
all=所有
current_year=今年

computing.all=全部
computing.Introduction=简介
@@ -1101,12 +1128,17 @@ modelarts.train_job_para.edit=编辑
modelarts.train_job_para.connfirm=确定
modelarts.evaluate_job=评测任务
modelarts.evaluate_job.new_job=新建评测任务
cloudbrain.benchmark.evaluate_scenes = 评测场景
cloudbrain.benchmark.evaluate_type=评测类型
cloudbrain.benchmark.algorithm=算法评测
cloudbrain.benchmark.model=模型评测
cloudbrain.benchmark.evaluate_child_type=子类型
cloudbrain.benchmark.evaluate_mirror=镜像
cloudbrain.benchmark.evaluate_train=训练程序
cloudbrain.benchmark.evaluate_test=测试程序
cloudbrain.benchmark.types={"type":[{"id":1,"rank_link":"https://git.openi.org.cn/benchmark/?username=admin&algType=detection","first":"目标检测","second":[{"id":1,"value":"无","attachment":"84cf39c4-d8bc-41aa-aaa3-182ce289b105","owner":"yangzhx","repo_name":"detection_benchmark_script"}]},{"id":2,"rank_link":"https://git.openi.org.cn/benchmark/?username=admin&algType=reid","first":"目标重识别","second":[{"id":1,"value":"车辆重识别","attachment":"84cf39c4-d8bc-41aa-aaa3-182ce289b105","owner":"JiahongXu","repo_name":"benchmark_reID_script"},{"id":2,"value":"基于图像的行人重识别","attachment":"84cf39c4-d8bc-41aa-aaa3-182ce289b105","owner":"JiahongXu","repo_name":"benchmark_reID_script"}]},{"id":3,"rank_link":"https://git.openi.org.cn/benchmark/?username=admin&algType=tracking","first":"多目标跟踪","second":[{"id":1,"value":"无","attachment":"84cf39c4-d8bc-41aa-aaa3-182ce289b105","owner":"lix07","repo_name":"MOT_benchmark_script"}]}]}
cloudbrain.benchmark.model.types={"type":[{"id":1,"rank_link":"https://git.openi.org.cn/benchmark/?username=admin&algType=detection","first":"目标检测","second":[{"id":1,"value":"无","attachment":"84cf39c4-d8bc-41aa-aaa3-182ce289b105","owner":"yangzhx","repo_name":"detection_benchmark_script"}]},{"id":2,"rank_link":"https://git.openi.org.cn/benchmark/?username=admin&algType=reid","first":"目标重识别","second":[{"id":1,"value":"车辆重识别","attachment":"84cf39c4-d8bc-41aa-aaa3-182ce289b105","owner":"JiahongXu","repo_name":"benchmark_reID_script"},{"id":2,"value":"基于图像的行人重识别","attachment":"84cf39c4-d8bc-41aa-aaa3-182ce289b105","owner":"JiahongXu","repo_name":"benchmark_reID_script"}]},{"id":3,"rank_link":"https://git.openi.org.cn/benchmark/?username=admin&algType=tracking","first":"多目标跟踪","second":[{"id":1,"value":"无","attachment":"84cf39c4-d8bc-41aa-aaa3-182ce289b105","owner":"lix07","repo_name":"MOT_benchmark_script"}]}]}
cloudbrain.morethanonejob=您已经创建了一个正在等待或运行中的同类任务,请等待任务结束再创建。

modelarts.infer_job_model = 模型名称
modelarts.infer_job_model_file = 模型文件
@@ -1291,6 +1323,7 @@ editor.directory_is_a_file='%s' 已经作为文件名在此项目中存在。
editor.file_is_a_symlink='%s' 是一个符号链接,无法在线编辑。
editor.filename_is_a_directory='%s' 已经作为目录名在此项目中存在。
editor.file_editing_no_longer_exists=正在编辑的文件 '%s' 已不存在。
editor.file_or_directory_editing_no_longer_exists=正在编辑的文件或文件夹 '%s' 已不存在。
editor.file_deleting_no_longer_exists=项目中不存在将被删除的文件‘%s’。
editor.file_changed_while_editing=文件内容在您进行编辑时已经发生变动。<a target="_blank" rel="noopener noreferrer" href="%s">单击此处</a> 查看变动的具体内容,或者 <strong>再次提交</strong> 覆盖已发生的变动。
editor.file_already_exists=此项目已经存在名为 '%s' 的文件。
@@ -1311,6 +1344,8 @@ editor.require_signed_commit=分支需要签名提交
editor.repo_too_large = 代码仓总大小不能超过%dMB
editor.repo_file_invalid = 提交的文件非法
editor.upload_file_too_much = 不能同时提交超过%d个文件
editor.rename = 重命名"%s"为"%s"
editor.file_changed_while_renaming=待重命名的文件或文件夹版本已发生变化,请您刷新页面后重试

commits.desc=浏览代码修改历史
commits.commits=次代码提交
@@ -3021,9 +3056,10 @@ memory = 内存
shared_memory = 共享内存

DEBUG = 调试任务
SNN4IMAGENET = 调试任务-脉冲神经网络图片分类测评
BRAINSCORE = 调试任务-神经相似性测评
SNN4IMAGENET = 评测任务
BRAINSCORE = 评测任务
TRAIN = 训练任务
INFERENCE = 推理任务
BENCHMARK = 评测任务
brain_area = 脑区


+ 10
- 4
package-lock.json View File

@@ -1123,6 +1123,12 @@
"vue-template-es2015-compiler": "^1.9.0"
},
"dependencies": {
"prettier": {
"version": "1.19.1",
"resolved": "https://registry.npmjs.org/prettier/-/prettier-1.19.1.tgz",
"integrity": "sha512-s7PoyDv/II1ObgQunCbB9PdLmUcBZcnWOcxDh7O0N/UwDEsHyqkW+Qh28jW+mVuCdx7gLB0BotYI1Y6uI9iyew==",
"optional": true
},
"source-map": {
"version": "0.6.1",
"resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
@@ -11003,10 +11009,10 @@
"integrity": "sha1-1PRWKwzjaW5BrFLQ4ALlemNdxtw="
},
"prettier": {
"version": "1.19.1",
"resolved": "https://registry.npmjs.org/prettier/-/prettier-1.19.1.tgz",
"integrity": "sha512-s7PoyDv/II1ObgQunCbB9PdLmUcBZcnWOcxDh7O0N/UwDEsHyqkW+Qh28jW+mVuCdx7gLB0BotYI1Y6uI9iyew==",
"optional": true
"version": "2.6.2",
"resolved": "https://registry.npmjs.org/prettier/-/prettier-2.6.2.tgz",
"integrity": "sha512-PkUpF+qoXTqhOeWL9fu7As8LXsIUZ1WYaJiY/a7McAQzxjk82OF0tibkFXVCDImZtWxbvojFjerkiLb0/q8mew==",
"dev": true
},
"pretty-error": {
"version": "2.1.1",


+ 2
- 1
package.json View File

@@ -68,6 +68,7 @@
"eslint-config-airbnb-base": "14.1.0",
"eslint-plugin-import": "2.20.2",
"eslint-plugin-vue": "6.2.2",
"prettier": "2.6.2",
"script-loader": "0.7.2",
"stylelint": "13.3.3",
"stylelint-config-standard": "20.0.0",
@@ -78,4 +79,4 @@
"browserslist": [
"defaults"
]
}
}

+ 45
- 0
public/home/home.js View File

@@ -6,6 +6,7 @@ if(isEmpty(token)){
token = meta.attr("content");
}
}

var swiperNewMessage = new Swiper(".newslist", {
direction: "vertical",
slidesPerView: 10,
@@ -15,6 +16,18 @@ var swiperNewMessage = new Swiper(".newslist", {
disableOnInteraction: false,
},
});
var swiperEvent = new Swiper(".event-list", {
slidesPerView: 2,
spaceBetween: 30,
pagination: {
el: ".swiper-pagination",
clickable: true,
},
autoplay: {
delay: 2500,
disableOnInteraction: false,
},
});
var swiperRepo = new Swiper(".homepro-list", {
slidesPerView: 1,
slidesPerColumn: 2,
@@ -433,6 +446,38 @@ function queryRecommendData(){
}
});

$.ajax({
type:"GET",
url:"/recommend/imageinfo",
headers: {
authorization:token,
},
dataType:"json",
async:false,
success:function(json){
displayActivity(json);
},
error:function(response) {
}
});
}

function displayActivity(json){
var activityDiv = document.getElementById("recommendactivity");
var html = "";
if (json != null && json.length > 0){
for(var i = 0; i < json.length;i++){
var record = json[i]
html += "<div class=\"swiper-slide\">";
html += "<a href=\"" + record["image_link"] + "\" class=\"ui fluid card\">";
html += " <div class=\"image\"><img src=\"" + record["url"] + "\"></div>"
html += "</a>";
html += "</div>";
}
}
activityDiv.innerHTML = html;
swiperEvent.updateSlides();
swiperEvent.updateProgress();
}

function displayRepo(json){


+ 2
- 2
routers/admin/cloudbrains.go View File

@@ -52,8 +52,8 @@ func CloudBrains(ctx *context.Context) {

var jobTypes []string
jobTypeNot := false
if jobType == string(models.JobTypeDebug) {
jobTypes = append(jobTypes, string(models.JobTypeSnn4imagenet), string(models.JobTypeBrainScore), string(models.JobTypeDebug))
if jobType == string(models.JobTypeBenchmark) {
jobTypes = append(jobTypes, string(models.JobTypeBenchmark), string(models.JobTypeBrainScore), string(models.JobTypeSnn4imagenet))
} else if jobType != "all" && jobType != "" {
jobTypes = append(jobTypes, jobType)
}


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

@@ -535,6 +535,9 @@ func RegisterRoutes(m *macaron.Macaron) {
m.Get("/restoreFork", repo.RestoreForkNumber)
m.Get("/downloadAll", repo.ServeAllProjectsPeriodStatisticsFile)
m.Get("/downloadAllOpenI", repo.ServeAllProjectsOpenIStatisticsFile)
m.Get("/summary", repo.GetLatestProjectsSummaryData)
m.Get("/summary/period", repo.GetProjectsSummaryData)
m.Get("/summary/download", repo.GetProjectsSummaryDataFile)
m.Group("/project", func() {
m.Get("", repo.GetAllProjectsPeriodStatistics)
m.Get("/numVisit", repo.ProjectNumVisit)
@@ -547,7 +550,15 @@ func RegisterRoutes(m *macaron.Macaron) {
})
}, operationReq)

m.Get("/query_user_metrics", operationReq, repo_ext.QueryMetrics)
m.Get("/query_metrics_current_month", operationReq, repo_ext.QueryUserMetricsCurrentMonth)
m.Get("/query_metrics_current_week", operationReq, repo_ext.QueryUserMetricsCurrentWeek)
m.Get("/query_metrics_current_year", operationReq, repo_ext.QueryUserMetricsCurrentYear)
m.Get("/query_metrics_last30_day", operationReq, repo_ext.QueryUserMetricsLast30Day)
m.Get("/query_metrics_last_month", operationReq, repo_ext.QueryUserMetricsLastMonth)
m.Get("/query_metrics_yesterday", operationReq, repo_ext.QueryUserMetricsYesterday)
m.Get("/query_metrics_all", operationReq, repo_ext.QueryUserMetricsAll)
m.Get("/query_user_metrics_page", operationReq, repo_ext.QueryUserMetricDataPage)

m.Get("/query_user_rank_list", operationReq, repo_ext.QueryRankingList)
m.Get("/query_user_static_page", operationReq, repo_ext.QueryUserStaticDataPage)
m.Get("/query_user_current_month", operationReq, repo_ext.QueryUserStaticCurrentMonth)


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

@@ -20,8 +20,10 @@ import (

const DEFAULT_PAGE_SIZE = 10
const DATE_FORMAT = "2006-01-02"
const MONTH_FORMAT = "2006-01"
const EXCEL_DATE_FORMAT = "20060102"
const CREATE_TIME_FORMAT = "2006/01/02 15:04:05"
const UPDATE_TIME_FORMAT = "2006-01-02 15:04:05"

type ProjectsPeriodData struct {
RecordBeginTime string `json:"recordBeginTime"`
@@ -60,6 +62,38 @@ type ProjectLatestData struct {
Top10 []UserInfo `json:"top10"`
}

type ProjectSummaryBaseData struct {
NumReposAdd int64 `json:"numReposAdd"`
NumRepoPublicAdd int64 `json:"numRepoPublicAdd"`
NumRepoPrivateAdd int64 `json:"numRepoPrivateAdd"`
NumRepoForkAdd int64 `json:"numRepoForkAdd"`
NumRepoMirrorAdd int64 `json:"numRepoMirrorAdd"`
NumRepoSelfAdd int64 `json:"numRepoSelfAdd"`
NumRepos int64 `json:"numRepos"`
CreatTime string `json:"creatTime"`
}

type ProjectSummaryData struct {
ProjectSummaryBaseData
NumRepoPublic int64 `json:"numRepoPublic"`
NumRepoPrivate int64 `json:"numRepoPrivate"`
NumRepoFork int64 `json:"numRepoFork"`
NumRepoMirror int64 `json:"numRepoMirror"`
NumRepoSelf int64 `json:"numRepoSelf"`

NumRepoOrgAdd int64 `json:"numRepoOrgAdd"`
NumRepoNotOrgAdd int64 `json:"numRepoNotOrgAdd"`

NumRepoOrg int64 `json:"numRepoOrg"`
NumRepoNotOrg int64 `json:"numRepoNotOrg"`
}

type ProjectSummaryPeriodData struct {
RecordBeginTime string `json:"recordBeginTime"`
TotalCount int64 `json:"totalCount"`
PageRecords []*ProjectSummaryBaseData `json:"pageRecords"`
}

func RestoreForkNumber(ctx *context.Context) {
repos, err := models.GetAllRepositories()
if err != nil {
@@ -73,6 +107,148 @@ func RestoreForkNumber(ctx *context.Context) {
ctx.JSON(http.StatusOK, struct{}{})
}

func GetLatestProjectsSummaryData(ctx *context.Context) {
stat, err := models.GetLatest2SummaryStatistic()
data := ProjectSummaryData{}
if err == nil && len(stat) > 0 {
data.NumRepos = stat[0].NumRepos
data.NumRepoOrg = stat[0].NumRepoOrg
data.NumRepoNotOrg = stat[0].NumRepos - stat[0].NumRepoOrg
data.NumRepoFork = stat[0].NumRepoFork
data.NumRepoMirror = stat[0].NumRepoMirror
data.NumRepoSelf = stat[0].NumRepoSelf
data.NumRepoPrivate = stat[0].NumRepoPrivate
data.NumRepoPublic = stat[0].NumRepoPublic
data.CreatTime = stat[0].CreatedUnix.Format(UPDATE_TIME_FORMAT)
if len(stat) == 2 {
data.NumReposAdd = stat[0].NumRepos - stat[1].NumRepos
data.NumRepoOrgAdd = stat[0].NumRepoOrg - stat[1].NumRepoOrg
data.NumRepoNotOrgAdd = (stat[0].NumRepos - stat[0].NumRepoOrg) - (stat[1].NumRepos - stat[1].NumRepoOrg)
data.NumRepoForkAdd = stat[0].NumRepoFork - stat[1].NumRepoFork
data.NumRepoMirrorAdd = stat[0].NumRepoMirror - stat[1].NumRepoMirror
data.NumRepoSelfAdd = stat[0].NumRepoSelf - stat[1].NumRepoSelf
data.NumRepoPrivateAdd = stat[0].NumRepoPrivate - stat[1].NumRepoPrivate
data.NumRepoPublicAdd = stat[0].NumRepoPublic - stat[1].NumRepoPublic
}
}
ctx.JSON(200, data)
}

func GetProjectsSummaryData(ctx *context.Context) {

var datas = make([]*ProjectSummaryBaseData, 0)

recordBeginTime, err := getGrowthRecordBeginTime()
if err != nil {
log.Error("Can not get record begin time", err)
ctx.Error(http.StatusBadRequest, ctx.Tr("repo.record_begintime_get_err"))
return
}
beginTime, endTime, err := getTimePeroid(ctx, recordBeginTime)

beginTime = beginTime.AddDate(0, 0, -1)

queryType := ctx.QueryTrim("type")

var count int64

if queryType == "all" || queryType == "current_year" {
dates := getEndOfMonthDates(beginTime, endTime)
count, _ = models.GetSummaryStatisticByDateCount(dates)
stats, err := models.GetAllSummaryStatisticByDates(dates)
if err != nil {
log.Warn("can not get summary data", err)
} else {

for i, v := range stats {
if i == 0 {
continue
}
data := ProjectSummaryBaseData{}
setStatisticsData(&data, v, stats[i-1])
createTime, _ := time.Parse(DATE_FORMAT, v.Date)
data.CreatTime = createTime.Format(MONTH_FORMAT)
datas = append(datas, &data)
}
}

} else {
count, _ = models.GetSummaryStatisticByTimeCount(beginTime, endTime)
stats, err := models.GetAllSummaryStatisticByTime(beginTime, endTime)
if err != nil {
log.Warn("can not get summary data", err)
} else {

for i, v := range stats {
if i == 0 {
continue
}
data := ProjectSummaryBaseData{}
setStatisticsData(&data, v, stats[i-1])
data.CreatTime = v.Date
datas = append(datas, &data)
}
}

}


projectSummaryPeriodData := ProjectSummaryPeriodData{
TotalCount: count - 1,
RecordBeginTime: recordBeginTime.Format(DATE_FORMAT),
PageRecords: reverse(datas),
}

ctx.JSON(200, projectSummaryPeriodData)

}

func reverse(datas []*ProjectSummaryBaseData ) []*ProjectSummaryBaseData {
for i := 0; i < len(datas)/2; i++ {
j := len(datas) - i - 1
datas[i], datas[j] = datas[j], datas[i]
}
return datas
}



func setStatisticsData(data *ProjectSummaryBaseData, v *models.SummaryStatistic, stats *models.SummaryStatistic) {
data.NumReposAdd = v.NumRepos - stats.NumRepos
data.NumRepoPublicAdd = v.NumRepoPublic - stats.NumRepoPublic
data.NumRepoPrivateAdd = v.NumRepoPrivate - stats.NumRepoPrivate
data.NumRepoMirrorAdd = v.NumRepoMirror - stats.NumRepoMirror
data.NumRepoForkAdd = v.NumRepoFork - stats.NumRepoFork
data.NumRepoSelfAdd = v.NumRepoSelf - stats.NumRepoSelf

data.NumRepos = v.NumRepos
}

func getEndOfMonthDates(beginTime time.Time, endTime time.Time) []string {
var dates = []string{}
date := endOfMonth(beginTime.AddDate(0, -1, 0))
dates = append(dates, date.Format(DATE_FORMAT))

tempDate := endOfMonth(beginTime)

for {
if tempDate.Before(endTime) {
dates = append(dates, tempDate.Format(DATE_FORMAT))
tempDate = endOfMonth(tempDate.AddDate(0, 0, 1))
} else {
break
}
}

dates = append(dates, endTime.AddDate(0, 0, -1).Format(DATE_FORMAT))

return dates
}

func endOfMonth(date time.Time) time.Time {
return date.AddDate(0, 1, -date.Day())
}

func GetAllProjectsPeriodStatistics(ctx *context.Context) {

recordBeginTime, err := getRecordBeginTime()
@@ -210,6 +386,122 @@ func ServeAllProjectsPeriodStatisticsFile(ctx *context.Context) {

}

func GetProjectsSummaryDataFile(ctx *context.Context) {

recordBeginTime, err := getGrowthRecordBeginTime()
if err != nil {
log.Error("Can not get record begin time", err)
ctx.Error(http.StatusBadRequest, ctx.Tr("repo.record_begintime_get_err"))
return
}
beginTime, endTime, err := getTimePeroid(ctx, recordBeginTime)
beginTime = beginTime.AddDate(0, 0, -1)
if err != nil {
log.Error("Parameter is wrong", err)
ctx.Error(http.StatusBadRequest, ctx.Tr("repo.parameter_is_wrong"))
return
}

page := ctx.QueryInt("page")
if page <= 0 {
page = 1
}
pageSize := 100

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
}

var projectAnalysis = ctx.Tr("repo.repo_stat_develop")
fileName := getSummaryFileName(ctx, beginTime, endTime, projectAnalysis)

f := excelize.NewFile()

index := f.NewSheet(projectAnalysis)
f.DeleteSheet("Sheet1")

for k, v := range allProjectsPeriodSummaryHeader(ctx) {
f.SetCellValue(projectAnalysis, k, v)
}

var total int64
queryType := ctx.QueryTrim("type")

var datas = make([]*ProjectSummaryBaseData, 0)

if queryType == "all" || queryType == "current_year" {
dates := getEndOfMonthDates(beginTime, endTime)
total, _ = models.GetSummaryStatisticByDateCount(dates)
totalPage := getTotalPage(total, pageSize)

for i := 0; i < totalPage; i++ {

stats, err := models.GetSummaryStatisticByDates(dates, i+1, pageSize)
if err != nil {
log.Warn("can not get summary data", err)
} else {
for j, v := range stats {
if j == 0 {
continue
}
data := ProjectSummaryBaseData{}
setStatisticsData(&data, v, stats[j-1])
createTime, _ := time.Parse(DATE_FORMAT, v.Date)
data.CreatTime = createTime.Format(MONTH_FORMAT)

datas = append(datas, &data)

}

}

}

} else {
total, _ = models.GetSummaryStatisticByTimeCount(beginTime, endTime)
totalPage := getTotalPage(total, pageSize)

for i := 0; i < totalPage; i++ {

stats, err := models.GetSummaryStatisticByTime(beginTime, endTime, i+1, pageSize)
if err != nil {
log.Warn("can not get summary data", err)
} else {
for j, v := range stats {
if j == 0 {
continue
}
data := ProjectSummaryBaseData{}
setStatisticsData(&data, v, stats[j-1])
data.CreatTime = v.Date
datas = append(datas, &data)

}

}

}
}
row := 2
datas = reverse(datas)
for _, data := range datas {
for k, v := range allProjectsPeriodSummaryValues(row, data, 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 ServeAllProjectsOpenIStatisticsFile(ctx *context.Context) {

page := ctx.QueryInt("page")
@@ -283,6 +575,9 @@ func getFileName(ctx *context.Context, beginTime time.Time, endTime time.Time, p
}
if ctx.QueryTrim("type") == "all" {
baseName = baseName + ctx.Tr("repo.all")
} else if ctx.QueryTrim("type") == "last_month" {
baseName = baseName + beginTime.AddDate(0, 0, -1).Format(EXCEL_DATE_FORMAT) + "_" + endTime.AddDate(0, 0, -2).Format(EXCEL_DATE_FORMAT)

} else {
baseName = baseName + beginTime.AddDate(0, 0, -1).Format(EXCEL_DATE_FORMAT) + "_" + endTime.AddDate(0, 0, -1).Format(EXCEL_DATE_FORMAT)
}
@@ -290,6 +585,22 @@ func getFileName(ctx *context.Context, beginTime time.Time, endTime time.Time, p
return frontName
}

func getSummaryFileName(ctx *context.Context, beginTime time.Time, endTime time.Time, projectAnalysis string) string {
baseName := projectAnalysis + "_"

if ctx.QueryTrim("type") == "all" {
baseName = baseName + ctx.Tr("repo.all")
} else if ctx.QueryTrim("type") == "current_year" {
baseName = baseName + ctx.Tr("repo.current_year")
} else if ctx.QueryTrim("type") == "last_month" {
baseName = baseName + beginTime.Format(EXCEL_DATE_FORMAT) + "_" + endTime.AddDate(0, 0, -2).Format(EXCEL_DATE_FORMAT)
} else {
baseName = baseName + beginTime.Format(EXCEL_DATE_FORMAT) + "_" + endTime.AddDate(0, 0, -1).Format(EXCEL_DATE_FORMAT)
}
frontName := baseName + ".xlsx"
return frontName
}

func allProjectsPeroidHeader(ctx *context.Context) map[string]string {

return map[string]string{"A1": ctx.Tr("admin.repos.id"), "B1": ctx.Tr("admin.repos.projectName"), "C1": ctx.Tr("repo.owner"), "D1": ctx.Tr("admin.repos.isPrivate"), "E1": ctx.Tr("admin.repos.openi"), "F1": ctx.Tr("admin.repos.visit"), "G1": ctx.Tr("admin.repos.download"), "H1": ctx.Tr("admin.repos.pr"), "I1": ctx.Tr("admin.repos.commit"),
@@ -297,6 +608,19 @@ func allProjectsPeroidHeader(ctx *context.Context) map[string]string {

}

func allProjectsPeriodSummaryHeader(ctx *context.Context) map[string]string {

return map[string]string{"A1": ctx.Tr("repo.date"), "B1": ctx.Tr("repo.repo_add"), "C1": ctx.Tr("repo.repo_total"), "D1": ctx.Tr("repo.repo_public_add"), "E1": ctx.Tr("repo.repo_private_add"), "F1": ctx.Tr("repo.repo_self_add"), "G1": ctx.Tr("repo.repo_fork_add"), "H1": ctx.Tr("repo.repo_mirror_add")}

}

func allProjectsPeriodSummaryValues(row int, rs *ProjectSummaryBaseData, ctx *context.Context) map[string]string {

return map[string]string{getCellName("A", row): rs.CreatTime, getCellName("B", row): strconv.FormatInt(rs.NumReposAdd, 10), getCellName("C", row): strconv.FormatInt(rs.NumRepos, 10), getCellName("D", row): strconv.FormatInt(rs.NumRepoPublicAdd, 10), getCellName("E", row): strconv.FormatInt(rs.NumRepoPrivateAdd, 10),
getCellName("F", row): strconv.FormatInt(rs.NumRepoSelfAdd, 10), getCellName("G", row): strconv.FormatInt(rs.NumRepoForkAdd, 10), getCellName("H", row): strconv.FormatInt(rs.NumRepoMirrorAdd, 10),
}
}

func allProjectsPeroidValues(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.DisplayName(), getCellName("C", row): rs.OwnerName, getCellName("D", row): getBoolDisplay(rs.IsPrivate, ctx), getCellName("E", row): strconv.FormatFloat(rs.RadarTotal, 'f', 2, 64),
getCellName("F", row): strconv.FormatInt(rs.NumVisits, 10), getCellName("G", row): strconv.FormatInt(rs.NumDownloads, 10), getCellName("H", row): strconv.FormatInt(rs.NumPulls, 10), getCellName("I", row): strconv.FormatInt(rs.NumCommits, 10),
@@ -633,6 +957,10 @@ func getRecordBeginTime() (time.Time, error) {
return time.ParseInLocation(DATE_FORMAT, setting.RadarMap.RecordBeginTime, time.Local)
}

func getGrowthRecordBeginTime() (time.Time, error) {
return time.ParseInLocation(DATE_FORMAT, setting.RadarMap.GrowthBeginTime, time.Local)
}

func getTotalPage(total int64, pageSize int) int {

another := 0


+ 109
- 0
routers/home.go View File

@@ -8,6 +8,7 @@ package routers
import (
"bytes"
"net/http"
"strconv"
"strings"

"code.gitea.io/gitea/services/repository"
@@ -92,6 +93,8 @@ func setRecommendURL(ctx *context.Context) {
ctx.Data["page_dev_yunlao_desc3"] = ctx.Tr("home.page_dev_yunlao_desc3")
ctx.Data["page_dev_yunlao_desc4"] = ctx.Tr("home.page_dev_yunlao_desc4")
ctx.Data["page_dev_yunlao_apply"] = ctx.Tr("home.page_dev_yunlao_apply")
ctx.Data["page_recommend_activity"] = ctx.Tr("home.page_recommend_activity")
ctx.Data["page_recommend_activity_desc"] = ctx.Tr("home.page_recommend_activity_desc")
}

func Dashboard(ctx *context.Context) {
@@ -602,7 +605,32 @@ func ExploreImages(ctx *context.Context) {
ctx.HTML(200, tplExploreImages)
}

func ExploreDataAnalysisUserTrend(ctx *context.Context) {
ctx.Data["url_params"]="UserTrend"
ctx.HTML(200, tplExploreExploreDataAnalysis)
}
func ExploreDataAnalysisUserAnalysis(ctx *context.Context) {
ctx.Data["url_params"]="UserAnalysis"
ctx.HTML(200, tplExploreExploreDataAnalysis)
}
func ExploreDataAnalysisProTrend(ctx *context.Context) {
ctx.Data["url_params"]="ProTrend"
ctx.HTML(200, tplExploreExploreDataAnalysis)
}
func ExploreDataAnalysisProAnalysis(ctx *context.Context) {
ctx.Data["url_params"]="ProAnalysis"
ctx.HTML(200, tplExploreExploreDataAnalysis)
}
func ExploreDataAnalysisOverview(ctx *context.Context) {
ctx.Data["url_params"]="Overview"
ctx.HTML(200, tplExploreExploreDataAnalysis)
}
func ExploreDataAnalysisBrainAnalysis(ctx *context.Context) {
ctx.Data["url_params"]="BrainAnalysis"
ctx.HTML(200, tplExploreExploreDataAnalysis)
}
func ExploreDataAnalysis(ctx *context.Context) {
ctx.Data["url_params"]=""
ctx.HTML(200, tplExploreExploreDataAnalysis)
}

@@ -640,6 +668,87 @@ func GetRecommendOrg() ([]map[string]interface{}, error) {
}
return resultOrg, nil
}
func GetImageInfo() ([]map[string]interface{}, error) {
url := setting.RecommentRepoAddr + "picture_info"
result, err := repository.RecommendFromPromote(url)

if err != nil {
return nil, err
}
imageInfo := make([]map[string]interface{}, 0)
for i := 0; i < (len(result) - 1); i++ {
line := result[i]
imageMap := make(map[string]interface{})
if line[0:4] == "url=" {
url := line[4:]
imageMap["url"] = url
if result[i+1][0:11] == "image_link=" {
image_link := result[i+1][11:]
imageMap["image_link"] = image_link
}
}
imageInfo = append(imageInfo, imageMap)
i = i + 1
}
return imageInfo, nil
}

func GetRankUser(index string) ([]map[string]interface{}, error) {
url := setting.RecommentRepoAddr + "user_rank_" + index
result, err := repository.RecommendFromPromote(url)

if err != nil {
return nil, err
}
resultOrg := make([]map[string]interface{}, 0)
for _, userRank := range result {
tmpIndex := strings.Index(userRank, " ")
userName := userRank
score := 0
if tmpIndex != -1 {
userName = userRank[0:tmpIndex]
tmpScore, err := strconv.Atoi(userRank[tmpIndex+1:])
if err != nil {
log.Info("convert to int error.")
}
score = tmpScore
}
user, err := models.GetUserByName(userName)
if err == nil {
userMap := make(map[string]interface{})
userMap["Name"] = user.Name
userMap["Description"] = user.Description
userMap["FullName"] = user.FullName
userMap["HomeLink"] = user.HomeLink()
userMap["ID"] = user.ID
userMap["Avatar"] = user.RelAvatarLink()
userMap["Score"] = score
resultOrg = append(resultOrg, userMap)
} else {
log.Info("query user error," + err.Error())
}
}
return resultOrg, nil
}

func GetImageInfoFromPromote(ctx *context.Context) {
imageInfo, err := GetImageInfo()
if err != nil {
ctx.ServerError("500", err)
return
}
ctx.JSON(200, imageInfo)
}

func GetUserRankFromPromote(ctx *context.Context) {
index := ctx.Params("index")
resultUserRank, err := GetRankUser(index)
if err != nil {
ctx.ServerError("500", err)
return
}
ctx.JSON(200, resultUserRank)
}

func RecommendOrgFromPromote(ctx *context.Context) {
resultOrg, err := GetRecommendOrg()


+ 18
- 1
routers/private/hook.go View File

@@ -199,7 +199,6 @@ func HookPreReceive(ctx *macaron.Context, opts private.HookOptions) {
env = append(env,
private.GitQuarantinePath+"="+opts.GitQuarantinePath)
}

for i := range opts.OldCommitIDs {
oldCommitID := opts.OldCommitIDs[i]
newCommitID := opts.NewCommitIDs[i]
@@ -368,6 +367,24 @@ func HookPreReceive(ctx *macaron.Context, opts private.HookOptions) {
ctx.PlainText(http.StatusOK, []byte("ok"))
}

// HookEnv
func HookEnv(ctx *macaron.Context) {
ownerName := ctx.Params(":owner")
repoName := ctx.Params(":repo")
log.Info("try to get hook env.ownerName=%s repoName=%s", ownerName, repoName)
repo, err := models.GetRepositoryByOwnerAndName(ownerName, repoName)
if err != nil {
log.Error("Unable to get repository: %s/%s Error: %v", ownerName, repoName, err)
ctx.JSON(http.StatusInternalServerError, map[string]interface{}{
"err": err.Error(),
})
return
}
result := make(map[string]string, 1)
result[models.EnvRepoSize] = fmt.Sprint(repo.Size)
ctx.JSON(http.StatusOK, &private.HookEnvResult{Config: result})
}

// HookPostReceive updates services and users
func HookPostReceive(ctx *macaron.Context, opts private.HookOptions) {
ownerName := ctx.Params(":owner")


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

@@ -6,9 +6,10 @@
package private

import (
"code.gitea.io/gitea/routers/repo"
"strings"

"code.gitea.io/gitea/routers/repo"

"code.gitea.io/gitea/modules/log"
"code.gitea.io/gitea/modules/private"
"code.gitea.io/gitea/modules/setting"
@@ -38,6 +39,7 @@ func RegisterRoutes(m *macaron.Macaron) {
m.Post("/hook/pre-receive/:owner/:repo", bind(private.HookOptions{}), HookPreReceive)
m.Post("/hook/post-receive/:owner/:repo", bind(private.HookOptions{}), HookPostReceive)
m.Post("/hook/set-default-branch/:owner/:repo/:branch", SetDefaultBranch)
m.Get("/hook/env/:owner/:repo", HookEnv)
m.Get("/serv/none/:keyid", ServNoCommand)
m.Get("/serv/command/:keyid/:owner/:repo", ServCommand)
m.Post("/manager/shutdown", Shutdown)
@@ -45,7 +47,7 @@ func RegisterRoutes(m *macaron.Macaron) {
m.Post("/manager/flush-queues", bind(private.FlushOptions{}), FlushQueues)
m.Post("/tool/update_all_repo_commit_cnt", UpdateAllRepoCommitCnt)
m.Post("/tool/repo_stat/:date", RepoStatisticManually)
m.Post("/tool/user_stat/:date", UserStatisticManually)
m.Get("/tool/org_stat", OrgStatisticManually)
m.Post("/tool/update_repo_visit/:date", UpdateRepoVisit)
m.Post("/task/history_handle/duration", repo.HandleTaskWithNoDuration)


+ 5
- 0
routers/private/tool.go View File

@@ -45,6 +45,11 @@ func RepoStatisticManually(ctx *macaron.Context) {
repo.TimingCountDataByDate(date)
}

func UserStatisticManually(ctx *macaron.Context) {
date := ctx.Params("date")
repo.TimingCountDataByDate(date)
}

func OrgStatisticManually() {
models.UpdateOrgStatistics()
}


+ 172
- 34
routers/repo/cloudbrain.go View File

@@ -188,6 +188,8 @@ func cloudBrainNewDataPrepare(ctx *context.Context) error {

ctx.Data["cloudbraintype"] = models.TypeCloudBrainOne

ctx.Data["benchmarkMode"] = ctx.Query("benchmarkMode")

return nil
}

@@ -249,7 +251,7 @@ func CloudBrainCreate(ctx *context.Context, form auth.CreateCloudBrainForm) {
return
}

if jobType != string(models.JobTypeBenchmark) && jobType != string(models.JobTypeDebug) && jobType != string(models.JobTypeSnn4imagenet) && jobType != string(models.JobTypeBrainScore) && jobType != string(models.JobTypeTrain) {
if jobType != string(models.JobTypeBenchmark) && jobType != string(models.JobTypeDebug) && jobType != string(models.JobTypeTrain) {
log.Error("jobtype error:", jobType, ctx.Data["MsgID"])
cloudBrainNewDataPrepare(ctx)
ctx.RenderWithErr("jobtype error", tpl, &form)
@@ -266,7 +268,7 @@ func CloudBrainCreate(ctx *context.Context, form auth.CreateCloudBrainForm) {
if count >= 1 {
log.Error("the user already has running or waiting task", ctx.Data["MsgID"])
cloudBrainNewDataPrepare(ctx)
ctx.RenderWithErr("you have already a running or waiting task, can not create more", tpl, &form)
ctx.RenderWithErr(ctx.Tr("repo.cloudbrain.morethanonejob"), tpl, &form)
return
}
}
@@ -379,7 +381,7 @@ func CloudBrainRestart(ctx *context.Context) {
if count >= 1 {
log.Error("the user already has running or waiting task", ctx.Data["MsgID"])
resultCode = "-1"
errorMsg = "you have already a running or waiting task, can not create more"
errorMsg = ctx.Tr("repo.cloudbrain.morethanonejob")
break
}
}
@@ -491,34 +493,22 @@ func cloudBrainShow(ctx *context.Context, tpName base.TplName, jobType models.Jo
}
}
taskRoles := jobRes.TaskRoles
if jobRes.JobStatus.State != string(models.JobFailed) {

taskRes, _ := models.ConvertToTaskPod(taskRoles[cloudbrain.SubTaskName].(map[string]interface{}))
ctx.Data["taskRes"] = taskRes
task.Status = taskRes.TaskStatuses[0].State
task.ContainerID = taskRes.TaskStatuses[0].ContainerID
task.ContainerIp = taskRes.TaskStatuses[0].ContainerIP
models.ParseAndSetDurationFromCloudBrainOne(jobRes, task)

if task.DeletedAt.IsZero() { //normal record
err = models.UpdateJob(task)
if err != nil {
ctx.Data["error"] = err.Error()
return
}
} else { //deleted record

taskRes, _ := models.ConvertToTaskPod(taskRoles[cloudbrain.SubTaskName].(map[string]interface{}))
ctx.Data["taskRes"] = taskRes
ctx.Data["ExitDiagnostics"] = taskRes.TaskStatuses[0].ExitDiagnostics
task.Status = taskRes.TaskStatuses[0].State
task.ContainerID = taskRes.TaskStatuses[0].ContainerID
task.ContainerIp = taskRes.TaskStatuses[0].ContainerIP
models.ParseAndSetDurationFromCloudBrainOne(jobRes, task)

if task.DeletedAt.IsZero() { //normal record
err = models.UpdateJob(task)
if err != nil {
ctx.Data["error"] = err.Error()
return
}
} else {
task.Status = jobRes.JobStatus.State
taskRes := models.TaskPod{TaskStatuses: []models.TaskStatuses{
{
State: jobRes.JobStatus.State,
},
}}
ctx.Data["taskRes"] = taskRes
jobRes.JobStatus.StartTime = time.Unix(int64(task.CreatedUnix), 0).Format("2006-01-02 15:04:05")
jobRes.JobStatus.EndTime = time.Unix(int64(task.UpdatedUnix), 0).Format("2006-01-02 15:04:05")
} else { //deleted record

}

ctx.Data["result"] = jobRes
@@ -536,6 +526,7 @@ func cloudBrainShow(ctx *context.Context, tpName base.TplName, jobType models.Jo
for _, benchmarkType := range GetBenchmarkTypes(ctx).BenchmarkType {
if task.BenchmarkTypeID == benchmarkType.Id {
ctx.Data["BenchmarkTypeName"] = benchmarkType.First
task.BenchmarkTypeName = benchmarkType.First
for _, benchmarkChildType := range benchmarkType.Second {
if task.BenchmarkChildTypeID == benchmarkChildType.Id {
ctx.Data["BenchmarkChildTypeName"] = benchmarkChildType.Value
@@ -546,6 +537,19 @@ func cloudBrainShow(ctx *context.Context, tpName base.TplName, jobType models.Jo
}
}
}

if task.JobType == string(models.JobTypeBenchmark) {
task.BenchmarkType = ctx.Tr("repo.cloudbrain.benchmark.algorithm")
} else if task.JobType == string(models.JobTypeSnn4imagenet) || task.JobType == string(models.JobTypeBrainScore) {
task.BenchmarkType = ctx.Tr("repo.cloudbrain.benchmark.model")
task.BenchmarkTypeName = task.JobType
ctx.Data["BenchmarkTypeName"] = task.JobType
if task.JobType == string(models.JobTypeBrainScore) {
ctx.Data["BenchmarkChildTypeName"] = getBrainRegion(task.BenchmarkChildTypeID)
}

}

if task.TrainJobDuration == "" {
if task.Duration == 0 {
var duration int64
@@ -1397,6 +1401,8 @@ func SyncCloudbrainStatus() {
var maxDuration int64
if task.JobType == string(models.JobTypeBenchmark) {
maxDuration = setting.BenchmarkMaxDuration
} else if task.JobType == string(models.JobTypeSnn4imagenet) || task.JobType == string(models.JobTypeBrainScore) {
maxDuration = setting.ModelBenchmarkMaxDuration
} else {
maxDuration = setting.MaxDuration
}
@@ -1646,7 +1652,7 @@ func CloudBrainBenchmarkIndex(ctx *context.Context) {
}

var jobTypes []string
jobTypes = append(jobTypes, string(models.JobTypeBenchmark))
jobTypes = append(jobTypes, string(models.JobTypeBenchmark), string(models.JobTypeBrainScore), string(models.JobTypeSnn4imagenet))
ciTasks, count, err := models.Cloudbrains(&models.CloudbrainsOptions{
ListOptions: models.ListOptions{
Page: page,
@@ -1676,8 +1682,21 @@ func CloudBrainBenchmarkIndex(ctx *context.Context) {
}
ciTasks[i].TrainJobDuration = models.ConvertDurationToStr(ciTasks[i].Duration)
}

ciTasks[i].BenchmarkTypeName = ""
if ciTasks[i].JobType == string(models.JobTypeBenchmark) {
ciTasks[i].BenchmarkType = ctx.Tr("repo.cloudbrain.benchmark.algorithm")
} else if ciTasks[i].JobType == string(models.JobTypeSnn4imagenet) || ciTasks[i].JobType == string(models.JobTypeBrainScore) {
ciTasks[i].BenchmarkType = ctx.Tr("repo.cloudbrain.benchmark.model")
ciTasks[i].BenchmarkTypeName = ciTasks[i].JobType

if ciTasks[i].JobType == string(models.JobTypeSnn4imagenet) {
ciTasks[i].BenchmarkTypeRankLink = setting.Snn4imagenetServerHost
} else {
ciTasks[i].BenchmarkTypeRankLink = setting.BrainScoreServerHost
}

}

if task.BenchmarkTypeID > 0 {
for _, benchmarkType := range GetBenchmarkTypes(ctx).BenchmarkType {
if task.BenchmarkTypeID == benchmarkType.Id {
@@ -1813,6 +1832,16 @@ func getBenchmarkResourceSpec(resourceSpecID int) (int, error) {
}

func CloudBrainBenchmarkCreate(ctx *context.Context, form auth.CreateCloudBrainForm) {
jobType := form.JobType
if jobType == string(models.JobTypeBenchmark) {
BenchMarkAlgorithmCreate(ctx, form)
} else {
ModelBenchmarkCreate(ctx, form)
}

}

func BenchMarkAlgorithmCreate(ctx *context.Context, form auth.CreateCloudBrainForm) {
ctx.Data["PageIsCloudBrain"] = true
displayJobName := form.DisplayJobName
jobName := util.ConvertDisplayJobNameToJobName(displayJobName)
@@ -1877,7 +1906,7 @@ func CloudBrainBenchmarkCreate(ctx *context.Context, form auth.CreateCloudBrainF
return
}

count, err := models.GetCloudbrainCountByUserID(ctx.User.ID, string(models.JobTypeBenchmark))
count, err := models.GetBenchmarkCountByUserID(ctx.User.ID)
if err != nil {
log.Error("GetCloudbrainCountByUserID failed:%v", err, ctx.Data["MsgID"])
cloudBrainNewDataPrepare(ctx)
@@ -1887,7 +1916,7 @@ func CloudBrainBenchmarkCreate(ctx *context.Context, form auth.CreateCloudBrainF
if count >= 1 {
log.Error("the user already has running or waiting task", ctx.Data["MsgID"])
cloudBrainNewDataPrepare(ctx)
ctx.RenderWithErr("you have already a running or waiting task, can not create more", tplCloudBrainBenchmarkNew, &form)
ctx.RenderWithErr(ctx.Tr("repo.cloudbrain.morethanonejob"), tplCloudBrainBenchmarkNew, &form)
return
}
}
@@ -1965,10 +1994,119 @@ func CloudBrainBenchmarkCreate(ctx *context.Context, form auth.CreateCloudBrainF
ctx.RenderWithErr(err.Error(), tplCloudBrainBenchmarkNew, &form)
return
}
ctx.Redirect(setting.AppSubURL + ctx.Repo.RepoLink + "/cloudbrain/benchmark")

}

func ModelBenchmarkCreate(ctx *context.Context, form auth.CreateCloudBrainForm) {
ctx.Data["PageIsCloudBrain"] = true
displayJobName := form.DisplayJobName
jobName := util.ConvertDisplayJobNameToJobName(displayJobName)
image := form.Image
uuid := form.Attachment
jobType := form.JobType
gpuQueue := form.GpuType
codePath := setting.JobPath + jobName + cloudbrain.CodeMountPath
resourceSpecId := form.ResourceSpecId
branchName := cloudbrain.DefaultBranchName
repo := ctx.Repo.Repository

tpl := tplCloudBrainBenchmarkNew
command := cloudbrain.Command

tasks, err := models.GetCloudbrainsByDisplayJobName(repo.ID, jobType, displayJobName)
if err == nil {
if len(tasks) != 0 {
log.Error("the job name did already exist", ctx.Data["MsgID"])
cloudBrainNewDataPrepare(ctx)
ctx.RenderWithErr("the job name did already exist", tpl, &form)
return
}
} else {
if !models.IsErrJobNotExist(err) {
log.Error("system error, %v", err, ctx.Data["MsgID"])
cloudBrainNewDataPrepare(ctx)
ctx.RenderWithErr("system error", tpl, &form)
return
}
}

if !jobNamePattern.MatchString(displayJobName) {
cloudBrainNewDataPrepare(ctx)
ctx.RenderWithErr(ctx.Tr("repo.cloudbrain_jobname_err"), tpl, &form)
return
}

if jobType != string(models.JobTypeSnn4imagenet) && jobType != string(models.JobTypeBrainScore) {
log.Error("jobtype error:", jobType, ctx.Data["MsgID"])
cloudBrainNewDataPrepare(ctx)
ctx.RenderWithErr("jobtype error", tpl, &form)
return
}

count, err := models.GetBenchmarkCountByUserID(ctx.User.ID)
if err != nil {
log.Error("GetCloudbrainCountByUserID failed:%v", err, ctx.Data["MsgID"])
cloudBrainNewDataPrepare(ctx)
ctx.RenderWithErr("system error", tpl, &form)
return
} else {
if count >= 1 {
log.Error("the user already has running or waiting task", ctx.Data["MsgID"])
cloudBrainNewDataPrepare(ctx)
ctx.RenderWithErr(ctx.Tr("repo.cloudbrain.morethanonejob"), tpl, &form)
return
}
}

downloadCode(repo, codePath, branchName)
uploadCodeToMinio(codePath+"/", jobName, cloudbrain.CodeMountPath+"/")

modelPath := setting.JobPath + jobName + cloudbrain.ModelMountPath + "/"
mkModelPath(modelPath)
uploadCodeToMinio(modelPath, jobName, cloudbrain.ModelMountPath+"/")

snn4imagenetPath := setting.JobPath + jobName + cloudbrain.Snn4imagenetMountPath
if setting.IsSnn4imagenetEnabled && jobType == string(models.JobTypeSnn4imagenet) {
downloadRateCode(repo, jobName, setting.Snn4imagenetOwner, setting.Snn4imagenetName, snn4imagenetPath, "", "")
uploadCodeToMinio(snn4imagenetPath+"/", jobName, cloudbrain.Snn4imagenetMountPath+"/")
command = fmt.Sprintf(cloudbrain.Snn4imagenetCommand, displayJobName, trimSpaceNewlineInString(form.Description))

}
benchmarkChildTypeID := 0
brainScorePath := setting.JobPath + jobName + cloudbrain.BrainScoreMountPath
if setting.IsBrainScoreEnabled && jobType == string(models.JobTypeBrainScore) {
downloadRateCode(repo, jobName, setting.BrainScoreOwner, setting.BrainScoreName, brainScorePath, "", "")
uploadCodeToMinio(brainScorePath+"/", jobName, cloudbrain.BrainScoreMountPath+"/")
benchmarkChildTypeID = form.BenchmarkChildTypeID
command = fmt.Sprintf(cloudbrain.BrainScoreCommand, getBrainRegion(benchmarkChildTypeID), displayJobName, trimSpaceNewlineInString(form.Description))
}

err = cloudbrain.GenerateTask(ctx, displayJobName, jobName, image, command, uuid, storage.GetMinioPath(jobName, cloudbrain.CodeMountPath+"/"),
storage.GetMinioPath(jobName, cloudbrain.ModelMountPath+"/"),
storage.GetMinioPath(jobName, cloudbrain.BenchMarkMountPath+"/"), storage.GetMinioPath(jobName, cloudbrain.Snn4imagenetMountPath+"/"),
storage.GetMinioPath(jobName, cloudbrain.BrainScoreMountPath+"/"), jobType, gpuQueue, form.Description, branchName, form.BootFile, form.Params,
0, benchmarkChildTypeID, resourceSpecId)
if err != nil {
cloudBrainNewDataPrepare(ctx)
ctx.RenderWithErr(err.Error(), tpl, &form)
return
}

ctx.Redirect(setting.AppSubURL + ctx.Repo.RepoLink + "/cloudbrain/benchmark")
}

func getBrainRegion(benchmarkChildTypeID int) string {
values := []string{"V1", "V2", "V4", "IT"}
return values[benchmarkChildTypeID]
}

func trimSpaceNewlineInString(s string) string {
re := regexp.MustCompile(`\r?\n`)
return re.ReplaceAllString(s, " ")

}

func BenchmarkDel(ctx *context.Context) {
if err := deleteCloudbrainJob(ctx); err != nil {
log.Error("deleteCloudbrainJob failed: %v", err, ctx.Data["msgID"])


+ 101
- 0
routers/repo/editor.go View File

@@ -5,10 +5,12 @@
package repo

import (
"code.gitea.io/gitea/routers/response"
repo_service "code.gitea.io/gitea/services/repository"
"encoding/json"
"fmt"
"io/ioutil"
"net/http"
"path"
"path/filepath"
"strings"
@@ -795,3 +797,102 @@ func GetClosestParentWithFiles(treePath string, commit *git.Commit) string {
}
return treePath
}

// RenameFilePost response for editing file
func RenameFilePost(ctx *context.Context, form auth.RenameRepoFileForm) {
renameFilePost(ctx, form)
}

func renameFilePost(ctx *context.Context, form auth.RenameRepoFileForm) {
if form.TreePath == "" || form.LastCommit == "" {
ctx.JSON(http.StatusOK, response.ServerError("param error"))
return
}
if form.TreePath == ctx.Repo.TreePath {
ctx.JSON(http.StatusOK, response.Success())
return
}

canCommit := renderCommitRights(ctx)
branchName := ctx.Repo.BranchName
if ctx.HasError() {
ctx.JSON(http.StatusOK, response.ServerError(ctx.Flash.ErrorMsg))
return
}

// Cannot commit to a an existing branch if user doesn't have rights
if branchName == ctx.Repo.BranchName && !canCommit {
ctx.Data["Err_NewBranchName"] = true
ctx.Data["commit_choice"] = frmCommitChoiceNewBranch
ctx.JSON(http.StatusOK, response.ServerError(ctx.Tr("repo.editor.cannot_commit_to_protected_branch", branchName)))
return
}

message := ctx.Tr("repo.editor.rename", ctx.Repo.TreePath, form.TreePath)

if err := repofiles.RenameRepoFile(ctx.Repo.Repository, ctx.User, &repofiles.RenameRepoFileOptions{
LastCommitID: form.LastCommit,
BranchName: branchName,
FromTreePath: ctx.Repo.TreePath,
TreePath: form.TreePath,
Message: message,
}); err != nil {
// This is where we handle all the errors thrown by repofiles.CreateOrUpdateRepoFile
if git.IsErrNotExist(err) {
ctx.JSON(http.StatusOK, response.ServerError(ctx.Tr("repo.editor.file_or_directory_editing_no_longer_exists", ctx.Repo.TreePath)))
} else if models.IsErrLFSFileLocked(err) {
ctx.JSON(http.StatusOK, response.ServerError(ctx.Tr("repo.editor.file_or_directory_editing_no_longer_exists", ctx.Tr("repo.editor.upload_file_is_locked", err.(models.ErrLFSFileLocked).Path, err.(models.ErrLFSFileLocked).UserName))))
} else if models.IsErrFilenameInvalid(err) {
ctx.JSON(http.StatusOK, response.ServerError(ctx.Tr("repo.editor.filename_is_invalid", form.TreePath)))
} else if models.IsErrFilePathInvalid(err) {
if fileErr, ok := err.(models.ErrFilePathInvalid); ok {
switch fileErr.Type {
case git.EntryModeSymlink:
ctx.JSON(http.StatusOK, response.ServerError(ctx.Tr("repo.editor.file_is_a_symlink", fileErr.Path)))
case git.EntryModeTree:
ctx.JSON(http.StatusOK, response.ServerError(ctx.Tr("repo.editor.filename_is_a_directory", fileErr.Path)))
case git.EntryModeBlob:
ctx.JSON(http.StatusOK, response.ServerError(ctx.Tr("repo.editor.directory_is_a_file", fileErr.Path)))
default:
ctx.JSON(http.StatusOK, response.ServerError(err.Error()))
}
} else {
ctx.JSON(http.StatusOK, response.ServerError(err.Error()))
}
} else if models.IsErrRepoFileAlreadyExists(err) {
ctx.JSON(http.StatusOK, response.ServerError(ctx.Tr("repo.editor.file_already_exists", form.TreePath)))
} else if git.IsErrBranchNotExist(err) {
// For when a user adds/updates a file to a branch that no longer exists
if branchErr, ok := err.(git.ErrBranchNotExist); ok {
ctx.JSON(http.StatusOK, response.ServerError(ctx.Tr("repo.editor.branch_does_not_exist", branchErr.Name)))
} else {
ctx.JSON(http.StatusOK, response.ServerError(err.Error()))
}
} else if models.IsErrBranchAlreadyExists(err) {
// For when a user specifies a new branch that already exists
ctx.Data["Err_NewBranchName"] = true
if branchErr, ok := err.(models.ErrBranchAlreadyExists); ok {
ctx.JSON(http.StatusOK, response.ServerError(ctx.Tr("repo.editor.branch_already_exists", branchErr.BranchName)))
} else {
ctx.JSON(http.StatusOK, response.ServerError(err.Error()))
ctx.Error(500, err.Error())
}
} else if models.IsErrCommitIDDoesNotMatch(err) {
ctx.JSON(http.StatusOK, response.ServerError(ctx.Tr("repo.editor.file_changed_while_renaming")))
} else if git.IsErrPushOutOfDate(err) {
ctx.JSON(http.StatusOK, response.ServerError(ctx.Tr("repo.editor.file_changed_while_renaming")))
} else if git.IsErrPushRejected(err) {
errPushRej := err.(*git.ErrPushRejected)
if len(errPushRej.Message) == 0 {
ctx.JSON(http.StatusOK, response.ServerError(ctx.Tr("repo.editor.push_rejected_no_message")))
} else {
ctx.JSON(http.StatusOK, response.ServerError(ctx.Tr("repo.editor.push_rejected", utils.SanitizeFlashErrorString(errPushRej.Message))))
}
} else {
ctx.JSON(http.StatusOK, response.ServerError(ctx.Tr("repo.editor.fail_to_update_file", form.TreePath, utils.SanitizeFlashErrorString(err.Error()))))
}
return
}
ctx.JSON(http.StatusOK, response.Success())

}

+ 1
- 1
routers/repo/modelarts.go View File

@@ -76,7 +76,7 @@ func DebugJobIndex(ctx *context.Context) {
}

var jobTypes []string
jobTypes = append(jobTypes, string(models.JobTypeSnn4imagenet), string(models.JobTypeBrainScore), string(models.JobTypeDebug))
jobTypes = append(jobTypes, string(models.JobTypeDebug))
ciTasks, count, err := models.Cloudbrains(&models.CloudbrainsOptions{
ListOptions: models.ListOptions{
Page: page,


+ 7
- 0
routers/repo/repo_summary_statistic.go View File

@@ -60,6 +60,12 @@ func SummaryStatisticDaily(date string) {
}
selfRepositoryNumber := repositoryNumer - mirrorRepositoryNumber - forkRepositoryNumber

organizationRepoNumber, err := models.GetAllOrgRepositoriesCount()
if err != nil {
log.Error("can not get org repository number", err)
organizationRepoNumber = 0
}

//repository size
repositorySize, err := models.GetAllRepositoriesSize()
if err != nil {
@@ -99,6 +105,7 @@ func SummaryStatisticDaily(date string) {
NumRepoPrivate: privateRepositoryNumer,
NumRepoPublic: publicRepositoryNumer,
NumRepoSelf: selfRepositoryNumber,
NumRepoOrg: organizationRepoNumber,
NumRepoBigModel: topicsCount[0],
NumRepoAI: topicsCount[1],
NumRepoVision: topicsCount[2],


+ 190
- 15
routers/repo/user_data_analysis.go View File

@@ -19,6 +19,59 @@ const (
PAGE_SIZE = 2000
)

func getUserMetricsExcelHeader(ctx *context.Context) map[string]string {
excelHeader := make([]string, 0)
excelHeader = append(excelHeader, ctx.Tr("user.metrics.date"))
excelHeader = append(excelHeader, ctx.Tr("user.metrics.newregistuser"))
excelHeader = append(excelHeader, ctx.Tr("user.metrics.newregistandactiveuser"))
excelHeader = append(excelHeader, ctx.Tr("user.metrics.hasactivateuser"))
excelHeader = append(excelHeader, ctx.Tr("user.metrics.newregistnotactiveuser"))
excelHeader = append(excelHeader, ctx.Tr("user.metrics.newuseractiveindex"))
excelHeader = append(excelHeader, ctx.Tr("user.metrics.totalregistuser"))
excelHeader = append(excelHeader, ctx.Tr("user.metrics.totalactiveduser"))
excelHeader = append(excelHeader, ctx.Tr("user.metrics.totalhasactivityuser"))

excelHeaderMap := make(map[string]string, 0)
var i byte
i = 0
for _, value := range excelHeader {
excelColumn := getColumn(i) + fmt.Sprint(1)
excelHeaderMap[excelColumn] = value
i++
}
return excelHeaderMap
}

func writeUserMetricsExcel(row int, xlsx *excelize.File, sheetName string, userMetrics *models.UserMetrics) {
rows := fmt.Sprint(row)
var tmp byte
tmp = 0
xlsx.SetCellValue(sheetName, getColumn(tmp)+rows, userMetrics.DisplayDate)
tmp = tmp + 1
xlsx.SetCellValue(sheetName, getColumn(tmp)+rows, userMetrics.ActivateRegistUser+userMetrics.NotActivateRegistUser)
tmp = tmp + 1
xlsx.SetCellValue(sheetName, getColumn(tmp)+rows, userMetrics.ActivateRegistUser)
tmp = tmp + 1
xlsx.SetCellValue(sheetName, getColumn(tmp)+rows, userMetrics.RegistActivityUser)
tmp = tmp + 1
xlsx.SetCellValue(sheetName, getColumn(tmp)+rows, userMetrics.NotActivateRegistUser)
tmp = tmp + 1
t := userMetrics.ActivateIndex * 100
value := "-"
if t < 100 && t > 0 {
value = fmt.Sprintf("%.2f", t) + "%"
} else if t >= 100 {
value = "100%"
}
xlsx.SetCellValue(sheetName, getColumn(tmp)+rows, value)
tmp = tmp + 1
xlsx.SetCellValue(sheetName, getColumn(tmp)+rows, userMetrics.TotalUser)
tmp = tmp + 1
xlsx.SetCellValue(sheetName, getColumn(tmp)+rows, userMetrics.TotalActivateRegistUser)
tmp = tmp + 1
xlsx.SetCellValue(sheetName, getColumn(tmp)+rows, userMetrics.TotalHasActivityUser)
}

func getExcelHeader(ctx *context.Context) map[string]string {
excelHeader := make([]string, 0)
excelHeader = append(excelHeader, ctx.Tr("user.static.id"))
@@ -196,20 +249,73 @@ func queryUserDataPage(ctx *context.Context, tableName string, queryObj interfac
mapInterface := make(map[string]interface{})
mapInterface["data"] = re
mapInterface["count"] = count

ctx.JSON(http.StatusOK, mapInterface)
}
}

func QueryMetrics(ctx *context.Context) {
startDate := ctx.Query("startDate")
endDate := ctx.Query("endDate")
startTime, _ := time.ParseInLocation("2006-01-02", startDate, time.Local)
endTime, _ := time.ParseInLocation("2006-01-02", endDate, time.Local)
result, count := models.QueryMetrics(startTime.Unix(), endTime.Unix())
mapInterface := make(map[string]interface{})
mapInterface["data"] = result
mapInterface["count"] = count
ctx.JSON(http.StatusOK, mapInterface)
func queryMetrics(ctx *context.Context, tableName string, startTime time.Time, endTime time.Time) {

IsReturnFile := ctx.QueryBool("IsReturnFile")

var count int64
result := make([]*models.UserMetrics, 0)
if tableName == "public.user_business_analysis_current_year" {
result = models.QueryMetricsForYear(startTime.Unix(), endTime.Unix())
count = int64(len(result))
} else if tableName == "public.user_business_analysis_all" {
result = models.QueryMetricsForAll(startTime.Unix(), endTime.Unix())
count = int64(len(result))
} else {
result, count = models.QueryMetricsPage(startTime.Unix(), endTime.Unix())
}
if IsReturnFile {
//writer exec file.
xlsx := excelize.NewFile()
sheetName := ctx.Tr("user.metrics.sheetname")
index := xlsx.NewSheet(sheetName)
xlsx.DeleteSheet("Sheet1")
dataHeader := getUserMetricsExcelHeader(ctx)
for k, v := range dataHeader {
//设置单元格的值
xlsx.SetCellValue(sheetName, k, v)
}
row := 1
log.Info("return count=" + fmt.Sprint(count))
for _, userRecord := range result {
row++
writeUserMetricsExcel(row, xlsx, sheetName, userRecord)
}
//设置默认打开的表单
xlsx.SetActiveSheet(index)
filename := sheetName + "_" + ctx.Tr("user.static."+tableName) + ".xlsx"
if tableName == "" {
filename = sheetName + "_" + getTimeFileName(startTime) + "_" + getTimeFileName(endTime) + ".xlsx"
}
ctx.Resp.Header().Set("Content-Disposition", "attachment; filename="+url.QueryEscape(filename))
ctx.Resp.Header().Set("Content-Type", "application/octet-stream")
if _, err := xlsx.WriteTo(ctx.Resp); err != nil {
log.Info("writer exel error." + err.Error())
}
} else {
mapInterface := make(map[string]interface{})
mapInterface["data"] = result
mapInterface["count"] = count
if tableName == "public.user_business_analysis_yesterday" {
mapInterface["datarecordbegintime"] = setting.RadarMap.GrowthBeginTime
if len(result) > 0 {
dateTime := time.Unix(result[0].CountDate, 0)
mapInterface["lastUpdatedTime"] = dateTime.Format("2006-01-02 15:04:05")
} else {
mapInterface["lastUpdatedTime"] = ""
}
}
ctx.JSON(http.StatusOK, mapInterface)
}
}
func getTimeFileName(t time.Time) string {
t = t.Local()
return t.Format("20060102")
}

func QueryRankingList(ctx *context.Context) {
@@ -224,34 +330,103 @@ func QueryRankingList(ctx *context.Context) {
ctx.JSON(http.StatusOK, mapInterface)
}

func QueryUserMetricsCurrentMonth(ctx *context.Context) {

currentTimeNow := time.Now()
pageEndTime := time.Date(currentTimeNow.Year(), currentTimeNow.Month(), currentTimeNow.Day(), 23, 59, 59, 0, currentTimeNow.Location())
pageStartTime := time.Date(currentTimeNow.Year(), currentTimeNow.Month(), 1, 0, 0, 0, 0, currentTimeNow.Location())
pageStartTime = getStartTime(pageStartTime)
queryMetrics(ctx, "public.user_business_analysis_current_month", pageStartTime, pageEndTime)
}
func QueryUserStaticCurrentMonth(ctx *context.Context) {
queryUserDataPage(ctx, "public.user_business_analysis_current_month", new(models.UserBusinessAnalysisCurrentMonth))
}

func getStartTime(pageStartTime time.Time) time.Time {
t, _ := time.ParseInLocation("2006-01-02", setting.RadarMap.GrowthBeginTime, time.Local)
t = t.UTC()
if pageStartTime.Before(t) {
pageStartTime = t
}
return pageStartTime
}

func QueryUserMetricsCurrentWeek(ctx *context.Context) {
currentTimeNow := time.Now()
offset := int(time.Monday - currentTimeNow.Weekday())
if offset > 0 {
offset = -6
}
pageStartTime := time.Date(currentTimeNow.Year(), currentTimeNow.Month(), currentTimeNow.Day(), 0, 0, 0, 0, time.Local).AddDate(0, 0, offset)
pageStartTime = getStartTime(pageStartTime)
pageEndTime := time.Date(currentTimeNow.Year(), currentTimeNow.Month(), currentTimeNow.Day(), 23, 59, 59, 0, currentTimeNow.Location())
queryMetrics(ctx, "public.user_business_analysis_current_week", pageStartTime, pageEndTime)
}
func QueryUserStaticCurrentWeek(ctx *context.Context) {
queryUserDataPage(ctx, "public.user_business_analysis_current_week", new(models.UserBusinessAnalysisCurrentWeek))
}

func QueryUserMetricsCurrentYear(ctx *context.Context) {
currentTimeNow := time.Now()
pageStartTime := time.Date(currentTimeNow.Year(), 1, 1, 0, 0, 0, 0, currentTimeNow.Location())
pageStartTime = getStartTime(pageStartTime)
pageEndTime := time.Date(currentTimeNow.Year(), currentTimeNow.Month(), currentTimeNow.Day(), 23, 59, 59, 0, currentTimeNow.Location())
queryMetrics(ctx, "public.user_business_analysis_current_year", pageStartTime, pageEndTime)
}
func QueryUserStaticCurrentYear(ctx *context.Context) {
queryUserDataPage(ctx, "public.user_business_analysis_current_year", new(models.UserBusinessAnalysisCurrentYear))
}

func QueryUserMetricsLast30Day(ctx *context.Context) {
currentTimeNow := time.Now()
pageStartTime := time.Date(currentTimeNow.Year(), currentTimeNow.Month(), currentTimeNow.Day(), 0, 0, 0, 0, time.Local).AddDate(0, 0, -30)
pageStartTime = getStartTime(pageStartTime)
pageEndTime := time.Date(currentTimeNow.Year(), currentTimeNow.Month(), currentTimeNow.Day(), 23, 59, 59, 0, currentTimeNow.Location())
queryMetrics(ctx, "public.user_business_analysis_last30_day", pageStartTime, pageEndTime)
}
func QueryUserStaticLast30Day(ctx *context.Context) {
queryUserDataPage(ctx, "public.user_business_analysis_last30_day", new(models.UserBusinessAnalysisLast30Day))
}

func QueryUserMetricsLastMonth(ctx *context.Context) {
currentTimeNow := time.Now()
thisMonth := time.Date(currentTimeNow.Year(), currentTimeNow.Month(), 1, 0, 0, 0, 0, currentTimeNow.Location())
pageStartTime := thisMonth.AddDate(0, -1, 0)
pageStartTime = getStartTime(pageStartTime)
pageEndTime := time.Date(currentTimeNow.Year(), currentTimeNow.Month(), 1, 23, 59, 59, 0, currentTimeNow.Location()).AddDate(0, 0, -1)
queryMetrics(ctx, "public.user_business_analysis_last_month", pageStartTime, pageEndTime)
}
func QueryUserStaticLastMonth(ctx *context.Context) {
queryUserDataPage(ctx, "public.user_business_analysis_last_month", new(models.UserBusinessAnalysisLastMonth))
}

func QueryUserMetricsYesterday(ctx *context.Context) {
currentTimeNow := time.Now()
pageStartTime := time.Date(currentTimeNow.Year(), currentTimeNow.Month(), currentTimeNow.Day(), 0, 0, 0, 0, time.Local)
pageStartTime = getStartTime(pageStartTime)
pageEndTime := time.Date(currentTimeNow.Year(), currentTimeNow.Month(), currentTimeNow.Day(), 23, 59, 59, 0, currentTimeNow.Location())
queryMetrics(ctx, "public.user_business_analysis_yesterday", pageStartTime, pageEndTime)
}
func QueryUserStaticYesterday(ctx *context.Context) {
queryUserDataPage(ctx, "public.user_business_analysis_yesterday", new(models.UserBusinessAnalysisYesterday))
}

func QueryUserMetricsAll(ctx *context.Context) {
currentTimeNow := time.Now()
pageStartTime := time.Date(2022, 4, 5, 0, 0, 0, 0, currentTimeNow.Location())
pageStartTime = getStartTime(pageStartTime)
pageEndTime := time.Date(currentTimeNow.Year(), currentTimeNow.Month(), currentTimeNow.Day(), 23, 59, 59, 0, currentTimeNow.Location())
queryMetrics(ctx, "public.user_business_analysis_all", pageStartTime, pageEndTime)
}
func QueryUserStaticAll(ctx *context.Context) {
queryUserDataPage(ctx, "public.user_business_analysis_all", new(models.UserBusinessAnalysisAll))
}

func QueryUserMetricDataPage(ctx *context.Context) {
startDate := ctx.Query("startDate")
endDate := ctx.Query("endDate")
startTime, _ := time.ParseInLocation("2006-01-02", startDate, time.Local)
startTime = startTime.UTC()
endTime, _ := time.ParseInLocation("2006-01-02", endDate, time.Local)
startTime = getStartTime(startTime)
queryMetrics(ctx, "", startTime, endTime)
}

func QueryUserStaticDataPage(ctx *context.Context) {
startDate := ctx.Query("startDate")
endDate := ctx.Query("endDate")


+ 5
- 0
routers/repo/view.go View File

@@ -608,6 +608,11 @@ func getContributorInfo(contributorInfos []*ContributorInfo, email string) *Cont

// Home render repository home page
func Home(ctx *context.Context) {
if ctx.Repo.CanEnableEditor() {
ctx.Data["CanEditFile"] = true
} else {
ctx.Data["CanEditFile"] = false
}
if len(ctx.Repo.Units) > 0 {
//get repo contributors info
contributors, err := git.GetContributors(ctx.Repo.Repository.RepoPath(), ctx.Repo.BranchName)


+ 32
- 0
routers/response/response.go View File

@@ -0,0 +1,32 @@
package response

const (
RESPONSE_CODE_SUCCESS = 0
RESPONSE_MSG_SUCCESS = "ok"
RESPONSE_CODE_ERROR_DEFAULT = 99
)

type AiforgeResponse struct {
Code int
Msg string
Data interface{}
}

func Success() *AiforgeResponse {
return &AiforgeResponse{Code: RESPONSE_CODE_SUCCESS, Msg: RESPONSE_MSG_SUCCESS}
}

func Error(code int, msg string) *AiforgeResponse {
return &AiforgeResponse{Code: code, Msg: msg}
}

func ServerError(msg string) *AiforgeResponse {
return &AiforgeResponse{Code: RESPONSE_CODE_ERROR_DEFAULT, Msg: msg}
}

func SuccessWithData(data interface{}) *AiforgeResponse {
return &AiforgeResponse{Code: RESPONSE_CODE_ERROR_DEFAULT, Msg: RESPONSE_MSG_SUCCESS, Data: data}
}
func ErrorWithData(code int, msg string, data interface{}) *AiforgeResponse {
return &AiforgeResponse{Code: code, Msg: msg, Data: data}
}

+ 10
- 0
routers/routes/routes.go View File

@@ -325,6 +325,8 @@ func RegisterRoutes(m *macaron.Macaron) {
m.Get("/action/notification", routers.ActionNotification)
m.Get("/recommend/org", routers.RecommendOrgFromPromote)
m.Get("/recommend/repo", routers.RecommendRepoFromPromote)
m.Get("/recommend/userrank/:index", routers.GetUserRankFromPromote)
m.Get("/recommend/imageinfo", routers.GetImageInfoFromPromote)
m.Post("/all/search/", routers.Search)
m.Get("/all/search/", routers.EmptySearch)
m.Get("/all/dosearch/", routers.SearchApi)
@@ -344,6 +346,13 @@ func RegisterRoutes(m *macaron.Macaron) {
m.Get("/code", routers.ExploreCode)
m.Get("/images", routers.ExploreImages)
m.Get("/data_analysis", routers.ExploreDataAnalysis)
m.Get("/data_analysis/UserTrend", routers.ExploreDataAnalysisUserTrend)
m.Get("/data_analysis/UserAnalysis", routers.ExploreDataAnalysisUserAnalysis)
m.Get("/data_analysis/ProAnalysis", routers.ExploreDataAnalysisProAnalysis)
m.Get("/data_analysis/ProTrend", routers.ExploreDataAnalysisProTrend)
m.Get("/data_analysis/Overview", routers.ExploreDataAnalysisOverview)
m.Get("/data_analysis/BrainAnalysis", routers.ExploreDataAnalysisBrainAnalysis)

}, ignSignIn)
m.Combo("/install", routers.InstallInit).Get(routers.Install).
Post(bindIgnErr(auth.InstallForm{}), routers.InstallPost)
@@ -933,6 +942,7 @@ func RegisterRoutes(m *macaron.Macaron) {
m.Combo("/_upload/*", repo.MustBeAbleToUpload).
Get(repo.UploadFile).
Post(bindIgnErr(auth.UploadRepoFileForm{}), repo.UploadFilePost)
m.Post("/_rename/*", bindIgnErr(auth.RenameRepoFileForm{}), repo.RenameFilePost)
}, context.RepoRefByType(context.RepoRefBranch), repo.MustBeEditable)
m.Group("", func() {
m.Post("/upload-file", repo.UploadFileToServer)


+ 2
- 2
routers/user/home.go View File

@@ -778,8 +778,8 @@ func Cloudbrains(ctx *context.Context) {

var jobTypes []string
jobTypeNot := false
if jobType == string(models.JobTypeDebug) {
jobTypes = append(jobTypes, string(models.JobTypeSnn4imagenet), string(models.JobTypeBrainScore), string(models.JobTypeDebug))
if jobType == string(models.JobTypeBenchmark) {
jobTypes = append(jobTypes, string(models.JobTypeBenchmark), string(models.JobTypeBrainScore), string(models.JobTypeSnn4imagenet))
} else if jobType != "all" && jobType != "" {
jobTypes = append(jobTypes, jobType)
}


+ 2
- 0
services/repository/repository.go View File

@@ -19,6 +19,8 @@ import (
pull_service "code.gitea.io/gitea/services/pull"
)

const SHELL_FLAG_ON = 1

// CreateRepository creates a repository for the user/organization.
func CreateRepository(doer, owner *models.User, opts models.CreateRepoOptions) (*models.Repository, error) {
repo, err := repo_module.CreateRepository(doer, owner, opts)


+ 128
- 74
templates/admin/cloudbrain/list.tmpl View File

@@ -1,6 +1,6 @@
{{template "base/head" .}}
<!-- 弹窗 -->
<div id="mask">
<!-- 弹窗 -->
<div id="mask">
<div id="loadingPage">
<div class="rect1"></div>
<div class="rect2"></div>
@@ -12,20 +12,26 @@
<!-- 提示框 -->
<div class="alert"></div>
<div class="admin user">
<div class="cloudbrain_debug" style="display: none;" data-debug="{{$.i18n.Tr "repo.debug"}}" data-debug-again="{{$.i18n.Tr "repo.debug_again"}}"></div>
<div class="cloudbrain_debug" style="display: none;" data-debug="{{$.i18n.Tr "repo.debug"}}"
data-debug-again="{{$.i18n.Tr "repo.debug_again"}}"
data-all-task="{{.i18n.Tr "admin.cloudbrain.all_task_types"}}"
data-all-compute="{{.i18n.Tr "admin.cloudbrain.all_computing_resources"}}"
data-all-status="{{.i18n.Tr "admin.cloudbrain.all_status"}}"></div>
{{template "admin/navbar" .}}
<div class="ui container" style="width: 80%;">
{{template "base/alert" .}}
<div class="ui grid" >
<div class="ui grid">
<div class="row" style="border: 1px solid #d4d4d5;margin-top: 15px;padding-top: 0;">
{{template "admin/cloudbrain/search" .}}
<div class="ui six wide column right aligned" style="margin: 1rem 0;">
<a class="ui compact blue basic icon button" style="box-shadow: none !important; padding: 0.8em;" href="/admin/cloudbrains/download"><i class="ri-download-line middle aligned icon"></i>{{.i18n.Tr "admin.cloudbrain.download_report"}}</a>
<a class="ui compact blue basic icon button" style="box-shadow: none !important; padding: 0.8em;"
href="/admin/cloudbrains/download"><i
class="ri-download-line middle aligned icon"></i>{{.i18n.Tr "admin.cloudbrain.download_report"}}</a>
</div>
<div class="ui sixteen wide column">
<!-- 任务展示 -->
<div class="dataset list">
<!-- 表头 -->
<!-- 表头 -->
<div class="ui grid stackable" style="background: #f0f0f0;;">
<div class="row">
<div class="two wide column nowrap">
@@ -38,13 +44,13 @@
<span>{{$.i18n.Tr "repo.modelarts.status"}}</span>
</div>
<div class="two wide column text center nowrap" style="width: 10% !important;">
<span>{{$.i18n.Tr "repo.modelarts.createtime"}}</span>
<span>{{$.i18n.Tr "repo.modelarts.createtime"}}</span>
</div>
<div class="one wide column text center nowrap">
<span>{{$.i18n.Tr "repo.cloudbrain_status_runtime"}}</span>
</div>
<div class="one wide column text center nowrap">
<span>{{$.i18n.Tr "repo.modelarts.computing_resources"}}</span>
<span>{{$.i18n.Tr "repo.modelarts.computing_resources"}}</span>
</div>
<div class="one wide column text center nowrap">
<span>{{$.i18n.Tr "repo.cloudbrain_creator"}}</span>
@@ -73,21 +79,40 @@
{{end}}
<!-- {{$JobID}} -->
<div class="two wide column nowrap">
{{if or (eq .JobType "DEBUG") (eq .JobType "SNN4IMAGENET") (eq .JobType "BRAINSCORE")}}
<a class="title" href="{{AppSubUrl}}/{{.Repo.OwnerName}}/{{.Repo.Name}}{{if eq .ComputeResource "CPU/GPU"}}/cloudbrain/{{$JobID}}{{else}}/modelarts/notebook/{{$JobID}}{{end}}" title="{{.DisplayJobName}}" style="font-size: 14px;">
<span class="fitted" style="width: 90%;vertical-align: middle;">{{.DisplayJobName}}</span>
{{if eq .JobType "DEBUG"}}
<a class="title"
href="{{AppSubUrl}}/{{.Repo.OwnerName}}/{{.Repo.Name}}{{if eq .ComputeResource "CPU/GPU"}}/cloudbrain/{{$JobID}}{{else}}/modelarts/notebook/{{$JobID}}{{end}}"
title="{{.DisplayJobName}}" style="font-size: 14px;">
<span class="fitted"
style="width: 90%;vertical-align: middle;">{{.DisplayJobName}}</span>
</a>
{{else if or (eq .JobType "SNN4IMAGENET") (eq .JobType "BRAINSCORE")}}
<a class="title"
href="{{AppSubUrl}}/{{.Repo.OwnerName}}/{{.Repo.Name}}/cloudbrain/benchmark/{{$JobID}}"
title="{{.DisplayJobName}}" style="font-size: 14px;">
<span class="fitted"
style="width: 90%;vertical-align: middle;">{{.DisplayJobName}}</span>
</a>
{{else if eq .JobType "INFERENCE"}}
<a class="title" href="{{AppSubUrl}}/{{.Repo.OwnerName}}/{{.Repo.Name}}/modelarts/inference-job/{{$JobID}}" title="{{.DisplayJobName}}" style="font-size: 14px;">
<span class="fitted" style="width: 90%;vertical-align: middle;">{{.DisplayJobName}}</span>
<a class="title"
href="{{AppSubUrl}}/{{.Repo.OwnerName}}/{{.Repo.Name}}/modelarts/inference-job/{{$JobID}}"
title="{{.DisplayJobName}}" style="font-size: 14px;">
<span class="fitted"
style="width: 90%;vertical-align: middle;">{{.DisplayJobName}}</span>
</a>
{{else if eq .JobType "TRAIN"}}
<a class="title" href="{{AppSubUrl}}/{{.Repo.OwnerName}}/{{.Repo.Name}}{{if eq .ComputeResource "CPU/GPU"}}/cloudbrain{{else}}/modelarts{{end}}/train-job/{{$JobID}}" title="{{.DisplayJobName}}" style="font-size: 14px;">
<span class="fitted" style="width: 90%;vertical-align: middle;">{{.DisplayJobName}}</span>
<a class="title"
href="{{AppSubUrl}}/{{.Repo.OwnerName}}/{{.Repo.Name}}{{if eq .ComputeResource "CPU/GPU"}}/cloudbrain{{else}}/modelarts{{end}}/train-job/{{$JobID}}"
title="{{.DisplayJobName}}" style="font-size: 14px;">
<span class="fitted"
style="width: 90%;vertical-align: middle;">{{.DisplayJobName}}</span>
</a>
{{else if eq .JobType "BENCHMARK"}}
<a class="title" href="{{AppSubUrl}}/{{.Repo.OwnerName}}/{{.Repo.Name}}/cloudbrain/benchmark/{{$JobID}}" title="{{.DisplayJobName}}" style="font-size: 14px;">
<span class="fitted" style="width: 90%;vertical-align: middle;">{{.DisplayJobName}}</span>
<a class="title"
href="{{AppSubUrl}}/{{.Repo.OwnerName}}/{{.Repo.Name}}/cloudbrain/benchmark/{{$JobID}}"
title="{{.DisplayJobName}}" style="font-size: 14px;">
<span class="fitted"
style="width: 90%;vertical-align: middle;">{{.DisplayJobName}}</span>
</a>
{{end}}
</div>
@@ -96,50 +121,68 @@
<span style="font-size: 12px;">{{.JobType}} </span>
</div>
<!-- 任务状态 -->
<div class="two wide column text center nowrap" style="padding-left: 2.2rem !important; width: 10% !important;">
<span class="job-status" id="{{$JobID}}" data-repopath='{{.Repo.OwnerName}}/{{.Repo.Name}}{{if eq .JobType "DEBUG"}}{{if eq .ComputeResource "CPU/GPU"}}/cloudbrain{{else}}/modelarts/notebook{{end}}{{else if eq .JobType "INFERENCE"}}/modelarts/inference-job{{else if eq .JobType "TRAIN"}}/modelarts/train-job{{else if eq .JobType "BENCHMARK"}}/cloudbrain{{end}}' data-jobid="{{$JobID}}" data-version="{{.VersionName}}">
<span><i id="{{$JobID}}-icon" style="vertical-align: middle;" class="{{.Status}}"></i><span id="{{$JobID}}-text" style="margin-left: 0.4em;font-size: 12px;">{{.Status}}</span></span>
<div class="two wide column text center nowrap"
style="padding-left: 2.2rem !important; width: 10% !important;">
<span class="job-status" id="{{$JobID}}"
data-repopath='{{.Repo.OwnerName}}/{{.Repo.Name}}{{if eq .JobType "DEBUG"}}{{if eq .ComputeResource "CPU/GPU"}}/cloudbrain{{else}}/modelarts/notebook{{end}}{{else if eq .JobType "INFERENCE"}}/modelarts/inference-job{{else if eq .JobType "TRAIN"}}/modelarts/train-job{{else if eq .JobType "BENCHMARK"}}/cloudbrain{{end}}'
data-jobid="{{$JobID}}" data-version="{{.VersionName}}">
<span><i id="{{$JobID}}-icon" style="vertical-align: middle;"
class="{{.Status}}"></i><span id="{{$JobID}}-text"
style="margin-left: 0.4em;font-size: 12px;">{{.Status}}</span></span>
</span>
</div>
<!-- 任务创建时间 -->
<div class="two wide column text center nowrap" style="width: 10% !important;">
<span style="font-size: 12px;" class="">{{TimeSinceUnix1 .Cloudbrain.CreatedUnix}}</span>
<span style="font-size: 12px;"
class="">{{TimeSinceUnix1 .Cloudbrain.CreatedUnix}}</span>
</div>
<!-- 任务运行时间 -->
<div class="one wide column text center nowrap">
<span style="font-size: 12px;" id="duration-{{$JobID}}">{{if .TrainJobDuration}}{{.TrainJobDuration}}{{else}}--{{end}}</span>
<span style="font-size: 12px;"
id="duration-{{$JobID}}">{{if .TrainJobDuration}}{{.TrainJobDuration}}{{else}}--{{end}}</span>
</div>
<!-- 计算资源 -->
<div class="one wide column text center nowrap">
<span style="font-size: 12px;">{{if .ComputeResource}}{{.ComputeResource}}{{else}}--{{end}}</span>
<span
style="font-size: 12px;">{{if .ComputeResource}}{{.ComputeResource}}{{else}}--{{end}}</span>
</div>
<!-- 创建者 -->
<div class="one wide column text center nowrap">
{{if .User.Name}}
<a href="{{AppSubUrl}}/{{.User.Name}}" title="{{.User.Name}}"><img class="ui avatar image" src="{{.User.RelAvatarLink}}"></a>
<a href="{{AppSubUrl}}/{{.User.Name}}" title="{{.User.Name}}"><img
class="ui avatar image" src="{{.User.RelAvatarLink}}"></a>
{{else}}
<a title="Ghost"><img class="ui avatar image" src="{{AppSubUrl}}/user/avatar/Ghost/-1"></a>
<a title="Ghost"><img class="ui avatar image"
src="{{AppSubUrl}}/user/avatar/Ghost/-1"></a>
{{end}}
</div>
<!-- 项目 -->
<div class="two wide column text center nowrap">
<a href="{{AppSubUrl}}/{{.Repo.OwnerName}}/{{.Repo.Name}}" title="{{.Repo.OwnerName}}/{{.Repo.Alias}}">{{.Repo.OwnerName}}/{{.Repo.Alias}}</a>
<a href="{{AppSubUrl}}/{{.Repo.OwnerName}}/{{.Repo.Name}}"
title="{{.Repo.OwnerName}}/{{.Repo.Alias}}">{{.Repo.OwnerName}}/{{.Repo.Alias}}</a>
</div>
<!-- 云脑侧名称 -->
<div class="two wide column text center nowrap" style="overflow: hidden;text-overflow:ellipsis;">
<div class="two wide column text center nowrap"
style="overflow: hidden;text-overflow:ellipsis;">
<span class="fitted" title="{{.JobName}}">{{.JobName}}</span>
</div>
<div class="two wide column text center nowrap" style="width: 17.5%!important;">
{{if eq .JobType "DEBUG" "SNN4IMAGENET" "BRAINSCORE"}}
{{if eq .JobType "DEBUG"}}
<div class="ui compact buttons">
<form id="debugAgainForm-{{$JobID}}">
{{$.CsrfTokenHtml}}
{{if eq .Status "RUNNING" "WAITING" "CREATING" "STARTING"}}
<a style="margin: 0 1rem;" id="ai-debug-{{$JobID}}" class='ui basic ai_debug {{if eq .Status "CREATING" "STOPPING" "WAITING" "STARTING"}}disabled {{else}}blue {{end}}button' data-jobid="{{$JobID}}" data-repopath='{{AppSubUrl}}/{{.Repo.OwnerName}}/{{.Repo.Name}}{{if eq .ComputeResource "CPU/GPU"}}/cloudbrain{{else}}/modelarts/notebook{{end}}/{{$JobID}}/'>
<a style="margin: 0 1rem;" id="ai-debug-{{$JobID}}"
class='ui basic ai_debug {{if eq .Status "CREATING" "STOPPING" "WAITING" "STARTING"}}disabled {{else}}blue {{end}}button'
data-jobid="{{$JobID}}"
data-repopath='{{AppSubUrl}}/{{.Repo.OwnerName}}/{{.Repo.Name}}{{if eq .ComputeResource "CPU/GPU"}}/cloudbrain{{else}}/modelarts/notebook{{end}}/{{$JobID}}/'>
{{$.i18n.Tr "repo.debug"}}
</a>
{{else}}
<a id="ai-debug-{{$JobID}}" class='ui basic ai_debug {{if eq .Status "CREATING" "STOPPING" "WAITING" "STARTING"}} disabled {{else}}blue {{end}}button' data-jobid="{{$JobID}}" data-repopath='{{AppSubUrl}}/{{.Repo.OwnerName}}/{{.Repo.Name}}{{if eq .ComputeResource "CPU/GPU"}}/cloudbrain{{else}}/modelarts/notebook{{end}}/{{$JobID}}/'>
<a id="ai-debug-{{$JobID}}"
class='ui basic ai_debug {{if eq .Status "CREATING" "STOPPING" "WAITING" "STARTING"}} disabled {{else}}blue {{end}}button'
data-jobid="{{$JobID}}"
data-repopath='{{AppSubUrl}}/{{.Repo.OwnerName}}/{{.Repo.Name}}{{if eq .ComputeResource "CPU/GPU"}}/cloudbrain{{else}}/modelarts/notebook{{end}}/{{$JobID}}/'>
{{$.i18n.Tr "repo.debug_again"}}
</a>
{{end}}
@@ -149,22 +192,33 @@
<!-- 停止任务 -->
<div class="ui compact buttons">
{{if eq .JobType "DEBUG" "BENCHMARK" "SNN4IMAGENET" "BRAINSCORE"}}
<form id="stopForm-{{$JobID}}" style="margin-left:-1px;">
<form id="stopForm-{{$JobID}}" style="margin-left:-1px;">
{{$.CsrfTokenHtml}}
<a style="padding: 0.5rem 1rem;" id="ai-stop-{{$JobID}}" class='ui basic ai_stop {{if eq .Status "KILLED" "FAILED" "START_FAILED" "KILLING" "COMPLETED" "SUCCEEDED" "STOPPED" "STOPPING"}}disabled {{else}} blue {{end}}button' data-repopath='{{AppSubUrl}}/{{.Repo.OwnerName}}/{{.Repo.Name}}{{if eq .ComputeResource "CPU/GPU"}}/cloudbrain{{else if eq .JobType "BENCHMARK" }}/cloudbrain/benchmark{{else if eq .ComputeResource "NPU" }}/modelarts/notebook{{end}}/{{$JobID}}/stop' data-jobid="{{$JobID}}">
<a style="padding: 0.5rem 1rem;" id="ai-stop-{{$JobID}}"
class='ui basic ai_stop {{if eq .Status "KILLED" "FAILED" "START_FAILED" "KILLING" "COMPLETED" "SUCCEEDED" "STOPPED" "STOPPING"}}disabled {{else}} blue {{end}}button'
data-repopath='{{AppSubUrl}}/{{.Repo.OwnerName}}/{{.Repo.Name}}{{if eq .ComputeResource "CPU/GPU"}}/cloudbrain{{else if eq .JobType "BENCHMARK" }}/cloudbrain/benchmark{{else if eq .ComputeResource "NPU" }}/modelarts/notebook{{end}}/{{$JobID}}/stop'
data-jobid="{{$JobID}}">
{{$.i18n.Tr "repo.stop"}}
</a>
</form>
{{else}}
<a style="padding: 0.5rem 1rem;" id="ai-stop-{{$JobID}}" class="ui basic ai_stop_version {{if eq .Status "KILLED" "FAILED" "START_FAILED" "KILLING" "COMPLETED" "SUCCEEDED" "STOPPED"}}disabled {{else}} blue {{end}}button" data-repopath="{{.Repo.OwnerName}}/{{.Repo.Name}}{{if eq .ComputeResource "CPU/GPU"}}/cloudbrain/train-job{{else}}/modelarts/{{if eq .JobType "INFERENCE"}}inference-job{{else}}train-job{{end}}{{end}}" data-jobid="{{$JobID}}" data-version="{{.VersionName}}" >
<a style="padding: 0.5rem 1rem;" id="ai-stop-{{$JobID}}"
class="ui basic ai_stop_version {{if eq .Status "KILLED" "FAILED" "START_FAILED" "KILLING" "COMPLETED" "SUCCEEDED" "STOPPED"}}disabled {{else}} blue {{end}}button"
data-repopath="{{.Repo.OwnerName}}/{{.Repo.Name}}{{if eq .ComputeResource "CPU/GPU"}}/cloudbrain/train-job{{else}}/modelarts/{{if eq .JobType "INFERENCE"}}inference-job{{else}}train-job{{end}}{{end}}"
data-jobid="{{$JobID}}" data-version="{{.VersionName}}">
{{$.i18n.Tr "repo.stop"}}
</a>
{{end}}
</div>
<!-- 删除任务 -->
<form class="ui compact buttons" id="delForm-{{$JobID}}" action='{{AppSubUrl}}/{{.Repo.OwnerName}}/{{.Repo.Name}}{{if eq .JobType "BENCHMARK"}}/cloudbrain/benchmark{{else if or (eq .JobType "SNN4IMAGENET") (eq .JobType "BRAINSCORE")}}/cloudbrain{{else if eq .JobType "DEBUG"}}{{if eq .ComputeResource "NPU"}}/modelarts/notebook{{else}}/cloudbrain{{end}}{{else if eq .JobType "TRAIN"}}{{if eq .ComputeResource "NPU"}}/modelarts/notebook{{else}}/cloudbrain{{end}}/train-job{{end}}/{{$JobID}}/del?isadminpage=true' method="post">
<form class="ui compact buttons" id="delForm-{{$JobID}}"
action='{{AppSubUrl}}/{{.Repo.OwnerName}}/{{.Repo.Name}}{{if eq .JobType "BENCHMARK"}}/cloudbrain/benchmark{{else if or (eq .JobType "SNN4IMAGENET") (eq .JobType "BRAINSCORE")}}/cloudbrain{{else if eq .JobType "DEBUG"}}{{if eq .ComputeResource "NPU"}}/modelarts/notebook{{else}}/cloudbrain{{end}}{{else if eq .JobType "TRAIN"}}{{if eq .ComputeResource "NPU"}}/modelarts/notebook{{else}}/cloudbrain{{end}}/train-job{{end}}/{{$JobID}}/del?isadminpage=true'
method="post">
{{$.CsrfTokenHtml}}
<a style="padding: 0.5rem 1rem;margin-left:0.2rem" id="ai-delete-{{$JobID}}" data-repopath="{{.Repo.OwnerName}}/{{.Repo.Name}}/modelarts/inference-job/{{$JobID}}/del_version?isadminpage=true" data-version="" class="ui basic ai_delete blue button" style="border-radius: .28571429rem;">
<a style="padding: 0.5rem 1rem;margin-left:0.2rem" id="ai-delete-{{$JobID}}"
data-repopath="{{.Repo.OwnerName}}/{{.Repo.Name}}/modelarts/inference-job/{{$JobID}}/del_version?isadminpage=true"
data-version="" class="ui basic ai_delete blue button"
style="border-radius: .28571429rem;">
{{$.i18n.Tr "repo.delete"}}
</a>
</form>
@@ -184,19 +238,23 @@
<div class="two wide column nowrap">
{{if eq .JobType "DEBUG"}}
<a class="title" href="" title="{{.DisplayJobName}}" style="font-size: 14px;">
<span class="fitted" style="width: 90%;vertical-align: middle;">{{.DisplayJobName}}</span>
<span class="fitted"
style="width: 90%;vertical-align: middle;">{{.DisplayJobName}}</span>
</a>
{{else if eq .JobType "INFERENCE"}}
<a class="title" href="" title="{{.DisplayJobName}}" style="font-size: 14px;">
<span class="fitted" style="width: 90%;vertical-align: middle;">{{.DisplayJobName}}</span>
<span class="fitted"
style="width: 90%;vertical-align: middle;">{{.DisplayJobName}}</span>
</a>
{{else if eq .JobType "TRAIN"}}
<a class="title" href="" title="{{.DisplayJobName}}" style="font-size: 14px;">
<span class="fitted" style="width: 90%;vertical-align: middle;">{{.DisplayJobName}}</span>
<span class="fitted"
style="width: 90%;vertical-align: middle;">{{.DisplayJobName}}</span>
</a>
{{else if eq .JobType "BENCHMARK"}}
<a class="title" href="" title="{{.DisplayJobName}}" style="font-size: 14px;">
<span class="fitted" style="width: 90%;vertical-align: middle;">{{.DisplayJobName}}</span>
<span class="fitted"
style="width: 90%;vertical-align: middle;">{{.DisplayJobName}}</span>
</a>
{{end}}
</div>
@@ -205,29 +263,38 @@
<span style="font-size: 12px;">{{.JobType}} </span>
</div>
<!-- 任务状态 -->
<div class="two wide column text center nowrap" style="padding-left: 2.2rem !important; width: 10% !important;">
<span class="job-status" id="{{$JobID}}" data-jobid="{{$JobID}}" data-version="{{.VersionName}}">
<span><i id="{{$JobID}}-icon" style="vertical-align: middle;" class="{{.Status}}"></i><span id="{{$JobID}}-text" style="margin-left: 0.4em;font-size: 12px;">{{.Status}}</span></span>
<div class="two wide column text center nowrap"
style="padding-left: 2.2rem !important; width: 10% !important;">
<span class="job-status" id="{{$JobID}}" data-jobid="{{$JobID}}"
data-version="{{.VersionName}}">
<span><i id="{{$JobID}}-icon" style="vertical-align: middle;"
class="{{.Status}}"></i><span id="{{$JobID}}-text"
style="margin-left: 0.4em;font-size: 12px;">{{.Status}}</span></span>
</span>
</div>
<!-- 任务创建时间 -->
<div class="two wide column text center nowrap" style="width: 10% !important;">
<span style="font-size: 12px;" class="">{{TimeSinceUnix1 .Cloudbrain.CreatedUnix}}</span>
<span style="font-size: 12px;"
class="">{{TimeSinceUnix1 .Cloudbrain.CreatedUnix}}</span>
</div>
<!-- 任务运行时间 -->
<div class="one wide column text center nowrap">
<span style="font-size: 12px;" id="duration-{{$JobID}}">{{if .TrainJobDuration}}{{.TrainJobDuration}}{{else}}--{{end}}</span>
<span style="font-size: 12px;"
id="duration-{{$JobID}}">{{if .TrainJobDuration}}{{.TrainJobDuration}}{{else}}--{{end}}</span>
</div>
<!-- 计算资源 -->
<div class="one wide column text center nowrap">
<span style="font-size: 12px;">{{if .ComputeResource}}{{.ComputeResource}}{{else}}--{{end}}</span>
<span
style="font-size: 12px;">{{if .ComputeResource}}{{.ComputeResource}}{{else}}--{{end}}</span>
</div>
<!-- 创建者 -->
<div class="one wide column text center nowrap">
{{if .User.Name}}
<a href="{{AppSubUrl}}/{{.User.Name}}" title="{{.User.Name}}"><img class="ui avatar image" src="{{.User.RelAvatarLink}}"></a>
<a href="{{AppSubUrl}}/{{.User.Name}}" title="{{.User.Name}}"><img
class="ui avatar image" src="{{.User.RelAvatarLink}}"></a>
{{else}}
<a title="Ghost"><img class="ui avatar image" src="{{AppSubUrl}}/user/avatar/Ghost/-1"></a>
<a title="Ghost"><img class="ui avatar image"
src="{{AppSubUrl}}/user/avatar/Ghost/-1"></a>
{{end}}
</div>
<!-- 项目 -->
@@ -235,7 +302,8 @@
<a href="" title="">--</a>
</div>
<!-- 云脑侧名称 -->
<div class="two wide column text center nowrap" style="overflow: hidden;text-overflow:ellipsis;">
<div class="two wide column text center nowrap"
style="overflow: hidden;text-overflow:ellipsis;">
<span class="fitted">{{.JobName}}</span>
</div>
<div class="two wide column text center nowrap" style="width: 17.5%!important;">
@@ -244,11 +312,12 @@
<form id="debugAgainForm-{{$JobID}}">
{{$.CsrfTokenHtml}}
{{if eq .Status "RUNNING" "WAITING" "CREATING" "STARTING"}}
<a style="margin: 0 1rem;" id="ai-debug-{{$JobID}}" class='ui basic disabled button' >
<a style="margin: 0 1rem;" id="ai-debug-{{$JobID}}"
class='ui basic disabled button'>
{{$.i18n.Tr "repo.debug"}}
</a>
{{else}}
<a id="ai-debug-{{$JobID}}" class='ui basic disabled button' >
<a id="ai-debug-{{$JobID}}" class='ui basic disabled button'>
{{$.i18n.Tr "repo.debug_again"}}
</a>
{{end}}
@@ -257,14 +326,17 @@
{{end}}
<!-- 停止任务 -->
<div class="ui compact buttons">
<a style="padding: 0.5rem 1rem;" id="ai-stop-{{$JobID}}" class="ui basic disabled button" data-jobid="{{$JobID}}" data-version="{{.VersionName}}" >
<a style="padding: 0.5rem 1rem;" id="ai-stop-{{$JobID}}"
class="ui basic disabled button" data-jobid="{{$JobID}}"
data-version="{{.VersionName}}">
{{$.i18n.Tr "repo.stop"}}
</a>
</div>
<!-- 删除任务 -->
<form class="ui compact buttons" id="delForm-{{$JobID}}" action='' method="post">
{{$.CsrfTokenHtml}}
<a style="padding: 0.5rem 1rem;margin-left:0.2rem" id="ai-delete-{{$JobID}}" class="ui basic disabled button" style="border-radius: .28571429rem;">
<a style="padding: 0.5rem 1rem;margin-left:0.2rem" id="ai-delete-{{$JobID}}"
class="ui basic disabled button" style="border-radius: .28571429rem;">
{{$.i18n.Tr "repo.delete"}}
</a>
</form>
@@ -276,14 +348,9 @@
{{end}}
<div id="app" style="margin-top: 2rem;">
<div class="center">
<el-pagination
background
@current-change="handleCurrentChange"
:current-page="page"
:page-sizes="[10]"
:page-size="10"
layout="total, sizes, prev, pager, next, jumper"
:total="{{.Page.Paginater.Total}}">
<el-pagination background @current-change="handleCurrentChange" :current-page="page"
:page-sizes="[10]" :page-size="10" layout="total, sizes, prev, pager, next, jumper"
:total="{{.Page.Paginater.Total}}">
</el-pagination>
</div>
</div>
@@ -314,17 +381,4 @@
</div>
</div>
</div>
{{template "base/footer" .}}
<script>
function getParams(){
const params = new URLSearchParams(window.location.search)
let jobType = !params.get('jobType')? '{{.i18n.Tr "admin.cloudbrain.all_task_types"}}' : params.get('jobType')
let listType = !params.get('listType')? '{{.i18n.Tr "admin.cloudbrain.all_computing_resources"}}' : params.get('listType')
let jobStatus = !params.get('jobStatus')? '{{.i18n.Tr "admin.cloudbrain.all_status"}}' : params.get('jobStatus').toUpperCase()
const dropdownValueArray = [jobType,listType,jobStatus]
$('#adminCloud .default.text ').each(function(index,e){
$(e).text(dropdownValueArray[index])
})
}
getParams()
</script>
{{template "base/footer" .}}

+ 2
- 2
templates/admin/cloudbrain/search.tmpl View File

@@ -16,8 +16,8 @@
<a class="item" href="{{$.Link}}?q={{$.Keyword}}&jobType=TRAIN&listType={{$.ListType}}&jobStatus={{$.JobStatus}}" data-value="TRAIN">TRAIN</a>
<a class="item" href="{{$.Link}}?q={{$.Keyword}}&jobType=INFERENCE&listType={{$.ListType}}&jobStatus={{$.JobStatus}}" data-value="INFERENCE">INFERENCE</a>
<a class="item" href="{{$.Link}}?q={{$.Keyword}}&jobType=BENCHMARK&listType={{$.ListType}}&jobStatus={{$.JobStatus}}" data-value="BENCHMARK">BENCHMARK</a>
<a class="item" href="{{$.Link}}?q={{$.Keyword}}&jobType=SNN4IMAGENET&listType={{$.ListType}}&jobStatus={{$.JobStatus}}" data-value="BENCHMARK">SNN4IMAGENET</a>
<a class="item" href="{{$.Link}}?q={{$.Keyword}}&jobType=BRAINSCORE&listType={{$.ListType}}&jobStatus={{$.JobStatus}}" data-value="BENCHMARK">BRAINSCORE</a>
<a class="item" href="{{$.Link}}?q={{$.Keyword}}&jobType=SNN4IMAGENET&listType={{$.ListType}}&jobStatus={{$.JobStatus}}" data-value="SNN4IMAGENET">SNN4IMAGENET</a>
<a class="item" href="{{$.Link}}?q={{$.Keyword}}&jobType=BRAINSCORE&listType={{$.ListType}}&jobStatus={{$.JobStatus}}" data-value="BRAINSCORE">BRAINSCORE</a>
</div>
</div>
<div class="ui selection dropdown" style="min-width: 10em;min-height:2.6em;border-radius: .28571429rem;margin-right: 1em;padding: .67em 3.2em .7em 1em;">


+ 3
- 3
templates/admin/cloudbrain/search_dashboard.tmpl View File

@@ -18,7 +18,7 @@
<div class="ui container" style="width: 80%;">
<div class="ui grid">
<div class="row">
<div class="ui {{if $.PageIsUserCloudBrain}}sixteen{{else}}six{{end}} wide column" style="margin: 1rem 0;" id="adminCloud">
<div class="ui {{if $.PageIsUserCloudBrain}}sixteen{{else}}six{{end}} wide column" style="margin: 1rem 0;" id="userCloud">
<div class="ui selection dropdown" style="min-width: 10em;min-height:2.6em;border-radius: .28571429rem;margin-right: 1em;padding: .67em 3.2em .7em 1em;">
<div class="default text" style="color: rgba(0,0,0,.87);">{{.i18n.Tr "admin.cloudbrain.all_task_types"}}</div>
<i class="dropdown icon"></i>
@@ -28,8 +28,8 @@
<a class="item" href="{{$.Link}}?q={{$.Keyword}}&jobType=TRAIN&listType={{$.ListType}}&jobStatus={{$.JobStatus}}" data-value="TRAIN">{{.i18n.Tr "cloudbrain.TRAIN"}}</a>
<a class="item" href="{{$.Link}}?q={{$.Keyword}}&jobType=INFERENCE&listType={{$.ListType}}&jobStatus={{$.JobStatus}}" data-value="INFERENCE">{{.i18n.Tr "cloudbrain.INFERENCE"}}</a>
<a class="item" href="{{$.Link}}?q={{$.Keyword}}&jobType=BENCHMARK&listType={{$.ListType}}&jobStatus={{$.JobStatus}}" data-value="BENCHMARK">{{.i18n.Tr "cloudbrain.BENCHMARK"}}</a>
<a class="item" href="{{$.Link}}?q={{$.Keyword}}&jobType=SNN4IMAGENET&listType={{$.ListType}}&jobStatus={{$.JobStatus}}" data-value="BENCHMARK">{{.i18n.Tr "cloudbrain.SNN4IMAGENET"}}</a>
<a class="item" href="{{$.Link}}?q={{$.Keyword}}&jobType=BRAINSCORE&listType={{$.ListType}}&jobStatus={{$.JobStatus}}" data-value="BENCHMARK">{{.i18n.Tr "cloudbrain.BRAINSCORE"}}</a>
<!-- <a class="item" href="{{$.Link}}?q={{$.Keyword}}&jobType=SNN4IMAGENET&listType={{$.ListType}}&jobStatus={{$.JobStatus}}" data-value="BENCHMARK">{{.i18n.Tr "cloudbrain.SNN4IMAGENET"}}</a>
<a class="item" href="{{$.Link}}?q={{$.Keyword}}&jobType=BRAINSCORE&listType={{$.ListType}}&jobStatus={{$.JobStatus}}" data-value="BENCHMARK">{{.i18n.Tr "cloudbrain.BRAINSCORE"}}</a> -->
</div>
</div>
<div class="ui selection dropdown" style="min-width: 10em;min-height:2.6em;border-radius: .28571429rem;margin-right: 1em;padding: .67em 3.2em .7em 1em;">


+ 8
- 4
templates/custom/select_dataset_train.tmpl View File

@@ -1,14 +1,17 @@

<div class="dataset-repolink" id="dataset-repolink-init" style="display: none;" data-repolink="{{.RepoLink}}" data-cloudranin-type="{{.cloudbraintype}}"></div>
<div class="inline required unite min_title field" id="dataset-base" style="margin-bottom: 0 !important;">
{{if .newInference}}
<label style="font-weight: normal;">{{.i18n.Tr "dataset.dataset"}}</label>&nbsp;&nbsp;&nbsp;&nbsp;
{{if or (.benchmarkMode) (.newInference)}}
<label style="font-weight: normal;">{{if .benchmarkMode}}{{.i18n.Tr "repo.model_manager"}}</label><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span>{{else}}{{.i18n.Tr "dataset.dataset"}}</label>&nbsp;&nbsp;&nbsp;&nbsp;{{end}}
{{else}}
<label style="font-weight: normal;">{{.i18n.Tr "dataset.dataset"}}</label>&nbsp;&nbsp;&nbsp;
{{end}}
<input type="hidden" name="attachment" :value="dataset_uuid">
<input class="disabled" type="text" :value="dataset_name" required onfocus="this.blur();" style="width: 48.5%;">
<el-button type="text" @click="dialogVisible = true" icon="el-icon-plus" style="color: #0366d6;"> {{.i18n.Tr "dataset.select_dataset"}}</el-button>
<el-button type="text" @click="dialogVisible = true" icon="el-icon-plus" style="color: #0366d6;"> {{if .benchmarkMode}}{{.i18n.Tr "repo.modelarts.infer_job.select_model"}}{{else}}{{.i18n.Tr "dataset.select_dataset"}}{{end}}</el-button>
{{if .benchmarkMode}}
<span class="tooltips" style="display: block;padding-left: 0.5rem;">说明:先使用数据集功能上传模型,然后从数据集列表选模型。</span>
{{end}}
<el-dialog
title="{{.i18n.Tr "dataset.select_dataset"}}"
:visible.sync="dialogVisible"
@@ -44,7 +47,7 @@
</div>
</div>
{{if not .benchmarkMode}}
</el-tab-pane>
<el-tab-pane label="{{.i18n.Tr "dataset.owner_dataset"}}" name="second">
<div style="display: flex;align-items: center;justify-content: space-between;padding: 1rem 0;border-bottom:1px solid #F5F5F5" v-for="(dataset,index) in myDataset" :key="index">
@@ -121,6 +124,7 @@
</div>

</el-tab-pane>
{{end}}
</el-tabs>
<div class="center">
<el-pagination


+ 9
- 3
templates/explore/data_analysis.tmpl View File

@@ -1,15 +1,21 @@
{{template "base/head_fluid" .}}
<input id="url_params" type="hidden" value={{.url_params}}/>
<div id="data_analysis" style="height: 100%;">
</div>

{{template "base/footer_fluid" .}}

<!-- <script>
localStorage.setItem("dataAnalysisURL","{{.url_params}}")
</script> -->
<style>
.full.height {
display: flex;
flex-flow: column wrap;
padding-bottom:0px;
/* flex-grow: 1; */
padding-bottom: 53px;
/* padding-bottom: 53px; */
}

</style>

+ 1
- 1
templates/explore/repo_right.tmpl View File

@@ -1,4 +1,4 @@
<a href="https://openi.org.cn/html/2020/qimengxingdong_0813/450.html" target="_blank"><img class="ui mini image" src="/img/banner-qimen-4X3.jpg" style="width:100%;"></a>
<a href="https://openi.org.cn/index.php?m=content&c=index&a=lists&catid=208" target="_blank"><img class="ui mini image" src="https://openi.org.cn/uploadfile/2022/0507/e8bdd42ed598f12.jpg" style="width:100%;"></a>

<div class="ui secondary pointing menu">
<div class="active item">


+ 14
- 0
templates/home.tmpl View File

@@ -36,6 +36,20 @@
<!--组织-->
<div class="ui container homeorg">
<div class="ui stackable grid">
<div class="sixteen wide tablet four wide computer column homeorg-tit">
<h2>{{.page_recommend_activity}}</h2>
<p><span class="ui text grey">{{.page_recommend_activity_desc}}</p>
</div>
<div class="sixteen wide tablet twelve wide computer column">
<div class="event-list">
<div class="swiper-wrapper" id="recommendactivity">
</div>
<div class="swiper-pagination"></div>
</div>
</div>

<div class="sixteen wide tablet four wide computer column homeorg-tit">
<h2>{{.page_recommend_org}}</h2>
<p><span class="ui text grey">{{.page_recommend_org_desc}}&nbsp;</span><a href="{{.RecommendURL}}">{{.page_recommend_org_commit}}</a></p>


+ 2
- 2
templates/org/create.tmpl View File

@@ -15,7 +15,7 @@
<span class="help">{{.i18n.Tr "org.org_name_helper"}}</span>
</div>

<div class="inline field {{if .Err_OrgVisibility}}error{{end}}">
<!-- <div class="inline field {{if .Err_OrgVisibility}}error{{end}}">
<span class="inline required field"><label for="visibility">{{.i18n.Tr "org.settings.visibility"}}</label></span>
<div class="inline-grouped-list">
<div class="ui radio checkbox">
@@ -31,7 +31,7 @@
<label>{{.i18n.Tr "org.settings.visibility.private"}}</label>
</div>
</div>
</div>
</div> -->

<div class="inline field" id="permission_box">
<label>{{.i18n.Tr "org.settings.permission"}}</label>


+ 5
- 3
templates/org/home.tmpl View File

@@ -39,7 +39,6 @@
</a>
{{end}}
{{end}}

{{if .OrgTopics}}
<a class=" tag_key ui small tag_lable topic omit icon_a" onclick="isUnfold()" id="icon_btn" >
<i class="ri-arrow-down-s-line" style="display:inline-block;vertical-align:top"></i>
@@ -168,7 +167,10 @@
document.getElementById("icon_btn").innerHTML="<i class=\"ri-arrow-down-s-line\" style=\"display:inline-block;vertical-align:top\"></i> &nbsp {{.i18n.Tr "org.unfold"}}"
}
}
isShowIconBtn()
iscontinueStatus()

if ({{.OrgTopics}}.length>0){
isShowIconBtn()
iscontinueStatus()
}
</script>

+ 2
- 2
templates/org/settings/options.tmpl View File

@@ -43,13 +43,13 @@
</div>
</div>
<div class="field">
<div class="ui radio checkbox">
<div class="ui radio disabled checkbox">
<input class="hidden enable-system-radio" tabindex="0" name="visibility" type="radio" value="1" {{if eq .CurrentVisibility 1}}checked{{end}}/>
<label>{{.i18n.Tr "org.settings.visibility.limited"}}</label>
</div>
</div>
<div class="field">
<div class="ui radio checkbox">
<div class="ui radio disabled checkbox">
<input class="hidden enable-system-radio" tabindex="0" name="visibility" type="radio" value="2" {{if eq .CurrentVisibility 2}}checked{{end}}/>
<label>{{.i18n.Tr "org.settings.visibility.private"}}</label>
</div>


+ 26
- 22
templates/repo/cloudbrain/benchmark/index.tmpl View File

@@ -2,9 +2,6 @@
{{template "base/head" .}}

<style>
.fontsize14{
font-size: 14px;
}
.padding0{
padding: 0 !important;
}
@@ -69,28 +66,31 @@
<!-- 表头 -->
<div class="ui grid stackable" style="background: #f0f0f0;;">
<div class="row">
<div class="three wide column padding0">
<div class="three wide column padding0" style="width: 18% !important;">
<span style="margin:0 6px">{{$.i18n.Tr "repo.cloudbrain_task"}}</span>
</div>
<div class="two wide column text center padding0">
<div class="two wide column text center padding0" style="width: 10.5% !important;">
<span>{{$.i18n.Tr "repo.modelarts.status"}}</span>
</div>
<div class="two wide column text center padding0">
<div class="two wide column text center padding0" style="width: 10.5% !important;">
<span>{{.i18n.Tr "repo.cloudbrain.benchmark.evaluate_scenes"}}</span>
</div>
<div class="two wide column text center padding0" style="width: 10.5% !important;">
<span>{{.i18n.Tr "repo.cloudbrain.benchmark.evaluate_type"}}</span>
</div>
<div class="two wide column text center padding0">
<div class="two wide column text center padding0" style="width: 8.5% !important;">
<span>{{$.i18n.Tr "repo.modelarts.createtime"}}</span>
</div>
<div class="one wide column text center padding0">
<div class="one wide column text center padding0" style="width: 8% !important;">
<span>{{$.i18n.Tr "repo.cloudbrain_status_runtime"}}</span>
</div>
<div class="two wide column text center padding0">
<div class="two wide column text center padding0" style="width: 8% !important;">
<span>{{$.i18n.Tr "repo.modelarts.computing_resources"}}</span>
</div>
<div class="one wide column text center padding0">
<div class="one wide column text center padding0" style="width: 6% !important;">
<span>{{$.i18n.Tr "repo.cloudbrain_creator"}}</span>
</div>
<div class="three wide column text center padding0">
<div class="three wide column text center padding0" style="width: 20% !important;">
<span>{{$.i18n.Tr "repo.cloudbrain_operate"}}</span>
</div>
</div>
@@ -101,36 +101,39 @@
<div class="row">

<!-- 任务名 -->
<div class="three wide column padding0">
<div class="three wide column padding0" style="width: 18% !important;">
<a class="title" href="{{$.Link}}/{{.Cloudbrain.ID}}" title="{{.DisplayJobName}}" style="font-size: 14px;">
<span class="fitted" style="width: 90%;vertical-align: middle;">{{.DisplayJobName}}</span>
</a>
</div>
<!-- 任务状态 -->
<div class="two wide column padding0" style="padding-left: 2.2rem !important;">
<div class="two wide column text center padding0" style="width: 10.5% !important;">
<span class="job-status" id="{{.Cloudbrain.ID}}" data-repopath="{{$.RepoRelPath}}{{if eq .ComputeResource "CPU/GPU"}}/cloudbrain{{else}}/modelarts/notebook{{end}}" data-jobid="{{.Cloudbrain.ID}}" data-version="{{.VersionName}}">
<span><i id="{{.Cloudbrain.ID}}-icon" style="vertical-align: middle;" class="{{.Status}}"></i><span id="{{.Cloudbrain.ID}}-text" style="margin-left: 0.4em;font-size: 12px;">{{.Status}}</span></span>
</span>
</div>
<div class="two wide column text center padding0">
<div class="two wide column text center padding0" style="width: 10.5% !important;">
{{.BenchmarkType}}
</div>
<div class="two wide column text center padding0" style="width: 10.5% !important;">
<a style="font-size: 12px;" href="{{.BenchmarkTypeRankLink}}" target="_blank">
{{.BenchmarkTypeName}}
{{.BenchmarkTypeName}}
</a>
</div>
<!-- 任务创建时间 -->
<div class="two wide column text center padding0">
<div class="two wide column text center padding0" style="width: 8.5% !important;">
<span style="font-size: 12px;" class="">{{TimeSinceUnix .Cloudbrain.CreatedUnix $.Lang}}</span>
</div>
<!-- 任务运行时间 -->
<div class="one wide column text center padding0">
<div class="one wide column text center padding0" style="width: 8% !important;">
<span style="font-size: 12px;" id="duration-{{.Cloudbrain.ID}}">{{.TrainJobDuration}}</span>
</div>
<!-- 计算资源 -->
<div class="two wide column text center padding0">
<div class="two wide column text center padding0" style="width: 8% !important;">
<span style="font-size: 12px;">{{.ComputeResource}}</span>
</div>
<!-- 创建者 -->
<div class="one wide column text center padding0">
<div class="one wide column text center padding0" style="width: 6% !important;">
{{if .User.Name}}
<a href="{{AppSubUrl}}/{{.User.Name}}" title="{{.User.Name}}"><img class="ui avatar image" src="{{.User.RelAvatarLink}}"></a>
{{else}}
@@ -138,7 +141,7 @@
{{end}}
</div>

<div class="three wide column text center padding0">
<div class="three wide column text center padding0" style="width: 20% !important;">
<div class="ui compact buttons" >
<!-- 停止任务 -->
<form id="stopForm-{{.Cloudbrain.ID}}" style="margin-left:-1px;">
@@ -154,10 +157,11 @@
</a>
{{end}}
</form>
{{if eq .JobType "BENCHMARK"}}
<a class="ui basic button {{if $.IsSigned}} blue{{else}} disabled{{end}}" href="{{$.RepoLink}}/cloudbrain/{{.Cloudbrain.ID}}/rate" target="_blank">
{{$.i18n.Tr "repo.score"}}
</a>
{{end}}
<!-- 删除任务 -->
<form id="delForm-{{.Cloudbrain.ID}}" action="{{if eq .ComputeResource "CPU/GPU"}}{{$.RepoLink}}/cloudbrain/benchmark{{else}}{{$.RepoLink}}/modelarts/notebook{{end}}/{{.Cloudbrain.ID}}/del" method="post">
<input type="hidden" name="debugListType" value="all">
@@ -226,4 +230,4 @@
</div>

</div>
{{template "base/footer" .}}
{{template "base/footer" .}}

+ 280
- 166
templates/repo/cloudbrain/benchmark/new.tmpl View File

@@ -1,70 +1,46 @@
{{template "base/head" .}}
<style>
.unite {
font-family: SourceHanSansSC-medium !important;
color: rgba(16, 16, 16, 100) !important;
}

.title {
font-size: 16px !important;
padding-left: 3rem !important;
}

.min_title {
font-size: 14px !important;
padding-left: 6rem !important;
margin-bottom: 2rem !important;

.unite{
font-family: SourceHanSansSC-medium !important;
color: rgba(16, 16, 16, 100) !important;
}

.title{
font-size: 16px !important;
padding-left: 3rem !important;
}
.min_title{
font-size: 14px !important;
padding-left: 6rem !important;
margin-bottom: 2rem !important;

}
.width{
width:100% !important;
}
.width80{
width: 80.7% !important;
margin-left: 10px;
}
.width85{
width: 85% !important;
margin-left: 4.5rem !important;
}
.width81{
margin-left: 1.5rem;
width: 81% !important;
}

.add{font-size: 18px;
padding: 0.5rem;
border: 1px solid rgba(187, 187, 187, 100);
border-radius: 0px 5px 5px 0px;
line-height: 21px;
text-align: center;
color: #C2C7CC;
}
.min{
font-size: 18px;
padding: 0.5rem;
border: 1px solid rgba(187, 187, 187, 100);
border-radius: 5px 0px 0px 5px;
line-height: 21px;
text-align: center;
color: #C2C7CC;
}
.nowrapx {
white-space: nowrap !important;
}
}

.width81 {
margin-left: 1.5rem;
width: 81% !important;
}

.width48 {
width: 48.5% !important;
}

.nowrapx {
white-space: nowrap !important;
}
</style>
<!-- <div class="ui page dimmer">
<div class="ui text loader">{{.i18n.Tr "loading"}}</div>
</div> -->
<div id="mask">
<div id="loadingPage">
<div class="rect1"></div>
<div class="rect2"></div>
<div class="rect3"></div>
<div class="rect4"></div>
<div class="rect5"></div>
</div>
<div id="loadingPage">
<div class="rect1"></div>
<div class="rect2"></div>
<div class="rect3"></div>
<div class="rect4"></div>
<div class="rect5"></div>
</div>
</div>
<div class="repository">
{{template "repo/header" .}}
@@ -74,168 +50,306 @@
{{.i18n.Tr "repo.modelarts.evaluate_job.new_job"}}
</h4>
<div class="ui attached segment">
<!-- equal width -->
<form class="ui form" action="{{.Link}}" method="post">
<input type="hidden" name="benchmarkMode" value="{{.benchmarkMode}}">

{{if eq .benchmarkMode "model"}}
<form class="ui form model_form" action="{{.Link}}?benchmarkMode=model" method="post">
{{.CsrfTokenHtml}}
<input type="hidden" name="action" value="update">


<div class="required unite min_title inline field">
<label style="font-weight: normal;">{{.i18n.Tr "repo.modelarts.train_job.job_name"}}</label>
<input style="width: 80%;" name="display_job_name" id="trainjob_job_name" placeholder={{.i18n.Tr "repo.modelarts.train_job.job_name"}} value="{{.display_job_name}}" tabindex="3" autofocus required maxlength="254">
</div>
<div class="unite min_title inline field">
<label style="font-weight: normal;" for="description">{{.i18n.Tr "repo.modelarts.train_job.description"}}&nbsp;&nbsp;</label>
<textarea style="width: 80%;" id="description" name="description" rows="3" maxlength="254" placeholder={{.i18n.Tr "repo.modelarts.train_job.new_place"}} onchange="this.value=this.value.substring(0, 255)" onkeydown="this.value=this.value.substring(0, 255)" onkeyup="this.value=this.value.substring(0, 255)">{{.description}}</textarea>
<label style="font-weight: normal;">{{.i18n.Tr "repo.cloudbrain.benchmark.evaluate_scenes"}}</label>
<div class="ui blue small menu compact selectcloudbrain">
<a class="item alogrithm_benchmark"
href="{{.Link}}?benchmarkMode=alogrithm">{{.i18n.Tr "repo.cloudbrain.benchmark.algorithm"}}</a>
<a class="active item model_benchmark"
href="{{.Link}}?benchmarkMode=model">{{.i18n.Tr "repo.cloudbrain.benchmark.model"}}</a>
</div>
</div>
<div>
<div class="required unite min_title inline field">
<label style="font-weight: normal;">{{.i18n.Tr "repo.modelarts.train_job.job_name"}}</label>
<input style="width: 80%;" name="display_job_name" id="trainjob_job_name"
placeholder={{.i18n.Tr "repo.modelarts.train_job.job_name"}} value="{{.display_job_name}}"
tabindex="3" autofocus required maxlength="254">
<span class="tooltips" style="display: block;">{{.i18n.Tr "cloudbrain.job_name_rule"}}</span>
</div>
<div class="required unite min_title inline field">
<label style="font-weight: normal;"
for="description">{{.i18n.Tr "repo.modelarts.train_job.description"}}</label>
<textarea style="width: 80%;" id="description" name="description" rows="3" required
maxlength="254" placeholder={{.i18n.Tr "repo.modelarts.train_job.new_place"}}
onchange="this.value=this.value.substring(0, 255)"
onkeydown="this.value=this.value.substring(0, 255)"
onkeyup="this.value=this.value.substring(0, 255)">{{.description}}</textarea>
</div>

<div class="required unite min_title inline field">
<div class="required unite min_title inline field">
<label style="font-weight: normal;">{{.i18n.Tr "cloudbrain.gpu_type"}}</label>
<select id="cloudbrain_gpu_type" class="ui search dropdown" placeholder="选择GPU类型" style='width:385px' name="gpu_type">
<select id="cloudbrain_gpu_type" class="ui search dropdown width48" placeholder="选择GPU类型"
name="gpu_type">
{{range .benchmark_gpu_types}}
<option value="{{.Queue}}">{{.Value}}</option>
<option value="{{.Queue}}">{{.Value}}</option>
{{end}}
</select>
</div>
</div>
<div class="required unite min_title two inline fields ">
<div class="required ten wide field" style="width: 26.5% !important;">
<label style="font-weight: normal;">{{.i18n.Tr "cloudbrain.task_type"}}</label>
<select id="cloudbrain_job_type" class="ui search dropdown job_type"
placeholder="select {{.i18n.Tr "cloudbrain.task_type"}}" name="job_type">
<option value="SNN4IMAGENET">SNN4IMAGENET</option>
<option value="BRAINSCORE">BRAINSCORE</option>
</select>
</div>
<div class="required six widde field" id="brainscore_child_type"
style="width: 15% !important;display: none;">
<label style="font-weight: normal;">{{.i18n.Tr "cloudbrain.brain_area"}}</label>
<select class="ui search dropdown" placeholder="select {{.i18n.Tr "cloudbrain.brain_area"}}"
name="benchmark_child_types_id">
<option value="0">V1</option>
<option value="1">V2</option>
<option value="2">V4</option>
<option value="3">IT</option>
</select>
</div>
<span>
<i class="question circle icon link"
data-content={{.i18n.Tr "repo.modelarts.train_job.boot_file_helper"}}
data-position="right center" data-variation="mini"></i>
</span>
<a id="benchmark_model_example" href="https://git.openi.org.cn/BDIP/snn4imagenet"
target="_blank">{{.i18n.Tr "cloudbrain.view_sample"}}</a>
</div>


<div class="required unite inline min_title fields" style="width: 90%;">
<div class="required eight wide field">
<label style="font-weight: normal;white-space: nowrap;">{{.i18n.Tr "repo.cloudbrain.benchmark.evaluate_type"}}</label>
<span>&nbsp;</span>
<select class="ui fluid selection search dropdown" id="benchmark_types_id" name="benchmark_types_id" >
{{range .benchmark_types}}
{{if eq .Id $.benchmarkTypeID}}
<option value="{{.Id}}" selected="true">{{.First}}</option>
{{else}}
<option value="{{.Id}}">{{.First}}</option>
{{end}}
<div id="images-new-cb">
</div>
{{template "custom/select_dataset_train" .}}
<div class="required unite min_title inline field" style="margin-top:2rem;">
<label style="font-weight: normal;">{{.i18n.Tr "cloudbrain.resource_specification"}}</label>
<select id="cloudbrain_resource_spec" class="ui search dropdown"
placeholder="{{.i18n.Tr "cloudbrain.select_specification"}}" style='width:385px'
name="resource_spec_id">
{{range .benchmark_resource_specs}}
<option name="resource_spec_id" value="{{.Id}}">
{{$.i18n.Tr "cloudbrain.gpu_num"}}:{{.GpuNum}},{{$.i18n.Tr "cloudbrain.cpu_num"}}:{{.CpuNum}},{{$.i18n.Tr "cloudbrain.memory"}}(MB):{{.MemMiB}},{{$.i18n.Tr "cloudbrain.shared_memory"}}(MB):{{.ShareMemMiB}}
</option>
{{end}}
</select>
</div>
<div class="eight wide field" id="engine_name">
<input type="hidden" id="benchmark_child_types_id_hidden" name="benchmark_child_types_id_hidden" value="{{.benchmark_child_types_id_hidden}}">
<label style="font-weight: normal;white-space: nowrap;">{{.i18n.Tr "repo.cloudbrain.benchmark.evaluate_child_type"}}</label>
<select class="ui fluid selection dropdown nowrapx" id="benchmark_child_types_id" style='width: 100%;' name="benchmark_child_types_id">
</select>
</div>
</div>
<div class="inline unite min_title field">
<button class="ui create_train_job green button">
{{.i18n.Tr "repo.cloudbrain.new"}}
</button>
<a class="ui button" href="/">{{.i18n.Tr "repo.cloudbrain.cancel"}}</a>
</div>
</div>

<div id="images-new-cb">

</form>
{{else}}
<form class="ui form alogrithm_form" action="{{.Link}}?benchmarkMode=alogrithm" method="post">
{{.CsrfTokenHtml}}
<input type="hidden" name="action" value="update">
<input type="hidden" name="job_type" value="BENCHMARK">
<div class="required unite min_title inline field">
<label style="font-weight: normal;">{{.i18n.Tr "repo.cloudbrain.benchmark.evaluate_scenes"}}</label>
<div class="ui blue small menu compact selectcloudbrain">
<a class="active item alogrithm_benchmark"
href="{{.Link}}?benchmarkMode=alogrithm">{{.i18n.Tr "repo.cloudbrain.benchmark.algorithm"}}</a>
<a class="item model_benchmark"
href="{{.Link}}?benchmarkMode=model">{{.i18n.Tr "repo.cloudbrain.benchmark.model"}}</a>
</div>
</div>

<div>
<div class="required unite min_title inline field">
<label style="font-weight: normal;">{{.i18n.Tr "repo.modelarts.train_job.job_name"}}</label>
<input style="width: 80%;" name="display_job_name" id="trainjob_job_name"
placeholder={{.i18n.Tr "repo.modelarts.train_job.job_name"}} value="{{.display_job_name}}"
tabindex="3" autofocus required maxlength="254">
<span class="tooltips" style="display: block;">{{.i18n.Tr "cloudbrain.job_name_rule"}}</span>
</div>
<div class="unite min_title inline field">
<label style="font-weight: normal;"
for="description">{{.i18n.Tr "repo.modelarts.train_job.description"}}&nbsp;&nbsp;</label>
<textarea style="width: 80%;" id="description" name="description" rows="3" maxlength="254"
placeholder={{.i18n.Tr "repo.modelarts.train_job.new_place"}}
onchange="this.value=this.value.substring(0, 255)"
onkeydown="this.value=this.value.substring(0, 255)"
onkeyup="this.value=this.value.substring(0, 255)">{{.description}}</textarea>
</div>

<div class="required unite min_title inline field">
<label style="font-weight: normal;">{{.i18n.Tr "cloudbrain.gpu_type"}}</label>
<select id="cloudbrain_gpu_type" class="ui search dropdown" placeholder="选择GPU类型"
style='width:385px' name="gpu_type">
{{range .benchmark_gpu_types}}
<option value="{{.Queue}}">{{.Value}}</option>
{{end}}
</select>
</div>
<div class="required unite inline min_title fields" style="width: 90%;">
<div class="required eight wide field">
<label
style="font-weight: normal;white-space: nowrap;">{{.i18n.Tr "repo.cloudbrain.benchmark.evaluate_type"}}</label>
<span>&nbsp;</span>
<select class="ui fluid selection search dropdown" id="benchmark_types_id"
name="benchmark_types_id">
{{range .benchmark_types}}
{{if eq .Id $.benchmarkTypeID}}
<option value="{{.Id}}" selected="true">{{.First}}</option>
{{else}}
<option value="{{.Id}}">{{.First}}</option>
{{end}}
{{end}}
</select>
</div>
<div class="eight wide field" id="engine_name">
<input type="hidden" id="benchmark_child_types_id_hidden"
name="benchmark_child_types_id_hidden" value="{{.benchmark_child_types_id_hidden}}">
<label
style="font-weight: normal;white-space: nowrap;">{{.i18n.Tr "repo.cloudbrain.benchmark.evaluate_child_type"}}</label>
<select class="ui fluid selection dropdown nowrapx" id="benchmark_child_types_id"
style='width: 100%;' name="benchmark_child_types_id">
</select>
</div>
</div>
<div id="images-new-cb">
</div>

<div class="required unite min_title inline field">
<div class="required unite min_title inline field">
<label style="font-weight: normal;">{{.i18n.Tr "cloudbrain.resource_specification"}}</label>
<select id="cloudbrain_resource_spec" class="ui search dropdown" placeholder="{{.i18n.Tr "cloudbrain.select_specification"}}" style='width:385px' name="resource_spec_id">
<select id="cloudbrain_resource_spec" class="ui search dropdown"
placeholder="{{.i18n.Tr "cloudbrain.select_specification"}}" style='width:385px'
name="resource_spec_id">
{{range .benchmark_resource_specs}}
<option name="resource_spec_id" value="{{.Id}}">{{$.i18n.Tr "cloudbrain.gpu_num"}}:{{.GpuNum}},{{$.i18n.Tr "cloudbrain.cpu_num"}}:{{.CpuNum}},{{$.i18n.Tr "cloudbrain.memory"}}(MB):{{.MemMiB}},{{$.i18n.Tr "cloudbrain.shared_memory"}}(MB):{{.ShareMemMiB}}</option>
<option name="resource_spec_id" value="{{.Id}}">
{{$.i18n.Tr "cloudbrain.gpu_num"}}:{{.GpuNum}},{{$.i18n.Tr "cloudbrain.cpu_num"}}:{{.CpuNum}},{{$.i18n.Tr "cloudbrain.memory"}}(MB):{{.MemMiB}},{{$.i18n.Tr "cloudbrain.shared_memory"}}(MB):{{.ShareMemMiB}}
</option>
{{end}}
</select>
</div>
</div>

<div class="inline unite min_title field required">
<label style="font-weight: normal;">{{.i18n.Tr "repo.cloudbrain.benchmark.evaluate_train"}}</label>
<input disabled="disabled" style="width: 33.5%;" name="train_file" id="train_file" value="train.py" tabindex="3" autofocus required maxlength="254" >
<a id="train_href_id" href="https://git.openi.org.cn/CV_benchmark/CV_reID_benchmark" target="_blank">{{.i18n.Tr "repo.cloudbrain.benchmark.evaluate_train"}}</a>
</div>
<div class="inline unite min_title field required">
<label
style="font-weight: normal;">{{.i18n.Tr "repo.cloudbrain.benchmark.evaluate_train"}}</label>
<input disabled="disabled" style="width: 33.5%;" name="train_file" id="train_file"
value="train.py" tabindex="3" autofocus required maxlength="254">
<a id="train_href_id" href="https://git.openi.org.cn/CV_benchmark/CV_reID_benchmark"
target="_blank">{{.i18n.Tr "repo.cloudbrain.benchmark.evaluate_train"}}</a>
</div>

<div class="inline unite min_title field required">
<label style="font-weight: normal;">{{.i18n.Tr "repo.cloudbrain.benchmark.evaluate_test"}}</label>
<input disabled="disabled" style="width: 33.5%;" name="test_file" id="test_file" value="test.py" tabindex="3" autofocus required maxlength="254" >
<a id="test_href_id" href="https://git.openi.org.cn/CV_benchmark/CV_reID_benchmark" target="_blank">{{.i18n.Tr "cloudbrain.view_sample"}}</a>
</div>
<div class="inline unite min_title field required">
<label
style="font-weight: normal;">{{.i18n.Tr "repo.cloudbrain.benchmark.evaluate_test"}}</label>
<input disabled="disabled" style="width: 33.5%;" name="test_file" id="test_file" value="test.py"
tabindex="3" autofocus required maxlength="254">
<a id="test_href_id" href="https://git.openi.org.cn/CV_benchmark/CV_reID_benchmark"
target="_blank">{{.i18n.Tr "cloudbrain.view_sample"}}</a>
</div>


<div class="inline unite min_title field">
<button class="ui create_train_job green button">
{{.i18n.Tr "repo.cloudbrain.new"}}
</button>
<a class="ui button" href="/">{{.i18n.Tr "repo.cloudbrain.cancel"}}</a>
<div class="inline unite min_title field">
<button class="ui create_train_job green button">
{{.i18n.Tr "repo.cloudbrain.new"}}
</button>
<a class="ui button" href="/">{{.i18n.Tr "repo.cloudbrain.cancel"}}</a>
</div>
</div>

<!-- 模态框 -->

</form>
{{end}}
</div>
</div>
</div>
{{template "base/footer" .}}

<script>
let repolink = {{.RepoLink}}

let repolink = {{.RepoLink }}
let url_href = window.location.pathname.split('create')[0]
$(".ui.button").attr('href',url_href)

$(".ui.button").attr('href', url_href)
$('.menu .item')
.tab();

$('#benchmark_types_id').change(function(){
$('#benchmark_types_id').change(function () {
setChildType();
})

function setChildType(){
$(document).ready(() => {
$('.ui.search.dropdown.job_type').dropdown({
onChange: function (value, text, $selectedItem) {
console.log(value, text)
if (value === "BRAINSCORE") {
$('#brainscore_child_type').css('display', 'block')
$('#benchmark_model_example').attr('href', 'https://git.openi.org.cn/BDIP/similarity2brain_ann')
} else {
$('#brainscore_child_type').css('display', 'none')
$('#benchmark_model_example').attr('href', 'https://git.openi.org.cn/BDIP/snn4imagenet')
}
}
})
})
function setChildType() {
let type_id = $('#benchmark_types_id').val();
if(type_id == 3){
$('#train_href_id').attr('href','https://git.openi.org.cn/CV_benchmark/CV_MOT_benchmark');
$('#test_href_id').attr('href','https://git.openi.org.cn/CV_benchmark/CV_MOT_benchmark');
}else{
$('#train_href_id').attr('href','https://git.openi.org.cn/CV_benchmark/CV_reID_benchmark');
$('#test_href_id').attr('href','https://git.openi.org.cn/CV_benchmark/CV_reID_benchmark');
if (type_id == 3) {
$('#train_href_id').attr('href', 'https://git.openi.org.cn/CV_benchmark/CV_MOT_benchmark');
$('#test_href_id').attr('href', 'https://git.openi.org.cn/CV_benchmark/CV_MOT_benchmark');
} else {
$('#train_href_id').attr('href', 'https://git.openi.org.cn/CV_benchmark/CV_reID_benchmark');
$('#test_href_id').attr('href', 'https://git.openi.org.cn/CV_benchmark/CV_reID_benchmark');
}
let child_selected_id = $('#benchmark_child_types_id_hidden').val();
let child_selected_id = $('#benchmark_child_types_id_hidden').val();
$.get(`${repolink}/cloudbrain/benchmark/get_child_types?benchmark_type_id=${type_id}`, (data) => {
const n_length = data['child_types'].length
let html=''
for (let i=0;i<n_length;i++){
if(child_selected_id == data['child_types'][i].id){
let html = ''
for (let i = 0; i < n_length; i++) {
if (child_selected_id == data['child_types'][i].id) {
html += `<option value="${data['child_types'][i].id}" selected="true">${data['child_types'][i].value}</option>`;
}else{
} else {
html += `<option value="${data['child_types'][i].id}">${data['child_types'][i].value}</option>`;
}
}
document.getElementById("benchmark_child_types_id").innerHTML=html;
document.getElementById("benchmark_child_types_id").innerHTML = html;
})
}

document.onreadystatechange = function() {
document.onreadystatechange = function () {
if (document.readyState === "complete") {
setChildType();
if ($('input[name=benchmarkMode]').val() === 'alogrithm' || $('input[name=benchmarkMode]').val() === '') {
setChildType();
}
}
}

function validate(){
function validate() {
$('.ui.form')
.form({
on: 'blur',
inline:true,
fields: {
image:{
identifier : 'image',
rules: [
{
type: 'empty',
prompt : '选择一个镜像'
}
]

.form({
on: 'blur',
fields: {
image: {
identifier: 'image',
rules: [
{
type: 'empty',
promt: ''
}
]
},
display_job_name: {
identifier: 'display_job_name',
rules: [
{
type: 'regExp[/^[a-zA-Z0-9-_]{1,64}[a-zA-Z0-9_]$/]',
promt: ''
}
]
},
},
onSuccess: function () {
// $('.ui.page.dimmer').dimmer('show')
document.getElementById("mask").style.display = "block"
},
onFailure: function (e) {
return false;
}
},
onSuccess: function(){
// $('.ui.page.dimmer').dimmer('show')
document.getElementById("mask").style.display = "block"
},
onFailure: function(e){
return false;
}
})
})
}


$('.ui.create_train_job.green.button').click(function(e) {
validate()
$('.ui.create_train_job.green.button').click(function (e) {
validate()
})
</script>
</script>

+ 396
- 261
templates/repo/cloudbrain/benchmark/show.tmpl View File

@@ -1,165 +1,199 @@
{{template "base/head" .}}
<style>
.according-panel-heading{
box-sizing: border-box;
padding: 8px 16px;
color: #252b3a;
background-color: #f2f5fc;
line-height: 1.5;
cursor: pointer;
-moz-user-select: none;
-webkit-user-select: none;
-ms-user-select: none;
-khtml-user-select: none;
user-select: none;
}
.accordion-panel-title {
margin-top: 0;
margin-bottom: 0;
color: #252b3a;
}
.accordion-panel-title-content{
vertical-align: middle;
display: inline-block;
width: calc(100% - 32px);
cursor: default;
}
.acc-margin-bottom {
margin-bottom: 5px;
}
.title_text {
font-size: 12px;
}
.ac-display-inblock {
display: inline-block;
}
.cti-mgRight-sm {
margin-right: 8px;
}
.ac-text-normal {
font-size: 14px;
color: #575d6c;
}
.uc-accordionTitle-black {
color: #333;
}
.accordion-border{
border:1px solid #cce2ff;
}
.padding0{
padding: 0 !important;
}
.content-pad{
padding: 15px 35px;
}
.content-margin{
margin:10px 5px ;
}
.tab_2_content {
min-height: 360px;
margin-left: 10px;
}
.ac-grid {
display: block;
*zoom: 1;
}
.ac-grid-col {
float: left;
width: 100%;
}
.ac-grid-col2 .ac-grid-col {
width: 50%;
}
.ti-form {
text-align: left;
max-width: 100%;
vertical-align: middle;
}
.ti-form>tbody {
font-size: 12px;
}
.ti-form>tbody, .ti-form>tbody>tr {
vertical-align: inherit;
}
.ti-text-form-label {

padding-bottom: 20px;
padding-right: 20px;
color: #8a8e99;
font-size: 12px;
white-space: nowrap !important;
width: 80px;
line-height: 30px;
}
.ti-text-form-content{
line-height: 30px;
padding-bottom: 20px;
}
.ti-form>tbody>tr>td {
vertical-align: top;
white-space: normal;
}
td, th {
padding: 0;
}
.ac-grid-col .text-span {
width: 450px;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
.redo-color{
color: #3291F8;
}
.ti-action-menu-item:not(:last-child){
margin-right: 10px;
padding-right: 11px;
text-decoration: none!important;
color: #526ecc;
cursor: pointer;
display: inline-block;
-moz-user-select: none;
-webkit-user-select: none;
-ms-user-select: none;
-khtml-user-select: none;
user-select: none;
position: relative;
}
.ti-action-menu-item:not(:last-child):after {
content: "";
display: inline-block;
position: absolute;
height: 12px;
right: 0;
top: 50%;
-webkit-transform: translateY(-6px);
-ms-transform: translateY(-6px);
-o-transform: translateY(-6px);
transform: translateY(-6px);
border-right: 1px solid #dfe1e6;
}
.text-width80{
width: 100px;
line-height: 30px;
}
.border-according{
border: 1px solid #dfe1e6;
}
.disabled {
.according-panel-heading {
box-sizing: border-box;
padding: 8px 16px;
color: #252b3a;
background-color: #f2f5fc;
line-height: 1.5;
cursor: pointer;
-moz-user-select: none;
-webkit-user-select: none;
-ms-user-select: none;
-khtml-user-select: none;
user-select: none;
}

.accordion-panel-title {
margin-top: 0;
margin-bottom: 0;
color: #252b3a;
}

.accordion-panel-title-content {
vertical-align: middle;
display: inline-block;
width: calc(100% - 32px);
cursor: default;
}

.acc-margin-bottom {
margin-bottom: 5px;
}

.title_text {
font-size: 12px;
}

.ac-display-inblock {
display: inline-block;
}

.cti-mgRight-sm {
margin-right: 8px;
}

.ac-text-normal {
font-size: 14px;
color: #575d6c;
}

.uc-accordionTitle-black {
color: #333;
}

.accordion-border {
border: 1px solid #cce2ff;
}

.padding0 {
padding: 0 !important;
}

.content-pad {
padding: 15px 35px;
}

.content-margin {
margin: 10px 5px;
}

.tab_2_content {
min-height: 425px;
margin-left: 10px;
}

.ac-grid {
display: block;
*zoom: 1;
}

.ac-grid-col {
float: left;
width: 100%;
}

.ac-grid-col2 .ac-grid-col {
width: 50%;
}

.ti-form {
text-align: left;
max-width: 100%;
vertical-align: middle;
}

.ti-form>tbody {
font-size: 12px;
}

.ti-form>tbody,
.ti-form>tbody>tr {
vertical-align: inherit;
}

.ti-text-form-label {

padding-bottom: 20px;
padding-right: 20px;
color: #8a8e99;
font-size: 12px;
white-space: nowrap !important;
width: 80px;
line-height: 30px;
}

.ti-text-form-content {
line-height: 30px;
padding-bottom: 20px;
}

.ti-form>tbody>tr>td {
vertical-align: top;
white-space: normal;
}

td,
th {
padding: 0;
}

.ac-grid-col .text-span {
width: 450px;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}

.redo-color {
color: #3291F8;
}

.ti-action-menu-item:not(:last-child) {
margin-right: 10px;
padding-right: 11px;
text-decoration: none !important;
color: #526ecc;
cursor: pointer;
display: inline-block;
-moz-user-select: none;
-webkit-user-select: none;
-ms-user-select: none;
-khtml-user-select: none;
user-select: none;
position: relative;
}

.ti-action-menu-item:not(:last-child):after {
content: "";
display: inline-block;
position: absolute;
height: 12px;
right: 0;
top: 50%;
-webkit-transform: translateY(-6px);
-ms-transform: translateY(-6px);
-o-transform: translateY(-6px);
transform: translateY(-6px);
border-right: 1px solid #dfe1e6;
}

.text-width80 {
width: 100px;
line-height: 30px;
}

.border-according {
border: 1px solid #dfe1e6;
}

.disabled {
cursor: default;
pointer-events: none;
color: rgba(0,0,0,.6) !important;
color: rgba(0, 0, 0, .6) !important;
opacity: .45 !important;
}
.pad20{

border:0px !important;
}
.model_file_bread{
margin-bottom: -0.5rem !important;
padding-left: 1rem;
padding-top: 0.5rem ;
}
}

.pad20 {

border: 0px !important;
}

.model_file_bread {
margin-bottom: -0.5rem !important;
padding-left: 1rem;
padding-top: 0.5rem;
}
</style>
<div id="mask">
<div id="loadingPage">
@@ -171,7 +205,7 @@ td, th {
</div>
</div>
<div class="repository">
{{template "repo/header" .}}
{{template "repo/header" .}}
<div class="ui container">
<h4 class="ui header" id="vertical-segment">
<div class="ui breadcrumb">
@@ -183,11 +217,12 @@ td, th {
{{$.i18n.Tr "repo.modelarts.evaluate_job"}}
</a>
<div class="divider"> / </div>
<div class="active section">{{.displayJobName}}</div>
</div>
<div class="active section">{{.displayJobName}}</div>
</div>
</h4>
{{range $k ,$v := .version_list_task}}
<div class="ui accordion border-according" id="accordion{{.VersionName}}" data-repopath="{{$.RepoRelPath}}" data-jobid="{{.JobID}}" data-version="{{.VersionName}}">
<div class="ui accordion border-according" id="accordion{{.VersionName}}"
data-repopath="{{$.RepoRelPath}}/cloudbrain" data-jobid="{{.ID}}" data-version="{{.VersionName}}">
<input type="hidden" id="jobId_input" name="jobId_input" value="{{.JobID}}">
<div class="{{if eq $k 0}}active{{end}} title padding0">
<div class="according-panel-heading">
@@ -197,18 +232,23 @@ td, th {
<span>
<div class="ac-display-inblock title_text acc-margin-bottom">
<span class="cti-mgRight-sm">
{{if not (eq .StartTime 0)}}
<td>{{TimeSinceUnix1 .StartTime}}</td>
{{else}}
<td>{{TimeSinceUnix1 .CreatedUnix}}<td>
{{end}}
</span>
{{if not (eq .StartTime 0)}}
<td>{{TimeSinceUnix1 .StartTime}}</td>
{{else}}
<td>{{TimeSinceUnix1 .CreatedUnix}}
<td>
{{end}}
</span>

<span class="cti-mgRight-sm">{{$.i18n.Tr "repo.modelarts.status"}}:
<span id="{{.VersionName}}-status-span"><i id="icon" style="vertical-align: middle;" class="{{.Status}}"></i><span id="text" style="margin-left: 0.4em;font-size: 12px;">{{.Status}}</span></span>
<span id="{{.VersionName}}-status-span"><i id="icon"
style="vertical-align: middle;" class="{{.Status}}"></i><span id="text"
style="margin-left: 0.4em;font-size: 12px;">{{.Status}}</span></span>
</span>
<span class="cti-mgRight-sm">{{$.i18n.Tr "repo.modelarts.train_job.dura_time"}}:</span>
<span class="cti-mgRight-sm uc-accordionTitle-black" id="{{.VersionName}}-duration-span">{{$.duration}}</span>
<span
class="cti-mgRight-sm">{{$.i18n.Tr "repo.modelarts.train_job.dura_time"}}:</span>
<span class="cti-mgRight-sm uc-accordionTitle-black"
id="{{.VersionName}}-duration-span">{{$.duration}}</span>

</div>
</span>
@@ -219,8 +259,10 @@ td, th {
<div class="{{if eq $k 0}}active{{end}} content">
<div class="content-pad">
<div class="ui pointing secondary menu" style="border-bottom: 1px solid rgba(34,36,38,.15);">
<a class="active item" data-tab="first{{$k}}">{{$.i18n.Tr "repo.modelarts.train_job.config"}}</a>
<a class="item" data-tab="second{{$k}}" onclick="loadLog({{.VersionName}})">{{$.i18n.Tr "repo.modelarts.log"}}</a>
<a class="active item"
data-tab="first{{$k}}">{{$.i18n.Tr "repo.modelarts.train_job.config"}}</a>
<a class="item" data-tab="second{{$k}}"
onclick="loadLog({{.VersionName}})">{{$.i18n.Tr "repo.modelarts.log"}}</a>
</div>
<div class="ui tab active" data-tab="first{{$k}}">
<div style="padding-top: 10px;">
@@ -250,31 +292,61 @@ td, th {
</div>
</td>
</tr>

<tr class="ti-no-ng-animate">
<td class="ti-no-ng-animate ti-text-form-label text-width80">
{{$.i18n.Tr "repo.modelarts.train_job.start_time"}}
{{$.i18n.Tr "repo.modelarts.createtime"}}
</td>

<td class="ti-text-form-content">
<div class="text-span text-span-w">
<span style="font-size: 12px;" class="">
{{if not (eq .StartTime 0)}}
{{TimeSinceUnix1 .StartTime}}
{{else}}
{{TimeSinceUnix1 .CreatedUnix}}
{{end}}
{{TimeSinceUnix1 .CreatedUnix}}
</span>
</div>
</td>
</tr>

<tr class="ti-no-ng-animate">
<td class="ti-no-ng-animate ti-text-form-label text-width80">
{{$.i18n.Tr "repo.cloudbrain.time.starttime"}}
</td>

<td class="ti-text-form-content">
<div class="text-span text-span-w"
id="{{.VersionName}}-startTime">
{{if not (eq .StartTime 0)}}
{{TimeSinceUnix1 .StartTime}}
{{else}}
--
{{end}}
</div>
</td>
</tr>

<tr class="ti-no-ng-animate">
<td class="ti-no-ng-animate ti-text-form-label text-width80">
{{$.i18n.Tr "repo.cloudbrain.time.endtime"}}
</td>

<td class="ti-text-form-content">
<div class="text-span text-span-w"
id="{{.VersionName}}-EndTime">
{{if not (eq .EndTime 0)}}
{{TimeSinceUnix1 .EndTime}}
{{else}}
--
{{end}}
</div>
</td>
</tr>
<tr class="ti-no-ng-animate">
<td class="ti-no-ng-animate ti-text-form-label text-width80">
{{$.i18n.Tr "repo.modelarts.train_job.dura_time"}}
</td>

<td class="ti-text-form-content">
<div class="text-span text-span-w" id="{{.VersionName}}-duration">
<div class="text-span text-span-w"
id="{{.VersionName}}-duration">
{{$.duration}}
</div>
</td>
@@ -290,100 +362,162 @@ td, th {
</div>
</td>
</tr>
<tr class="ti-no-ng-animate">
<td class="ti-no-ng-animate ti-text-form-label text-width80">
{{$.i18n.Tr "repo.cloudbrain.benchmark.evaluate_scenes"}}

</td>

<td class="ti-text-form-content">
<div class="text-span text-span-w"
id="{{.VersionName}}-BenchmarkTypeName">
{{.BenchmarkType}}
</div>
</td>
</tr>
<tr class="ti-no-ng-animate">
<td class="ti-no-ng-animate ti-text-form-label text-width80">
{{$.i18n.Tr "repo.cloudbrain.benchmark.evaluate_type"}}
</td>

<td class="ti-text-form-content">
<div class="text-span text-span-w" id="{{.VersionName}}-BenchmarkTypeName">
{{$.BenchmarkTypeName}}
<div class="text-span text-span-w"
id="{{.VersionName}}-BenchmarkTypeName">
{{.BenchmarkTypeName}}
</div>
</td>
</tr>



</tbody>
</table>
</div>
<div class="ac-grid-col">
<table class="ti-form">
<tbody class="ti-text-form">


<tr class="ti-no-ng-animate">
<td class="ti-no-ng-animate ti-text-form-label text-width80">
{{$.i18n.Tr "repo.cloudbrain.benchmark.evaluate_train"}}
</td>

<td class="ti-text-form-content">
<div class="text-span text-span-w">
train.py
</div>
</td>
</tr>
<tr class="ti-no-ng-animate">
<td class="ti-no-ng-animate ti-text-form-label text-width80">
{{$.i18n.Tr "repo.cloudbrain.benchmark.evaluate_test"}}
</td>

<td class="ti-text-form-content">
<div class="text-span text-span-w">
test.py
</div>
</td>
</tr>

<tr class="ti-no-ng-animate">
<td class="ti-no-ng-animate ti-text-form-label text-width80">
{{$.i18n.Tr "repo.modelarts.train_job.description"}}
</td>

<td class="ti-text-form-content">
<div class="text-span text-span-w" title="{{.Description}}">
{{.Description}}
</div>
</td>
</tr>

<tr class="ti-no-ng-animate">
<td class="ti-no-ng-animate ti-text-form-label text-width80">
{{$.i18n.Tr "repo.modelarts.train_job.standard"}}
</td>

<td class="ti-text-form-content">
<div class="text-span text-span-w">
{{$.resource_spec}}
</div>
</td>
</tr>

<tr class="ti-no-ng-animate">
<td class="ti-no-ng-animate ti-text-form-label text-width80">
{{$.i18n.Tr "repo.cloudbrain_creator"}}
</td>

<td class="ti-text-form-content">
<div class="text-span text-span-w" id="{{.VersionName}}-mirror">
{{.User.Name}}
</div>
</td>
</tr>
<tr class="ti-no-ng-animate">
<table class="ti-form">
<tbody class="ti-text-form">


<tr class="ti-no-ng-animate">
<td class="ti-no-ng-animate ti-text-form-label text-width80">
{{$.i18n.Tr "repo.cloudbrain.benchmark.evaluate_train"}}
</td>

<td class="ti-text-form-content">
<div class="text-span text-span-w">
{{if eq .JobType "BENCHMARK"}}
train.py
{{else}}
--
{{end}}
</div>
</td>
</tr>
<tr class="ti-no-ng-animate">
<td class="ti-no-ng-animate ti-text-form-label text-width80">
{{$.i18n.Tr "repo.cloudbrain.benchmark.evaluate_test"}}
</td>

<td class="ti-text-form-content">
<div class="text-span text-span-w">
{{if eq .JobType "BENCHMARK"}}
test.py
{{else}}
--
{{end}}
</div>
</td>
</tr>

<tr class="ti-no-ng-animate">
<td class="ti-no-ng-animate ti-text-form-label text-width80">
{{$.i18n.Tr "repo.modelarts.train_job.description"}}
</td>

<td class="ti-text-form-content">
<div class="text-span text-span-w" title="{{.Description}}">
{{if .Description}}
{{.Description}}
{{else}}
--
{{end}}
</div>
</td>
</tr>
<tr class="ti-no-ng-animate">
<td class="ti-no-ng-animate ti-text-form-label text-width80">
{{$.i18n.Tr "cloudbrain.gpu_type"}}
</td>

<td class="ti-text-form-content">
<div class="text-span text-span-w">
{{$.resource_type}}
</div>
</td>
</tr>
<tr class="ti-no-ng-animate">
<td class="ti-no-ng-animate ti-text-form-label text-width80">
{{$.i18n.Tr "repo.modelarts.train_job.standard"}}
</td>

<td class="ti-text-form-content">
<div class="text-span text-span-w">
{{$.resource_spec}}
</div>
</td>
</tr>
<tr class="ti-no-ng-animate">
<td class="ti-no-ng-animate ti-text-form-label text-width80">
{{$.i18n.Tr "repo.model_manager"}}
</td>

<td class="ti-text-form-content">
<div class="text-span text-span-w" id="{{.VersionName}}-mirror">
{{$.datasetname}}
</div>
</td>
</tr>
<tr class="ti-no-ng-animate">
<td class="ti-no-ng-animate ti-text-form-label text-width80">
{{$.i18n.Tr "repo.cloudbrain_creator"}}
</td>

<td class="ti-text-form-content">
<div class="text-span text-span-w" id="{{.VersionName}}-mirror">
{{if .User}}
{{.User.Name}}
{{else}}
--
{{end}}
</div>
</td>
</tr>
<tr class="ti-no-ng-animate">
<td class="ti-no-ng-animate ti-text-form-label text-width80">
{{if eq .BenchmarkTypeName "BRAINSCORE"}}
{{$.i18n.Tr "cloudbrain.brain_area"}}
{{else}}
{{$.i18n.Tr "repo.cloudbrain.benchmark.evaluate_child_type"}}
{{end}}
</td>

<td class="ti-text-form-content">
<div class="text-span text-span-w" id="{{.VersionName}}-BenchmarkChildTypeName">
<div class="text-span text-span-w"
id="{{.VersionName}}-BenchmarkChildTypeName">

{{if $.BenchmarkChildTypeName}}
{{$.BenchmarkChildTypeName}}
{{else}}
--
{{end}}
</div>
</td>
</tr>
</tbody>
</table>
</div>
</tr>

</tbody>
</table>
</div>
</div>
</div>

@@ -394,9 +528,10 @@ td, th {
<div class="ui message message{{.VersionName}}" style="display: none;">
<div id="header"></div>
</div>
<div class="ui attached log" id="log{{.VersionName}}" style="height: 300px !important; overflow: auto;">
<input type="hidden" name="end_line" value>
<input type="hidden" name="start_line" value>
<div class="ui attached log" id="log{{.VersionName}}"
style="height: 300px !important; overflow: auto;">
<input type="hidden" name="end_line" value>
<input type="hidden" name="start_line" value>
<pre id="log_file{{.VersionName}}"></pre>
</div>

@@ -437,17 +572,17 @@ td, th {
<script>
$('.menu .item').tab()

$(document).ready(function(){
$('.ui.accordion').accordion({selector:{trigger:'.icon'}});
$(document).ready(function () {
$('.ui.accordion').accordion({ selector: { trigger: '.icon' } });
});
$(document).ready(function(){
$(document).ready(function () {
$('.secondary.menu .item').tab();
});

let userName
let repoPath
let jobName
$(document).ready(function(){
$(document).ready(function () {
let url = window.location.href;
let urlArr = url.split('/')
userName = urlArr.slice(-5)[0]
@@ -455,17 +590,17 @@ td, th {
jobName = urlArr.slice(-1)[0]
})

function loadLog(version_name){
function loadLog(version_name) {
document.getElementById("mask").style.display = "block"
$.get(`/api/v1/repos/${userName}/${repoPath}/cloudbrain/${jobName}/log?version_name=${version_name}&lines=50&order=asc`, (data) => {
$('input[name=end_line]').val(data.EndLine)
$('input[name=start_line]').val(data.StartLine)
$(`#log_file${version_name}`).text(data.Content)
document.getElementById("mask").style.display = "none"
}).fail(function(err) {
}).fail(function (err) {
console.log(err);
document.getElementById("mask").style.display = "none"
});
}

</script>
</script>

+ 2
- 1
templates/repo/cloudbrain/models/dir_list.tmpl View File

@@ -20,8 +20,9 @@
<span class="time-since poping up">{{.ModTime}}</span>
</td>
</tr>

{{end}}
</tbody>
</table>

{{end}}
{{end}}

+ 84
- 68
templates/repo/cloudbrain/new.tmpl View File

@@ -17,6 +17,7 @@
padding-top: 100px;
color: #000000
}

/* 加载圈css效果图 */

#loadingPage {
@@ -58,23 +59,27 @@
}

@-webkit-keyframes sk-stretchdelay {

0%,
40%,
100% {
-webkit-transform: scaleY(0.4)
}

20% {
-webkit-transform: scaleY(1.0)
}
}

@keyframes sk-stretchdelay {

0%,
40%,
100% {
transform: scaleY(0.4);
-webkit-transform: scaleY(0.4);
}

20% {
transform: scaleY(1.0);
-webkit-transform: scaleY(1.0);
@@ -93,15 +98,12 @@
display: none;
}

.icons{
.icons {
/* position: absolute !important;
right: 150px;
top: 14px;
z-index: 2; */
}



</style>

<div id="mask">
@@ -117,7 +119,7 @@
<div class="repository">
{{template "repo/header" .}}
<div class="repository new repo ui middle very relaxed page grid">
<div class="column">
{{template "base/alert" .}}
<div class="ui negative message" id="messageInfo">
@@ -133,43 +135,45 @@
<label>{{.i18n.Tr "cloudbrain.compute_resource"}}</label>
<div class="ui blue small menu compact selectcloudbrain">
<a class="active item" href="{{.RepoLink}}/cloudbrain/create">
<svg class="svg" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="16" height="16">
<path fill="none" d="M0 0h24v24H0z"/>
<path d="M3 2.992C3 2.444 3.445 2 3.993 2h16.014a1 1 0 0 1 .993.992v18.016a.993.993 0 0 1-.993.992H3.993A1 1 0 0 1 3 21.008V2.992zM19 11V4H5v7h14zm0 2H5v7h14v-7zM9 6h6v2H9V6zm0 9h6v2H9v-2z"/>
<svg class="svg" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="16"
height="16">
<path fill="none" d="M0 0h24v24H0z" />
<path
d="M3 2.992C3 2.444 3.445 2 3.993 2h16.014a1 1 0 0 1 .993.992v18.016a.993.993 0 0 1-.993.992H3.993A1 1 0 0 1 3 21.008V2.992zM19 11V4H5v7h14zm0 2H5v7h14v-7zM9 6h6v2H9V6zm0 9h6v2H9v-2z" />
</svg>
CPU/GPU
</a>
<a class="item" href="{{.RepoLink}}/modelarts/notebook/create">
<svg class="svg" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="16" height="16">
<path fill="none" d="M0 0h24v24H0z"/>
<path d="M3 2.992C3 2.444 3.445 2 3.993 2h16.014a1 1 0 0 1 .993.992v18.016a.993.993 0 0 1-.993.992H3.993A1 1 0 0 1 3 21.008V2.992zM19 11V4H5v7h14zm0 2H5v7h14v-7zM9 6h6v2H9V6zm0 9h6v2H9v-2z"/>
<svg class="svg" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="16"
height="16">
<path fill="none" d="M0 0h24v24H0z" />
<path
d="M3 2.992C3 2.444 3.445 2 3.993 2h16.014a1 1 0 0 1 .993.992v18.016a.993.993 0 0 1-.993.992H3.993A1 1 0 0 1 3 21.008V2.992zM19 11V4H5v7h14zm0 2H5v7h14v-7zM9 6h6v2H9V6zm0 9h6v2H9v-2z" />
</svg>
Ascend NPU</a>
</div>
</div>
<div class="inline required field">
<label>{{.i18n.Tr "cloudbrain.task_name"}}</label>
<input name="display_job_name" id="cloudbrain_job_name" placeholder="input {{.i18n.Tr "cloudbrain.task_name"}}" value="{{.display_job_name}}" tabindex="3" autofocus required maxlength="255" onkeyup="this.value=this.value.replace(/[, ]/g,'')">
<input name="display_job_name" id="cloudbrain_job_name"
placeholder="{{.i18n.Tr "cloudbrain.task_name"}}" value="{{.display_job_name}}" tabindex="3"
autofocus required maxlength="255" onkeyup="this.value=this.value.replace(/[, ]/g,'')">
</div>

<div class="inline required field">
<label>{{.i18n.Tr "cloudbrain.task_type"}}</label>
<select id="cloudbrain_job_type" class="ui search dropdown" placeholder="select {{.i18n.Tr "cloudbrain.task_type"}}" style='width:385px' name="job_type">
<select id="cloudbrain_job_type" class="ui search dropdown"
placeholder="{{.i18n.Tr "cloudbrain.task_type"}}" style='width:385px' name="job_type">
<option name="job_type" value="DEBUG">DEBUG</option>
{{if .is_snn4imagenet_enabled}}
<option name="job_type" value="SNN4IMAGENET">SNN4IMAGENET</option>
{{end}}
{{if .is_brainscore_enabled}}
<option name="job_type" value="BRAINSCORE">BRAINSCORE</option>
{{end}}
</select>
</div>

<div class="inline required field cloudbrain_benchmark">
<label style="vertical-align: top; margin-top:9px">数据集类别</label>
<select class="ui search dropdown" multiple="multiple" id="cloudbrain_benchmark_category" style='width:385px'>
<select class="ui search dropdown" multiple="multiple" id="cloudbrain_benchmark_category"
style='width:385px'>
{{range .benchmark_categories}}
<option value="{{.Value}}">{{.Value}}</option>
<option value="{{.Value}}">{{.Value}}</option>
{{end}}
</select>
<div class="mini ui buttons" style="vertical-align: top; margin-top:9px">
@@ -178,32 +182,33 @@
<button class="ui positive button active all_selected">全选</button>
</div>
</div>
<input id="store_category" type="hidden" name="get_benchmark_category">
<input id="store_category" type="hidden" name="get_benchmark_category">
<div class="inline required field">
<label>{{.i18n.Tr "repo.modelarts.code_version"}}</label>
<select class="ui dropdown width80 left2" id="code_version" name="branch_name">
{{if .branch_name}}
<option name="branch_name" value="{{.branch_name}}">{{.branch_name}}</option>
{{range $k, $v :=.Branches}}
{{ if ne $v $.branch_name }}
<option name="branch_name" value="{{$v}}">{{$v}}</option>
{{end}}
{{end}}
<option name="branch_name" value="{{.branch_name}}">{{.branch_name}}</option>
{{range $k, $v :=.Branches}}
{{ if ne $v $.branch_name }}
<option name="branch_name" value="{{$v}}">{{$v}}</option>
{{end}}
{{end}}
{{else}}
<option name="branch_name" value="{{.branchName}}">{{.branchName}}</option>
{{range $k, $v :=.Branches}}
{{ if ne $v $.branchName }}
<option name="branch_name" value="{{$v}}">{{$v}}</option>
{{end}}
{{end}}
<option name="branch_name" value="{{.branchName}}">{{.branchName}}</option>
{{range $k, $v :=.Branches}}
{{ if ne $v $.branchName }}
<option name="branch_name" value="{{$v}}">{{$v}}</option>
{{end}}
{{end}}
{{end}}
</select>
</div>
<div class="inline required field">
<label>{{.i18n.Tr "cloudbrain.gpu_type"}}</label>
<select id="cloudbrain_gpu_type" class="ui search dropdown" placeholder="选择GPU类型" style='width:385px' name="gpu_type">
<select id="cloudbrain_gpu_type" class="ui search dropdown" placeholder="选择GPU类型"
style='width:385px' name="gpu_type">
{{range .gpu_types}}
<option value="{{.Queue}}">{{.Value}}</option>
<option value="{{.Queue}}">{{.Value}}</option>
{{end}}
</select>
</div>
@@ -224,40 +229,50 @@
<div id="images-new-cb">

</div>
{{template "custom/select_dataset" .}}
<div class="inline required field">
<label>{{.i18n.Tr "cloudbrain.resource_specification"}}</label>
<select id="cloudbrain_resource_spec" class="ui search dropdown" placeholder="{{.i18n.Tr "cloudbrain.select_specification"}}" style='width:385px' name="resource_spec_id">
<select id="cloudbrain_resource_spec" class="ui search dropdown"
placeholder="{{.i18n.Tr "cloudbrain.select_specification"}}" style='width:385px'
name="resource_spec_id">
{{range .resource_specs}}
<option name="resource_spec_id" value="{{.Id}}">{{$.i18n.Tr "cloudbrain.gpu_num"}}:{{.GpuNum}},{{$.i18n.Tr "cloudbrain.cpu_num"}}:{{.CpuNum}},{{$.i18n.Tr "cloudbrain.memory"}}(MB):{{.MemMiB}},{{$.i18n.Tr "cloudbrain.shared_memory"}}(MB):{{.ShareMemMiB}}</option>
<option name="resource_spec_id" value="{{.Id}}">
{{$.i18n.Tr "cloudbrain.gpu_num"}}:{{.GpuNum}},{{$.i18n.Tr "cloudbrain.cpu_num"}}:{{.CpuNum}},{{$.i18n.Tr "cloudbrain.memory"}}(MB):{{.MemMiB}},{{$.i18n.Tr "cloudbrain.shared_memory"}}(MB):{{.ShareMemMiB}}
</option>
{{end}}
</select>
</div>

<div class="inline required field">
<label>{{.i18n.Tr "cloudbrain.dataset_storage_path"}}</label>
<input name="dataset_path" id="cloudbrain_dataset_path" value="{{.dataset_path}}" tabindex="3" disabled autofocus required maxlength="255" readonly="readonly">
<input name="dataset_path" id="cloudbrain_dataset_path" value="{{.dataset_path}}" tabindex="3"
disabled autofocus required maxlength="255" readonly="readonly">
</div>
<div class="inline required field">
<label>{{.i18n.Tr "cloudbrain.model_storage_path"}}</label>
<input name="model_path" id="cloudbrain_model_path" value="{{.model_path}}" tabindex="3" disabled autofocus required maxlength="255" readonly="readonly">
<input name="model_path" id="cloudbrain_model_path" value="{{.model_path}}" tabindex="3"
disabled autofocus required maxlength="255" readonly="readonly">
</div>
<div class="inline required field">
<label>{{.i18n.Tr "cloudbrain.code_storage_path"}}</label>
<input name="code_path" id="cloudbrain_code_path" value="{{.code_path}}" tabindex="3" disabled autofocus required maxlength="255" readonly="readonly">
<input name="code_path" id="cloudbrain_code_path" value="{{.code_path}}" tabindex="3" disabled
autofocus required maxlength="255" readonly="readonly">
</div>
<div class="inline required field cloudbrain_benchmark">
<label>{{.i18n.Tr "cloudbrain.benchmark_path"}}</label>
<input name="benchmark_path" id="cloudbrain_benchmark_path" value="{{.benchmark_path}}" tabindex="3" disabled autofocus required maxlength="255" readonly="readonly">
<input name="benchmark_path" id="cloudbrain_benchmark_path" value="{{.benchmark_path}}"
tabindex="3" disabled autofocus required maxlength="255" readonly="readonly">
</div>
<div class="inline required field cloudbrain_snn4imagenet">
<label>{{.i18n.Tr "cloudbrain.snn4imagenet_path"}}</label>
<input name="snn4imagenet_path" id="cloudbrain_snn4imagenet_path" value="{{.snn4imagenet_path}}" tabindex="3" disabled autofocus required maxlength="255" readonly="readonly">
<input name="snn4imagenet_path" id="cloudbrain_snn4imagenet_path" value="{{.snn4imagenet_path}}"
tabindex="3" disabled autofocus required maxlength="255" readonly="readonly">
</div>
<div class="inline required field cloudbrain_brainscore">
<label>{{.i18n.Tr "cloudbrain.brainscore_path"}}</label>
<input name="brainscore_path" id="cloudbrain_brainscore_path" value="{{.brainscore_path}}" tabindex="3" disabled autofocus required maxlength="255" readonly="readonly">
<input name="brainscore_path" id="cloudbrain_brainscore_path" value="{{.brainscore_path}}"
tabindex="3" disabled autofocus required maxlength="255" readonly="readonly">
</div>
<div class="inline required field" hidden>
<label>{{.i18n.Tr "cloudbrain.start_command"}}</label>
@@ -266,10 +281,11 @@

<div class="inline field">
<label></label>
<button class="ui green button" >
{{.i18n.Tr "repo.cloudbrain.new"}}
</button>
<a class="ui button cancel" href="{{.RepoLink}}/debugjob?debugListType=all">{{.i18n.Tr "repo.cloudbrain.cancel"}}</a>
<button class="ui green button">
{{.i18n.Tr "repo.cloudbrain.new"}}
</button>
<a class="ui button cancel"
href="{{.RepoLink}}/debugjob?debugListType=all">{{.i18n.Tr "repo.cloudbrain.cancel"}}</a>
</div>
</div>
</form>
@@ -287,32 +303,32 @@
// $(".icon.icons").css("visibility","visible")
// });

$('#messageInfo').css('display','none')
function clearValue(){
context=inputs[0]
context.value=''
$(".icon.icons").css("visibility","hidden")
$('#messageInfo').css('display', 'none')
function clearValue() {
context = inputs[0]
context.value = ''
$(".icon.icons").css("visibility", "hidden")
}
form.onsubmit = function(e){
form.onsubmit = function (e) {
let value_task = $("input[name='display_job_name']").val()
let value_image = $("input[name='image']").val()
let value_data = $("input[name='attachment']").val()
let re = /^[a-z0-9][a-z0-9-_]{1,34}[a-z0-9-]$/
let flag = re.test(value_task)
if(!flag){
$('#messageInfo').css('display','block')
if (!flag) {
$('#messageInfo').css('display', 'block')
let str = '只能以小写字母或数字开头且只包含小写字母、数字、_和-,不能以_结尾,最长36个字符。'
$('#messageInfo p').text(str)
return false
}
let min_value_task = value_task.toLowerCase()
$("input[name='display_job_name']").attr("value",min_value_task)
$("input[name='display_job_name']").attr("value", min_value_task)
document.getElementById("mask").style.display = "block"

}

// 页面加载完毕后遮罩层隐藏
document.onreadystatechange = function() {
document.onreadystatechange = function () {
if (document.readyState === "complete") {
document.getElementById("mask").style.display = "none"
}
@@ -332,24 +348,24 @@
// });


$(".ui.button.reset").click(function(e){
$(".ui.button.reset").click(function (e) {
e.preventDefault()
$('#cloudbrain_benchmark_category')
.dropdown("clear", true)
.dropdown("clear", true)
})

$(".ui.positive.button.active.all_selected").click(function(e){
$(".ui.positive.button.active.all_selected").click(function (e) {
e.preventDefault()
var selected_value = new Array()
$("#cloudbrain_benchmark_category option").each(function(){
$("#cloudbrain_benchmark_category option").each(function () {
selected_value.push($(this).val())
});
$('#cloudbrain_benchmark_category')
.dropdown("set exactly", selected_value)
.dropdown("set exactly", selected_value)
})

$(function() {
$("#cloudbrain_job_type").change(function() {
$(function () {
$("#cloudbrain_job_type").change(function () {
if ($(this).val() == 'BENCHMARK') {
$(".cloudbrain_benchmark").show();
} else if ($(this).val() == 'SNN4IMAGENET') {
@@ -364,10 +380,10 @@
})
})

$('.ui.green.button').click(function() {
$('.ui.green.button').click(function () {
selected_value = $("#cloudbrain_benchmark_category").val()
$('#store_category').attr("value", selected_value)
})


</script>
</script>

+ 463
- 378
templates/repo/cloudbrain/show.tmpl View File

@@ -1,171 +1,205 @@
{{template "base/head" .}}
<style>
.according-panel-heading{
box-sizing: border-box;
padding: 8px 16px;
color: #252b3a;
background-color: #f2f5fc;
line-height: 1.5;
cursor: pointer;
-moz-user-select: none;
-webkit-user-select: none;
-ms-user-select: none;
-khtml-user-select: none;
user-select: none;
}
.accordion-panel-title {
margin-top: 0;
margin-bottom: 0;
color: #252b3a;
}
.accordion-panel-title-content{
vertical-align: middle;
display: inline-block;
width: calc(100% - 32px);
cursor: default;
}
.acc-margin-bottom {
margin-bottom: 5px;
}
.title_text {
font-size: 12px;
}
.ac-display-inblock {
display: inline-block;
}
.cti-mgRight-sm {
margin-right: 8px;
}
.ac-text-normal {
font-size: 14px;
color: #575d6c;
}
.uc-accordionTitle-black {
color: #333;
}
.accordion-border{
border:1px solid #cce2ff;
}
.padding0{
padding: 0 !important;
}
.content-pad{
padding: 15px 35px;
}
.content-margin{
margin:10px 5px ;
}
.tab_2_content {
min-height: 420px;
margin-left: 10px;
}
.ac-grid {
display: block;
*zoom: 1;
}
.ac-grid-col {
float: left;
width: 100%;
}
.ac-grid-col2 .ac-grid-col {
width: 50%;
}
.ti-form {
text-align: left;
max-width: 100%;
vertical-align: middle;
}
.ti-form>tbody {
font-size: 12px;
}
.ti-form>tbody, .ti-form>tbody>tr {
vertical-align: inherit;
}
.info_text {
padding-bottom: 20px;
padding-right: 20px;
font-size: 12px;
}

.ti-text-form-label {

padding-bottom: 20px;
padding-right: 20px;
color: #8a8e99;
font-size: 12px;
white-space: nowrap !important;
width: 80px;
line-height: 30px;
}
.ti-text-form-content{
line-height: 30px;
padding-bottom: 20px;
}
.ti-form>tbody>tr>td {
vertical-align: top;
white-space: normal;
}
td, th {
padding: 0;
}
.ac-grid-col .text-span {
width: 450px;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
.redo-color{
color: #3291F8;
}
.ti-action-menu-item:not(:last-child){
margin-right: 10px;
padding-right: 11px;
text-decoration: none!important;
color: #526ecc;
cursor: pointer;
display: inline-block;
-moz-user-select: none;
-webkit-user-select: none;
-ms-user-select: none;
-khtml-user-select: none;
user-select: none;
position: relative;
}
.ti-action-menu-item:not(:last-child):after {
content: "";
display: inline-block;
position: absolute;
height: 12px;
right: 0;
top: 50%;
-webkit-transform: translateY(-6px);
-ms-transform: translateY(-6px);
-o-transform: translateY(-6px);
transform: translateY(-6px);
border-right: 1px solid #dfe1e6;
}
.text-width80{
width: 100px;
line-height: 30px;
}
.border-according{
border: 1px solid #dfe1e6;
}
.disabled {
.according-panel-heading {
box-sizing: border-box;
padding: 8px 16px;
color: #252b3a;
background-color: #f2f5fc;
line-height: 1.5;
cursor: pointer;
-moz-user-select: none;
-webkit-user-select: none;
-ms-user-select: none;
-khtml-user-select: none;
user-select: none;
}

.accordion-panel-title {
margin-top: 0;
margin-bottom: 0;
color: #252b3a;
}

.accordion-panel-title-content {
vertical-align: middle;
display: inline-block;
width: calc(100% - 32px);
cursor: default;
}

.acc-margin-bottom {
margin-bottom: 5px;
}

.title_text {
font-size: 12px;
}

.ac-display-inblock {
display: inline-block;
}

.cti-mgRight-sm {
margin-right: 8px;
}

.ac-text-normal {
font-size: 14px;
color: #575d6c;
}

.uc-accordionTitle-black {
color: #333;
}

.accordion-border {
border: 1px solid #cce2ff;
}

.padding0 {
padding: 0 !important;
}

.content-pad {
padding: 15px 35px;
}

.content-margin {
margin: 10px 5px;
}

.tab_2_content {
min-height: 420px;
margin-left: 10px;
}

.ac-grid {
display: block;
*zoom: 1;
}

.ac-grid-col {
float: left;
width: 100%;
}

.ac-grid-col2 .ac-grid-col {
width: 50%;
}

.ti-form {
text-align: left;
max-width: 100%;
vertical-align: middle;
}

.ti-form>tbody {
font-size: 12px;
}

.ti-form>tbody,
.ti-form>tbody>tr {
vertical-align: inherit;
}

.info_text {
padding-bottom: 20px;
padding-right: 20px;
font-size: 12px;
}

.ti-text-form-label {

padding-bottom: 20px;
padding-right: 20px;
color: #8a8e99;
font-size: 12px;
white-space: nowrap !important;
width: 80px;
line-height: 30px;
}

.ti-text-form-content {
line-height: 30px;
padding-bottom: 20px;
}

.ti-form>tbody>tr>td {
vertical-align: top;
white-space: normal;
}

td,
th {
padding: 0;
}

.ac-grid-col .text-span {
width: 450px;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}

.redo-color {
color: #3291F8;
}

.ti-action-menu-item:not(:last-child) {
margin-right: 10px;
padding-right: 11px;
text-decoration: none !important;
color: #526ecc;
cursor: pointer;
display: inline-block;
-moz-user-select: none;
-webkit-user-select: none;
-ms-user-select: none;
-khtml-user-select: none;
user-select: none;
position: relative;
}

.ti-action-menu-item:not(:last-child):after {
content: "";
display: inline-block;
position: absolute;
height: 12px;
right: 0;
top: 50%;
-webkit-transform: translateY(-6px);
-ms-transform: translateY(-6px);
-o-transform: translateY(-6px);
transform: translateY(-6px);
border-right: 1px solid #dfe1e6;
}

.text-width80 {
width: 100px;
line-height: 30px;
}

.border-according {
border: 1px solid #dfe1e6;
}

.disabled {
cursor: default;
pointer-events: none;
color: rgba(0,0,0,.6) !important;
color: rgba(0, 0, 0, .6) !important;
opacity: .45 !important;
}
.pad20{

border:0px !important;
}
.model_file_bread{
margin-bottom: -0.5rem !important;
padding-left: 1rem;
padding-top: 0.5rem ;
}
}

.pad20 {

border: 0px !important;
}

.model_file_bread {
margin-bottom: -0.5rem !important;
padding-left: 1rem;
padding-top: 0.5rem;
}
</style>


@@ -179,7 +213,7 @@ td, th {
</div>
</div>
<div class="repository">
{{template "repo/header" .}}
{{template "repo/header" .}}
<div class="ui container">
<h4 class="ui header" id="vertical-segment">
<div class="ui breadcrumb">
@@ -191,11 +225,12 @@ td, th {
{{$.i18n.Tr "repo.modelarts.notebook"}}
</a>
<div class="divider"> / </div>
<div class="active section">{{.displayJobName}}</div>
</div>
<div class="active section">{{.displayJobName}}</div>
</div>
</h4>
{{range $k ,$v := .version_list_task}}
<div class="ui accordion border-according" id="accordion{{.VersionName}}" data-repopath="{{$.RepoRelPath}}" data-jobid="{{.JobID}}" data-version="{{.VersionName}}">
<div class="ui accordion border-according" id="accordion{{.VersionName}}"
data-repopath="{{$.RepoRelPath}}/cloudbrain" data-jobid="{{.ID}}" data-version="{{.VersionName}}">
<input type="hidden" id="jobId_input" name="jobId_input" value="{{.JobID}}">
<div class="{{if eq $k 0}}active{{end}} title padding0">
<div class="according-panel-heading">
@@ -205,19 +240,26 @@ td, th {
<span>
<div class="ac-display-inblock title_text acc-margin-bottom">
<span class="cti-mgRight-sm">
{{if not (eq .StartTime 0)}}
<td>{{TimeSinceUnix1 .StartTime}}</td>
{{else}}
<td>{{TimeSinceUnix1 .CreatedUnix}}<td>
{{end}}
</span>
{{if not (eq .StartTime 0)}}
<td>{{TimeSinceUnix1 .StartTime}}</td>
{{else}}
<td>{{TimeSinceUnix1 .CreatedUnix}}
<td>
{{end}}
</span>

<span class="cti-mgRight-sm">{{$.i18n.Tr "repo.modelarts.status"}}:
<span id="{{.VersionName}}-status-span"><i id="icon" style="vertical-align: middle;" class="{{.Status}}"></i><span id="text" style="margin-left: 0.4em;font-size: 12px;">{{.Status}}</span></span>
<span id="{{.VersionName}}-status-span"><i id="icon"
style="vertical-align: middle;" class="{{.Status}}"></i><span id="text"
style="margin-left: 0.4em;font-size: 12px;">{{.Status}}</span></span>
</span>
<span class="cti-mgRight-sm">{{$.i18n.Tr "repo.modelarts.train_job.dura_time"}}:</span>
<span class="cti-mgRight-sm uc-accordionTitle-black" id="{{.VersionName}}-duration-span">{{$.duration}}</span>

<span class="cti-mgRight-sm">{{$.i18n.Tr "repo.modelarts.train_job.dura_time"}}:
</span>
<span class="cti-mgRight-sm uc-accordionTitle-black"
id="{{.VersionName}}-duration-span">{{$.duration}}</span>
<span data-tooltip="刷新" style="cursor: pointer;" data-inverted=""
onclick="refreshStatus({{.VersionName}})"><i
class="redo icon redo-color"></i></span>
</div>
</span>
</span>
@@ -227,8 +269,10 @@ td, th {
<div class="{{if eq $k 0}}active{{end}} content">
<div class="content-pad">
<div class="ui pointing secondary menu" style="border-bottom: 1px solid rgba(34,36,38,.15);">
<a class="active item" data-tab="first{{$k}}">{{$.i18n.Tr "repo.modelarts.train_job.config"}}</a>
<a class="item" data-tab="second{{$k}}" onclick="javascript:parseLog()">{{$.i18n.Tr "repo.cloudbrain.runinfo"}}</a>
<a class="active item"
data-tab="first{{$k}}">{{$.i18n.Tr "repo.modelarts.train_job.config"}}</a>
<a class="item" data-tab="second{{$k}}"
onclick="javascript:parseLog()">{{$.i18n.Tr "repo.cloudbrain.runinfo"}}</a>
</div>
<div class="ui tab active" data-tab="first{{$k}}">
<div style="padding-top: 10px;">
@@ -259,192 +303,199 @@ td, th {
</td>
</tr>
<tr class="ti-no-ng-animate">
<td class="ti-no-ng-animate ti-text-form-label text-width80">
{{$.i18n.Tr "repo.cloudbrain_creator"}}
</td>

<td class="ti-text-form-content">
<div class="text-span text-span-w" id="{{.VersionName}}-mirror">
{{.User.Name}}
</div>
</td>
<td class="ti-no-ng-animate ti-text-form-label text-width80">
{{$.i18n.Tr "repo.cloudbrain_creator"}}
</td>

<td class="ti-text-form-content">
<div class="text-span text-span-w" id="{{.VersionName}}-mirror">
{{.User.Name}}
</div>
</td>
</tr>
<tr class="ti-no-ng-animate">
<td class="ti-no-ng-animate ti-text-form-label text-width80">
{{$.i18n.Tr "repo.modelarts.computing_resources"}}
</td>
<td class="ti-text-form-content">
<div class="text-span text-span-w"
id="{{.VersionName}}-computeresource">
{{.ComputeResource}}
</div>
</td>
</tr>
<tr class="ti-no-ng-animate">
<td class="ti-no-ng-animate ti-text-form-label text-width80">
{{$.i18n.Tr "repo.modelarts.computing_resources"}}
</td>
<td class="ti-text-form-content">
<div class="text-span text-span-w" id="{{.VersionName}}-computeresource">
{{.ComputeResource}}
</div>
</td>
<td class="ti-no-ng-animate ti-text-form-label text-width80">
{{$.i18n.Tr "cloudbrain.task_type"}}
</td>
<td class="ti-text-form-content">
<div class="text-span text-span-w"
id="{{.VersionName}}-computeresource">
{{.JobType}}
</div>
</td>
</tr>
<tr class="ti-no-ng-animate">
<td class="ti-no-ng-animate ti-text-form-label text-width80">
{{$.i18n.Tr "repo.modelarts.code_version"}}
</td>
<td class="ti-text-form-content">
<div class="text-span text-span-w" id="{{.VersionName}}-code">
{{.BranchName}}
</div>
</td>
</tr>
<tr class="ti-no-ng-animate">
<td class="ti-no-ng-animate ti-text-form-label text-width80">
{{$.i18n.Tr "cloudbrain.task_type"}}
</td>
<td class="ti-text-form-content">
<div class="text-span text-span-w" id="{{.VersionName}}-computeresource">
{{.JobType}}
</div>
</td>
<td class="ti-no-ng-animate ti-text-form-label text-width80">
{{$.i18n.Tr "cloudbrain.gpu_type"}}
</td>

<td class="ti-text-form-content">
<div class="text-span text-span-w">
{{$.resource_type}}
</div>
</td>
</tr>
<tr class="ti-no-ng-animate">
<td class="ti-no-ng-animate ti-text-form-label text-width80">
{{$.i18n.Tr "repo.modelarts.code_version"}}
</td>
<td class="ti-text-form-content">
<div class="text-span text-span-w" id="{{.VersionName}}-code">
{{.BranchName}}
</div>
</td>
<td class="ti-no-ng-animate ti-text-form-label text-width80">
{{$.i18n.Tr "repo.modelarts.createtime"}}
</td>

<td class="ti-text-form-content">
<div class="text-span text-span-w"
id="{{.VersionName}}-createtime">
{{TimeSinceUnix1 .CreatedUnix}}
</div>
</td>
</tr>

<tr class="ti-no-ng-animate">
<td class="ti-no-ng-animate ti-text-form-label text-width80">
{{$.i18n.Tr "cloudbrain.gpu_type"}}
</td>

<td class="ti-text-form-content">
<div class="text-span text-span-w">
{{$.resource_type}}
</div>
</td>
<td class="ti-no-ng-animate ti-text-form-label text-width80">
{{$.i18n.Tr "repo.modelarts.train_job.dura_time"}}
</td>

<td class="ti-text-form-content">
<div class="text-span text-span-w"
id="{{.VersionName}}-duration">
{{$.duration}}
</div>
</td>
</tr>
<tr class="ti-no-ng-animate">
<td class="ti-no-ng-animate ti-text-form-label text-width80">
{{$.i18n.Tr "repo.modelarts.createtime"}}
</td>

<td class="ti-text-form-content">
<div class="text-span text-span-w" id="{{.VersionName}}-createtime">
{{TimeSinceUnix1 .CreatedUnix}}
</div>
</td>
</tr>

<tr class="ti-no-ng-animate">
<td class="ti-no-ng-animate ti-text-form-label text-width80">
{{$.i18n.Tr "repo.modelarts.train_job.dura_time"}}
</td>

<td class="ti-text-form-content">
<div class="text-span text-span-w" id="{{.VersionName}}-duration">
{{$.duration}}
</div>
</td>
</tr>




</tbody>
</table>
</div>
<div class="ac-grid-col">
<table class="ti-form">
<tbody class="ti-text-form">
<tr class="ti-no-ng-animate">
<td class="ti-no-ng-animate ti-text-form-label text-width80">
{{$.i18n.Tr "cloudbrain.mirror"}}
</td>

<td class="ti-text-form-content">
<div class="text-span text-span-w" id="{{.VersionName}}-mirror">
{{.Image}}
</div>
</td>
</tr>
<tr class="ti-no-ng-animate">
<td class="ti-no-ng-animate ti-text-form-label text-width80">
{{$.i18n.Tr "repo.modelarts.train_job.dataset"}}
</td>

<td class="ti-text-form-content">
<div class="text-span text-span-w" id="{{.VersionName}}-BenchmarkTypeName">
{{$.datasetname}}
</div>
</td>
</tr>
<tr class="ti-no-ng-animate">
<td class="ti-no-ng-animate ti-text-form-label text-width80">
{{$.i18n.Tr "repo.modelarts.train_job.standard"}}
</td>

<td class="ti-text-form-content">
<div class="text-span text-span-w">
{{$.i18n.Tr "cloudbrain.gpu_num"}}:{{$.GpuNum}},{{$.i18n.Tr "cloudbrain.cpu_num"}}:{{$.CpuNum}},{{$.i18n.Tr "cloudbrain.memory"}}(MB):{{$.MemMiB}},{{$.i18n.Tr "cloudbrain.shared_memory"}}(MB):{{$.ShareMemMiB}}
</div>
</td>
</tr>
<tr class="ti-no-ng-animate">
<td class="ti-no-ng-animate ti-text-form-label text-width80">
{{$.i18n.Tr "cloudbrain.dataset_storage_path"}}
</td>

<td class="ti-text-form-content">
<div class="text-span text-span-w" id="dataset_storage_path">
<table class="ti-form">
<tbody class="ti-text-form">
<tr class="ti-no-ng-animate">
<td class="ti-no-ng-animate ti-text-form-label text-width80">
{{$.i18n.Tr "cloudbrain.mirror"}}
</td>

<td class="ti-text-form-content">
<div class="text-span text-span-w" id="{{.VersionName}}-mirror">
{{.Image}}
</div>
</td>
</tr>
<tr class="ti-no-ng-animate">
<td class="ti-no-ng-animate ti-text-form-label text-width80">
{{$.i18n.Tr "repo.modelarts.train_job.dataset"}}
</td>

<td class="ti-text-form-content">
<div class="text-span text-span-w"
id="{{.VersionName}}-BenchmarkTypeName">
{{$.datasetname}}
</div>
</td>
</tr>

<tr class="ti-no-ng-animate">
<td class="ti-no-ng-animate ti-text-form-label text-width80">
{{$.i18n.Tr "repo.modelarts.train_job.standard"}}
</td>

<td class="ti-text-form-content">
<div class="text-span text-span-w">
{{$.i18n.Tr "cloudbrain.gpu_num"}}:{{$.GpuNum}},{{$.i18n.Tr "cloudbrain.cpu_num"}}:{{$.CpuNum}},{{$.i18n.Tr "cloudbrain.memory"}}(MB):{{$.MemMiB}},{{$.i18n.Tr "cloudbrain.shared_memory"}}(MB):{{$.ShareMemMiB}}
</div>
</td>
</tr>
<tr class="ti-no-ng-animate">
<td class="ti-no-ng-animate ti-text-form-label text-width80">
{{$.i18n.Tr "cloudbrain.dataset_storage_path"}}
</td>

<td class="ti-text-form-content">
<div class="text-span text-span-w" id="dataset_storage_path">
{{$.dataset_path}}
</div>
</td>
</tr>
<tr class="ti-no-ng-animate">
<td class="ti-no-ng-animate ti-text-form-label text-width80">
{{$.i18n.Tr "cloudbrain.model_storage_path"}}
</td>
<td class="ti-text-form-content">
<div class="text-span text-span-w" id="model_storage_path">
</div>
</td>
</tr>
<tr class="ti-no-ng-animate">
<td class="ti-no-ng-animate ti-text-form-label text-width80">
{{$.i18n.Tr "cloudbrain.model_storage_path"}}
</td>
<td class="ti-text-form-content">
<div class="text-span text-span-w" id="model_storage_path">
{{$.model_path}}
</div>
</td>
</tr>
<tr class="ti-no-ng-animate">
<td class="ti-no-ng-animate ti-text-form-label text-width80">
{{$.i18n.Tr "cloudbrain.code_storage_path"}}
</td>
<td class="ti-text-form-content">
<div class="text-span text-span-w" id="code_storage_path">
</div>
</td>
</tr>
<tr class="ti-no-ng-animate">
<td class="ti-no-ng-animate ti-text-form-label text-width80">
{{$.i18n.Tr "cloudbrain.code_storage_path"}}
</td>
<td class="ti-text-form-content">
<div class="text-span text-span-w" id="code_storage_path">
{{$.code_path}}
</div>
</td>
</tr>
<tr class="ti-no-ng-animate">
<td class="ti-no-ng-animate ti-text-form-label text-width80">
{{$.i18n.Tr "repo.cloudbrain.time.starttime"}}
</td>

<td class="ti-text-form-content">
<div class="text-span text-span-w" id="{{.VersionName}}-startTime">
{{if not (eq .StartTime 0)}}
{{TimeSinceUnix1 .StartTime}}
{{else}}
--
{{end}}
</div>
</td>
</tr>
<tr class="ti-no-ng-animate">
<td class="ti-no-ng-animate ti-text-form-label text-width80">
{{$.i18n.Tr "repo.cloudbrain.time.endtime"}}
</td>

<td class="ti-text-form-content">
<div class="text-span text-span-w" id="{{.VersionName}}-EndTime">
{{if not (eq .EndTime 0)}}
{{TimeSinceUnix1 .EndTime}}
{{else}}
--
{{end}}
</div>
</td>
</tr>
</tbody>
</table>
</div>
</div>
</td>
</tr>
<tr class="ti-no-ng-animate">
<td class="ti-no-ng-animate ti-text-form-label text-width80">
{{$.i18n.Tr "repo.cloudbrain.time.starttime"}}
</td>

<td class="ti-text-form-content">
<div class="text-span text-span-w"
id="{{.VersionName}}-startTime">
{{if not (eq .StartTime 0)}}
{{TimeSinceUnix1 .StartTime}}
{{else}}
--
{{end}}
</div>
</td>
</tr>

<tr class="ti-no-ng-animate">
<td class="ti-no-ng-animate ti-text-form-label text-width80">
{{$.i18n.Tr "repo.cloudbrain.time.endtime"}}
</td>

<td class="ti-text-form-content">
<div class="text-span text-span-w"
id="{{.VersionName}}-EndTime">
{{if not (eq .EndTime 0)}}
{{TimeSinceUnix1 .EndTime}}
{{else}}
--
{{end}}
</div>
</td>
</tr>


</tbody>
</table>
</div>
</div>
</div>

@@ -455,10 +506,11 @@ td, th {
<div class="ui message message{{.VersionName}}" style="display: none;">
<div id="header"></div>
</div>
<div class="ui attached log" id="log{{.VersionName}}" style="height: 390px !important; overflow: auto;">
<div class="ui attached log" id="log{{.VersionName}}"
style="height: 390px !important; overflow: auto;">
<input type="hidden" id="json_value" value="{{$.result.JobStatus.AppExitDiagnostics}}">
<span id="info_display" class="info_text">
</span>
</div>

@@ -498,38 +550,71 @@ td, th {

<script>
$('.menu .item').tab()
$(document).ready(function(){
$('.ui.accordion').accordion({selector:{trigger:'.icon'}});
$(document).ready(function () {
$('.ui.accordion').accordion({ selector: { trigger: '.icon' } });
});
$(document).ready(function(){
$(document).ready(function () {
$('.secondary.menu .item').tab();
});

function parseLog(){
let jsonValue = document.getElementById("json_value").value;
let jsonObj = JSON.parse(jsonValue);
let podRoleName = jsonObj["podRoleName"];
let html = "";
if (podRoleName != null){
let task0 = podRoleName["task1-0"];
let podEvents = jsonObj["podEvents"];
let podEventArray = podEvents[task0];
if(podEventArray != null){
for(var i=0; i < podEventArray.length;i++){
html +="<p><b>[" +podEventArray[i]["reason"] + "]</b></p>";
html +="<p>" +podEventArray[i]["message"] + "</p>";
html +="<p>" +podEventArray[i]["action"] + "</p>";
}
}
let extras= jsonObj["extras"];
if(extras != null){
for(var i=0; i < extras.length;i++){
html +="<p><b>[" +extras[i]["reason"] + "]</b></p>";
html +="<p>" +extras[i]["message"] + "</p>";
html +="<p>" +extras[i]["action"] + "</p>";
function parseLog() {
let jsonValue = document.getElementById("json_value").value;
let jsonObj = JSON.parse(jsonValue);
let podRoleName = jsonObj["podRoleName"];
let html = "";
if (podRoleName != null) {
let task0 = podRoleName["task1-0"];
let podEvents = jsonObj["podEvents"];
let podEventArray = podEvents[task0];
if (podEventArray != null) {
for (var i = 0; i < podEventArray.length; i++) {
if (podEventArray[i]["reason"] != "") {
html += "<p><b>[" + podEventArray[i]["reason"] + "]</b></p>";
html += "<p>" + podEventArray[i]["message"] + "</p>";
html += "<p>" + podEventArray[i]["action"] + "</p>";
}
}
}
let extras = jsonObj["extras"];
if (extras != null) {
for (var i = 0; i < extras.length; i++) {
if (extras[i]["reason"] != "") {
html += "<p><b>[" + extras[i]["reason"] + "]</b></p>";
html += "<p>" + extras[i]["message"] + "</p>";
html += "<p>" + extras[i]["action"] + "</p>";
}
}
}
}
}
document.getElementById("info_display").innerHTML = html;
}
function stopBubbling(e) {
e = window.event || e;
if (e.stopPropagation) {
e.stopPropagation(); //阻止事件 冒泡传播
} else {
e.cancelBubble = true; //ie兼容
}
}

function refreshStatus(version_name) {
$(".ui.accordion.border-according").each((index, job) => {
const jobID = job.dataset.jobid;
const repoPath = job.dataset.repopath;
const versionname = job.dataset.version
$.get(`/api/v1/repos/${repoPath}/cloudbrain/${jobID}?version_name=${versionname}`, (data) => {
// header status and duration
//$(`#${version_name}-duration-span`).text(data.JobDuration)
$(`#${version_name}-status-span span`).text(data.JobStatus)
$(`#${version_name}-status-span i`).attr("class", data.JobStatus)
// detail status and duration
//$('#'+version_name+'-duration').text(data.JobDuration)
$('#' + version_name + '-status').text(data.JobStatus)
parseLog()
}).fail(function (err) {
console.log(err);
});
stopBubbling(arguments.callee.caller.arguments[0])
})
}
document.getElementById("info_display").innerHTML=html;
}
</script>

+ 482
- 404
templates/repo/cloudbrain/trainjob/show.tmpl
File diff suppressed because it is too large
View File


+ 259
- 215
templates/repo/datasets/index.tmpl View File

@@ -1,41 +1,47 @@
{{template "base/head" .}}
<style>
.selectcloudbrain .active.item{
color: #0087f5 !important;
border: 1px solid #0087f5;
margin: -1px;
background: #FFF !important;
}
.selectcloudbrain .active.item {
color: #0087f5 !important;
border: 1px solid #0087f5;
margin: -1px;
background: #FFF !important;
}

.dataset_title{
font-size: 14px;
.dataset_title {
font-size: 14px;
max-width: 80%;
display: inline-block !important;
margin-left: 6px !important;
padding-right: 0 !important;
}
.wrapper {
}

.wrapper {
display: flex;
overflow: hidden;
padding: 0 1rem;
}
.exp{
}

.exp {
display: none;
}
.exp:checked+.text{
}

.exp:checked+.text {
max-height: none;
}
.exp:checked+.text::after{
}

.exp:checked+.text::after {
visibility: hidden;
}
.exp:checked+.text .btn::before{
}

.exp:checked+.text .btn::before {
visibility: hidden;
}
.exp:checked+.text .btn::after{
}

.exp:checked+.text .btn::after {
content:'{{$.i18n.Tr "org.fold"}}'
}
}

.wrapper>.text {
.wrapper>.text {
font-family: SourceHanSansSC-regular;
font-size: 14px;
color: #101010;
@@ -48,21 +54,24 @@
transition: .3s max-height;
word-wrap: break-word;
word-break: break-all;
}
.wrapper>.text::before {
}

.wrapper>.text::before {
content: '';
height: calc(100% - 20px);
float: right;
}
.wrapper>.text::after {
}

.wrapper>.text::after {
content: '';
width: 999vw;
height: 999vw;
position: absolute;
box-shadow: inset calc(100px - 999vw) calc(30px - 999vw) 0 0 #fff;
margin-left: -100px;
}
.btn{
}

.btn {
position: relative;
float: right;
clear: both;
@@ -72,181 +81,212 @@
background: #3F51B5;
line-height: 20px;
border-radius: 4px;
color: #fff;
color: #fff;
cursor: pointer;
/* margin-top: -30px; */
}
.btn::after{
}

.btn::after {
content:'{{$.i18n.Tr "org.unfold"}}'
}
.btn::before{
}

.btn::before {
content: '...';
position: absolute;
left: -5px;
color: #333;
transform: translateX(-100%)
}
}

.el-button--text {
color: #0366d6;
}

.heart-stroke {
stroke: #666;
stroke-width: 2;
fill: #fff
}

.el-button--text{color:#0366d6 ;}
.heart-stroke{
stroke: #666;
stroke-width: 2;
fill: #fff
}
.stars_active{
fill: #FA8C16 !important;
stroke:#FA8C16 !important
}
.diy-popper{
max-width: 400px;
}
.stars_active {
fill: #FA8C16 !important;
stroke: #FA8C16 !important
}

.diy-popper {
max-width: 400px;
}
</style>
<div class="repository">
{{template "repo/header" .}}
{{if .dataset}}
<div id="dataset-range-value" data-num-stars="{{.dataset.NumStars}}" data-star-active="{{$.IsStaringDataset}}" style="display: none;">
{{range .Attachments}}
<div class="item" data-private="{{.IsPrivate}}" data-decompress-state="{{.DecompressState}}"></div>
<div id="dataset-range-value" data-num-stars="{{.dataset.NumStars}}" data-star-active="{{$.IsStaringDataset}}"
style="display: none;">
{{range .Attachments}}
<div class="item" data-private="{{.IsPrivate}}" data-decompress-state="{{.DecompressState}}"></div>
{{end}}
</div>
<div id="dataset-base">
<div class="ui container">
<div class="ui mobile reversed stackable grid">
<div class="row">
<div class="column thirteen wide"><h2>{{.dataset.Title}}</h2></div>
<div class="column thirteen wide">
<h2>{{.dataset.Title}}</h2>
</div>
<div class="column three wide right aligned">
<span style="display: flex;align-items: center;justify-content: flex-end;height: 36px;">
{{if $.IsSigned}}
<div style="line-height: 1;margin-right: 4px;margin-bottom: -2px;padding: 0 10px;" @click="postStar({{.dataset.ID}},'{{.Link}}')">
<svg width="1.4em" height="1.4em" viewBox="0 0 32 32" class="heart-stroke" :class='{stars_active:star_active}'><path d="M4.4 6.54c-1.761 1.643-2.6 3.793-2.36 6.056.24 2.263 1.507 4.521 3.663 6.534a29110.9 29110.9 0 0010.296 9.633l10.297-9.633c2.157-2.013 3.424-4.273 3.664-6.536.24-2.264-.599-4.412-2.36-6.056-1.73-1.613-3.84-2.29-6.097-1.955-1.689.25-3.454 1.078-5.105 2.394l-.4.319-.398-.319c-1.649-1.316-3.414-2.143-5.105-2.394a7.612 7.612 0 00-1.113-.081c-1.838 0-3.541.694-4.983 2.038z"></path></svg>
</div>
<span style="line-height: 1;">${num_stars}</span>
{{else}}
<div style="line-height: 1;margin-right: 4px;margin-bottom: -2px;padding: 0 10px;">
<svg width="1.4em" height="1.4em" viewBox="0 0 32 32" class="heart-stroke" :class='{stars_active:star_active}'><path d="M4.4 6.54c-1.761 1.643-2.6 3.793-2.36 6.056.24 2.263 1.507 4.521 3.663 6.534a29110.9 29110.9 0 0010.296 9.633l10.297-9.633c2.157-2.013 3.424-4.273 3.664-6.536.24-2.264-.599-4.412-2.36-6.056-1.73-1.613-3.84-2.29-6.097-1.955-1.689.25-3.454 1.078-5.105 2.394l-.4.319-.398-.319c-1.649-1.316-3.414-2.143-5.105-2.394a7.612 7.612 0 00-1.113-.081c-1.838 0-3.541.694-4.983 2.038z"></path></svg>
</div>
<span style="line-height: 1;">${num_stars}</span>
{{end}}
<a style="margin-left:30px;" href="{{.RepoLink}}/datasets/edit/{{.dataset.ID}}" class="ui primary basic mini {{if not $.CanWrite}} disabled {{end}} button">{{.i18n.Tr "repo.modelarts.modify"}}</a>
</span>
<span style="display: flex;align-items: center;justify-content: flex-end;height: 36px;">
{{if $.IsSigned}}
<div style="line-height: 1;margin-right: 4px;margin-bottom: -2px;padding: 0 10px;"
@click="postStar({{.dataset.ID}},'{{.Link}}')">
<svg width="1.4em" height="1.4em" viewBox="0 0 32 32" class="heart-stroke"
:class='{stars_active:star_active}'>
<path
d="M4.4 6.54c-1.761 1.643-2.6 3.793-2.36 6.056.24 2.263 1.507 4.521 3.663 6.534a29110.9 29110.9 0 0010.296 9.633l10.297-9.633c2.157-2.013 3.424-4.273 3.664-6.536.24-2.264-.599-4.412-2.36-6.056-1.73-1.613-3.84-2.29-6.097-1.955-1.689.25-3.454 1.078-5.105 2.394l-.4.319-.398-.319c-1.649-1.316-3.414-2.143-5.105-2.394a7.612 7.612 0 00-1.113-.081c-1.838 0-3.541.694-4.983 2.038z">
</path>
</svg>
</div>
<span style="line-height: 1;">${num_stars}</span>
{{else}}
<div style="line-height: 1;margin-right: 4px;margin-bottom: -2px;padding: 0 10px;">
<svg width="1.4em" height="1.4em" viewBox="0 0 32 32" class="heart-stroke"
:class='{stars_active:star_active}'>
<path
d="M4.4 6.54c-1.761 1.643-2.6 3.793-2.36 6.056.24 2.263 1.507 4.521 3.663 6.534a29110.9 29110.9 0 0010.296 9.633l10.297-9.633c2.157-2.013 3.424-4.273 3.664-6.536.24-2.264-.599-4.412-2.36-6.056-1.73-1.613-3.84-2.29-6.097-1.955-1.689.25-3.454 1.078-5.105 2.394l-.4.319-.398-.319c-1.649-1.316-3.414-2.143-5.105-2.394a7.612 7.612 0 00-1.113-.081c-1.838 0-3.541.694-4.983 2.038z">
</path>
</svg>
</div>
<span style="line-height: 1;">${num_stars}</span>
{{end}}
<a style="margin-left:30px;" href="{{.RepoLink}}/datasets/edit/{{.dataset.ID}}"
class="ui primary basic mini {{if not $.CanWrite}} disabled {{end}} button">{{.i18n.Tr "repo.modelarts.modify"}}</a>
</span>
</div>
{{if or (.dataset.Category) (.dataset.Task) (.dataset.License)}}
<div class="column thirteen wide">
{{if .dataset.Category}}
{{$category := .dataset.Category}}
<a class="ui repo-topic label topic" href="{{AppSubUrl}}/explore/datasets?sort={{$.SortType}}&q={{$.Keyword}}&tab={{$.TabName}}&category={{.dataset.Category}}&task={{$.Task}}&license={{$.License}}">{{$.i18n.Tr (printf "dataset.category.%s" $category)}}</a>
{{end}}
{{if .dataset.Task}}
{{$task := .dataset.Task}}
<a class="ui repo-topic label topic" href="{{AppSubUrl}}/explore/datasets?sort={{$.SortType}}&q={{$.Keyword}}&tab={{$.TabName}}&category={{$.Category}}&task={{.dataset.Task}}&license={{$.License}}">{{$.i18n.Tr (printf "dataset.task.%s" $task)}}</a>
{{end}}
{{if .dataset.License}}
<a class="ui repo-topic label topic" href="{{AppSubUrl}}/explore/datasets?sort={{$.SortType}}&q={{$.Keyword}}&tab={{$.TabName}}&category={{$.Category}}&task={{$.Task}}&license={{.dataset.License}}">{{.dataset.License}}</a>
{{end}}
{{if .dataset.Category}}
{{$category := .dataset.Category}}
<a class="ui repo-topic label topic"
href="{{AppSubUrl}}/explore/datasets?sort={{$.SortType}}&q={{$.Keyword}}&tab={{$.TabName}}&category={{.dataset.Category}}&task={{$.Task}}&license={{$.License}}">{{$.i18n.Tr (printf "dataset.category.%s" $category)}}</a>
{{end}}
{{if .dataset.Task}}
{{$task := .dataset.Task}}
<a class="ui repo-topic label topic"
href="{{AppSubUrl}}/explore/datasets?sort={{$.SortType}}&q={{$.Keyword}}&tab={{$.TabName}}&category={{$.Category}}&task={{.dataset.Task}}&license={{$.License}}">{{$.i18n.Tr (printf "dataset.task.%s" $task)}}</a>
{{end}}
{{if .dataset.License}}
<a class="ui repo-topic label topic"
href="{{AppSubUrl}}/explore/datasets?sort={{$.SortType}}&q={{$.Keyword}}&tab={{$.TabName}}&category={{$.Category}}&task={{$.Task}}&license={{.dataset.License}}">{{.dataset.License}}</a>
{{end}}
</div>
{{end}}
</div>
{{if .dataset.Description}}
<div class="row" style="padding-top: 0;">
<div class=" wrapper">
<input id="exp1" class="exp" type="checkbox">
<div class="text">
<label class="btn" for="exp1"></label>
{{.dataset.Description}}
</div>
<div class=" wrapper">
<input id="exp1" class="exp" type="checkbox">
<div class="text">
<label class="btn" for="exp1"></label>
{{.dataset.Description}}
</div>
</div>
</div>
{{end}}
<div class="row">
<div class="column ten wide"></div>
<div class="column six wide right aligned">
<el-select v-model="datasetType" style="width: 40%;" size="small" @change="changeDatasetType">
<i slot="prefix" style="display: inline-block;color: #101010;" class="el-input__icon ri-archive-drawer-line"></i>
<el-option label="{{$.i18n.Tr "repo.gpu_type_all"}}" value="-1"></el-option>
<el-option label="CPU/GPU" value="0"></el-option>
<el-option label="NPU" value="1"></el-option>
</el-select>
<el-button icon="el-icon-upload" {{if not $.CanWrite}} disabled {{end}} type="primary" size="small" @click="gotoUpload('{{.RepoLink}}',{{.dataset.ID}})">{{$.i18n.Tr "dataset.dataset_upload"}}</el-button>
<el-select v-model="datasetType" style="width: 40%;" size="small" @change="changeDatasetType">
<i slot="prefix" style="display: inline-block;color: #101010;"
class="el-input__icon ri-archive-drawer-line"></i>
<el-option label="{{$.i18n.Tr "repo.gpu_type_all"}}" value="-1"></el-option>
<el-option label="CPU/GPU" value="0"></el-option>
<el-option label="NPU" value="1"></el-option>
</el-select>
<el-button icon="el-icon-upload" {{if not $.CanWrite}} disabled {{end}} type="primary" size="small"
@click="gotoUpload('{{.RepoLink}}',{{.dataset.ID}})">{{$.i18n.Tr "dataset.dataset_upload"}}</el-button>
</div>
</div>
<div class="row">
<div class="ui sixteen wide column dataset">
<div class="ui grid stackable" style="background: #f0f0f0;;">
<div class="row">
<!-- 数据集名称 -->
<div class="four wide column" style="width: 24% !important;">
<span style="margin:0 6px">{{$.i18n.Tr "dataset.dataset_file_name"}}</span>
</div>
<div class="one wide column text center" style="width: 7.25% !important;">
{{$.i18n.Tr "repo.model.manage.size"}}
</div>
<div class="two wide column text center">
{{$.i18n.Tr "dataset.dataset_available_clusters"}}
</div>
<div class="one wide column text center">
{{$.i18n.Tr "repo.modelarts.status"}}
</div>
<div class="one wide column text center">
{{$.i18n.Tr "repo.cloudbrain_creator"}}
</div>
<div class="three wide column text center">
{{$.i18n.Tr "dataset.dataset_upload_time"}}
</div>
<div class="four wide column text center">
{{$.i18n.Tr "repo.cloudbrain_operate"}}
</div>
</div>
<div class="ui grid stackable" style="background: #f0f0f0;;">
<div class="row">
<!-- 数据集名称 -->
<div class="four wide column" style="width: 24% !important;">
<span style="margin:0 6px">{{$.i18n.Tr "dataset.dataset_file_name"}}</span>
</div>
<div class="one wide column text center" style="width: 7.25% !important;">
{{$.i18n.Tr "repo.model.manage.size"}}
</div>
<div class="two wide column text center">
{{$.i18n.Tr "dataset.dataset_available_clusters"}}
</div>
<div class="one wide column text center">
{{$.i18n.Tr "repo.modelarts.status"}}
</div>
<div class="one wide column text center">
{{$.i18n.Tr "repo.cloudbrain_creator"}}
</div>
<div class="three wide column text center">
{{$.i18n.Tr "dataset.dataset_upload_time"}}
</div>
<div class="four wide column text center">
{{$.i18n.Tr "repo.cloudbrain_operate"}}
</div>
</div>
{{range $k, $v :=.Attachments}}
<div class="ui grid stackable item" id="{{.UUID}}">
<div class="row">
<!-- 数据集名称 -->
</div>
{{range $k, $v :=.Attachments}}
<div class="ui grid stackable item" id="{{.UUID}}">
<div class="row">
<!-- 数据集名称 -->

<div class="four wide column" style="width: 24% !important;display: flex;align-items: center;">
{{if .Description}}
<el-tooltip class="item" effect="dark" placement="top" popper-class="diy-popper">
<div slot="content" >{{.Description}}</br><span><i class="ri-download-line"></i>{{$.i18n.Tr "dataset.download"}}:{{.DownloadCount}}</span></div>
<a class="dataset_title title" href="{{.DownloadURL}}" title="{{.Name}}" style="border: none;">
{{.Name}}
</a>
</el-tooltip>
{{else}}
<el-tooltip class="item" effect="dark" placement="top" popper-class="diy-popper">
<div slot="content" ><span><i class="ri-download-line"></i>{{$.i18n.Tr "dataset.download"}}:{{.DownloadCount}}</span></div>
<a class="dataset_title title" href="{{.DownloadURL}}" title="{{.Name}}" style="border: none;">
{{.Name}}
</a>
</el-tooltip>
{{end}}
<i class="ri-lock-2-line" style="color: #fa8c16;" v-if="privates[{{$k}}]"></i>
<!-- <i class="COMPLETED" v-if="zipStatus[{{$k}}]==1"></i>
<div class="four wide column" style="width: 24% !important;display: flex;align-items: center;">
{{if .Description}}
<el-tooltip class="item" effect="dark" placement="top" popper-class="diy-popper">
<div slot="content">{{.Description}}</br><span><i
class="ri-download-line"></i>{{$.i18n.Tr "dataset.download"}}:{{.DownloadCount}}</span></div>
<a class="dataset_title title" href="{{.DownloadURL}}" title="{{.Name}}" style="border: none;">
{{.Name}}
</a>
</el-tooltip>
{{else}}
<el-tooltip class="item" effect="dark" placement="top" popper-class="diy-popper">
<div slot="content"><span><i
class="ri-download-line"></i>{{$.i18n.Tr "dataset.download"}}:{{.DownloadCount}}</span></div>
<a class="dataset_title title" href="{{.DownloadURL}}" title="{{.Name}}" style="border: none;">
{{.Name}}
</a>
</el-tooltip>
{{end}}
<i class="ri-lock-2-line" style="color: #fa8c16;" v-if="privates[{{$k}}]"></i>
<!-- <i class="COMPLETED" v-if="zipStatus[{{$k}}]==1"></i>
<i class="WAITING" v-if="zipStatus[{{$k}}]==2"></i>
<i class="FAILED" v-if="zipStatus[{{$k}}]==3"></i> -->
</div>
<div class="one wide column text center" style="width: 7.25% !important;">
{{.Size | FileSize}}
</div>
<div class="two wide column text center">
{{.Type | AttachmentResourceType}}
</div>
<div class="one wide column text center">
{{$x:=.IsPrivate | AttachmentStatus}}
<span style="color: #fa8c16;" v-if="privates[{{$k}}]">{{$.i18n.Tr "home.show_private"}}</span>
<span style="color: #13c28d;" v-else="privates[{{$k}}]">{{$.i18n.Tr "org.settings.visibility.public"}}</span>
</div>
<div class="one wide column text center">
{{if .Uploader.Name}}
<a href="{{AppSubUrl}}/{{.Uploader.Name}}" title="{{.Uploader.Name}}"><img class="ui avatar image" src="{{AppSubUrl}}/user/avatar/{{.Uploader.Name}}/-1"></a>
{{else}}
<a title="Ghost"><img class="ui avatar image" src="{{AppSubUrl}}/user/avatar/Ghost/-1"></a>
{{end}}
</div>
<div class="three wide column text center">
{{.CreatedUnix | TimeSinceUnix1}}
</div>
<div class="four wide column text right">
<!-- <el-button type="text">下载</el-button>
</div>
<div class="one wide column text center" style="width: 7.25% !important;">
{{.Size | FileSize}}
</div>
<div class="two wide column text center">
{{.Type | AttachmentResourceType}}
</div>
<div class="one wide column text center">
{{$x:=.IsPrivate | AttachmentStatus}}
<span style="color: #fa8c16;" v-if="privates[{{$k}}]">{{$.i18n.Tr "home.show_private"}}</span>
<span style="color: #13c28d;"
v-else="privates[{{$k}}]">{{$.i18n.Tr "org.settings.visibility.public"}}</span>
</div>
<div class="one wide column text center">
{{if .Uploader.Name}}
<a href="{{AppSubUrl}}/{{.Uploader.Name}}" title="{{.Uploader.Name}}"><img class="ui avatar image"
src="{{AppSubUrl}}/user/avatar/{{.Uploader.Name}}/-1"></a>
{{else}}
<a title="Ghost"><img class="ui avatar image" src="{{AppSubUrl}}/user/avatar/Ghost/-1"></a>
{{end}}
</div>
<div class="three wide column text center">
{{.CreatedUnix | TimeSinceUnix1}}
</div>
<div class="four wide column text right">
<!-- <el-button type="text">下载</el-button>
<el-button type="text">预览</el-button>
<el-button type="text">标注</el-button>
<el-button type="text">
@@ -258,77 +298,81 @@
<el-button slot="reference" type="text"><i class="ri-more-line"></i></el-button>
</el-popover>
</el-button> -->
<div class="ui compact buttons">
<a class="ui basic blue button" href="{{.DownloadURL}}">{{$.i18n.Tr "dataset.download"}}</a>
{{if eq .DecompressState 1}}
<a class="ui basic blue button" href="datasets/dirs/{{.UUID}}?type={{$.Type}}" data-tooltip='{{$.i18n.Tr "dataset.directory"}}'>{{$.i18n.Tr "preview"}}</a>
{{end}}
{{if and (.CanDel) (not $.Repository.IsPrivate)}}
<span class="ui basic blue button" style="color: #13c28d !important;" @click="setPrivate('{{.UUID}}',false,{{$k}})" v-if="privates[{{$k}}]">{{$.i18n.Tr "dataset.set_public"}}</span>
<span class="ui basic blue button" style="color: #fa8c16 !important;" @click="setPrivate('{{.UUID}}',true,{{$k}})" v-else="privates[{{$k}}]">{{$.i18n.Tr "dataset.set_private"}}</span>
{{end}}
<!-- {{if $.CanRead}}
<div class="ui compact buttons">

<a class="ui basic blue button" href="{{.DownloadURL}}">{{$.i18n.Tr "dataset.download"}}</a>

{{if eq .DecompressState 1}}
<a class="ui basic blue button" href="datasets/dirs/{{.UUID}}?type={{$.Type}}"
data-tooltip='{{$.i18n.Tr "dataset.directory"}}'>{{$.i18n.Tr "preview"}}</a>
{{end}}
{{if and (.CanDel) (not $.Repository.IsPrivate)}}
<span class="ui basic blue button" style="color: #13c28d !important;"
@click="setPrivate('{{.UUID}}',false,{{$k}})"
v-if="privates[{{$k}}]">{{$.i18n.Tr "dataset.set_public"}}</span>
<span class="ui basic blue button" style="color: #fa8c16 !important;"
@click="setPrivate('{{.UUID}}',true,{{$k}})"
v-else="privates[{{$k}}]">{{$.i18n.Tr "dataset.set_private"}}</span>
{{end}}
<!-- {{if $.CanRead}}
<a class="ui basic blue button" href="datasets/label/{{.UUID}}?type={{$.Type}}" data-tooltip='{{$.i18n.Tr "dataset.create_label_task"}}'>标注</a>
{{else}}
<a class="ui basic disabled button">标注</a>
{{end}} -->
<a class="ui basic blue button">
<el-dropdown size="medium">
<span class="el-dropdown-link">
{{$.i18n.Tr "repo.more"}}<i class="el-icon-arrow-down el-icon--right"></i>
</span>
<el-dropdown-menu slot="dropdown">
<el-dropdown-item class="clipboard" data-clipboard-text="{{.DownloadURL}}" data-clipboard-action="copy">{{$.i18n.Tr "dataset.copy_url"}}</el-dropdown-item>
<!-- <el-dropdown-item class="clipboard" data-clipboard-text="{{.Md5}}" data-clipboard-action="copy">{{$.i18n.Tr "dataset.copy_md5"}}</el-dropdown-item>-->
{{if and ($.CanWrite) (eq .DecompressState 1) }}
<el-dropdown-item @click.native="gotoAnnotate('{{$.RepoLink}}','{{.UUID}}',{{.Type}})">{{$.i18n.Tr "dataset.annotation"}}</el-dropdown-item>
{{end}}
{{if .CanDel}}
<el-dropdown-item @click.native="gotoDatasetEidt('{{$.RepoLink}}',{{.ID}})">{{$.i18n.Tr "dataset.modify_description"}}</el-dropdown-item>
<el-dropdown-item style="color: red;" @click.native="delDataset('{{.UUID}}')">{{$.i18n.Tr "dataset.delete"}}</el-dropdown-item>
{{end}}
</el-dropdown-menu>
</el-dropdown>
</a>
</div>
</div>
<a class="ui basic blue button">
<el-dropdown size="medium">
<span class="el-dropdown-link">
{{$.i18n.Tr "repo.more"}}<i class="el-icon-arrow-down el-icon--right"></i>
</span>
<el-dropdown-menu slot="dropdown">
<el-dropdown-item @click.native="copyUrl('{{.DownloadURL}}')">{{$.i18n.Tr "dataset.copy_url"}}
</el-dropdown-item>
<!-- <el-dropdown-item class="clipboard" data-clipboard-text="{{.Md5}}" data-clipboard-action="copy">{{$.i18n.Tr "dataset.copy_md5"}}</el-dropdown-item>-->
{{if and ($.CanWrite) (eq .DecompressState 1) }}
<el-dropdown-item @click.native="gotoAnnotate('{{$.RepoLink}}','{{.UUID}}',{{.Type}})">
{{$.i18n.Tr "dataset.annotation"}}</el-dropdown-item>
{{end}}
{{if .CanDel}}
<el-dropdown-item @click.native="gotoDatasetEidt('{{$.RepoLink}}',{{.ID}})">
{{$.i18n.Tr "dataset.modify_description"}}</el-dropdown-item>
<el-dropdown-item style="color: red;" @click.native="delDataset('{{.UUID}}')">
{{$.i18n.Tr "dataset.delete"}}</el-dropdown-item>
{{end}}
</el-dropdown-menu>
</el-dropdown>
</a>
</div>
</div>
</div>
{{end}}
</div>
{{end}}

</div>

</div>
</div>
</div>
</div>
<div id="app" style="margin-top: 2rem;">
<div class="center">
<el-pagination
background
@current-change="handleCurrentChange"
:current-page="page"
:page-sizes="[10]"
:page-size="10"
layout="total, sizes, prev, pager, next, jumper"
:total="{{.Page.Paginater.Total}}">
</el-pagination>
<el-pagination background @current-change="handleCurrentChange" :current-page="page" :page-sizes="[10]"
:page-size="10" layout="total, sizes, prev, pager, next, jumper" :total="{{.Page.Paginater.Total}}">
</el-pagination>
</div>
</div>
{{else}}
<div class="ui placeholder segment bgtask-none">
<div class="ui icon header bgtask-header-pic"></div>
<div class="bgtask-content-header">{{.i18n.Tr "dataset.dataset_no_create"}}</div>
{{if $.CanWrite}}
<a class="ui green button" href="{{.RepoLink}}/datasets/create">{{.i18n.Tr "dataset.create_new_dataset"}}</a>
{{end}}
<div class="bgtask-content">
<div class="bgtask-content-txt">{{.i18n.Tr "dataset.dataset_explain"}}</div>
<div class="bgtask-content-txt">{{.i18n.Tr "dataset.dataset_instructions_for_use"}}<a href="https://git.openi.org.cn/zeizei/OpenI_Learning">{{.i18n.Tr "dataset.dataset_camp_course"}}</a></div>
</div>
<div class="ui icon header bgtask-header-pic"></div>
<div class="bgtask-content-header">{{.i18n.Tr "dataset.dataset_no_create"}}</div>
{{if $.CanWrite}}
<a class="ui green button" href="{{.RepoLink}}/datasets/create">{{.i18n.Tr "dataset.create_new_dataset"}}</a>
{{end}}
<div class="bgtask-content">
<div class="bgtask-content-txt">{{.i18n.Tr "dataset.dataset_explain"}}</div>
<div class="bgtask-content-txt">{{.i18n.Tr "dataset.dataset_instructions_for_use"}}<a
href="https://git.openi.org.cn/zeizei/OpenI_Learning">{{.i18n.Tr "dataset.dataset_camp_course"}}</a></div>
</div>
</div>
{{end}}
</div>
@@ -343,4 +387,4 @@
</div>
{{template "base/delete_modal_actions" .}}
</div>
{{template "base/footer" .}}
{{template "base/footer" .}}

+ 161
- 114
templates/repo/debugjob/index.tmpl View File

@@ -2,20 +2,23 @@
{{template "base/head" .}}

<style>
.label_after::after{
.label_after::after {
margin: -.2em 0 0 .2em;
content: '\00a0';
}
.selectcloudbrain .active.item{
}

.selectcloudbrain .active.item {
color: #0087f5 !important;
border: 1px solid #0087f5;
margin: -1px;
background: #FFF !important;
}

#deletemodel {
width: 100%;
height: 100%;
}

/* 弹窗 */

#mask {
@@ -73,28 +76,33 @@
}

@-webkit-keyframes sk-stretchdelay {

0%,
40%,
100% {
-webkit-transform: scaleY(0.4)
}

20% {
-webkit-transform: scaleY(1.0)
}
}

@keyframes sk-stretchdelay {

0%,
40%,
100% {
transform: scaleY(0.4);
-webkit-transform: scaleY(0.4);
}

20% {
transform: scaleY(1.0);
-webkit-transform: scaleY(1.0);
}
}

/* 消息框 */

.alert {
@@ -137,6 +145,7 @@
width: calc(100% - 260px);
box-sizing: border-box;
}

/* 弹窗 (background) */

#imageModal {
@@ -151,6 +160,7 @@
background-color: rgb(0, 0, 0);
background-color: rgba(0, 0, 0, 0.4);
}

/* 弹窗内容 */

.modal-content {
@@ -160,6 +170,7 @@
border: 1px solid #888;
width: 30%;
}

/* 关闭按钮 */

.close {
@@ -184,12 +195,12 @@
cursor: pointer;
pointer-events: none;
}
.time-show{

.time-show {
font-size: 10px;
margin-top: 0.4rem;
display: inline-block;
}

</style>

<!-- 弹窗 -->
@@ -208,49 +219,56 @@
{{template "repo/header" .}}
{{template "base/alert" .}}
<!-- 提示框 -->
<div class="cloudbrain_debug" style="display: none;" data-debug="{{$.i18n.Tr "repo.debug"}}" data-debug-again="{{$.i18n.Tr "repo.debug_again"}}"></div>
<div class="cloudbrain_debug" style="display: none;" data-debug="{{$.i18n.Tr "repo.debug"}}"
data-debug-again="{{$.i18n.Tr "repo.debug_again"}}"></div>
<!-- 列表容器 -->
<div class="ui container">

<div class="ui two column stackable grid">
<div class="column">
<div class="ui blue small menu compact selectcloudbrain">
<a class="active item" href="{{.RepoLink}}/debugjob?debugListType=all">{{$.i18n.Tr "repo.modelarts.notebook"}}</a>
<a class="item" href="{{.RepoLink}}/modelarts/train-job">{{$.i18n.Tr "repo.modelarts.train_job"}}</a>
<a class="item" href="{{.RepoLink}}/modelarts/inference-job">{{$.i18n.Tr "repo.modelarts.infer_job"}}</a>
<a class="item" href="{{.RepoLink}}/cloudbrain/benchmark">{{$.i18n.Tr "repo.modelarts.evaluate_job"}}</a>
</div>
<div class="column">
<div class="ui blue small menu compact selectcloudbrain">
<a class="active item"
href="{{.RepoLink}}/debugjob?debugListType=all">{{$.i18n.Tr "repo.modelarts.notebook"}}</a>
<a class="item"
href="{{.RepoLink}}/modelarts/train-job">{{$.i18n.Tr "repo.modelarts.train_job"}}</a>
<a class="item"
href="{{.RepoLink}}/modelarts/inference-job">{{$.i18n.Tr "repo.modelarts.infer_job"}}</a>
<a class="item"
href="{{.RepoLink}}/cloudbrain/benchmark">{{$.i18n.Tr "repo.modelarts.evaluate_job"}}</a>
</div>
<div class="column right aligned">
<div class="ui selection dropdown" style="min-width: 10em;min-height:2.6em;border-radius: .28571429rem;margin-right: 1em;padding: .67em 3.2em .7em 1em;">
{{svg "octicon-server" 16}}
<div class="default text" style="color: rgba(0,0,0,.87);"></div>
<i class="dropdown icon"></i>
<div class="menu">
<div class="item" data-value="all">{{$.i18n.Tr "repo.gpu_type_all"}}</div>
<div class="item" data-value="CPU/GPU">CPU/GPU</div>
<div class="item" data-value="NPU">NPU</div>
</div>
</div>
<div class="column right aligned">
<div class="ui selection dropdown"
style="min-width: 10em;min-height:2.6em;border-radius: .28571429rem;margin-right: 1em;padding: .67em 3.2em .7em 1em;">
{{svg "octicon-server" 16}}
<div class="default text" style="color: rgba(0,0,0,.87);"></div>
<i class="dropdown icon"></i>
<div class="menu">
<div class="item" data-value="all">{{$.i18n.Tr "repo.gpu_type_all"}}</div>
<div class="item" data-value="CPU/GPU">CPU/GPU</div>
<div class="item" data-value="NPU">NPU</div>
</div>
{{if .Permission.CanWrite $.UnitTypeCloudBrain}}
<a class="ui green button" href="{{.RepoLink}}/cloudbrain/create">{{$.i18n.Tr "repo.modelarts.train_job.new_debug"}}</a>
{{else}}
<a class="ui disabled button">{{$.i18n.Tr "repo.modelarts.train_job.new_debug"}}</a>
{{end}}
</div>
{{if .Permission.CanWrite $.UnitTypeCloudBrain}}
<a class="ui green button"
href="{{.RepoLink}}/cloudbrain/create">{{$.i18n.Tr "repo.modelarts.train_job.new_debug"}}</a>
{{else}}
<a class="ui disabled button">{{$.i18n.Tr "repo.modelarts.train_job.new_debug"}}</a>
{{end}}
</div>
</div>
{{if eq 0 (len .Tasks)}}
<div class="ui placeholder segment bgtask-none">
<div class="ui icon header bgtask-header-pic"></div>
<div class="bgtask-content-header">{{$.i18n.Tr "repo.debug_task_not_created"}}</div>
<div class="bgtask-content">
{{if $.RepoIsEmpty}}
<div class="bgtask-content-txt">{{$.i18n.Tr "repo.repo_not_initialized" .RepoLink | Safe}}</div>
{{end}}
<div class="bgtask-content-txt">{{$.i18n.Tr "repo.debug_task_running_limit"}}</div>
<div class="bgtask-content-txt">{{$.i18n.Tr "repo.dataset_desc"}}</div>
<div class="bgtask-content-txt">{{$.i18n.Tr "repo.platform_instructions" | Safe}}</div>
</div>
<div class="ui icon header bgtask-header-pic"></div>
<div class="bgtask-content-header">{{$.i18n.Tr "repo.debug_task_not_created"}}</div>
<div class="bgtask-content">
{{if $.RepoIsEmpty}}
<div class="bgtask-content-txt">{{$.i18n.Tr "repo.repo_not_initialized" .RepoLink | Safe}}</div>
{{end}}
<div class="bgtask-content-txt">{{$.i18n.Tr "repo.debug_task_running_limit"}}</div>
<div class="bgtask-content-txt">{{$.i18n.Tr "repo.dataset_desc"}}</div>
<div class="bgtask-content-txt">{{$.i18n.Tr "repo.platform_instructions" | Safe}}</div>
</div>
</div>
{{else}}
<!-- 中下列表展示区 -->
@@ -287,29 +305,40 @@
<div class="row">
<!-- 任务名 -->
<div class="four wide column">
<a class="title" href='{{if eq .ComputeResource "CPU/GPU"}}{{$.RepoLink}}/cloudbrain/{{.Cloudbrain.ID}}{{else}}{{$.RepoLink}}/modelarts/notebook/{{.Cloudbrain.ID}}{{end}}' title="{{.JobName}}" style="font-size: 14px;">
<span class="fitted text_over" style="width: 90%;vertical-align: middle;">{{.DisplayJobName}}</span>
<a class="title"
href='{{if eq .ComputeResource "CPU/GPU"}}{{$.RepoLink}}/cloudbrain/{{.Cloudbrain.ID}}{{else}}{{$.RepoLink}}/modelarts/notebook/{{.Cloudbrain.ID}}{{end}}'
title="{{.DisplayJobName}}" style="font-size: 14px;">
<span class="fitted text_over"
style="width: 90%;vertical-align: middle;">{{.DisplayJobName}}</span>
</a>
</div>
<div class="two wide column text center">
<!--任务状态 -->
<span class="job-status" id="{{.Cloudbrain.ID}}" data-repopath="{{$.RepoRelPath}}{{if eq .ComputeResource "CPU/GPU"}}/cloudbrain{{else}}/modelarts/notebook{{end}}" data-jobid="{{.Cloudbrain.ID}}" data-resource="{{.ComputeResource}}">
<span><i id="{{.Cloudbrain.ID}}-icon" style="vertical-align: middle;" class="{{.Status}}"></i><span id="{{.Cloudbrain.ID}}-text" style="margin-left: 0.4em;font-size: 12px;">{{.Status}}</span></span>
<!--任务状态 -->
<span class="job-status" id="{{.Cloudbrain.ID}}"
data-repopath="{{$.RepoRelPath}}{{if eq .ComputeResource "CPU/GPU"}}/cloudbrain{{else}}/modelarts/notebook{{end}}"
data-jobid="{{.Cloudbrain.ID}}" data-resource="{{.ComputeResource}}">
<span><i id="{{.Cloudbrain.ID}}-icon" style="vertical-align: middle;"
class="{{.Status}}"></i><span id="{{.Cloudbrain.ID}}-text"
style="margin-left: 0.4em;font-size: 12px;">{{.Status}}</span></span>
</span>
</div>
<div class="two wide column text center">
<!-- 任务创建时间 -->
<span style="font-size: 12px;margin-left: 0.4rem;" class="">{{TimeSinceUnix .Cloudbrain.CreatedUnix $.Lang}}</span>
<span style="font-size: 12px;margin-left: 0.4rem;"
class="">{{TimeSinceUnix .Cloudbrain.CreatedUnix $.Lang}}</span>
</div>
<div class="two wide column text center">
<!-- 任务计算资源 -->
<span style="font-size: 12px;margin-left: 0.4rem;" class="">{{.ComputeResource}}</span>
<!-- 任务计算资源 -->
<span style="font-size: 12px;margin-left: 0.4rem;"
class="">{{.ComputeResource}}</span>
</div>
<div class="one wide column text center">
{{if .User.Name}}
<a href="{{AppSubUrl}}/{{.User.Name}}" title="{{.User.Name}}"><img class="ui avatar image" src="{{.User.RelAvatarLink}}"></a>
<a href="{{AppSubUrl}}/{{.User.Name}}" title="{{.User.Name}}"><img
class="ui avatar image" src="{{.User.RelAvatarLink}}"></a>
{{else}}
<a title="Ghost"><img class="ui avatar image" src="{{AppSubUrl}}/user/avatar/Ghost/-1"></a>
<a title="Ghost"><img class="ui avatar image"
src="{{AppSubUrl}}/user/avatar/Ghost/-1"></a>
{{end}}
</div>
<div class="five wide column text center">
@@ -323,79 +352,103 @@
<form id="debugAgainForm-{{.Cloudbrain.ID}}">
{{$.CsrfTokenHtml}}
{{if .CanDebug}}
{{if eq .Status "RUNNING" "WAITING" "CREATING" "STARTING"}}
<a style="margin: 0 1rem;" id="ai-debug-{{.Cloudbrain.ID}}" class='ui basic ai_debug {{if eq .Status "CREATING" "STOPPING" "WAITING" "STARTING"}}disabled {{else}}blue {{end}}button' data-jobid="{{.Cloudbrain.ID}}" data-repopath='{{$.RepoLink}}{{if eq .ComputeResource "CPU/GPU"}}/cloudbrain{{else}}/modelarts/notebook{{end}}/{{.Cloudbrain.ID}}/'>
{{$.i18n.Tr "repo.debug"}}
</a>
{{else}}
<a id="ai-debug-{{.Cloudbrain.ID}}" class='ui basic ai_debug {{if eq .Status "CREATING" "STOPPING" "WAITING" "STARTING"}} disabled {{else}}blue {{end}}button' data-jobid="{{.Cloudbrain.ID}}" data-repopath='{{$.RepoLink}}{{if eq .ComputeResource "CPU/GPU"}}/cloudbrain{{else}}/modelarts/notebook{{end}}/{{.Cloudbrain.ID}}/' data-linkpath='{{$.Link}}'>
{{$.i18n.Tr "repo.debug_again"}}
</a>
{{end}}
{{if eq .Status "RUNNING" "WAITING" "CREATING" "STARTING"}}
<a style="margin: 0 1rem;" id="ai-debug-{{.Cloudbrain.ID}}"
class='ui basic ai_debug {{if eq .Status "CREATING" "STOPPING" "WAITING" "STARTING"}}disabled {{else}}blue {{end}}button'
data-jobid="{{.Cloudbrain.ID}}"
data-repopath='{{$.RepoLink}}{{if eq .ComputeResource "CPU/GPU"}}/cloudbrain{{else}}/modelarts/notebook{{end}}/{{.Cloudbrain.ID}}/'>
{{$.i18n.Tr "repo.debug"}}
</a>
{{else}}
{{if eq .Status "RUNNING" "WAITING" "CREATING" "STARTING"}}
<a class="ui basic disabled button">
{{$.i18n.Tr "repo.debug"}}
</a>
{{else}}
<a class="ui basic disabled button">
{{$.i18n.Tr "repo.debug_again"}}
</a>
{{end}}
<a id="ai-debug-{{.Cloudbrain.ID}}"
class='ui basic ai_debug {{if eq .Status "CREATING" "STOPPING" "WAITING" "STARTING"}} disabled {{else}}blue {{end}}button'
data-jobid="{{.Cloudbrain.ID}}"
data-repopath='{{$.RepoLink}}{{if eq .ComputeResource "CPU/GPU"}}/cloudbrain{{else}}/modelarts/notebook{{end}}/{{.Cloudbrain.ID}}/'
data-linkpath='{{$.Link}}'>
{{$.i18n.Tr "repo.debug_again"}}
</a>
{{end}}
{{else}}
{{if eq .Status "RUNNING" "WAITING" "CREATING" "STARTING"}}
<a class="ui basic disabled button">
{{$.i18n.Tr "repo.debug"}}
</a>
{{else}}
<a class="ui basic disabled button">
{{$.i18n.Tr "repo.debug_again"}}
</a>
{{end}}
{{end}}
</form>

<!-- 停止 -->
<form id="stopForm-{{.Cloudbrain.ID}}" style="margin-left:-1px;">
<form id="stopForm-{{.Cloudbrain.ID}}" style="margin-left:-1px;">
{{$.CsrfTokenHtml}}
{{if .CanDel}}
<a id="ai-stop-{{.Cloudbrain.ID}}" class='ui basic ai_stop {{if eq .Status "STOPPED" "FAILED" "START_FAILED" "STOPPING" "CREATING" "STARTING" "SUCCEEDED"}}disabled {{else}}blue {{end}}button' data-repopath="{{$.RepoLink}}{{if eq .ComputeResource "CPU/GPU"}}/cloudbrain{{else}}/modelarts/notebook{{end}}/{{.Cloudbrain.ID}}/stop" data-jobid="{{.Cloudbrain.ID}}">
<a id="ai-stop-{{.Cloudbrain.ID}}"
class='ui basic ai_stop {{if eq .Status "STOPPED" "FAILED" "START_FAILED" "STOPPING" "CREATING" "STARTING" "SUCCEEDED"}}disabled {{else}}blue {{end}}button'
data-repopath="{{$.RepoLink}}{{if eq .ComputeResource "CPU/GPU"}}/cloudbrain{{else}}/modelarts/notebook{{end}}/{{.Cloudbrain.ID}}/stop"
data-jobid="{{.Cloudbrain.ID}}">
{{$.i18n.Tr "repo.stop"}}
</a>
{{else}}
<a class="ui basic disabled button">
{{$.i18n.Tr "repo.stop"}}
<a class="ui basic disabled button">
{{$.i18n.Tr "repo.stop"}}
</a>
{{end}}
</form>
<!-- 删除 -->
<form id="delForm-{{.Cloudbrain.ID}}" action="{{if eq .ComputeResource "CPU/GPU"}}{{$.RepoLink}}/cloudbrain{{else}}{{$.RepoLink}}/modelarts/notebook{{end}}/{{.Cloudbrain.ID}}/del" method="post">
<form id="delForm-{{.Cloudbrain.ID}}"
action="{{if eq .ComputeResource "CPU/GPU"}}{{$.RepoLink}}/cloudbrain{{else}}{{$.RepoLink}}/modelarts/notebook{{end}}/{{.Cloudbrain.ID}}/del"
method="post">
<input type="hidden" name="debugListType" value="{{$.ListType}}">
{{$.CsrfTokenHtml}}
{{if .CanDel}}
<a id="ai-delete-{{.Cloudbrain.ID}}" class='ui basic ai_delete {{if eq .Status "STOPPED" "FAILED" "START_FAILED"}}blue {{else}}disabled {{end}}button' style="border-radius: .28571429rem;">
<a id="ai-delete-{{.Cloudbrain.ID}}"
class='ui basic ai_delete {{if eq .Status "STOPPED" "FAILED" "START_FAILED"}}blue {{else}}disabled {{end}}button'
style="border-radius: .28571429rem;">
{{$.i18n.Tr "repo.delete"}}
</a>
{{else}}
<a class="ui basic button disabled" style="border-radius: .28571429rem;">
<a class="ui basic button disabled" style="border-radius: .28571429rem;">
{{$.i18n.Tr "repo.delete"}}
</a>
{{end}}
</form>
</div>
<div class="ui compact buttons" style="{{if eq .ComputeResource "CPU/GPU"}} visibility: visible {{else}} visibility: hidden{{end}}">
<div class="ui dropdown" id="model_more" style="padding: .58928571em 1.125em .58928571em;">
<div class="ui compact buttons"
style="{{if eq .ComputeResource "CPU/GPU"}} visibility: visible {{else}} visibility: hidden{{end}}">
<div class="ui dropdown" id="model_more"
style="padding: .58928571em 1.125em .58928571em;">
<div class="text">{{$.i18n.Tr "repo.more"}}</div>
<i class="dropdown icon"></i>
<div class="menu" style="right: auto;">
<div class="item" style="padding: 0 !important;">
{{if .CanDebug}}
<a id="model-image-{{.Cloudbrain.ID}}" class='imageBtn ui basic {{if ne .Status "RUNNING"}}disabled {{else}}blue {{end}}button' href="{{$.RepoLink}}/cloudbrain/{{.Cloudbrain.ID}}/commit_image">{{$.i18n.Tr "repo.submit_image"}}</a>
<a id="model-image-{{.Cloudbrain.ID}}"
class='imageBtn ui basic {{if ne .Status "RUNNING"}}disabled {{else}}blue {{end}}button'
href="{{$.RepoLink}}/cloudbrain/{{.Cloudbrain.ID}}/commit_image">{{$.i18n.Tr "repo.submit_image"}}</a>
{{else}}
<a class="imageBtn ui basic disabled button">{{$.i18n.Tr "repo.submit_image"}}</a>
<a
class="imageBtn ui basic disabled button">{{$.i18n.Tr "repo.submit_image"}}</a>
{{end}}
</div>
<div class="item" style="padding: 0 !important;">
<!-- 模型下载 -->
<!-- 模型下载 -->
{{if .CanDebug}}
<a class="ui basic blue button" href="{{$.RepoLink}}/cloudbrain/{{.Cloudbrain.ID}}/models" target="_blank">{{$.i18n.Tr "repo.download"}}</a>
<a class="ui basic blue button"
href="{{$.RepoLink}}/cloudbrain/{{.Cloudbrain.ID}}/models"
target="_blank">{{$.i18n.Tr "repo.download"}}</a>
{{else}}
<a class="ui basic disabled button">{{$.i18n.Tr "repo.download"}}</a>
<a
class="ui basic disabled button">{{$.i18n.Tr "repo.download"}}</a>
{{end}}
</div>
{{if and (ne .JobType "DEBUG") (eq .Cloudbrain.Type 0)}}
<div class="item" style="padding: 0 !important;">
<a class="ui basic blue button" href="{{$.RepoLink}}/cloudbrain/{{.Cloudbrain.ID}}/rate" target="_blank">
<a class="ui basic blue button"
href="{{$.RepoLink}}/cloudbrain/{{.Cloudbrain.ID}}/rate"
target="_blank">
评分
</a>
</div>
@@ -405,20 +458,15 @@
</div>
</div>
<!-- 镜像列表弹窗 -->
</div>
</div>
{{end}}
{{end}}
<div id="app" style="margin-top: 2rem;">
<div class="center">
<el-pagination
background
@current-change="handleCurrentChange"
:current-page="page"
:page-sizes="[10]"
:page-size="10"
layout="total, sizes, prev, pager, next, jumper"
:total="{{.Page.Paginater.Total}}">
<el-pagination background @current-change="handleCurrentChange" :current-page="page"
:page-sizes="[10]" :page-size="10" layout="total, sizes, prev, pager, next, jumper"
:total="{{.Page.Paginater.Total}}">
</el-pagination>
</div>
</div>
@@ -457,42 +505,41 @@
{{template "base/footer" .}}
<script>
// 调试和评分新开窗口
const {AppSubUrl, StaticUrlPrefix, csrf} = window.config;
let url={{.RepoLink}}
let redirect_to = {{$.Link}}
let getParam=getQueryVariable('debugListType')
const { AppSubUrl, StaticUrlPrefix, csrf } = window.config;
let url = {{.RepoLink }}
let redirect_to = {{ $.Link }}
let getParam = getQueryVariable('debugListType')

let dropdownValue = ['all','',false].includes(getParam)? '{{$.i18n.Tr "repo.gpu_type_all"}}' : getParam
let dropdownValue = ['all', '', false].includes(getParam) ? '{{$.i18n.Tr "repo.gpu_type_all"}}' : getParam
// localStorage.setItem('all',location.href)
function getQueryVariable(variable)
{
function getQueryVariable(variable) {
let query = window.location.search.substring(1);
let vars = query.split("&");
for (let i=0;i<vars.length;i++) {
let pair = vars[i].split("=");
if(pair[0] == variable){return pair[1];}
for (let i = 0; i < vars.length; i++) {
let pair = vars[i].split("=");
if (pair[0] == variable) { return pair[1]; }
}
return(false);
return (false);
}
$(document).ready(function(){
dropdownValue = dropdownValue==="CPU%2FGPU"? 'CPU/GPU' : dropdownValue
$(document).ready(function () {
dropdownValue = dropdownValue === "CPU%2FGPU" ? 'CPU/GPU' : dropdownValue
$('.default.text').text(dropdownValue)
$('.ui.dropdown')
.dropdown({
action: 'hide',
})
.dropdown({
action: 'hide',
})
$('.ui.selection.dropdown').dropdown({
onChange:function(value){
onChange: function (value) {

location.href = `${url}/debugjob?debugListType=${value}`
}
})
$('.message .close')
.on('click', function() {
$(this)
.closest('.message')
.transition('fade')
})
.on('click', function () {
$(this)
.closest('.message')
.transition('fade')
})
})

</script>
</script>

+ 244
- 199
templates/repo/home.tmpl View File

@@ -1,102 +1,114 @@
{{template "base/head" .}}
<style>
.repository.file.list #repo-desc {
font-size: 1.0em;
margin-bottom: 1.0rem;
}
#contributorInfo > a:nth-child(n+26){
display:none;
}
#contributorInfo > a{
width: 2.0em;
float: left;
margin: .25em;
}
.edit-link{
vertical-align: top;
display: inline-block;
overflow: hidden;
word-break: keep-all;
white-space: nowrap;
text-overflow: ellipsis;
width: 16.5em;
}
#contributorInfo > a.circular{
height: 2.0em;
padding: 0;
overflow: hidden;
letter-spacing:1.0em;
text-indent: 0.6em;
line-height: 2.0em;
text-transform:capitalize;
color: #FFF;
}
#contributorInfo > a.circular:nth-child(9n+1){
background-color: #4ccdec;
}
#contributorInfo > a.circular:nth-child(9n+2){
background-color: #e0b265;
}
#contributorInfo > a.circular:nth-child(9n+3){
background-color: #d884b7;
}
#contributorInfo > a.circular:nth-child(9n+4){
background-color: #8c6bdc;
}
#contributorInfo > a.circular:nth-child(9n+5){
background-color: #3cb99f;
}
#contributorInfo > a.circular:nth-child(9n+6){
background-color: #6995b9;
}
#contributorInfo > a.circular:nth-child(9n+7){
background-color: #ab91a7;
}
#contributorInfo > a.circular:nth-child(9n+8){
background-color: #bfd0aa;
}
.vue_menu {
cursor: auto;
position: absolute;
outline: none;
top: 100%;
margin: 0em;
padding: 0em 0em;
background: #fff;
font-size: 1em;
text-shadow: none;
text-align: left;
/* -webkit-box-shadow: 0px 2px 3px 0px rgb(34 36 38 / 15%); */
box-shadow: 0px 2px 3px 0px rgba(34, 36, 38, 0.15);
border: 1px solid rgba(34,36,38,0.15);
border-radius: 0.28571429rem;
-webkit-transition: opacity 0.1s ease;
transition: opacity 0.1s ease;
z-index: 11;
will-change: transform, opacity;
width: 100% !important;

-webkit-animation-iteration-count: 1;
animation-iteration-count: 1;
-webkit-animation-duration: 300ms;
animation-duration: 300ms;
-webkit-animation-timing-function: ease;
animation-timing-function: ease;
-webkit-animation-fill-mode: both;
animation-fill-mode: both;
}




.repository.file.list #repo-desc {
font-size: 1.0em;
margin-bottom: 1.0rem;
}

#contributorInfo>a:nth-child(n+26) {
display: none;
}

#contributorInfo>a {
width: 2.0em;
float: left;
margin: .25em;
}

.edit-link {
vertical-align: top;
display: inline-block;
overflow: hidden;
word-break: keep-all;
white-space: nowrap;
text-overflow: ellipsis;
width: 16.5em;
}

#contributorInfo>a.circular {
height: 2.0em;
padding: 0;
overflow: hidden;
letter-spacing: 1.0em;
text-indent: 0.6em;
line-height: 2.0em;
text-transform: capitalize;
color: #FFF;
}

#contributorInfo>a.circular:nth-child(9n+1) {
background-color: #4ccdec;
}

#contributorInfo>a.circular:nth-child(9n+2) {
background-color: #e0b265;
}

#contributorInfo>a.circular:nth-child(9n+3) {
background-color: #d884b7;
}

#contributorInfo>a.circular:nth-child(9n+4) {
background-color: #8c6bdc;
}

#contributorInfo>a.circular:nth-child(9n+5) {
background-color: #3cb99f;
}

#contributorInfo>a.circular:nth-child(9n+6) {
background-color: #6995b9;
}

#contributorInfo>a.circular:nth-child(9n+7) {
background-color: #ab91a7;
}

#contributorInfo>a.circular:nth-child(9n+8) {
background-color: #bfd0aa;
}

.vue_menu {
cursor: auto;
position: absolute;
outline: none;
top: 100%;
margin: 0em;
padding: 0em 0em;
background: #fff;
font-size: 1em;
text-shadow: none;
text-align: left;
/* -webkit-box-shadow: 0px 2px 3px 0px rgb(34 36 38 / 15%); */
box-shadow: 0px 2px 3px 0px rgba(34, 36, 38, 0.15);
border: 1px solid rgba(34, 36, 38, 0.15);
border-radius: 0.28571429rem;
-webkit-transition: opacity 0.1s ease;
transition: opacity 0.1s ease;
z-index: 11;
will-change: transform, opacity;
width: 100% !important;

-webkit-animation-iteration-count: 1;
animation-iteration-count: 1;
-webkit-animation-duration: 300ms;
animation-duration: 300ms;
-webkit-animation-timing-function: ease;
animation-timing-function: ease;
-webkit-animation-fill-mode: both;
animation-fill-mode: both;
}
</style>
<div class="repository file list">
{{template "repo/header" .}}
<div class="ui container">
<div class="ui negative message" style="display: none;">

</div>
{{template "base/alert" .}}

{{if and .Permission.IsAdmin (not .Repository.IsArchived)}}
<!-- <div class="ui repo-topic-edit grid form segment error" id="topic_edit" style="display:none">
<!-- <div class="ui repo-topic-edit grid form segment error" id="topic_edit" style="display:none">
<div class="fourteen wide column">
<div class="field">
<div class="ui fluid multiple search selection dropdown">
@@ -114,33 +126,33 @@
</div>
</div> -->

{{end}}
<div class="hide" id="validate_prompt">
<span id="count_prompt">{{.i18n.Tr "repo.topic.count_prompt"}}</span>
<span id="format_prompt">{{.i18n.Tr "repo.topic.format_prompt"}}</span>
</div>
{{end}}
<div class="hide" id="validate_prompt">
<span id="count_prompt">{{.i18n.Tr "repo.topic.count_prompt"}}</span>
<span id="format_prompt">{{.i18n.Tr "repo.topic.format_prompt"}}</span>
</div>
<div class="ui repo-description stackable grid">

{{if .RepoSearchEnabled}}
<div class="ui repo-search four wide column">
<form class="ui form ignore-dirty" action="{{.RepoLink}}/search" method="get">
<div class="field">
<div class="ui action input">
<input name="q" value="{{.Keyword}}" placeholder="{{.i18n.Tr "repo.search.search_repo"}}">
<button class="ui icon button" type="submit">
<i class="search icon"></i>
</button>
</div>
<div class="ui repo-search four wide column">
<form class="ui form ignore-dirty" action="{{.RepoLink}}/search" method="get">
<div class="field">
<div class="ui action input">
<input name="q" value="{{.Keyword}}" placeholder="{{.i18n.Tr "repo.search.search_repo"}}">
<button class="ui icon button" type="submit">
<i class="search icon"></i>
</button>
</div>
</form>
</div>
</div>
</form>
</div>
{{end}}
</div>

{{if .Repository.IsArchived}}
<div class="ui warning message">
{{.i18n.Tr "repo.archive.title"}}
</div>
<div class="ui warning message">
{{.i18n.Tr "repo.archive.title"}}
</div>
{{end}}
{{template "repo/sub_menu" .}}
<div class="ui stackable secondary menu mobile--margin-between-items mobile--no-negative-margins">
@@ -149,97 +161,122 @@
{{ $l := Subtract $n 1}}
<!-- If home page, show new PR. If not, show breadcrumb -->
{{if eq $n 0}}
{{if and .CanCompareOrPull .IsViewBranch (not .Repository.IsArchived)}}
<div class="fitted item">
<a href="{{.BaseRepo.Link}}/compare/{{.BaseRepo.DefaultBranch | EscapePound}}...{{if ne .Repository.Owner.Name .BaseRepo.Owner.Name}}{{.Repository.Owner.Name}}:{{end}}{{.BranchName | EscapePound}}">
<button id="new-pull-request" class="ui compact basic button">{{if .PullRequestCtx.Allowed}}{{.i18n.Tr "repo.pulls.compare_changes"}}{{else}}{{.i18n.Tr "action.compare_branch"}}{{end}}</button>
</a>
{{if and .Repository.IsFork .PullRequestCtx.Allowed}}
{{if gt .FetchUpstreamCnt 0 }}
<a href="{{.Repository.Link}}/compare/{{.BranchName | EscapePound}}...{{.BaseRepo.Owner.Name}}:{{if .UpstreamSameBranchName}}{{.BranchName | EscapePound}}{{else}}{{.BaseRepo.DefaultBranch | EscapePound}}{{end}}">
<button id="new-pull-request" class="ui compact basic button" title="{{$.i18n.Tr (TrN $.i18n.Lang .FetchUpstreamCnt "repo.pulls.commits_count_1" "repo.pulls.commits_count_n") .FetchUpstreamCnt}}">{{.i18n.Tr "repo.pulls.fetch_upstream"}}</button>
</a>
{{else if lt .FetchUpstreamCnt 0}}
<a href="{{.Repository.Link}}/compare/{{.BranchName | EscapePound}}...{{.BaseRepo.Owner.Name}}:{{.BaseRepo.DefaultBranch | EscapePound}}">
<button id="new-pull-request" class="ui compact basic button" title="{{.i18n.Tr "repo.pulls.upstream_error"}}">{{.i18n.Tr "repo.pulls.fetch_upstream"}}</button>
</a>
{{else}}
<a href="{{.Repository.Link}}/compare/{{.BranchName | EscapePound}}...{{.BaseRepo.Owner.Name}}:{{if .UpstreamSameBranchName}}{{.BranchName | EscapePound}}{{else}}{{.BaseRepo.DefaultBranch | EscapePound}}{{end}}">
<button id="new-pull-request" class="ui compact basic button" title="{{.i18n.Tr "repo.pulls.upstream_up_to_date"}}">{{.i18n.Tr "repo.pulls.fetch_upstream"}}</button>
</a>
{{end}}
{{end}}
</div>
{{if and .CanCompareOrPull .IsViewBranch (not .Repository.IsArchived)}}
<div class="fitted item">
<a
href="{{.BaseRepo.Link}}/compare/{{.BaseRepo.DefaultBranch | EscapePound}}...{{if ne .Repository.Owner.Name .BaseRepo.Owner.Name}}{{.Repository.Owner.Name}}:{{end}}{{.BranchName | EscapePound}}">
<button id="new-pull-request"
class="ui compact basic button">{{if .PullRequestCtx.Allowed}}{{.i18n.Tr "repo.pulls.compare_changes"}}{{else}}{{.i18n.Tr "action.compare_branch"}}{{end}}</button>
</a>
{{if and .Repository.IsFork .PullRequestCtx.Allowed}}
{{if gt .FetchUpstreamCnt 0 }}
<a
href="{{.Repository.Link}}/compare/{{.BranchName | EscapePound}}...{{.BaseRepo.Owner.Name}}:{{if .UpstreamSameBranchName}}{{.BranchName | EscapePound}}{{else}}{{.BaseRepo.DefaultBranch | EscapePound}}{{end}}">
<button id="new-pull-request" class="ui compact basic button"
title="{{$.i18n.Tr (TrN $.i18n.Lang .FetchUpstreamCnt "repo.pulls.commits_count_1" "repo.pulls.commits_count_n") .FetchUpstreamCnt}}">{{.i18n.Tr "repo.pulls.fetch_upstream"}}</button>
</a>
{{else if lt .FetchUpstreamCnt 0}}
<a
href="{{.Repository.Link}}/compare/{{.BranchName | EscapePound}}...{{.BaseRepo.Owner.Name}}:{{.BaseRepo.DefaultBranch | EscapePound}}">
<button id="new-pull-request" class="ui compact basic button"
title="{{.i18n.Tr "repo.pulls.upstream_error"}}">{{.i18n.Tr "repo.pulls.fetch_upstream"}}</button>
</a>
{{else}}
<a
href="{{.Repository.Link}}/compare/{{.BranchName | EscapePound}}...{{.BaseRepo.Owner.Name}}:{{if .UpstreamSameBranchName}}{{.BranchName | EscapePound}}{{else}}{{.BaseRepo.DefaultBranch | EscapePound}}{{end}}">
<button id="new-pull-request" class="ui compact basic button"
title="{{.i18n.Tr "repo.pulls.upstream_up_to_date"}}">{{.i18n.Tr "repo.pulls.fetch_upstream"}}</button>
</a>
{{end}}
{{end}}
</div>
{{end}}
{{else}}
<div class="fitted item"><span class="ui breadcrumb repo-path"><a class="section" href="{{.RepoLink}}/src/{{EscapePound .BranchNameSubURL}}" title="{{.Repository.Name}}">{{EllipsisString .Repository.Name 30}}</a>{{range $i, $v := .TreeNames}}<span class="divider">/</span>{{if eq $i $l}}<span class="active section" title="{{$v}}">{{EllipsisString $v 30}}</span>{{else}}{{ $p := index $.Paths $i}}<span class="section"><a href="{{EscapePound $.BranchLink}}/{{EscapePound $p}}" title="{{$v}}">{{EllipsisString $v 30}}</a></span>{{end}}{{end}}</span></div>
<div class="fitted item"><span class="ui breadcrumb repo-path"><a class="section"
href="{{.RepoLink}}/src/{{EscapePound .BranchNameSubURL}}"
title="{{.Repository.Name}}">{{EllipsisString .Repository.Name 30}}</a>{{range $i, $v := .TreeNames}}<span
class="divider">/</span>{{if eq $i $l}}<span class="active section"
title="{{$v}}">{{EllipsisString $v 30}}</span>{{else}}{{ $p := index $.Paths $i}}<span
class="section"><a href="{{EscapePound $.BranchLink}}/{{EscapePound $p}}"
title="{{$v}}">{{EllipsisString $v 30}}</a></span>{{end}}{{end}}</span></div>
{{end}}
<div class="right fitted item" id="file-buttons">
<div class="ui tiny blue buttons">
{{if .Repository.CanEnableEditor}}
{{if .CanAddFile}}
<a href="{{.RepoLink}}/_new/{{EscapePound .BranchName}}/{{EscapePound .TreePath}}" class="ui button">
{{.i18n.Tr "repo.editor.new_file"}}
</a>
{{end}}
{{if .CanUploadFile}}
<a href="{{.RepoLink}}/_upload/{{EscapePound .BranchName}}/{{EscapePound .TreePath}}" class="ui button">
{{.i18n.Tr "repo.editor.upload_file"}}
</a>
{{end}}
{{if .CanAddFile}}
<a href="{{.RepoLink}}/_new/{{EscapePound .BranchName}}/{{EscapePound .TreePath}}"
class="ui button">
{{.i18n.Tr "repo.editor.new_file"}}
</a>
{{end}}
{{if .CanUploadFile}}
<a href="{{.RepoLink}}/_upload/{{EscapePound .BranchName}}/{{EscapePound .TreePath}}"
class="ui button">
{{.i18n.Tr "repo.editor.upload_file"}}
</a>
{{end}}
{{end}}
{{if and (ne $n 0) (not .IsViewFile) (not .IsBlame) }}
<a href="{{.RepoLink}}/commits/{{EscapePound .BranchNameSubURL}}/{{EscapePound .TreePath}}" class="ui button">
{{.i18n.Tr "repo.file_history"}}
</a>
<a href="{{.RepoLink}}/commits/{{EscapePound .BranchNameSubURL}}/{{EscapePound .TreePath}}"
class="ui button">
{{.i18n.Tr "repo.file_history"}}
</a>
{{end}}
</div>

</div>
<div class="fitted item">
{{if eq $n 0}}
{{if .Repository.IsTemplate}}
<div class="ui tiny blue buttons">
<a href="{{AppSubUrl}}/repo/create?template_id={{.Repository.ID}}" class="ui button">
{{.i18n.Tr "repo.use_template"}}
</a>
</div>
{{end}}
{{if .Repository.IsTemplate}}
<div class="ui tiny blue buttons">
<a href="{{AppSubUrl}}/repo/create?template_id={{.Repository.ID}}" class="ui button">
{{.i18n.Tr "repo.use_template"}}
</a>
</div>
{{end}}
{{end}}
</div>
<div class="fitted item">

<!-- Only show clone panel in repository home page -->
{{if eq $n 0}}
<div class="ui action tiny input" id="clone-panel">
{{if not $.DisableHTTP}}
<button class="ui basic clone button" id="repo-clone-https" data-link="{{.CloneLink.HTTPS}}">
{{if UseHTTPS}}HTTPS{{else}}HTTP{{end}}
</button>
{{end}}
{{if and (not $.DisableSSH) (or $.IsSigned $.ExposeAnonSSH)}}
<button class="ui basic clone button" id="repo-clone-ssh" data-link="{{.CloneLink.SSH}}">
SSH
</button>
{{end}}
{{if not $.DisableHTTP}}
<input id="repo-clone-url" value="{{$.CloneLink.HTTPS}}" readonly>
{{else if and (not $.DisableSSH) (or $.IsSigned $.ExposeAnonSSH)}}
<input id="repo-clone-url" value="{{$.CloneLink.SSH}}" readonly>
{{end}}
{{if or (not $.DisableHTTP) (and (not $.DisableSSH) (or $.IsSigned $.ExposeAnonSSH))}}
<button class="ui basic icon button poping up clipboard" id="clipboard-btn" data-original="{{.i18n.Tr "repo.copy_link"}}" data-success="{{.i18n.Tr "repo.copy_link_success"}}" data-error="{{.i18n.Tr "repo.copy_link_error"}}" data-content="{{.i18n.Tr "repo.copy_link"}}" data-variation="inverted tiny" data-clipboard-target="#repo-clone-url">
{{svg "octicon-clippy" 16}}
</button>
{{end}}
<div class="ui basic jump dropdown icon button poping up" data-content="{{.i18n.Tr "repo.download_archive"}}" data-variation="tiny inverted" data-position="top right">
<i class="download icon"></i>
<div class="menu">
<a class="item" href="{{$.RepoLink}}/archive/{{EscapePound $.BranchName}}.zip">{{svg "octicon-file-zip" 16}}&nbsp;ZIP</a>
<a class="item" href="{{$.RepoLink}}/archive/{{EscapePound $.BranchName}}.tar.gz">{{svg "octicon-file-zip" 16}}&nbsp;TAR.GZ</a>
</div>
<div class="ui action tiny input" id="clone-panel">
{{if not $.DisableHTTP}}
<button class="ui basic clone button" id="repo-clone-https" data-link="{{.CloneLink.HTTPS}}">
{{if UseHTTPS}}HTTPS{{else}}HTTP{{end}}
</button>
{{end}}
{{if and (not $.DisableSSH) (or $.IsSigned $.ExposeAnonSSH)}}
<button class="ui basic clone button" id="repo-clone-ssh" data-link="{{.CloneLink.SSH}}">
SSH
</button>
{{end}}
{{if not $.DisableHTTP}}
<input id="repo-clone-url" value="{{$.CloneLink.HTTPS}}" readonly>
{{else if and (not $.DisableSSH) (or $.IsSigned $.ExposeAnonSSH)}}
<input id="repo-clone-url" value="{{$.CloneLink.SSH}}" readonly>
{{end}}
{{if or (not $.DisableHTTP) (and (not $.DisableSSH) (or $.IsSigned $.ExposeAnonSSH))}}
<button class="ui basic icon button poping up clipboard" id="clipboard-btn"
data-original="{{.i18n.Tr "repo.copy_link"}}"
data-success="{{.i18n.Tr "repo.copy_link_success"}}"
data-error="{{.i18n.Tr "repo.copy_link_error"}}" data-content="{{.i18n.Tr "repo.copy_link"}}"
data-variation="inverted tiny" data-clipboard-target="#repo-clone-url">
{{svg "octicon-clippy" 16}}
</button>
{{end}}
<div class="ui basic jump dropdown icon button poping up"
data-content="{{.i18n.Tr "repo.download_archive"}}" data-variation="tiny inverted"
data-position="top right">
<i class="download icon"></i>
<div class="menu">
<a class="item"
href="{{$.RepoLink}}/archive/{{EscapePound $.BranchName}}.zip">{{svg "octicon-file-zip" 16}}&nbsp;ZIP</a>
<a class="item"
href="{{$.RepoLink}}/archive/{{EscapePound $.BranchName}}.tar.gz">{{svg "octicon-file-zip" 16}}&nbsp;TAR.GZ</a>
</div>
</div>
</div>
{{end}}
</div>
</div>
@@ -247,22 +284,24 @@
<div class="ui mobile reversed stackable grid">
<div class="ui ten wide tablet twelve wide computer column">
{{if .IsViewFile}}
{{template "repo/view_file" .}}
{{template "repo/view_file" .}}
{{else if .IsBlame}}
{{template "repo/blame" .}}
{{template "repo/blame" .}}
{{else}}
{{template "repo/view_list" .}}
{{template "repo/view_list" .}}
{{end}}
</div>
<div class="ui six wide tablet four wide computer column">
<div id="repo-desc" data-IsAdmin= "{{.Permission.IsAdmin}}" data-IsArchived="{{.Repository.IsArchived}}" >
<h4 id="about-desc" class="ui header">简介</h4>
<input type="hidden" id="edit-alias" value="{{.Repository.Alias}}">
<div id="repo-desc" data-IsAdmin="{{.Permission.IsAdmin}}"
data-IsArchived="{{.Repository.IsArchived}}">
<h4 id="about-desc" class="ui header">简介</h4>
<input type="hidden" id="edit-alias" value="{{.Repository.Alias}}">
<p>
{{if .Repository.DescriptionHTML}}
<span class="description" style="word-break:break-all">{{.Repository.DescriptionHTML}}</span>
<span class="description"
style="word-break:break-all">{{.Repository.DescriptionHTML}}</span>
{{else}}
<span class="no-description text-italic">{{.i18n.Tr "repo.no_desc"}}</span>
<span class="no-description text-italic">{{.i18n.Tr "repo.no_desc"}}</span>
{{end}}

</p>
@@ -274,7 +313,8 @@
{{if .Repository.Website}}
<p class="ui">
<i class="gray linkify icon"></i>
<a class="link edit-link" target="_blank" title="{{.Repository.Website}}" href="{{.Repository.Website}}">{{.Repository.Website}}</a>
<a class="link edit-link" target="_blank" title="{{.Repository.Website}}"
href="{{.Repository.Website}}">{{.Repository.Website}}</a>
</p>

{{end}}
@@ -284,11 +324,13 @@

<div id="repo-topics1" style="flex: 1;">
{{range .Topics}}
<a class="ui repo-topic small label topic" href="{{AppSubUrl}}/explore/repos?q={{.Name}}&topic=">{{.Name}}</a>
<a class="ui repo-topic small label topic"
href="{{AppSubUrl}}/explore/repos?q={{.Name}}&topic=">{{.Name}}</a>
{{end}}
</div>
<div>
{{if and .Permission.IsAdmin (not .Repository.IsArchived)}}<i id="manage_topic" style="cursor: pointer;" class="plus icon"></i>{{end}}
{{if and .Permission.IsAdmin (not .Repository.IsArchived)}}<i id="manage_topic"
style="cursor: pointer;" class="plus icon"></i>{{end}}
</div>
<div id="topic_edit" class="vue_menu" style="display:none">
<div id="topic_edit1">
@@ -302,7 +344,7 @@
<p class="ui">
<i class="grey code icon"></i>
{{range .LanguageStats}}
{{.Language}}
{{.Language}}
{{end}}
</p>

@@ -311,7 +353,7 @@
{{if .LICENSE}}
<p class="ui">
<i class="grey clone icon"></i>
{{.LICENSE}}
{{.LICENSE}}
</p>

{{end}}
@@ -326,19 +368,22 @@
{{else}}
<strong>贡献者 ({{len .ContributorInfo}}+)</strong>
{{end}}
<div class="ui right">
<!-- <a class="membersmore text grey" href="{{.RepoLink}}/contributors">全部 {{svg "octicon-chevron-right" 16}}</a> -->
<a class="membersmore text grey" href="{{.RepoLink}}/contributors?type={{if .IsViewBranch}}branch{{else}}tag{{end}}&name={{.BranchName}}">全部 {{svg "octicon-chevron-right" 16}}</a>
<a class="membersmore text grey"
href="{{.RepoLink}}/contributors?type={{if .IsViewBranch}}branch{{else}}tag{{end}}&name={{.BranchName}}">全部
{{svg "octicon-chevron-right" 16}}</a>
</div>
</h4>
<div class="ui members" id="contributorInfo">
{{range .ContributorInfo}}
{{if .UserInfo}}
<a href="{{AppSubUrl}}/{{.UserInfo.Name}}"><img class="ui avatar image" src="{{.UserInfo.RelAvatarLink}}"></a>
{{else if .Email}}
<a href="mailto:{{.Email}}" class="circular ui button">{{.Email}}</a>
{{end}}
{{if .UserInfo}}
<a href="{{AppSubUrl}}/{{.UserInfo.Name}}"><img class="ui avatar image"
src="{{.UserInfo.RelAvatarLink}}"></a>
{{else if .Email}}
<a href="mailto:{{.Email}}" class="circular ui button">{{.Email}}</a>
{{end}}
{{end}}
</div>
</div>
@@ -357,4 +402,4 @@
// });
// });
</script>
{{template "base/footer" .}}
{{template "base/footer" .}}

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

@@ -1,179 +1,213 @@
{{template "base/head" .}}
<style>
.according-panel-heading{
box-sizing: border-box;
padding: 8px 16px;
color: #252b3a;
background-color: #f2f5fc;
line-height: 1.5;
cursor: pointer;
-moz-user-select: none;
-webkit-user-select: none;
-ms-user-select: none;
-khtml-user-select: none;
user-select: none;
}
.accordion-panel-title {
margin-top: 0;
margin-bottom: 0;
color: #252b3a;
}
.accordion-panel-title-content{
vertical-align: middle;
display: inline-block;
width: calc(100% - 32px);
cursor: default;
}
.acc-margin-bottom {
margin-bottom: 5px;
}
.title_text {
font-size: 12px;
}
.ac-display-inblock {
display: inline-block;
}
.cti-mgRight-sm {
margin-right: 8px;
}
.ac-text-normal {
font-size: 14px;
color: #575d6c;
}
.uc-accordionTitle-black {
color: #333;
}
.accordion-border{
border:1px solid #cce2ff;
}
.padding0{
padding: 0 !important;
}
.content-pad{
padding: 15px 35px;
}
.content-margin{
margin:10px 5px ;
}
.tab_2_content {
min-height: 460px;
margin-left: 10px;
}
.ac-grid {
display: block;
*zoom: 1;
}
.ac-grid-col {
float: left;
width: 100%;
}
.ac-grid-col2 .ac-grid-col {
width: 50%;
}
.ti-form {
text-align: left;
max-width: 100%;
vertical-align: middle;
}
.ti-form>tbody {
font-size: 12px;
}
.ti-form>tbody, .ti-form>tbody>tr {
vertical-align: inherit;
}
.info_text {
padding-bottom: 20px;
padding-right: 20px;
font-size: 12px;
}

.ti-text-form-label {

padding-bottom: 20px;
padding-right: 20px;
color: #8a8e99;
font-size: 12px;
white-space: nowrap !important;
width: 80px;
line-height: 30px;
}
.ti-text-form-content{
line-height: 30px;
padding-bottom: 20px;
}

.ti-form>tbody>tr>td {
vertical-align: top;
white-space: normal;
}
td, th {
padding: 0;
}
.ac-grid-col .text-span {
width: 450px;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
.text-span-new {
width: 800px;
overflow: hidden;
text-overflow: ellipsis;
height: 20%;
word-break: break-all;
}
.redo-color{
color: #3291F8;
}
.ti-action-menu-item:not(:last-child){
margin-right: 10px;
padding-right: 11px;
text-decoration: none!important;
color: #526ecc;
cursor: pointer;
display: inline-block;
-moz-user-select: none;
-webkit-user-select: none;
-ms-user-select: none;
-khtml-user-select: none;
user-select: none;
position: relative;
}
.ti-action-menu-item:not(:last-child):after {
content: "";
display: inline-block;
position: absolute;
height: 12px;
right: 0;
top: 50%;
-webkit-transform: translateY(-6px);
-ms-transform: translateY(-6px);
-o-transform: translateY(-6px);
transform: translateY(-6px);
border-right: 1px solid #dfe1e6;
}
.text-width80{
width: 100px;
line-height: 30px;
}
.border-according{
border: 1px solid #dfe1e6;
}
.disabled {
.according-panel-heading {
box-sizing: border-box;
padding: 8px 16px;
color: #252b3a;
background-color: #f2f5fc;
line-height: 1.5;
cursor: pointer;
-moz-user-select: none;
-webkit-user-select: none;
-ms-user-select: none;
-khtml-user-select: none;
user-select: none;
}

.accordion-panel-title {
margin-top: 0;
margin-bottom: 0;
color: #252b3a;
}

.accordion-panel-title-content {
vertical-align: middle;
display: inline-block;
width: calc(100% - 32px);
cursor: default;
}

.acc-margin-bottom {
margin-bottom: 5px;
}

.title_text {
font-size: 12px;
}

.ac-display-inblock {
display: inline-block;
}

.cti-mgRight-sm {
margin-right: 8px;
}

.ac-text-normal {
font-size: 14px;
color: #575d6c;
}

.uc-accordionTitle-black {
color: #333;
}

.accordion-border {
border: 1px solid #cce2ff;
}

.padding0 {
padding: 0 !important;
}

.content-pad {
padding: 15px 35px;
}

.content-margin {
margin: 10px 5px;
}

.tab_2_content {
min-height: 460px;
margin-left: 10px;
}

.ac-grid {
display: block;
*zoom: 1;
}

.ac-grid-col {
float: left;
width: 100%;
}

.ac-grid-col2 .ac-grid-col {
width: 50%;
}

.ti-form {
text-align: left;
max-width: 100%;
vertical-align: middle;
}

.ti-form>tbody {
font-size: 12px;
}

.ti-form>tbody,
.ti-form>tbody>tr {
vertical-align: inherit;
}

.info_text {
padding-bottom: 20px;
padding-right: 20px;
font-size: 12px;
}

.ti-text-form-label {

padding-bottom: 20px;
padding-right: 20px;
color: #8a8e99;
font-size: 12px;
white-space: nowrap !important;
width: 80px;
line-height: 30px;
}

.ti-text-form-content {
line-height: 30px;
padding-bottom: 20px;
}

.ti-form>tbody>tr>td {
vertical-align: top;
white-space: normal;
}

td,
th {
padding: 0;
}

.ac-grid-col .text-span {
width: 450px;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}

.text-span-new {
width: 800px;
overflow: hidden;
text-overflow: ellipsis;
height: 20%;
word-break: break-all;
}

.redo-color {
color: #3291F8;
}

.ti-action-menu-item:not(:last-child) {
margin-right: 10px;
padding-right: 11px;
text-decoration: none !important;
color: #526ecc;
cursor: pointer;
display: inline-block;
-moz-user-select: none;
-webkit-user-select: none;
-ms-user-select: none;
-khtml-user-select: none;
user-select: none;
position: relative;
}

.ti-action-menu-item:not(:last-child):after {
content: "";
display: inline-block;
position: absolute;
height: 12px;
right: 0;
top: 50%;
-webkit-transform: translateY(-6px);
-ms-transform: translateY(-6px);
-o-transform: translateY(-6px);
transform: translateY(-6px);
border-right: 1px solid #dfe1e6;
}

.text-width80 {
width: 100px;
line-height: 30px;
}

.border-according {
border: 1px solid #dfe1e6;
}

.disabled {
cursor: default;
pointer-events: none;
color: rgba(0,0,0,.6) !important;
color: rgba(0, 0, 0, .6) !important;
opacity: .45 !important;
}
.pad20{

border:0px !important;
}
.model_file_bread{
margin-bottom: -0.5rem !important;
padding-left: 1rem;
padding-top: 0.5rem ;
}
}

.pad20 {

border: 0px !important;
}

.model_file_bread {
margin-bottom: -0.5rem !important;
padding-left: 1rem;
padding-top: 0.5rem;
}
</style>
<div id="mask">
<div id="loadingPage">
@@ -185,7 +219,7 @@ td, th {
</div>
</div>
<div class="repository">
{{template "repo/header" .}}
{{template "repo/header" .}}
<div class="ui container">
<h4 class="ui header" id="vertical-segment">
<div class="ui breadcrumb">
@@ -194,36 +228,42 @@ td, th {
</a>
<div class="divider"> / </div>
<a class="section backTodeBug" href="{{.RepoLink}}/debugjob?debugListType=all">
{{$.i18n.Tr "repo.modelarts.notebook"}}
{{$.i18n.Tr "repo.modelarts.notebook"}}
</a>
<div class="divider"> / </div>
{{with .task}}
{{with .task}}
<div class="active section">{{.DisplayJobName}}</div>
{{end}}
</div>
</div>
</h4>
{{with .task}}
<div class="ui accordion border-according" id="accordion" data-repopath="" data-jobid="" data-version="">
<div class="ui accordion border-according" id="accordion" data-repopath="{{$.RepoRelPath}}/modelarts/notebook"
data-jobid="{{.ID}}" data-version="">
<div class="active title padding0">
<div class="according-panel-heading">
<div class="accordion-panel-title">
<!-- <i class="dropdown icon"></i> -->
<!-- <i class="dropdown icon"></i> -->
<span class="accordion-panel-title-content">
<span>
<div class="ac-display-inblock title_text acc-margin-bottom">
<span class="cti-mgRight-sm">
{{if not (eq .StartTime 0)}}
<td>{{TimeSinceUnix1 .StartTime}}</td>
{{else}}
<td>{{TimeSinceUnix1 .CreatedUnix}}<td>
{{end}}
</span>
{{if not (eq .StartTime 0)}}
<td>{{TimeSinceUnix1 .StartTime}}</td>
{{else}}
<td>{{TimeSinceUnix1 .CreatedUnix}}
<td>
{{end}}
</span>

<span class="cti-mgRight-sm">{{$.i18n.Tr "repo.modelarts.status"}}:
<span id="{{.VersionName}}-status-span"><i id="icon" style="vertical-align: middle;" class="{{.Status}}"></i><span id="text" style="margin-left: 0.4em;font-size: 12px;">{{.Status}}</span></span>
<span id="{{.VersionName}}-status-span"><i id="icon"
style="vertical-align: middle;" class="{{.Status}}"></i><span id="text"
style="margin-left: 0.4em;font-size: 12px;">{{.Status}}</span></span>
</span>
<span class="cti-mgRight-sm">{{$.i18n.Tr "repo.modelarts.train_job.dura_time"}}:</span>
<span class="cti-mgRight-sm uc-accordionTitle-black" id="{{.VersionName}}-duration-span">{{$.duration}}</span>
<span
class="cti-mgRight-sm">{{$.i18n.Tr "repo.modelarts.train_job.dura_time"}}:</span>
<span class="cti-mgRight-sm uc-accordionTitle-black"
id="{{.VersionName}}-duration-span">{{$.duration}}</span>

</div>
</span>
@@ -265,36 +305,38 @@ td, th {
</td>
</tr>
<tr class="ti-no-ng-animate">
<td class="ti-no-ng-animate ti-text-form-label text-width80">
{{$.i18n.Tr "repo.cloudbrain_creator"}}
</td>
<td class="ti-no-ng-animate ti-text-form-label text-width80">
{{$.i18n.Tr "repo.cloudbrain_creator"}}
</td>

<td class="ti-text-form-content">
<div class="text-span text-span-w" id="{{.VersionName}}-mirror">
{{.User.Name}}
</div>
</td>
<td class="ti-text-form-content">
<div class="text-span text-span-w" id="{{.VersionName}}-mirror">
{{.User.Name}}
</div>
</td>
</tr>
<tr class="ti-no-ng-animate">
<td class="ti-no-ng-animate ti-text-form-label text-width80">
{{$.i18n.Tr "repo.modelarts.computing_resources"}}
</td>
<td class="ti-text-form-content">
<div class="text-span text-span-w" id="{{.VersionName}}-computeresource">
{{.ComputeResource}}
</div>
</td>
<td class="ti-no-ng-animate ti-text-form-label text-width80">
{{$.i18n.Tr "repo.modelarts.computing_resources"}}
</td>
<td class="ti-text-form-content">
<div class="text-span text-span-w"
id="{{.VersionName}}-computeresource">
{{.ComputeResource}}
</div>
</td>
</tr>
<tr class="ti-no-ng-animate">
<td class="ti-no-ng-animate ti-text-form-label text-width80">
{{$.i18n.Tr "repo.modelarts.createtime"}}
</td>
<td class="ti-no-ng-animate ti-text-form-label text-width80">
{{$.i18n.Tr "repo.modelarts.createtime"}}
</td>

<td class="ti-text-form-content">
<div class="text-span text-span-w" id="{{.VersionName}}-createtime">
{{TimeSinceUnix1 .CreatedUnix}}
</div>
</td>
<td class="ti-text-form-content">
<div class="text-span text-span-w"
id="{{.VersionName}}-createtime">
{{TimeSinceUnix1 .CreatedUnix}}
</div>
</td>
</tr>

<tr class="ti-no-ng-animate">
@@ -303,40 +345,41 @@ td, th {
</td>

<td class="ti-text-form-content">
<div class="text-span text-span-w" id="{{.VersionName}}-duration">
<div class="text-span text-span-w"
id="{{.VersionName}}-duration">
{{$.duration}}
</div>
</td>
</tr>
<tr class="ti-no-ng-animate">
<td class="ti-no-ng-animate ti-text-form-label text-width80">
{{$.i18n.Tr "repo.cloudbrain.datasetdownload"}}
</td>
<td class="ti-no-ng-animate ti-text-form-label text-width80">
{{$.i18n.Tr "repo.cloudbrain.datasetdownload"}}
</td>

<td class="ti-text-form-content">
<div class="text-span-new" id="model_description">
<td class="ti-text-form-content">
<div class="text-span-new" id="model_description">
{{$.datasetDownloadLink}}
</div>
</td>
</div>
</td>
</tr>
<tr class="ti-no-ng-animate">
<td class="ti-no-ng-animate ti-text-form-label text-width80">
{{$.i18n.Tr "cloudbrain.description"}}
</td>
<tr class="ti-no-ng-animate">
<td class="ti-no-ng-animate ti-text-form-label text-width80">
{{$.i18n.Tr "cloudbrain.description"}}
</td>

<td class="ti-text-form-content">
<div class="text-span-new" id="model_description">
<td class="ti-text-form-content">
<div class="text-span-new" id="model_description">
{{.Description}}
</div>
</td>
</div>
</td>
</tr>
</tbody>
</table>
</div>
<div class="ac-grid-col">
<table class="ti-form">
<tbody class="ti-text-form">
<table class="ti-form">
<tbody class="ti-text-form">

<tr class="ti-no-ng-animate">
<td class="ti-no-ng-animate ti-text-form-label text-width80">
@@ -350,33 +393,34 @@ td, th {
</td>
</tr>

<tr class="ti-no-ng-animate">
<td class="ti-no-ng-animate ti-text-form-label text-width80">
{{$.i18n.Tr "repo.modelarts.train_job.dataset"}}
</td>

<td class="ti-text-form-content">
<div class="text-span text-span-w" id="{{.VersionName}}-BenchmarkTypeName">
{{.DatasetName}}
</div>
</td>
</tr>

<tr class="ti-no-ng-animate">
<td class="ti-no-ng-animate ti-text-form-label text-width80">
{{$.i18n.Tr "repo.modelarts.train_job.dataset"}}
</td>

<td class="ti-text-form-content">
<div class="text-span text-span-w"
id="{{.VersionName}}-BenchmarkTypeName">
{{.DatasetName}}
</div>
</td>
</tr>


<tr class="ti-no-ng-animate">
<td class="ti-no-ng-animate ti-text-form-label text-width80">
{{$.i18n.Tr "repo.modelarts.train_job.standard"}}
</td>

<td class="ti-text-form-content">
<div class="text-span text-span-w">
{{$.resource_spec}}
</div>
</td>
</tr>
<tr class="ti-no-ng-animate">
<td class="ti-no-ng-animate ti-text-form-label text-width80">
{{$.i18n.Tr "repo.modelarts.train_job.standard"}}
</td>

<td class="ti-text-form-content">
<div class="text-span text-span-w">
{{$.resource_spec}}
</div>
</td>
</tr>
<tr class="ti-no-ng-animate">
<td class="ti-no-ng-animate ti-text-form-label text-width80">
{{$.i18n.Tr "repo.cloudbrain.time.starttime"}}
@@ -384,44 +428,46 @@ td, th {

<td class="ti-text-form-content">
<div class="text-span text-span-w">
<div class="text-span text-span-w" id="{{.VersionName}}-startTime">
<div class="text-span text-span-w"
id="{{.VersionName}}-startTime">
{{if not (eq .StartTime 0)}}
{{TimeSinceUnix1 .StartTime}}
{{else}}
--
{{end}}
{{TimeSinceUnix1 .StartTime}}
{{else}}
--
{{end}}
</div>
</div>
</td>
</tr>

<tr class="ti-no-ng-animate">
<td class="ti-no-ng-animate ti-text-form-label text-width80">
{{$.i18n.Tr "repo.cloudbrain.time.endtime"}}
</td>

<td class="ti-text-form-content">
<div class="text-span text-span-w" id="{{.VersionName}}-EndTime">
{{if not (eq .EndTime 0)}}
{{TimeSinceUnix1 .EndTime}}
{{else}}
--
{{end}}
</div>
</td>
</tr>
</tbody>
</table>
</div>
<td class="ti-no-ng-animate ti-text-form-label text-width80">
{{$.i18n.Tr "repo.cloudbrain.time.endtime"}}
</td>

<td class="ti-text-form-content">
<div class="text-span text-span-w"
id="{{.VersionName}}-EndTime">
{{if not (eq .EndTime 0)}}
{{TimeSinceUnix1 .EndTime}}
{{else}}
--
{{end}}
</div>
</td>
</tr>


</tbody>
</table>
</div>
</div>
</div>

</div>
</div>

</div>
</div>
@@ -457,24 +503,10 @@ td, th {
<script>
$('.menu .item').tab()

$(document).ready(function(){
$('.ui.accordion').accordion({selector:{trigger:'.icon'}});
$(document).ready(function () {
$('.ui.accordion').accordion({ selector: { trigger: '.icon' } });
});
$(document).ready(function(){
$(document).ready(function () {
$('.secondary.menu .item').tab();
});

let userName
let repoPath
let jobName
$(document).ready(function(){
let url = window.location.href;
let urlArr = url.split('/')
userName = urlArr.slice(-5)[0]
repoPath = urlArr.slice(-4)[0]
jobName = urlArr.slice(-1)[0]
})


</script>
</script>

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

@@ -239,7 +239,7 @@ const params = new URLSearchParams(location.search)
if(!location.search){
$('.default.text').text(all)
}else{
if(params.has('listType') && params.get('listType')=='all'){
if(!params.has('listType') || params.get('listType')=='all'){
$('.default.text').text(all)
}
else{


+ 569
- 536
templates/repo/modelarts/trainjob/show.tmpl
File diff suppressed because it is too large
View File


+ 146
- 81
templates/repo/view_list.tmpl View File

@@ -1,109 +1,174 @@
<table id="repo-files-table" class="ui single line table">
<div id="mask">
<div id="loadingPage">
<div class="rect1"></div>
<div class="rect2"></div>
<div class="rect3"></div>
<div class="rect4"></div>
<div class="rect5"></div>
</div>
</div>
<table id="repo-files-table" class="ui single line table can-context-menu" data-can-editfile="{{.CanEditFile}}">
{{.CsrfTokenHtml}}
<thead>
<tr class="commit-list">
<th colspan="2">
{{if .LatestCommitUser}}
<img class="ui avatar image img-12" src="{{.LatestCommitUser.RelAvatarLink}}" />
{{if .LatestCommitUser.FullName}}
<a href="{{AppSubUrl}}/{{.LatestCommitUser.Name}}"><strong>{{.LatestCommitUser.FullName}}</strong></a>
{{else}}
<a href="{{AppSubUrl}}/{{.LatestCommitUser.Name}}"><strong>{{if .LatestCommit.Author}}{{.LatestCommit.Author.Name}}{{else}}{{.LatestCommitUser.Name}}{{end}}</strong></a>
{{end}}
<img class="ui avatar image img-12" src="{{.LatestCommitUser.RelAvatarLink}}" />
{{if .LatestCommitUser.FullName}}
<a href="{{AppSubUrl}}/{{.LatestCommitUser.Name}}"><strong>{{.LatestCommitUser.FullName}}</strong></a>
{{else}}
{{if .LatestCommit.Author}}
<img class="ui avatar image img-12" src="{{AvatarLink .LatestCommit.Author.Email}}" />
<strong>{{.LatestCommit.Author.Name}}</strong>
{{end}}
<a
href="{{AppSubUrl}}/{{.LatestCommitUser.Name}}"><strong>{{if .LatestCommit.Author}}{{.LatestCommit.Author.Name}}{{else}}{{.LatestCommitUser.Name}}{{end}}</strong></a>
{{end}}
<a rel="nofollow" class="ui sha label {{if .LatestCommit.Signature}} isSigned {{if .LatestCommitVerification.Verified }} isVerified{{if eq .LatestCommitVerification.TrustStatus "trusted"}}{{else if eq .LatestCommitVerification.TrustStatus "untrusted"}}Untrusted{{else}}Unmatched{{end}}{{else if .LatestCommitVerification.Warning}} isWarning{{end}}{{end}}" href="{{.RepoLink}}/commit/{{.LatestCommit.ID}}">
{{else}}
{{if .LatestCommit.Author}}
<img class="ui avatar image img-12" src="{{AvatarLink .LatestCommit.Author.Email}}" />
<strong>{{.LatestCommit.Author.Name}}</strong>
{{end}}
{{end}}
<a rel="nofollow"
class="ui sha label {{if .LatestCommit.Signature}} isSigned {{if .LatestCommitVerification.Verified }} isVerified{{if eq .LatestCommitVerification.TrustStatus "trusted"}}{{else if eq .LatestCommitVerification.TrustStatus "untrusted"}}Untrusted{{else}}Unmatched{{end}}{{else if .LatestCommitVerification.Warning}} isWarning{{end}}{{end}}"
href="{{.RepoLink}}/commit/{{.LatestCommit.ID}}">
<span class="shortsha">{{ShortSha .LatestCommit.ID.String}}</span>
{{if .LatestCommit.Signature}}
<div class="ui detail icon button">
{{if .LatestCommitVerification.Verified}}
<div title="{{if eq .LatestCommitVerification.TrustStatus "trusted"}}{{else if eq .LatestCommitVerification.TrustStatus "untrusted"}}{{.i18n.Tr "repo.commits.signed_by_untrusted_user"}}: {{else}}{{.i18n.Tr "repo.commits.signed_by_untrusted_user_unmatched"}}: {{end}}{{.LatestCommitVerification.Reason}}">
{{if ne .LatestCommitVerification.SigningUser.ID 0}}
<i class="lock icon"></i>
<img class="ui signature avatar image" src="{{.LatestCommitVerification.SigningUser.RelAvatarLink}}" />
{{else}}
<i title="{{.LatestCommitVerification.Reason}}" class="icons">
<i class="lock icon"></i>
<i class="tiny inverted cog icon centerlock"></i>
</i>
<img class="ui signature avatar image" src="{{AvatarLink .LatestCommitVerification.SigningEmail}}" />
{{end}}
</div>
<div class="ui detail icon button">
{{if .LatestCommitVerification.Verified}}
<div
title="{{if eq .LatestCommitVerification.TrustStatus "trusted"}}{{else if eq .LatestCommitVerification.TrustStatus "untrusted"}}{{.i18n.Tr "repo.commits.signed_by_untrusted_user"}}: {{else}}{{.i18n.Tr "repo.commits.signed_by_untrusted_user_unmatched"}}: {{end}}{{.LatestCommitVerification.Reason}}">
{{if ne .LatestCommitVerification.SigningUser.ID 0}}
<i class="lock icon"></i>
<img class="ui signature avatar image"
src="{{.LatestCommitVerification.SigningUser.RelAvatarLink}}" />
{{else}}
<i title="{{$.i18n.Tr .LatestCommitVerification.Reason}}" class="unlock icon"></i>
<i title="{{.LatestCommitVerification.Reason}}" class="icons">
<i class="lock icon"></i>
<i class="tiny inverted cog icon centerlock"></i>
</i>
<img class="ui signature avatar image"
src="{{AvatarLink .LatestCommitVerification.SigningEmail}}" />
{{end}}
</div>
{{else}}
<i title="{{$.i18n.Tr .LatestCommitVerification.Reason}}" class="unlock icon"></i>
{{end}}
</div>
{{end}}
</a>
{{template "repo/commit_status" .LatestCommitStatus}}
{{ $commitLink:= printf "%s/commit/%s" .RepoLink .LatestCommit.ID }}
<span class="grey commit-summary" title="{{.LatestCommit.Summary}}"><span class="message-wrapper">{{RenderCommitMessageLinkSubject .LatestCommit.Message $.RepoLink $commitLink $.Repository.ComposeMetas}}</span>
{{if IsMultilineCommitMessage .LatestCommit.Message}}
<button class="basic compact mini ui icon button commit-button"><i class="ellipsis horizontal icon"></i></button>
<pre class="commit-body" style="display: none;">{{RenderCommitBody .LatestCommit.Message $.RepoLink $.Repository.ComposeMetas}}</pre>
{{end}}
<span class="grey commit-summary" title="{{.LatestCommit.Summary}}"><span
class="message-wrapper">{{RenderCommitMessageLinkSubject .LatestCommit.Message $.RepoLink $commitLink $.Repository.ComposeMetas}}</span>
{{if IsMultilineCommitMessage .LatestCommit.Message}}
<button class="basic compact mini ui icon button commit-button"><i
class="ellipsis horizontal icon"></i></button>
<pre class="commit-body"
style="display: none;">{{RenderCommitBody .LatestCommit.Message $.RepoLink $.Repository.ComposeMetas}}</pre>
{{end}}
</span>
</th>
<th class="text grey right age">{{if .LatestCommit.Author}}{{TimeSince .LatestCommit.Author.When $.Lang}}{{end}}</th>
<th class="text grey right age">
{{if .LatestCommit.Author}}{{TimeSince .LatestCommit.Author.When $.Lang}}{{end}}</th>
</tr>
</thead>
<tbody>
{{if .HasParentPath}}
<tr class="has-parent">
<td colspan="3">{{svg "octicon-mail-reply" 16}}<a href="{{EscapePound .BranchLink}}{{.ParentPath}}">..</a></td>
</tr>
<tr class="has-parent">
<td colspan="3">{{svg "octicon-mail-reply" 16}}<a href="{{EscapePound .BranchLink}}{{.ParentPath}}">..</a>
</td>
</tr>
{{end}}
{{range $item := .Files}}
{{$entry := index $item 0}}
{{$commit := index $item 1}}
<tr>
{{if $entry.IsSubModule}}
<td>
<span class="truncate">
{{svg "octicon-inbox" 16}}
{{$refURL := $commit.RefURL AppUrl $.Repository.FullName}}
{{if $refURL}}
<a href="{{$refURL}}">{{$entry.Name}}</a> @ <a href="{{$refURL}}/commit/{{$commit.RefID}}">{{ShortSha $commit.RefID}}</a>
{{else}}
{{$entry.Name}} @ {{ShortSha $commit.RefID}}
{{end}}
</span>
</td>
{{else}}
<td class="name four wide">
<span class="truncate">
{{if $entry.IsDir}}
{{$subJumpablePathName := $entry.GetSubJumpablePathName}}
{{$subJumpablePath := SubJumpablePath $subJumpablePathName}}
{{svg "octicon-file-directory" 16}}
<a href="{{EscapePound $.TreeLink}}/{{EscapePound $subJumpablePathName}}" title="{{$subJumpablePathName}}">
{{if eq (len $subJumpablePath) 2}}
<span class="jumpable-path">{{index $subJumpablePath 0}}</span>{{index $subJumpablePath 1}}
{{else}}
{{index $subJumpablePath 0}}
{{end}}
</a>
{{else}}
{{svg (printf "octicon-%s" (EntryIcon $entry)) 16}}
<a href="{{EscapePound $.TreeLink}}/{{EscapePound $entry.Name}}" title="{{$entry.Name}}">{{$entry.Name}}</a>
{{end}}
</span>
</td>
{{end}}
<td class="message nine wide">
<span class="truncate">
<a href="{{$.RepoLink}}/commit/{{$commit.ID}}" title="{{$commit.Summary}}">{{$commit.Summary | RenderEmoji}}</a>
</span>
</td>
<td class="text right age three wide">{{TimeSince $commit.Committer.When $.Lang}}</td>
</tr>
{{$entry := index $item 0}}
{{$commit := index $item 1}}
<tr>
{{if $entry.IsSubModule}}
<td>
<span class="truncate">
{{svg "octicon-inbox" 16}}
{{$refURL := $commit.RefURL AppUrl $.Repository.FullName}}
{{if $refURL}}
<a href="{{$refURL}}">{{$entry.Name}}</a> @ <a
href="{{$refURL}}/commit/{{$commit.RefID}}">{{ShortSha $commit.RefID}}</a>
{{else}}
{{$entry.Name}} @ {{ShortSha $commit.RefID}}
{{end}}
</span>
</td>
{{else}}
<td class="name four wide modified-contextmenu">
<span class="truncate">
{{if $entry.IsDir}}
{{$subJumpablePathName := $entry.GetSubJumpablePathName}}
{{$subJumpablePath := SubJumpablePath $subJumpablePathName}}
{{svg "octicon-file-directory" 16}}
<a href="{{EscapePound $.TreeLink}}/{{EscapePound $subJumpablePathName}}"
title="{{$subJumpablePathName}}">
{{if eq (len $subJumpablePath) 2}}
<span class="jumpable-path">{{index $subJumpablePath 0}}</span>{{index $subJumpablePath 1}}
{{else}}
{{index $subJumpablePath 0}}
{{end}}
</a>
{{else}}
{{svg (printf "octicon-%s" (EntryIcon $entry)) 16}}
<a href="{{EscapePound $.TreeLink}}/{{EscapePound $entry.Name}}"
title="{{$entry.Name}}">{{$entry.Name}}</a>
{{end}}
</span>
</td>
{{end}}

<td class="message nine wide">
<span class="truncate">
<a href="{{$.RepoLink}}/commit/{{$commit.ID}}"
title="{{$commit.Summary}}">{{$commit.Summary | RenderEmoji}}</a>
</span>
</td>
<td class="text right age three wide">{{TimeSince $commit.Committer.When $.Lang}}</td>
</tr>
<tr style="display: none !important;" class="context-menu-one">
<td colspan="12">
<div class="ui column form" method="POST">
<div class="two fields" style="margin: 0;">
<div class="five wide field">
<input class="ui input" name="new_filename" type="text" value=""
onkeyup="this.value=this.value.replace(/[, ]/g,'')">
</div>
<div class="five wide field">
<button class="ui blue button popup-save" type="button"
data-postBasePath="{{$.RepoLink}}/_rename/{{EscapePound $.BranchName}}{{if $.TreePath}}/{{EscapePound $.TreePath}}{{end}}/{{$entry.Name}}"
data-commit="{{$.LatestCommit.ID}}"
data-treepath="{{if $.TreePath}}{{EscapePound $.TreePath}}/{{end}}">保存</button>
<button class="ui basic button popup-close" type="button">取消</button>
</div>
</div>
</div>
</td>
</tr>
{{end}}
</tbody>
</table>
{{if .ReadmeExist}}
{{template "repo/view_file" .}}
{{template "repo/view_file" .}}
{{end}}

<!-- 确认模态框 -->
<div id="deletemodel">
<div class="ui basic modal context-menu-delete">
<div class="ui icon header">
<i class="trash icon"></i> {{.i18n.Tr "cloudbrain.delete_task"}}
</div>

<div class="content">
<p>{{.i18n.Tr "cloudbrain.task_delete_confirm"}}</p>
</div>
<div class="actions">
<div class="ui red basic inverted cancel button">
<i class="remove icon"></i> {{.i18n.Tr "cloudbrain.operate_cancel"}}
</div>
<div class="ui green basic inverted ok button">
<i class="checkmark icon"></i> {{.i18n.Tr "cloudbrain.operate_confirm"}}
</div>
</div>
</div>
</div>

+ 135
- 99
templates/user/dashboard/cloudbrains.tmpl View File

@@ -1,6 +1,6 @@
{{template "base/head" .}}
<!-- 弹窗 -->
<div id="mask">
<!-- 弹窗 -->
<div id="mask">
<div id="loadingPage">
<div class="rect1"></div>
<div class="rect2"></div>
@@ -12,16 +12,22 @@
<!-- 提示框 -->
<div class="alert"></div>
<div class="explore users">
<div class="cloudbrain_debug" style="display: none;" data-debug="{{$.i18n.Tr "repo.debug"}}" data-debug-again="{{$.i18n.Tr "repo.debug_again"}}"></div>
<div class="cloudbrain_debug" style="display: none;" data-debug="{{$.i18n.Tr "repo.debug"}}"
data-debug-again="{{$.i18n.Tr "repo.debug_again"}}" data-debug-task="{{$.i18n.Tr "cloudbrain.DEBUG"}}"
data-train-task="{{$.i18n.Tr "cloudbrain.TRAIN"}}" data-inference-task="{{$.i18n.Tr "cloudbrain.INFERENCE"}}"
data-benchmark-task="{{$.i18n.Tr "cloudbrain.BENCHMARK"}}"
data-all-task="{{.i18n.Tr "admin.cloudbrain.all_task_types"}}"
data-all-compute="{{.i18n.Tr "admin.cloudbrain.all_computing_resources"}}"
data-all-status="{{.i18n.Tr "admin.cloudbrain.all_status"}}"></div>
{{template "admin/cloudbrain/search_dashboard" .}}
<div class="ui container" style="width: 80%;">
{{template "base/alert" .}}
<div class="ui grid" >
<div class="row" >
<div class="ui grid">
<div class="row">
<div class="ui sixteen wide column">
<!-- 任务展示 -->
<div class="dataset list">
<!-- 表头 -->
<!-- 表头 -->
<div class="ui grid stackable" style="background: #f0f0f0;;">
<div class="row">
<div class="three wide column nowrap" style="width:15%">
@@ -34,19 +40,19 @@
<span style="margin:0 6px">{{$.i18n.Tr "repo.cloudbrain_task_type"}}</span>
</div>
<div class="two wide column text center nowrap" style="width: 11% !important;">
<span>{{$.i18n.Tr "repo.modelarts.createtime"}}</span>
<span>{{$.i18n.Tr "repo.modelarts.createtime"}}</span>
</div>
<div class="one wide column text center nowrap" style="width:8.5% !important;">
<span>{{$.i18n.Tr "repo.cloudbrain_status_runtime"}}</span>
</div>
<div class="one wide column text center nowrap" style="width:8.5% !important;">
<span>{{$.i18n.Tr "repo.modelarts.computing_resources"}}</span>
<span>{{$.i18n.Tr "repo.modelarts.computing_resources"}}</span>
</div>
<div class="two wide column text center nowrap" style="width: 14.5%!important;">
<span>{{$.i18n.Tr "repository"}}</span>
</div>
<div class="three wide column text center nowrap" style="width: 21.5%!important;">
<span>{{$.i18n.Tr "repo.cloudbrain_operate"}}</span>
</div>
@@ -65,66 +71,100 @@
{{end}}
<!-- {{$JobID}} -->
<div class="three wide column nowrap" style="width:15%">
{{if or (eq .JobType "DEBUG") (eq .JobType "SNN4IMAGENET") (eq .JobType "BRAINSCORE")}}
<a class="title" href="{{AppSubUrl}}/{{.Repo.OwnerName}}/{{.Repo.Name}}{{if eq .ComputeResource "CPU/GPU"}}/cloudbrain/{{$JobID}}{{else}}/modelarts/notebook/{{$JobID}}{{end}}" title="{{.DisplayJobName}}" style="font-size: 14px;">
<span class="fitted" style="width: 90%;vertical-align: middle;">{{.DisplayJobName}}</span>
{{if eq .JobType "DEBUG"}}
<a class="title"
href="{{AppSubUrl}}/{{.Repo.OwnerName}}/{{.Repo.Name}}{{if eq .ComputeResource "CPU/GPU"}}/cloudbrain/{{$JobID}}{{else}}/modelarts/notebook/{{$JobID}}{{end}}"
title="{{.DisplayJobName}}" style="font-size: 14px;">
<span class="fitted"
style="width: 90%;vertical-align: middle;">{{.DisplayJobName}}</span>
</a>
{{else if or (eq .JobType "SNN4IMAGENET") (eq .JobType "BRAINSCORE")}}
<a class="title"
href="{{AppSubUrl}}/{{.Repo.OwnerName}}/{{.Repo.Name}}/cloudbrain/benchmark/{{$JobID}}"
title="{{.DisplayJobName}}" style="font-size: 14px;">
<span class="fitted"
style="width: 90%;vertical-align: middle;">{{.DisplayJobName}}</span>
</a>
{{else if eq .JobType "INFERENCE"}}
<a class="title" href="{{AppSubUrl}}/{{.Repo.OwnerName}}/{{.Repo.Name}}/modelarts/inference-job/{{$JobID}}" title="{{.DisplayJobName}}" style="font-size: 14px;">
<span class="fitted" style="width: 90%;vertical-align: middle;">{{.DisplayJobName}}</span>
<a class="title"
href="{{AppSubUrl}}/{{.Repo.OwnerName}}/{{.Repo.Name}}/modelarts/inference-job/{{$JobID}}"
title="{{.DisplayJobName}}" style="font-size: 14px;">
<span class="fitted"
style="width: 90%;vertical-align: middle;">{{.DisplayJobName}}</span>
</a>
{{else if eq .JobType "TRAIN"}}
<a class="title" href="{{AppSubUrl}}/{{.Repo.OwnerName}}/{{.Repo.Name}}/{{if eq .ComputeResource "NPU"}}modelarts{{else}}cloudbrain{{end}}/train-job/{{$JobID}}" title="{{.DisplayJobName}}" style="font-size: 14px;">
<span class="fitted" style="width: 90%;vertical-align: middle;">{{.DisplayJobName}}</span>
<a class="title"
href="{{AppSubUrl}}/{{.Repo.OwnerName}}/{{.Repo.Name}}/{{if eq .ComputeResource "NPU"}}modelarts{{else}}cloudbrain{{end}}/train-job/{{$JobID}}"
title="{{.DisplayJobName}}" style="font-size: 14px;">
<span class="fitted"
style="width: 90%;vertical-align: middle;">{{.DisplayJobName}}</span>
</a>
{{else if eq .JobType "BENCHMARK"}}
<a class="title" href="{{AppSubUrl}}/{{.Repo.OwnerName}}/{{.Repo.Name}}/cloudbrain/benchmark/{{$JobID}}" title="{{.DisplayJobName}}" style="font-size: 14px;">
<span class="fitted" style="width: 90%;vertical-align: middle;">{{.DisplayJobName}}</span>
<a class="title"
href="{{AppSubUrl}}/{{.Repo.OwnerName}}/{{.Repo.Name}}/cloudbrain/benchmark/{{$JobID}}"
title="{{.DisplayJobName}}" style="font-size: 14px;">
<span class="fitted"
style="width: 90%;vertical-align: middle;">{{.DisplayJobName}}</span>
</a>
{{end}}
</div>
<!-- 任务状态 -->
<div class="two wide column text center nowrap" style="padding-left: 2.2rem !important; width: 11% !important;">
<span class="job-status" id="{{$JobID}}" data-repopath='{{.Repo.OwnerName}}/{{.Repo.Name}}{{if eq .JobType "DEBUG"}}{{if eq .ComputeResource "CPU/GPU"}}/cloudbrain{{else}}/modelarts/notebook{{end}}{{else if eq .JobType "INFERENCE"}}/modelarts/inference-job{{else if eq .JobType "TRAIN"}}{{if eq .ComputeResource "NPU"}}/modelarts/train-job{{else}}/cloudbrain/train-job{{end}}{{else if eq .JobType "BENCHMARK"}}/cloudbrain{{end}}' data-jobid="{{$JobID}}" data-version="{{.VersionName}}">
<span><i id="{{$JobID}}-icon" style="vertical-align: middle;" class="{{.Status}}"></i><span id="{{$JobID}}-text" style="margin-left: 0.4em;font-size: 12px;">{{.Status}}</span></span>
<div class="two wide column text center nowrap"
style="padding-left: 2.2rem !important; width: 11% !important;">
<span class="job-status" id="{{$JobID}}"
data-repopath='{{.Repo.OwnerName}}/{{.Repo.Name}}{{if eq .JobType "DEBUG"}}{{if eq .ComputeResource "CPU/GPU"}}/cloudbrain{{else}}/modelarts/notebook{{end}}{{else if eq .JobType "INFERENCE"}}/modelarts/inference-job{{else if eq .JobType "TRAIN"}}{{if eq .ComputeResource "NPU"}}/modelarts/train-job{{else}}/cloudbrain/train-job{{end}}{{else if eq .JobType "BENCHMARK"}}/cloudbrain{{end}}'
data-jobid="{{$JobID}}" data-version="{{.VersionName}}">
<span><i id="{{$JobID}}-icon" style="vertical-align: middle;"
class="{{.Status}}"></i><span id="{{$JobID}}-text"
style="margin-left: 0.4em;font-size: 12px;">{{.Status}}</span></span>
</span>
</div>
<!-- 任务类型 -->
{{$JobType := $.i18n.Tr (printf "cloudbrain.%s" .JobType)}}
<div class="one wide column text center nowrap" style="width:10%">
<span style="font-size: 12px;" title="{{$JobType}}">{{$JobType}}</span>
<span style="font-size: 12px;" title="{{.JobType}}">{{$JobType}}</span>
</div>
<!-- 任务创建时间 -->
<div class="two wide column text center nowrap" style="width: 11% !important;">
<span style="font-size: 12px;" class="">{{TimeSinceUnix1 .Cloudbrain.CreatedUnix}}</span>
<span style="font-size: 12px;"
class="">{{TimeSinceUnix1 .Cloudbrain.CreatedUnix}}</span>
</div>
<!-- 任务运行时间 -->
<div class="one wide column text center nowrap" style="width:8.5% !important;">
<span style="font-size: 12px;" id="duration-{{$JobID}}">{{if .TrainJobDuration}}{{.TrainJobDuration}}{{else}}--{{end}}</span>
<span style="font-size: 12px;"
id="duration-{{$JobID}}">{{if .TrainJobDuration}}{{.TrainJobDuration}}{{else}}--{{end}}</span>
</div>
<!-- 计算资源 -->
<div class="one wide column text center nowrap" style="width:8.5% !important;">
<span style="font-size: 12px;">{{if .ComputeResource}}{{.ComputeResource}}{{else}}--{{end}}</span>
<span
style="font-size: 12px;">{{if .ComputeResource}}{{.ComputeResource}}{{else}}--{{end}}</span>
</div>
<!-- 项目 -->
<div class="two wide column text center nowrap" style="width: 14.5%!important;">
<a href="{{AppSubUrl}}/{{.Repo.OwnerName}}/{{.Repo.Name}}" title="{{.Repo.OwnerName}}/{{.Repo.Alias}}">{{.Repo.OwnerName}}/{{.Repo.Alias}}</a>
<a href="{{AppSubUrl}}/{{.Repo.OwnerName}}/{{.Repo.Name}}"
title="{{.Repo.OwnerName}}/{{.Repo.Alias}}">{{.Repo.OwnerName}}/{{.Repo.Alias}}</a>
</div>
<div class="three wide column text center nowrap" style="width: 21.5%!important;">
{{if eq .JobType "DEBUG" "SNN4IMAGENET" "BRAINSCORE"}}
{{if eq .JobType "DEBUG"}}
<div class="ui compact buttons">
<form id="debugAgainForm-{{$JobID}}">
{{$.CsrfTokenHtml}}
{{if eq .Status "RUNNING" "WAITING" "CREATING" "STARTING"}}
<a style="margin: 0 1rem;" id="ai-debug-{{$JobID}}" class='ui basic ai_debug {{if eq .Status "CREATING" "STOPPING" "WAITING" "STARTING"}}disabled {{else}}blue {{end}}button' data-jobid="{{$JobID}}" data-repopath='{{AppSubUrl}}/{{.Repo.OwnerName}}/{{.Repo.Name}}{{if eq .ComputeResource "CPU/GPU"}}/cloudbrain{{else}}/modelarts/notebook{{end}}/{{$JobID}}/'>
<a style="margin: 0 1rem;" id="ai-debug-{{$JobID}}"
class='ui basic ai_debug {{if eq .Status "CREATING" "STOPPING" "WAITING" "STARTING"}}disabled {{else}}blue {{end}}button'
data-jobid="{{$JobID}}"
data-repopath='{{AppSubUrl}}/{{.Repo.OwnerName}}/{{.Repo.Name}}{{if eq .ComputeResource "CPU/GPU"}}/cloudbrain{{else}}/modelarts/notebook{{end}}/{{$JobID}}/'>
{{$.i18n.Tr "repo.debug"}}
</a>
{{else}}
<a id="ai-debug-{{$JobID}}" class='ui basic ai_debug {{if eq .Status "CREATING" "STOPPING" "WAITING" "STARTING"}} disabled {{else}}blue {{end}}button' data-jobid="{{$JobID}}" data-repopath='{{AppSubUrl}}/{{.Repo.OwnerName}}/{{.Repo.Name}}{{if eq .ComputeResource "CPU/GPU"}}/cloudbrain{{else}}/modelarts/notebook{{end}}/{{$JobID}}/'>
<a id="ai-debug-{{$JobID}}"
class='ui basic ai_debug {{if eq .Status "CREATING" "STOPPING" "WAITING" "STARTING"}} disabled {{else}}blue {{end}}button'
data-jobid="{{$JobID}}"
data-repopath='{{AppSubUrl}}/{{.Repo.OwnerName}}/{{.Repo.Name}}{{if eq .ComputeResource "CPU/GPU"}}/cloudbrain{{else}}/modelarts/notebook{{end}}/{{$JobID}}/'>
{{$.i18n.Tr "repo.debug_again"}}
</a>
{{end}}
@@ -134,22 +174,42 @@
<!-- 停止任务 -->
<div class="ui compact buttons">
{{if eq .JobType "DEBUG" "BENCHMARK" "SNN4IMAGENET" "BRAINSCORE"}}
<form id="stopForm-{{$JobID}}" style="margin-left:-1px;">
<form id="stopForm-{{$JobID}}" style="margin-left:-1px;">
{{$.CsrfTokenHtml}}
<a style="padding: 0.5rem 1rem;" id="ai-stop-{{$JobID}}" class='ui basic ai_stop {{if eq .Status "KILLED" "FAILED" "START_FAILED" "KILLING" "COMPLETED" "SUCCEEDED" "STOPPED" "STOPPING" "CREATE_FAILED"}}disabled {{else}} blue {{end}}button' data-repopath='{{AppSubUrl}}/{{.Repo.OwnerName}}/{{.Repo.Name}}{{if eq .ComputeResource "CPU/GPU"}}/cloudbrain{{else if eq .JobType "BENCHMARK" }}/cloudbrain/benchmark{{else if eq .ComputeResource "NPU" }}/modelarts/notebook{{end}}/{{$JobID}}/stop' data-jobid="{{$JobID}}">
<a style="padding: 0.5rem 1rem;" id="ai-stop-{{$JobID}}"
class='ui basic ai_stop {{if eq .Status "KILLED" "FAILED" "START_FAILED" "KILLING" "COMPLETED" "SUCCEEDED" "STOPPED" "STOPPING" "CREATE_FAILED"}}disabled {{else}} blue {{end}}button'
data-repopath='{{AppSubUrl}}/{{.Repo.OwnerName}}/{{.Repo.Name}}{{if eq .ComputeResource "CPU/GPU"}}/cloudbrain{{else if eq .JobType "BENCHMARK" }}/cloudbrain/benchmark{{else if eq .ComputeResource "NPU" }}/modelarts/notebook{{end}}/{{$JobID}}/stop'
data-jobid="{{$JobID}}">
{{$.i18n.Tr "repo.stop"}}
</a>
</form>
{{else}}
<a style="padding: 0.5rem 1rem;" id="ai-stop-{{$JobID}}" class='ui basic ai_stop_version {{if eq .Status "KILLED" "FAILED" "START_FAILED" "KILLING" "COMPLETED" "STOPPED" "SUCCEEDED" "CREATE_FAILED"}}disabled {{else}} blue {{end}}button' data-repopath='{{.Repo.OwnerName}}/{{.Repo.Name}}/{{if eq .JobType "INFERENCE"}}modelarts/inference-job{{else if eq .JobType "TRAIN"}}{{if eq .ComputeResource "NPU"}}modelarts/train-job{{else}}cloudbrain/train-job{{end}}{{end}}' data-jobid="{{$JobID}}" data-version="{{.VersionName}}" >
<a style="padding: 0.5rem 1rem;" id="ai-stop-{{$JobID}}"
class='ui basic ai_stop_version {{if eq .Status "KILLED" "FAILED" "START_FAILED" "KILLING" "COMPLETED" "STOPPED" "SUCCEEDED" "CREATE_FAILED"}}disabled {{else}} blue {{end}}button'
data-repopath='{{.Repo.OwnerName}}/{{.Repo.Name}}/{{if eq .JobType "INFERENCE"}}modelarts/inference-job{{else if eq .JobType "TRAIN"}}{{if eq .ComputeResource "NPU"}}modelarts/train-job{{else}}cloudbrain/train-job{{end}}{{end}}'
data-jobid="{{$JobID}}" data-version="{{.VersionName}}">
{{$.i18n.Tr "repo.stop"}}
</a>
{{end}}
</div>
{{if eq .JobType "BENCHMARK"}}
<div class="ui compact buttons">
<a class="ui basic button {{if $.IsSigned}} blue{{else}} disabled{{end}}"
href="{{$.RepoLink}}/cloudbrain/{{.Cloudbrain.ID}}/rate" target="_blank">
{{$.i18n.Tr "repo.score"}}
</a>
</div>

{{end}}
<!-- 删除任务 -->
<form class="ui compact buttons" id="delForm-{{$JobID}}" action='{{AppSubUrl}}/{{.Repo.OwnerName}}/{{.Repo.Name}}{{if eq .JobType "BENCHMARK"}}/cloudbrain/benchmark{{else if or (eq .JobType "SNN4IMAGENET") (eq .JobType "BRAINSCORE")}}/cloudbrain{{else if eq .JobType "DEBUG"}}{{if eq .ComputeResource "NPU"}}/modelarts/notebook{{else}}/cloudbrain{{end}}{{else if eq .JobType "TRAIN"}}{{if eq .ComputeResource "NPU"}}/modelarts/train-job{{else}}/cloudbrain/train-job{{end}}{{end}}/{{$JobID}}/del?ishomepage=true' method="post">
<form class="ui compact buttons" id="delForm-{{$JobID}}"
action='{{AppSubUrl}}/{{.Repo.OwnerName}}/{{.Repo.Name}}{{if eq .JobType "BENCHMARK"}}/cloudbrain/benchmark{{else if or (eq .JobType "SNN4IMAGENET") (eq .JobType "BRAINSCORE")}}/cloudbrain{{else if eq .JobType "DEBUG"}}{{if eq .ComputeResource "NPU"}}/modelarts/notebook{{else}}/cloudbrain{{end}}{{else if eq .JobType "TRAIN"}}{{if eq .ComputeResource "NPU"}}/modelarts/train-job{{else}}/cloudbrain/train-job{{end}}{{end}}/{{$JobID}}/del?ishomepage=true'
method="post">
{{$.CsrfTokenHtml}}
<a style="padding: 0.5rem 1rem;margin-left:0.2rem" id="ai-delete-{{$JobID}}" data-repopath="{{.Repo.OwnerName}}/{{.Repo.Name}}/modelarts/inference-job/{{$JobID}}/del_version?ishomepage=true" data-version="" class="ui basic ai_delete blue button" style="border-radius: .28571429rem;">
<a style="padding: 0.5rem 1rem;margin-left:0.2rem" id="ai-delete-{{$JobID}}"
data-repopath="{{.Repo.OwnerName}}/{{.Repo.Name}}/modelarts/inference-job/{{$JobID}}/del_version?ishomepage=true"
data-version="" class="ui basic ai_delete blue button"
style="border-radius: .28571429rem;">
{{$.i18n.Tr "repo.delete"}}
</a>
</form>
@@ -169,48 +229,59 @@
<div class="three wide column nowrap" style="width:15%">
{{if eq .JobType "DEBUG"}}
<a class="title" href="" title="{{.DisplayJobName}}" style="font-size: 14px;">
<span class="fitted" style="width: 90%;vertical-align: middle;">{{.DisplayJobName}}</span>
<span class="fitted"
style="width: 90%;vertical-align: middle;">{{.DisplayJobName}}</span>
</a>
{{else if eq .JobType "INFERENCE"}}
<a class="title" href="" title="{{.DisplayJobName}}" style="font-size: 14px;">
<span class="fitted" style="width: 90%;vertical-align: middle;">{{.DisplayJobName}}</span>
<span class="fitted"
style="width: 90%;vertical-align: middle;">{{.DisplayJobName}}</span>
</a>
{{else if eq .JobType "TRAIN"}}
<a class="title" href="" title="{{.DisplayJobName}}" style="font-size: 14px;">
<span class="fitted" style="width: 90%;vertical-align: middle;">{{.DisplayJobName}}</span>
<span class="fitted"
style="width: 90%;vertical-align: middle;">{{.DisplayJobName}}</span>
</a>
{{else if eq .JobType "BENCHMARK"}}
<a class="title" href="" title="{{.DisplayJobName}}" style="font-size: 14px;">
<span class="fitted" style="width: 90%;vertical-align: middle;">{{.DisplayJobName}}</span>
<span class="fitted"
style="width: 90%;vertical-align: middle;">{{.DisplayJobName}}</span>
</a>
{{end}}
</div>
<!-- 任务状态 -->
<div class="two wide column text center nowrap" style="padding-left: 2.2rem !important; width: 11% !important;">
<span class="job-status" id="{{$JobID}}" data-jobid="{{$JobID}}" data-version="{{.VersionName}}">
<span><i id="{{$JobID}}-icon" style="vertical-align: middle;" class="{{.Status}}"></i><span id="{{$JobID}}-text" style="margin-left: 0.4em;font-size: 12px;">{{.Status}}</span></span>
<div class="two wide column text center nowrap"
style="padding-left: 2.2rem !important; width: 11% !important;">
<span class="job-status" id="{{$JobID}}" data-jobid="{{$JobID}}"
data-version="{{.VersionName}}">
<span><i id="{{$JobID}}-icon" style="vertical-align: middle;"
class="{{.Status}}"></i><span id="{{$JobID}}-text"
style="margin-left: 0.4em;font-size: 12px;">{{.Status}}</span></span>
</span>
</div>
<!-- 任务类型 -->
{{$JobType := $.i18n.Tr (printf "cloudbrain.%s" .JobType)}}
<div class="one wide column text center nowrap" style="width:10%">
<span style="font-size: 12px;" title="{{$JobType}}">{{$JobType}}</span>
<span style="font-size: 12px;" title="{{.JobType}}">{{$JobType}}</span>
</div>
<!-- 任务创建时间 -->
<div class="two wide column text center nowrap" style="width: 11% !important;">
<span style="font-size: 12px;" class="">{{TimeSinceUnix1 .Cloudbrain.CreatedUnix}}</span>
<span style="font-size: 12px;"
class="">{{TimeSinceUnix1 .Cloudbrain.CreatedUnix}}</span>
</div>
<!-- 任务运行时间 -->
<div class="one wide column text center nowrap" style="width:8.5% !important;">
<span style="font-size: 12px;" id="duration-{{$JobID}}">{{if .TrainJobDuration}}{{.TrainJobDuration}}{{else}}--{{end}}</span>
<span style="font-size: 12px;"
id="duration-{{$JobID}}">{{if .TrainJobDuration}}{{.TrainJobDuration}}{{else}}--{{end}}</span>
</div>
<!-- 计算资源 -->
<div class="one wide column text center nowrap" style="width:8.5% !important;">
<span style="font-size: 12px;">{{if .ComputeResource}}{{.ComputeResource}}{{else}}--{{end}}</span>
<span
style="font-size: 12px;">{{if .ComputeResource}}{{.ComputeResource}}{{else}}--{{end}}</span>
</div>
<!-- 创建者 -->
<!-- 项目 -->
<div class="two wide column text center nowrap" style="width: 14.5%!important;">
<a href="" title="">--</a>
@@ -221,11 +292,12 @@
<form id="debugAgainForm-{{$JobID}}">
{{$.CsrfTokenHtml}}
{{if eq .Status "RUNNING" "WAITING" "CREATING" "STARTING"}}
<a style="margin: 0 1rem;" id="ai-debug-{{$JobID}}" class='ui basic disabled button' >
<a style="margin: 0 1rem;" id="ai-debug-{{$JobID}}"
class='ui basic disabled button'>
{{$.i18n.Tr "repo.debug"}}
</a>
{{else}}
<a id="ai-debug-{{$JobID}}" class='ui basic disabled button' >
<a id="ai-debug-{{$JobID}}" class='ui basic disabled button'>
{{$.i18n.Tr "repo.debug_again"}}
</a>
{{end}}
@@ -234,14 +306,17 @@
{{end}}
<!-- 停止任务 -->
<div class="ui compact buttons">
<a style="padding: 0.5rem 1rem;" id="ai-stop-{{$JobID}}" class="ui basic disabled button" data-jobid="{{$JobID}}" data-version="{{.VersionName}}" >
<a style="padding: 0.5rem 1rem;" id="ai-stop-{{$JobID}}"
class="ui basic disabled button" data-jobid="{{$JobID}}"
data-version="{{.VersionName}}">
{{$.i18n.Tr "repo.stop"}}
</a>
</div>
<!-- 删除任务 -->
<form class="ui compact buttons" id="delForm-{{$JobID}}" action='' method="post">
{{$.CsrfTokenHtml}}
<a style="padding: 0.5rem 1rem;margin-left:0.2rem" id="ai-delete-{{$JobID}}" class="ui basic disabled button" style="border-radius: .28571429rem;">
<a style="padding: 0.5rem 1rem;margin-left:0.2rem" id="ai-delete-{{$JobID}}"
class="ui basic disabled button" style="border-radius: .28571429rem;">
{{$.i18n.Tr "repo.delete"}}
</a>
</form>
@@ -253,14 +328,9 @@
{{end}}
<div id="app" style="margin-top: 2rem;">
<div class="center">
<el-pagination
background
@current-change="handleCurrentChange"
:current-page="page"
:page-sizes="[10]"
:page-size="10"
layout="total, sizes, prev, pager, next, jumper"
:total="{{.Page.Paginater.Total}}">
<el-pagination background @current-change="handleCurrentChange" :current-page="page"
:page-sizes="[10]" :page-size="10" layout="total, sizes, prev, pager, next, jumper"
:total="{{.Page.Paginater.Total}}">
</el-pagination>
</div>
</div>
@@ -291,38 +361,4 @@
</div>
</div>
</div>
{{template "base/footer" .}}
<script>
function getParams(){
const params = new URLSearchParams(window.location.search)
params.get('jobType')
let jobType
if(!params.get('jobType')){
jobType = '{{.i18n.Tr "admin.cloudbrain.all_task_types"}}'
}else{
if(params.get('jobType') === 'DEBUG'){
jobType = '{{$.i18n.Tr (printf "cloudbrain.DEBUG")}}'
}else if(params.get('jobType') === 'TRAIN'){
jobType = '{{$.i18n.Tr (printf "cloudbrain.TRAIN")}}'
}
else if(params.get('jobType') === 'INFERENCE'){
jobType = '{{$.i18n.Tr (printf "cloudbrain.INFERENCE")}}'
}
else if(params.get('jobType') === 'SNN4IMAGENET'){
jobType = '{{$.i18n.Tr (printf "cloudbrain.SNN4IMAGENET")}}'
}else if(params.get('jobType') === 'BENCHMARK'){
jobType = '{{$.i18n.Tr (printf "cloudbrain.BENCHMARK")}}'
}
else{
jobType = '{{$.i18n.Tr (printf "cloudbrain.BRAINSCORE")}}'
}
}
let listType = !params.get('listType')? '{{.i18n.Tr "admin.cloudbrain.all_computing_resources"}}' : params.get('listType')
let jobStatus = !params.get('jobStatus')? '{{.i18n.Tr "admin.cloudbrain.all_status"}}' : params.get('jobStatus').toUpperCase()
const dropdownValueArray = [jobType,listType,jobStatus]
$('#adminCloud .default.text ').each(function(index,e){
$(e).text(dropdownValueArray[index])
})
}
getParams()
</script>
{{template "base/footer" .}}

+ 76
- 105
web_src/js/components/DataAnalysis.vue View File

@@ -1,108 +1,61 @@
<template>
<div style="height:100%">
<el-tabs tab-position="left" v-model="activeName" style="height:100%" @tab-click="handleClick" >
<el-tab-pane label="概览" name="first" >
<span slot="label">
<el-image style="width: 13px; height: 13px" src="/img/overview_rgb.svg">
</el-image>
概览
</span>
<div >暂无内容.......</div>
<el-row style="height:100%;width: 100%; flex:1" >
<el-col :span="3" style="height:100%;padding-right:15px;">
<el-menu
:default-active="this.$router.path"
class="el-menu-vertical-demo"
:router="true" style="height:100%; background-color: #F5F5F6;" >
<el-menu-item index="/Overview" >
<i class="ri-home-4-line"></i>
<span slot="title">概览</span>
</el-menu-item>
<el-submenu index="/">
<template slot="title">
<i class="ri-numbers-line"></i>
<span>项目分析</span>
</template>
<el-menu-item index="/ProTrend">增长趋势分析</el-menu-item>
<el-menu-item index="/ProAnalysis">详细数据</el-menu-item>
</el-submenu>
<el-submenu index="2">
<template slot="title">
<i class="ri-contacts-line"></i>
<span>用户分析</span>
</template>
<el-menu-item index="/UserTrend">增长趋势分析</el-menu-item>
<el-menu-item index="/UserAnalysis">活动分析</el-menu-item>
</el-submenu>
<el-menu-item index="/BrainAnalysis">
<i class="ri-server-fill"></i>
<span slot="title">云脑分析(建设中..)</span>
</el-menu-item>
</el-menu>
</el-col>
<router-view> </router-view>
</el-row>
</template>

</el-tab-pane>
<el-tab-pane label="项目分析" name="second" id="second" >
<ProAnalysis ref='ProAnalysis'id="pro" v-if="isRouterAlive"></ProAnalysis>
<span slot="label">
<el-image style="width: 13px; height: 13px" src="/img/pro_rgb.svg">
</el-image>
项目分析
</span>
</el-tab-pane>
<el-tab-pane name="third" id='third' >
<span slot='label'>
<el-image style="width: 13px; height: 13px" src="/img/user_rgb.svg">
</el-image>
用户分析
</span>
<UserAnalysis ref='UserAnalysis' v-if="isRouterAlive1" id ="usr"></UserAnalysis>
</el-tab-pane>
<el-tab-pane name="four" id='four' >
<BrainAnalysis ref='BrainAnalysis'id="brain" v-if="isRouterAlive"></BrainAnalysis>
<span slot="label">
<el-image style="width: 13px; height: 13px" src="/img/pro_rgb.svg">
</el-image>
云脑分析(建设中..)
</span>
</el-tab-pane>
</el-tabs>
</div>
</template>

<script>
import ProAnalysis from './ProAnalysis.vue'
import UserAnalysis from './UserAnalysis.vue'
import BrainAnalysis from './BrainAnalysis.vue'

export default {

components:{
'ProAnalysis':ProAnalysis,
'UserAnalysis':UserAnalysis,
'BrainAnalysis':BrainAnalysis,
},
data() {
return {
activeName:"second",
loading:true,
loading1:true,
isRouterAlive: true,
isRouterAlive1: true,
isSecond:true,
isThird:false,
}
},
methods:{
handleClick(tab, event){
if(tab.name=="second"){
this.reload()

this.isSecond = true
this.isThird = false
this.$refs.ProAnalysis.getAllProList("all",7)
}
if(tab.name=="third"){

this.reload1()
this.isSecond = false
this.isThird = true

this.$refs.UserAnalysis.getUpdateTime()
this.$refs.UserAnalysis.getUserList("all_usr",7)

}

},
reload () {
this.isRouterAlive = false
this.$nextTick(() => (this.isRouterAlive = true))
},
reload1 () {
this.isRouterAlive1 = false
this.$nextTick(() => (this.isRouterAlive1 = true))
}

},
}
</script>
<style scoped>
<script>
export default{
data(){
return {
Path_router:'/'
}
},
created(){
var url_params = document.getElementById("url_params").value;
if (url_params!='' && url_params!=undefined && url_params!='/'){
this.$router.path = '/'+url_params.split('/')[0]
}else{
this.$router.path = '/ProAnalysis'
}
},
}
</script>
<style scoped>
/deep/ .is-active{
color: #238BFC ;
background-color: #FFFF ;
color: #238BFC ;
}
/deep/ .ui-container{
background-color: #FFFF;
@@ -137,8 +90,26 @@
/deep/ .el-tabs__item:hover .el-image{
filter:none
}
/deep/ .el-image{
filter:grayscale(100%)

.bk{
background-color: #F5F5F6;
}
.el-menu-item.is-active {
color: #409eff;
background-color: #FFFFFF !important;
}
/deep/ .el-submenu.is-active .el-submenu__title {
color: #409eff
}
/deep/ .el-submenu.is-active .el-submenu__title i{
color: #409eff
}
/deep/ .el-menu, .el-menu--horizontal>.el-menu-item:not(.is-disabled):focus, .el-menu--horizontal>.el-menu-item:not(.is-disabled):hover, .el-menu--horizontal>.el-submenu .el-submenu__title:hover {
background-color: #F5F5F6;
}
/deep/ .el-pagination {
padding-bottom: 30px;
}

</style>
</style>

+ 5
- 0
web_src/js/components/Overview.vue View File

@@ -0,0 +1,5 @@
<template>
<div>
暂无内容
</div>
</template>

+ 55
- 12
web_src/js/components/ProAnalysis.vue View File

@@ -1,8 +1,8 @@
<template>
<div style="width: 100%;">
<div class="el-col el-col-21" style="padding-right:10px " >
<div id = "pro_main">
<div style="margin-top: 10px;">
<b class="pro_item">项目分析</b> <span class="update_time">数据更新时间:</span> <span style="font-size: 12px;">{{lastUpdatedTime}}&nbsp/&nbsp从{{recordBeginTime}}开始统计</span>
<b class="pro_item">详细数据</b> <span class="update_time">数据更新时间:</span> <span style="font-size: 12px;">{{lastUpdatedTime}}&nbsp/&nbsp从{{recordBeginTime}}开始统计</span>
</div>
<bar-label :width="'95%'" :height="'500px'"></bar-label>
@@ -29,11 +29,11 @@
</span>
<span style="float:right; margin-right: 20px;">
<div style="display:inline-block;margin-left: 20px; ">
<a class="el-icon-download" v-if="tableData!=''" :href= "'../api/v1/projectboard/downloadAll/?type='+this.params.type+'&beginTime='+this.params.beginTime+'&endTime='+this.params.endTime+'&q='+this.params.q+'&sort=openi'" ></a>
<a class="el-icon-download" v-if="tableData!=''" :href= "'../../api/v1/projectboard/downloadAll/?type='+this.params.type+'&beginTime='+this.params.beginTime+'&endTime='+this.params.endTime+'&q='+this.params.q+'&sort=openi'" ></a>
<i class="el-icon-download" v-else="tableData=''" href="#" style="color:rgba(187, 187, 187, 100);" @click='popMark()'></i>
<!-- <span ><a id = "download_file" :href= "'../api/v1/projectboard/downloadAll/?type='+this.params.type+'&beginTime='+this.params.beginTime+'&endTime='+this.params.endTime+'&q='+this.params.q+'&sort=openi'" >下载报告</a> </span> -->
<span >
<a id = "download_file" v-if="tableData!=''" :href= "'../api/v1/projectboard/downloadAll/?type='+this.params.type+'&beginTime='+this.params.beginTime+'&endTime='+this.params.endTime+'&q='+this.params.q+'&sort=openi'">下载报告</a>
<a id = "download_file" v-if="tableData!=''" :href= "'../../api/v1/projectboard/downloadAll/?type='+this.params.type+'&beginTime='+this.params.beginTime+'&endTime='+this.params.endTime+'&q='+this.params.q+'&sort=openi'">下载报告</a>
<a id = "download_file" v-else="tableData=''" href= "#" style="color:rgba(187, 187, 187, 100);" @click='popMark()'>下载报告</a>
</span>
</div>
@@ -59,6 +59,7 @@
>
</el-table-column>
<el-table-column
fixed
label="项目名称中文"
align="left"
prop="name"
@@ -404,8 +405,7 @@
value_time: '',
search:'',
dynamic:7,
download_a:"",
downLoadSrc:'',


//单个项目参数
@@ -652,7 +652,7 @@
getAllProList(type_val,index){
console.log("类型:"+type_val)
// console.log("类型:"+type_val)
this.dynamic = index
if (typeof type_val=="undefined" || type_val=="null" || type_val==""){
this.params.type=''
@@ -665,7 +665,7 @@
this.value_time=[]
}
this.$axios.get('../api/v1/projectboard/project',{
this.$axios.get('../../api/v1/projectboard/project',{
params:this.params
}).then((res)=>{
@@ -720,7 +720,7 @@
},
getOneProData(pro_id){
this.$axios.get('../api/v1/projectboard/project/'+pro_id,{
this.$axios.get('../../api/v1/projectboard/project/'+pro_id,{
}).then((res)=>{
this.tableDataIDTotal = res.data
this.tableDataContTop10=res.data.top10
@@ -731,7 +731,7 @@
},
getOneProList(pro_id,type_val,bool_val,index){
this.dynamic_pro=index
console.log("日期类型:"+type_val)
// console.log("日期类型:"+type_val)
if (typeof type_val=="undefined" || type_val=="null" || type_val==""){
this.paramsID.type=''
this.paramsID.beginTime= this.formatDate(this.create_time_pro[0].getFullYear(),this.create_time_pro[0].getMonth() + 1,this.create_time_pro[0].getDate())
@@ -743,7 +743,7 @@
this.paramsID.endTime=''
}
this.paramsID.openi=bool_val
this.$axios.get('../api/v1/projectboard/project/'+pro_id+"/period",{
this.$axios.get('../../api/v1/projectboard/project/'+pro_id+"/period",{
params:this.paramsID
}).then((res)=>{
if (bool_val){
@@ -923,12 +923,24 @@
type : 'category',
boundaryGap: false,
data : xdata_openI,
axisLine: {
show: false, //x轴线消失
},
axisTick:{
show:false//刻度隐藏
}
}
],
yAxis : [
{
type : 'value',
axisLine: {
show: false, //x轴线消失
},
axisTick:{
show:false//刻度隐藏
}
}
],
@@ -1011,6 +1023,12 @@
},
legend: {
data:['浏览量','下载量','commit'],
selected:{
// '浏览量':true,
// '下载量':true,
// 'commit':true,
}

// orient: 'vertical',
// top:'top',  
},
@@ -1029,12 +1047,24 @@
{
type : 'category',
data : xdata,
axisLine: {
show: false, //x轴线消失
},
axisTick:{
show:false//刻度隐藏
}
}
],
yAxis : [
{
type : 'value',
type : 'value',
axisLine: {
show: false, //x轴线消失
},
axisTick:{
show:false//刻度隐藏
}
}
],
series : [
@@ -1059,6 +1089,16 @@
]
};
// this.echartsSelectData.resize()
var checkboxs=document.getElementsByName('checkboxchart');
for(var i=0; i<checkboxs.length; i++){
// console.log("selectArr[i]:",this.option.legend.data[i])
if(checkboxs[i].checked){
this.option.legend.selected[this.option.legend.data[i]]=true;
}else{
this.option.legend.selected[this.option.legend.data[i]]=false;
}
}

this.echartsSelectData.setOption(this.option)
// setTimeout(function (){
// window.onresize = function () {
@@ -1299,6 +1339,9 @@
/deep/ .el-range-separator{
width: 20% !important;
}
/deep/ .el-pagination {
padding-bottom: 30px;
}

.colorChange {
background-color: #1684FC;


+ 903
- 0
web_src/js/components/ProTrend.vue View File

@@ -0,0 +1,903 @@
<template>
<div class="el-col el-col-21" style="padding-right:10px ">
<div id='pro_tend' >
<div style="margin-top: 10px;">
<b class="pro_item">增长趋势分析</b> <span class="update_time">数据更新时间:</span> <span style="font-size: 12px;">{{lastUpdatedTime}}&nbsp/&nbsp从{{recordBeginTime}}开始统计</span>
</div>
<div style="margin-top:20px">
<el-row>
<el-col :span='1' class ='item_list_first'>
<el-row class="item_title_h">
&nbsp;
</el-row>
<el-row class="item_h">
昨天
</el-row>
<el-row class="item_h">
累计
</el-row>
</el-col>
<el-col span='23' >
<el-col :span='3' class ='item_list'>
<el-row class="item_title_h">
项目
</el-row>
<el-row class="item_h num_color">
{{tableDataSummary.numReposAdd}}
</el-row>
<el-row class="item_h">
{{ tableDataSummary.numRepos}}
</el-row>
</el-col>
<el-col :span='3' >
<el-row class ='item_list_p item_title_h'>
公开
</el-row>
<el-row class="item_h num_color">
{{tableDataSummary.numRepoPublicAdd}}
</el-row >
<el-row class="item_h">
{{tableDataSummary.numRepoPublic}}
</el-row>
</el-col>
<el-col :span='3' class ='item_list'>
<el-row class="item_title_h">
私有
</el-row>
<el-row class="item_h num_color">
{{tableDataSummary.numRepoPrivateAdd}}
</el-row>
<el-row class="item_h">
{{tableDataSummary.numRepoPrivate}}
</el-row>
</el-col>
<el-col :span='3'>
<el-row class ='item_list_p item_title_h'>
自建
</el-row>
<el-row class="item_h num_color">
{{tableDataSummary.numRepoSelfAdd}}
</el-row >
<el-row class="item_h">
{{tableDataSummary.numRepoSelf}}
</el-row>
</el-col>
<el-col :span='3' >
<el-row class ='item_list_p item_title_h'>
派生
</el-row>
<el-row class="item_h num_color">
{{tableDataSummary.numRepoForkAdd}}
</el-row >
<el-row class="item_h">
{{tableDataSummary.numRepoFork}}
</el-row>
</el-col>
<el-col :span='3' class ='item_list '>
<el-row class="item_title_h">
镜像
</el-row>
<el-row class="item_h num_color">
{{tableDataSummary.numRepoMirrorAdd}}
</el-row>
<el-row class="item_h">
{{tableDataSummary.numRepoMirror}}
</el-row>
</el-col>
<el-col :span='3'>
<el-row class ='item_list_p item_title_h'>
组织
</el-row>
<el-row class="item_h num_color">
{{tableDataSummary.numRepoOrgAdd}}
</el-row>
<el-row class="item_h">
{{tableDataSummary.numRepoOrg}}
</el-row>
</el-col>
<el-col :span='2'>
<el-row class="item_title_h">
个人
</el-row>
<el-row class="item_h num_color">
{{tableDataSummary.numRepoNotOrgAdd}}
</el-row>
<el-row class="item_h">
{{tableDataSummary.numRepoNotOrg}}
</el-row>
</el-col>
</el-col>
</el-row>
</div>
<div style="margin-top: 20px;">
<span class="sta_iterm">统计周期:</span>
<!-- <button type="button" class='btnFirst' id ="yesterday" v-bind:class="{colorChange:1==dynamic}" @click="resetPage(),getPeriodProList('yesterday',1)">昨天</button> -->
<button type="button" class='btn' id = "current_week" v-bind:class="{colorChange:1==dynamic}" @click="resetPage(),getPeriodProList('current_week',1)">本周</button>
<button type="button" class='btn' id = "current_month" v-bind:class="{colorChange:2==dynamic}" @click="resetPage(),getPeriodProList('current_month',2)">本月</button>
<button type="button" class='btn' id = "last_month" v-bind:class="{colorChange:3==dynamic}" @click="resetPage(),getPeriodProList('last_month',3)">上月</button>
<button type="button" class='btn' id = "monthly" v-bind:class="{colorChange:4==dynamic}" @click="resetPage(),getPeriodProList('monthly',4)">近30天</button>
<button type="button" class='btn' id = "current_year" v-bind:class="{colorChange:5==dynamic}" @click="resetPage(),getPeriodProList('current_year',5)">今年</button>
<button type="button" class='btnLast' id = "all" v-bind:class="{colorChange:6==dynamic}" @click="resetPage(),getPeriodProList('all',6)">所有</button>
<span style="margin-left: 20px;">
<el-date-picker
v-model="value_time"
prefix-icon="el-icon-time"
@change="resetPage(),getPeriodProList('',0)"
type="daterange"
size='small'
range-separator="至"
start-placeholder="开始日期"
end-placeholder="结束日期">
</el-date-picker>
</span>
<span style="float:right; margin-right: 20px;">
<div style="display:inline-block;margin-left: 20px; ">
<a class="el-icon-download" v-if="tableData!=''" :href= "'../../api/v1/projectboard/downloadAll/?type='+this.params.type+'&beginTime='+this.params.beginTime+'&endTime='+this.params.endTime+'&q='+this.params.q+'&sort=openi'" ></a>
<i class="el-icon-download" v-else="tableData=''" href="#" style="color:rgba(187, 187, 187, 100);" @click='popMark()'></i>
<!-- <span ><a id = "download_file" :href= "'../api/v1/projectboard/downloadAll/?type='+this.params.type+'&beginTime='+this.params.beginTime+'&endTime='+this.params.endTime+'&q='+this.params.q+'&sort=openi'" >下载报告</a> </span> -->
<span >
<a id = "download_file" v-if="tableData!=''" :href= "'../../api/v1/projectboard/summary/download?type='+this.params.type+'&beginTime='+this.params.beginTime+'&endTime='+this.params.endTime">下载报告</a>
<a id = "download_file" v-else="tableData=''" href= "#" style="color:rgba(187, 187, 187, 100);" @click='popMark()'>下载报告</a>
</span>
</div>
</span>
</div>
<div class="item_echart" id ='linecharts'>
<div style="margin: 15px 10px 30px;">
<label for="label" @change='clickCheckBox'>
<input type="checkbox" class="checkboxchart" name="checkboxchart" checked="checked" value="新增项目"/> 新增项目
<input type="checkbox" class="checkboxchart" name="checkboxchart" checked="checked" value="新增公开项目"/>新增公开项目
<input type="checkbox" class="checkboxchart" name="checkboxchart" checked="checked" value="新增私有项目"/>新增私有项目
<input type="checkbox" class="checkboxchart" name="checkboxchart" value="新增自建项目"/>新增自建项目
<input type="checkbox" class="checkboxchart" name="checkboxchart" value="新增派生项目"/>新增派生项目
<input type="checkbox" class="checkboxchart" name="checkboxchart" value="新增镜像项目"/>新增镜像项目
<input type="checkbox" class="checkboxchart" name="checkboxchart" value="累计项目"/>累计项目
</label>
</div>
<div id ="selectData" style="height: 300px;">

</div>

</div>
<div style="margin-top: 30px;">
<el-table
:data="tableData.slice((page-1)*pageSize,page*pageSize)"
style="width: 100%"
:header-cell-style="tableHeaderStyle"
:cell-style='cellStyle'>
<el-table-column
label="日期"
align="left"
prop="creatTime"
>
</el-table-column>
<el-table-column
label="新增项目"
align="center"
prop="numReposAdd"
>
</el-table-column>
<el-table-column
label="累计项目"
align="center"
prop="numRepos"
>
</el-table-column>
<el-table-column
prop="numRepoPublicAdd"
label="新增公开项目"
align="center">
</el-table-column>
<el-table-column
prop="numRepoPrivateAdd"
label="新增私有项目"
align="center">
</el-table-column>
<el-table-column
prop="numRepoSelfAdd"
label="新增自建项目"
align="center">
</el-table-column>
<el-table-column
prop="numRepoForkAdd"
label="新增派生项目"
align="center">
</el-table-column>
<el-table-column
prop="numRepoMirrorAdd"
label="新增镜像项目"
align="center">
</el-table-column>
</el-table>
</div>
<div style="margin-top:50px;text-align:center">
<el-pagination
background
@size-change="handleSizeChange"
@current-change="handleCurrentChange"
:current-page="page"
:page-size="pageSize"
:page-sizes="[5,10,20]"
layout="total, sizes,prev, pager, next,jumper"
:total="tableData.length">
</el-pagination>
</div>
</div>
</div>
</template>

<script>
// import barLabel from './basic/barLabel.vue';
const {AppSubUrl, StaticUrlPrefix, csrf} = window.config;

import { export2Excel } from '../excel/util.js'
export default{
name:'ProAnalysis',
components: {
// barLabel,
},
data() {
return {
recordBeginTime:'',
lastUpdatedTime:'',
page:1,
pageSize:10,
params:{type:'monthly',page:1,pagesize:10,beginTime:'',endTime:''},
tableData: [],
tableDataSummary:{},
totalPage:0,
totalNum:0,
pickerOptions: {
},
value_time: '',
dynamic:4,
echartsSelectData:'',
option:'',
};
},
methods: {
// download_file(){
// this.params.type='all'
// },
popMark(){
alert("数据为空时,不能下载!")
},
exportData(){
// this.getOneProList(this.pro_id,'all',true,7)
// this.getOneProList(this.pro_id,'all',false,7)
// this.fileName()
if (this.tableData!=''){
this.page=1
var saveFileName = this.getFileName()
export2Excel(this.columns,this.tableData,saveFileName)
}else{
alert("数据为空时,不能下载!")
}
},
getFileName(){

var now = new Date(); // 当前日期
var nowDayOfWeek = now.getDay(); // 今天本周的第几天
var nowDay = now.getDate(); // 当前日
var nowMonth = now.getMonth(); // 当前月
var nowYear = now.getFullYear(); // 当前年
var today = this.saveFormatDate(nowYear,nowMonth+1,nowDay);
var tmp = new Date(now.setTime(now.getTime()-24*60*60*1000));
var yesterday = this.saveFormatDate(tmp.getFullYear(),tmp.getMonth()+1,tmp.getDate());
var yesterday_tmp = this.formatDate(tmp.getFullYear(),tmp.getMonth()+1,tmp.getDate())

var startDate=''
var endDate=''
var saveFileName = ''
if (typeof this.paramsID.type=="undefined" || this.paramsID.type=="null" || this.paramsID.type==""){
// startDate= this.saveFormatDate(this.create_time_pro[0].getFullYear(),this.create_time_pro[0].getMonth() + 1,this.create_time_pro[0].getDate());
endDate = this.saveFormatDate(this.create_time_pro[1].getFullYear(),this.create_time_pro[1].getMonth() + 1,this.create_time_pro[1].getDate());
var tmp = this.formatDate(this.create_time_pro[0].getFullYear(),this.create_time_pro[0].getMonth() + 1,this.create_time_pro[0].getDate())
startDate = this.comparedate(tmp,this.recordBeginTime)

console.log("comparedate:"+startDate)
saveFileName = this.alias+"_"+startDate+'_'+endDate
}else{
switch(this.paramsID.type){
case "yesterday":{
startDate = this.comparedate(yesterday_tmp,this.recordBeginTime)
endDate = startDate

saveFileName = this.alias+"_"+startDate+'_'+ endDate
break
}
case "current_week":{
var now = new Date(); // 当前日期
var nowDayOfWeek = now.getDay(); // 今天本周的第几天
var day = nowDayOfWeek || 7;
startDate = this.formatDate(now.getFullYear(), nowMonth+1, nowDay + 1 - day);
startDate = this.comparedate(startDate,this.recordBeginTime)

endDate = yesterday
saveFileName = this.alias+"_"+startDate+'_'+ endDate
break
}
case "current_month":{
startDate = this.formatDate(nowYear,nowMonth+1,1);
startDate = this.comparedate(startDate,this.recordBeginTime)

endDate = yesterday
saveFileName = this.alias+"_"+startDate+'_'+ endDate
break
}
case "last_month":{

let lastMonthDate = new Date(); // 上月日期
lastMonthDate.setDate(1);
lastMonthDate.setMonth(lastMonthDate.getMonth()-1);
let lastYear = lastMonthDate.getFullYear();
let lastMonth = lastMonthDate.getMonth();

startDate=this.formatDate(lastYear, lastMonth+1, 1);
startDate = this.comparedate(startDate,this.recordBeginTime)


var monthStartDate = new Date(lastYear, lastMonth, 1);
var monthEndDate = new Date(lastYear, lastMonth+1, 1);
var days = (monthEndDate - monthStartDate) / (1000 * 60 * 60 * 24)

endDate=this.saveFormatDate(lastYear, lastMonth+1, days); //月份从0开始,所以+1保存月份
saveFileName = this.alias+"_"+startDate+'_'+ endDate
break
}
case "monthly":{
var temp=new Date(now - 1000 * 60 * 60 * 24 * 30)
startDate = this.formatDate(temp.getFullYear(),temp.getMonth()+1,temp.getDate());
startDate = this.comparedate(startDate,this.recordBeginTime)

endDate = yesterday
saveFileName = this.alias+"_"+startDate+'_'+ endDate
break
}
case "current_year":{
startDate = this.formatDate(now.getFullYear(), 1, 1);
startDate = this.comparedate(startDate,this.recordBeginTime)

endDate = yesterday
saveFileName = this.alias+"_"+startDate+'_'+ endDate
break
}
case "all":{
console.log("e:"+today)
startDate = 'all'
endDate = yesterday
saveFileName = this.alias+'_所有'
break
}
}
}
return saveFileName

},
resetPage(){
this.page=1
this.params.page = 1
},
resetCurrentPage(){
this.page=1
},
handleSizeChange(val){
this.pageSize = val
},
handleCurrentChange(val){
this.page = val;
},
saveFormatDate(myyear,mymonth,myweekday) {
// var myyear = this.date.getFullYear();
// var mymonth = this.date.getMonth() + 1;
// var myweekday = this.date.getDate();
if (mymonth < 10) {
mymonth = "0" + mymonth;
}
if (myweekday < 10) {
myweekday = "0" + myweekday;
}
console.log((myyear +''+ mymonth +''+ myweekday))
return (myyear +''+ mymonth +''+ myweekday);
},
formatDate(myyear,mymonth,myweekday) {
// var myyear = this.date.getFullYear();
// var mymonth = this.date.getMonth() + 1;
// var myweekday = this.date.getDate();
if (mymonth < 10) {
mymonth = "0" + mymonth;
}
if (myweekday < 10) {
myweekday = "0" + myweekday;
}
return (myyear +'-'+ mymonth +'-'+ myweekday);
},
//获得某月的天数
getPeriodProList(type_val,index){
// console.log("类型:"+type_val)
this.dynamic = index
if (typeof type_val=="undefined" || type_val=="null" || type_val==""){
this.params.type=''
this.params.beginTime=this.formatDate(this.value_time[0].getFullYear(),this.value_time[0].getMonth() + 1,this.value_time[0].getDate())
this.params.endTime=this.formatDate(this.value_time[1].getFullYear(),this.value_time[1].getMonth() + 1,this.value_time[1].getDate())
}else{
this.params.type=type_val
this.params.beginTime=''
this.params.endTime=''
this.value_time=[]
}
// console.log("params:",this.params)
this.$axios.get('../../api/v1/projectboard/summary/period',{
params:this.params
}).then((res)=>{
this.recordBeginTime=res.data.recordBeginTime
// this.lastUpdatedTime=res.data.creatTime
this.tableData = res.data.pageRecords
this.totalPage=res.data.totalPage
// this.totalNum = res.data.totalCount//this.totalPage*this.params.pagesize
// console.log("res.data:"+res.data)
this.drawSelectData()

})
},
getSummaryPro(){
this.$axios.get('../../api/v1/projectboard/summary',{
}).then((res)=>{
this.tableDataSummary = res.data
this.lastUpdatedTime = res.data.creatTime
})
},
tableHeaderStyle({row,column,rowIndex,columnIndex}){
if(rowIndex===0){
return 'background:#f5f5f6;color:#606266'
}
},
cellStyle({row,column,rowIndex,columnIndex}){
if(rowIndex%2 === 1){
return 'background:#f5f5f6;color:#606266'
}
},
drawSelectData(){
// $("#selectData").removeAttr("selectData").empty();
var xdata=[]
var ydata_add_pro=[]
var ydata_add_public_pro=[]
var ydata_add_private_pro=[]
var ydata_add_self=[]
var ydata_add_fork=[]
var ydata_add_mirror=[]
var ydata_cumulative_pro=[]
// if ()
for(var i =0;i<this.tableData.length;i++){
xdata.push(this.tableData[this.tableData.length-1-i].creatTime);
ydata_add_pro.push(this.tableData[this.tableData.length-1-i].numReposAdd)
ydata_add_public_pro.push(this.tableData[this.tableData.length-1-i].numRepoPublicAdd)
ydata_add_private_pro.push(this.tableData[this.tableData.length-1-i].numRepoPrivateAdd)
ydata_add_self.push(this.tableData[this.tableData.length-1-i].numRepoSelfAdd)
ydata_add_fork.push(this.tableData[this.tableData.length-1-i].numRepoForkAdd)
ydata_add_mirror.push(this.tableData[this.tableData.length-1-i].numRepoMirrorAdd)
ydata_cumulative_pro.push(this.tableData[this.tableData.length-1-i].numRepos)
}
// console.log("ydata_openI:"+ydata_add_pro)
// console.log(xdata)
this.option = {
title : {
text: '',


textStyle: {
                fontSize: 12,
            },
left:'center',
top:'bottom',

subtext: '',

},
tooltip : {
trigger: 'axis',
backgroundColor:'rgba(255,255,255,0.8)',
color:'black',
borderWidth:'1',
borderColor:'gray',
textStyle:{
color:'black'
},
},
legend: {
data:['新增项目','新增公开项目','新增私有项目','新增自建项目','新增派生项目','新增镜像项目','累计项目'],
selected:{
// '新增项目':true,
// '新增公开项目':true,
// '新增私有项目':true,
//                                 '新增自建项目':false,
//                                 '新增派生项目':false,
//                                 '新增镜像项目':false,
//                                 '累计项目':false
                            }
// orient: 'vertical',
// top:'top',  
},
toolbox: {
show : false,
feature : {
mark : {show: true},
dataView : {show: false, readOnly: false},
magicType : {show: true, type: ['line', 'bar']},
restore : {show: false},
saveAsImage : {show: true}
}
},
calculable : true,
xAxis : [
{
type : 'category',
data : xdata,
axisLine: {
show: false, //x轴线消失
},
axisTick:{
show:false//刻度隐藏
}
}
],
yAxis : [
{
type : 'value',
axisLine: {
show: false, //y轴线消失
},
axisTick:{
show:false//刻度隐藏
}
}
],
series : [
{ name:"新增项目",
data: ydata_add_pro,
type: 'line',
areaStyle: {},
itemStyle:{
normal:{
lineStyle:{
color:"#3894FF",
},
color:"#3894FF",
}
},
},
{
name:"新增公开项目",
data: ydata_add_public_pro,
type: 'line',
areaStyle: {},
itemStyle:{
normal:{
lineStyle:{
color:"#67B3BB",
},
color:"#67B3BB",
}
},
},
{
name:"新增私有项目",
data: ydata_add_private_pro,
type: 'line',
areaStyle: {},
itemStyle:{
normal:{
lineStyle:{
color:"#58A55C",
},
color:"#58A55C",
}
},
},
{
name:"新增自建项目",
data: ydata_add_self,
type: 'line',
areaStyle: {},
itemStyle:{
normal:{
lineStyle:{
color:"#F2BD42",
},
color:"#F2BD42",
}
},
},
{
name:"新增派生项目",
data: ydata_add_fork,
type: 'line',
areaStyle: {},
itemStyle:{
normal:{
lineStyle:{
color:"#DAA67B",
},
color:"#DAA67B",
}
},
},
{
name:"新增镜像项目",
data: ydata_add_mirror,
type: 'line',
areaStyle: {},
itemStyle:{
normal:{
lineStyle:{
color:"#2E4552",
},
color:"#2E4552",
}
},
},
{
name:"累计项目",
data: ydata_cumulative_pro,
type: 'line',
areaStyle: {},
itemStyle:{
normal:{
lineStyle:{
color:"#4786B4",
},
color:"#4786B4",
}
},
},

]
};
// this.echartsSelectData.resize()
var checkboxs=document.getElementsByName('checkboxchart');
for(var i=0; i<checkboxs.length; i++){
// console.log("selectArr[i]:",this.option.legend.data[i])
if(checkboxs[i].checked){
this.option.legend.selected[this.option.legend.data[i]]=true;
}else{
this.option.legend.selected[this.option.legend.data[i]]=false;
}
}
this.echartsSelectData.setOption(this.option)
// setTimeout(function (){
// window.onresize = function () {
// this.echartsSelectData.resize;
// }
// },200)

// // 使用刚指定的选择项数据显示图表。
// var selectArr = this.echartsSelectData.getOption().legend[0].data;//legend所有值
// var checkboxs=document.getElementsByName('checkboxchart');
// $(".checkboxchart").click(function(){
// var obj = {};
// for(var i=0; i<checkboxs.length; i++){
// if(checkboxs[i].checked){
// obj[selectArr[i]] = true;
// }else{
// obj[selectArr[i]] = false;
// }
// }
// option.legend.selected = obj;
// this.echartsSelectData.setOption(option);
// });


},
clickCheckBox(){
// 使用刚指定的选择项数据显示图表。
var selectArr = this.echartsSelectData.getOption().legend[0].data;//legend所有值
var checkboxs=document.getElementsByName('checkboxchart');
// $(".checkboxchart").click(function(){
var obj = {};
for(var i=0; i<checkboxs.length; i++){
if(checkboxs[i].checked){
obj[selectArr[i]] = true;
}else{
obj[selectArr[i]] = false;
}
}
this.option.legend.selected = obj;
this.echartsSelectData.setOption(this.option);
// });

},
comparedate(date1,date2){
// console.log("date1:"+date1)
// console.log("date1:"+date2)
var oDate1 = new Date(date1);
var oDate2 = new Date(date2);
if(oDate1.getTime() < oDate2.getTime()){
var data = date2.split('-')
return data[0]+''+data[1]+''+data[2]
} else {
var data = date1.split('-')
return data[0]+''+data[1]+''+data[2]
}
},

},
filters:{
},


mounted() {

this.getPeriodProList("monthly",4);
this.getSummaryPro();
document.getElementById('selectData').style.width = document.getElementById('pro_tend').offsetWidth*0.8+'px'
this.echartsSelectData = this.$echarts.init(document.getElementById('selectData'))
},

watch:{
},

created() {
this.getSummaryPro();
this.getPeriodProList("monthly",4);
},
updated(){
if(document.querySelectorAll('img[avatar]').length!==0){
window.LetterAvatar.transform()
}
}
}
</script>

<style scoped>
.item_list_first{
border-right: 1px solid rgba(219,219,219,100);
padding-right: 10px;
}

.item_list{
border-right: 1px solid rgba(219,219,219,100);
padding:0px 10px;
}
.item_list_p{
border-right: 1px solid rgba(219,219,219,100);
padding:0px 10px;
}
.item_h{
line-height: 40px;
text-align: center;
}
.item_title_h{
line-height: 28px;
text-align: center;
}
.num_color{
color: #0366D6;
font-weight: bold;
}

.pro_item{
font-size: 16px;
color: rgba(16, 16, 16, 100);
font-family: SourceHanSansSC-bold;
}
.sta_item{
font-size: 14px;
color: rgb(0 0 0);
font-family: SourceHanSansSC-bold;
}
.update_time{
line-height: 17px;
font-size: 12px;
color:rgba(187, 187, 187, 100);
margin-left: 10px;
}
.btnFirst{
line-height: 1.5;
margin: -3.5px;
border: 1px solid rgba(22, 132, 252, 100);
border-right: none;
background: #FFFF;
color: #1684FC;
width: 60px;
height: 30px;
border-radius:4px 0px 0px 4px;
}
.btn{
line-height: 1.5;
margin: -3.5px;
border: 1px solid rgba(22, 132, 252, 100);
border-right: none;
background: #FFFF;
color: #1684FC;
width: 60px;
height: 30px;
}
.btnLast{
line-height: 1.5;
margin: -3.5px;
border: 1px solid rgba(22, 132, 252, 100);
/* border-right: none; */
background: #FFFF;
color: #1684FC;
width: 60px;
height: 30px;
border-radius:0px 4px 4px 0px;
}
.btnFirst, .btn, .btnLast {
cursor: pointer;
}

/deep/ .el-table tbody tr:hover>td {
background-color:#D3D3D3!important;
opacity:1
}
/deep/ .el-table {
font-size: 12px;
}
/deep/ .el-range-separator{
width: 20% !important;
}
/deep/ .el-pagination {
padding-bottom: 30px;
}
.colorChange {
background-color: #1684FC;
color: #FFFF;
cursor: default;
}
.items{
text-align: center;
border-right:1px solid rgba(219, 219, 219, 100);
}
.item_l{
margin-right: 5px;
border:1px solid rgba(219, 219, 219, 100);
height: 370px;
width: 100%;
}
.item_r{
margin-right:5px;
border:1px solid rgba(219, 219, 219, 100);
height: 370px;
overflow:auto
}
.item_echart{
margin-top: 10px;
margin-right: 5px;
border:1px solid rgba(219, 219, 219, 100);
height: 350px;
width: 100%;
}
.item_content{
color:#0366D6;
margin-top: 10px;
font-weight:bold;
}
</style>

+ 17
- 14
web_src/js/components/UserAnalysis.vue View File

@@ -1,7 +1,7 @@
<template>
<div>
<div class="el-col el-col-21" style="padding-right:10px">
<div style="margin-top: 10px;">
<b class="pro_item">用户分析</b> <span class="update_time">数据更新时间:</span><span style="font-size: 12px;">{{lastUpdatedTime}} &nbsp/&nbsp从{{recordBeginTime}}开始统计</span>
<b class="pro_item">活动分析</b> <span class="update_time">数据更新时间:</span><span style="font-size: 12px;">{{lastUpdatedTime}} &nbsp/&nbsp从{{recordBeginTime}}开始统计</span>
</div>
<div style="margin-top: 20px;">
<span class="sta_iterm">统计周期:</span>
@@ -54,12 +54,13 @@
>
</el-table-column>
<el-table-column
fixed
label="用户名"
align="left"
prop="Name"
width="100px">
<template slot-scope="scope">
<a :href="AppSubUrl +'../../../'+ scope.row.Name">{{scope.row.Name}} </a>
<a :href="AppSubUrl +'../../../../'+ scope.row.Name">{{scope.row.Name}} </a>
</template>
</el-table-column>
<el-table-column
@@ -259,7 +260,7 @@
params:{startDate:'',endDate:'',page:1,pageSize:10,userName:''},
tableData: [],
totalNum:0,
dataUrl:'../api/v1/query_user_static_page',
dataUrl:'../../api/v1/query_user_static_page',
pickerOptions: {
},
value_time: '',
@@ -334,7 +335,7 @@
return days;
},
getUpdateTime(){
this.$axios.get('../api/v1/projectboard/project',{
this.$axios.get('../../api/v1/projectboard/project',{
params:this.params_pro
}).then((res)=>{
this.recordBeginTime=res.data.recordBeginTime
@@ -357,7 +358,7 @@
let lastYear = lastMonthDate.getYear();
let lastMonth = lastMonthDate.getMonth();

this.dataUrl = '../api/v1/query_user_static_page';
this.dataUrl = '../../api/v1/query_user_static_page';

if (typeof type_val=="undefined" || type_val=="null" || type_val==""){
this.params.startDate= this.formatDate(this.value_time[0].getFullYear(),this.value_time[0].getMonth() + 1,this.value_time[0].getDate());
@@ -366,37 +367,37 @@
switch(type_val){
case "yesterday_usr":{
this.value_time=[]
this.dataUrl = '../api/v1/query_user_yesterday';
this.dataUrl = '../../api/v1/query_user_yesterday';
break
}
case "current_week_usr":{
this.value_time=[]
this.dataUrl = '../api/v1/query_user_current_week';
this.dataUrl = '../../api/v1/query_user_current_week';
break
}
case "current_month_usr":{
this.value_time=[]
this.dataUrl = '../api/v1/query_user_current_month';
this.dataUrl = '../../api/v1/query_user_current_month';
break
}
case "last_month_usr":{
this.value_time=[]
this.dataUrl = '../api/v1/query_user_last_month';
this.dataUrl = '../../api/v1/query_user_last_month';
break
}
case "monthly_usr":{
this.value_time=[]
this.dataUrl = '../api/v1/query_user_last30_day';
this.dataUrl = '../../api/v1/query_user_last30_day';
break
}
case "current_year_usr":{
this.value_time=[]
this.dataUrl = '../api/v1/query_user_current_year';
this.dataUrl = '../../api/v1/query_user_current_year';
break
}
case "all_usr":{
this.value_time=[]
this.dataUrl = '../api/v1/query_user_all';
this.dataUrl = '../../api/v1/query_user_all';
break
}
}
@@ -561,7 +562,9 @@
/deep/ .el-range-separator{
width: 20% !important;
}

/deep/ .el-pagination {
padding-bottom: 30px;
}
.colorChange {
background-color: #1684FC;
color: #FFFF;


+ 949
- 0
web_src/js/components/UserTrend.vue View File

@@ -0,0 +1,949 @@
<template>
<div class="el-col el-col-21" style="padding-right:10px">
<div id='user_tend'>
<div style="margin-top: 10px;">
<b class="pro_item">增长趋势分析</b> <span class="update_time">数据更新时间:</span><span style="font-size: 12px;">{{lastUpdatedTime}} &nbsp/&nbsp从{{recordBeginTime}}开始统计</span>
</div>
<div id = 'isShow'>
<el-col :span="11">
<el-col id="ys_add_user" class="draw_region">

</el-col>
<el-col :span="8" :style="{ height: '180px'}" v-if="ys_count>0">
<span class="yesterday_blk yesterday_title" >昨日新增注册用户数 </span>
<span class="yesterday_blk yesterday_color1 yesterday_pdrt yesterday_text">未激活:<span class="bold_num">{{ tableDataYesterday.NotActivateRegistUser }}</span> 人 </span>
<span class="yesterday_blk yesterday_color2 yesterday_pdrt yesterday_text">已激活: <span class="bold_num">{{ tableDataYesterday.ActivateRegistUser }} </span>人</span>
<span class="yesterday_blk yesterday_pdrt yesterday_text">有贡献活动: <span class="bold_num">{{ tableDataYesterday.HasActivityUser }} </span>人</span>
</el-col>
</el-col>
<el-col :span="13">
<el-col id="ys_all_user" class="draw_region">

</el-col>
<el-col :span="8" :style="{ height: '180px'}" v-if="ys_count>0">
<span class="yesterday_blk yesterday_title" >注册用户数 </span>
<span class="yesterday_blk yesterday_color2 yesterday_pdrt yesterday_text">未激活:<span class="bold_num">{{ tableDataYesterday.TotalNotActivateRegistUser }} </span>人</span>
<span class="yesterday_blk yesterday_color1 yesterday_pdrt yesterday_text">已激活:<span class="bold_num">{{ tableDataYesterday.TotalActivateRegistUser}} </span>人 </span>
<span class="yesterday_blk yesterday_pdrt yesterday_text">有贡献活动:<span class="bold_num"> {{ tableDataYesterday.TotalHasActivityUser}} </span>人</span>
</el-col>
</el-col>
</div>

<div style="margin-top: 20px;">
<span class="sta_iterm">统计周期:</span>
<button type="button" class='btn' id = "current_week_usr" v-bind:class="{colorChange:1==dynamic}" @click="resetPage(),getUserList('current_week_usr',1)">本周</button>
<button type="button" class='btn' id = "current_month_usr" v-bind:class="{colorChange:2==dynamic}" @click="resetPage(),getUserList('current_month_usr',2)">本月</button>
<button type="button" class='btn' id = "last_month_usr" v-bind:class="{colorChange:3==dynamic}" @click="resetPage(),getUserList('last_month_usr',3)">上月</button>
<button type="button" class='btn' id = "monthly_usr" v-bind:class="{colorChange:4==dynamic}" @click="resetPage(),getUserList('monthly_usr',4)">近30天</button>
<button type="button" class='btn' id = "current_year_usr" v-bind:class="{colorChange:5==dynamic}" @click="resetPage(),getUserList('current_year_usr',5)">今年</button>
<button type="button" class='btnLast' id = "all_usr" v-bind:class="{colorChange:6==dynamic}" @click="resetPage(),getUserList('all_usr',6)">所有</button>
<span style="margin-left: 20px;">
<el-date-picker
v-model="value_time"
prefix-icon="el-icon-time"
@change="resetPage(),getUserList('',0)"
type="daterange"
size='small'
unlink-panels
range-separator="至"
start-placeholder="开始日期"
end-placeholder="结束日期">
</el-date-picker>
</span>
<span style="float:right; margin-right: 20px;" >
<a style="display:inline-block;margin-left: 20px; " id = 'download'>
<a class="el-icon-download" v-if="tableData!=''" :href= "this.dataUrl + '?startDate='+this.params.startDate+'&endDate='+this.params.endDate+'&IsReturnFile=true' " ></a>
<i class="el-icon-download" v-else="tableData=''" href="#" style="color:rgba(187, 187, 187, 100);" @click='popMark()'></i>
<span >
<a v-if="tableData!=''" :href= "this.dataUrl + '?startDate='+this.params.startDate+'&endDate='+this.params.endDate+'&IsReturnFile=true' " >下载报告</a>
<a v-else="tableData=''" href= "#" style="color:rgba(187, 187, 187, 100);" @click='popMark()'>下载报告</a>
</span>
</a>
<!-- <span style="display:inline-block;margin-left: 20px; ">
<el-input size="small" placeholder="输入用户名搜索" v-model="search" class="input-with-select" @keyup.enter.native="searchName() "><i slot="suffix" class="el-input__icon el-icon-search" @click="searchName() "></i>
</el-input>
</span> -->
</span>
</div>

<div class="item_echart" id ='linecharts'>
<div style="margin: 15px 10px 30px;">
<label for="label" @change='clickCheckBox'>
<input type="checkbox" class="checkboxchart" name="checkboxchart" checked="checked" value="新增项目"/> 新增注册用户
<input type="checkbox" class="checkboxchart" name="checkboxchart" checked="checked" value="新增公开项目"/>新增已激活
<input type="checkbox" class="checkboxchart" name="checkboxchart" checked="checked" value="新增私有项目"/>新增有贡献活动
<input type="checkbox" class="checkboxchart" name="checkboxchart" value="新增自建项目"/>新增未激活
<input type="checkbox" class="checkboxchart" name="checkboxchart" value="新增派生项目"/>累计注册用户
<input type="checkbox" class="checkboxchart" name="checkboxchart" value="新增镜像项目"/>累计已激活
<input type="checkbox" class="checkboxchart" name="checkboxchart" value="累计项目"/>累计有贡献活动
</label>
</div>
<div id ="selectData" style="height: 300px;">

</div>

</div>

<div style="margin-top: 30px;">
<el-table
:data="tableData.slice((page-1)*pageSize,page*pageSize)"
style="width: 100%"
:header-cell-style="tableHeaderStyle"
:cell-style='cellStyle'>
<el-table-column
label="日期"
prop="DisplayDate"
align="center"
stripe
>
</el-table-column>
<el-table-column
label="新增注册用户"
prop="TotalRegistUser"
align="center">
</el-table-column>
<el-table-column
prop="ActivateRegistUser"
label="新增已激活"
width="120px"
align="center">
</el-table-column>
<el-table-column
prop="HasActivityUser"
label="新增有贡献活动"
align="center">
</el-table-column>
<el-table-column
prop="NotActivateRegistUser"
label="新增未激活"
align="center">
</el-table-column>
<el-table-column
prop="ActivateIndex"
label="新增用户激活率"
align="center">
<template slot-scope="scope">
{{scope.row.ActivateIndex | rounding}}
</template>
</el-table-column>
<el-table-column
prop="TotalUser"
label="累计注册用户"
align="center">
</el-table-column>
<el-table-column
prop="TotalActivateRegistUser"
label="累计已激活"
align="center">
</el-table-column>

<el-table-column
prop="TotalHasActivityUser"
label="累计有贡献活动"
align="center">
</el-table-column>
</el-table>
</div>
<div style="margin-top:50px;text-align:center">
<el-pagination
background
@size-change="handleSizeChange"
@current-change="handleCurrentChange"
:current-page="page"
:page-size="pageSize"
:page-sizes="[5,10,20]"
layout="total, sizes, prev, pager, next,jumper"
:total="tableData.length">
</el-pagination>
</div>
</div>
</div>
</template>

<script>
import { export2Excel } from '../excel/util.js'
export default{
name:'UserAnalysis',
data() {
return {
type_val:'',
recordBeginTime:'',
lastUpdatedTime:'',
page:1,
pageSize:10,
params:{startDate:'',endDate:''},
tableData: [],
totalNum:0,
dataUrl:'../../api/v1/query_user_metrics_page',
dataYesterdayUrl:'../../api/v1/query_metrics_yesterday',
ys_count:0,
tableDataYesterday: {},
option:'',
optionYesterdayUser:'',
optionYesterdaAllUser:'',
echartsSelectData:'',
echartsYsAddUser:'',
echartsYsAllUser:'',
pickerOptions: {
},
value_time: '',
search:'',
data:'',
// columns: [{title: 'ID',key: 'ID'},{title: '用户名',key: 'Name'},{title: 'PR数',key: 'CodeMergeCount'},{title: 'commit数',key:'CommitCount'},{title: '提出任务数',key: 'IssueCount'},{title: '评论数',key: 'CommentCount'},{title: '关注项目数',key: 'FocusRepoCount'},{title: '点赞项目数',key: 'StarRepoCount'},{title: '登录次数',key: 'LoginCount'},{title:'关注者数',key:'WatchedCount'},{title:'commit代码行数',key:'CommitCodeSize'},{title:'已解决任务数',key:'SolveIssueCount'},{title:'百科页面贡献次数',key:'EncyclopediasCount'},{title:'创建项目',key:'CreateRepoCount'},{title:'用户注册时间',key:'RegistDate'},{title:'云脑任务数',key:'CloudBrainTaskNum'},{title:'云脑运行时间(小时)',key:'CloudBrainRunTime'},{title:'上传(提交)数据集文件数',key:'CommitDatasetNum'},{title:'提交模型数',key:'CommitModelCount'},{title:'用户指数',key:'UserIndex'},{title:'系统统计时间',key:'CountDate'}],
blob:'',
fileName:'',
dynamic:4,

params_pro:{type:'all',page:1,pagesize:10,beginTime:'',endTime:'',q:'',sort:'openi'},
};
},
methods: {

popMark(){
alert("数据为空时,不能下载!")
},
// exportData(){
// // this.getUserList('all_usr',7)
// var saveFileName = this.getFileName()
// export2Excel(this.columns,this.tableData,saveFileName)
// },
// getFileName(){
// var saveFileName=''
// var Date=(this.params.startDate).split('-')
// var startDate=Date[0]+''+Date[1]+''+Date[2]
// Date=(this.params.endDate).split('-')
// var endDate=Date[0]+Date[1]+Date[2]
// saveFileName = '用户分析_'+this.search+''+startDate+'_'+endDate
// if (this.type_val=='all_usr'){
// saveFileName = '用户分析_'+this.search+'_all'
// }
// return saveFileName

// },
handleCurrentChange(val){
this.page = val
},
handleSizeChange(val){
this.pageSize = val
},
resetPage(){
this.page=1
},
addUser(val1, val2){
return (val1+val2)

},
formatDate(myyear,mymonth,myweekday) {
// var myyear = this.date.getFullYear();
// var mymonth = this.date.getMonth() + 1;
// var myweekday = this.date.getDate();
if (mymonth < 10) {
mymonth = "0" + mymonth;
}
if (myweekday < 10) {
myweekday = "0" + myweekday;
}
return (myyear + "-" + mymonth + "-" + myweekday);
},

// 获得某月的天数
getMonthDays(nowYear,month){
let monthStartDate = new Date(nowYear, month, 1);
let monthEndDate = new Date(nowYear, month + 1, 1);
let days = (monthEndDate - monthStartDate)/(1000 * 60 * 60 * 24);
return days;
},
getUpdateTime(){
this.$axios.get('../../api/v1/query_metrics_yesterday',{
params:this.params_pro
}).then((res)=>{
this.recordBeginTime=res.data.datarecordbegintime
this.lastUpdatedTime=res.data.lastUpdatedTime
})
},
getUserList(type_val,index){
this.type_val = type_val
this.dynamic = index;
var now = new Date(); // 当前日期
var nowDayOfWeek = now.getDay(); // 今天本周的第几天
var nowDay = now.getDate(); // 当前日
var nowMonth = now.getMonth(); // 当前月
var nowYear = now.getFullYear(); // 当前年
var today = this.formatDate(nowYear,nowMonth+1,nowDay);

let lastMonthDate = new Date(); // 上月日期
lastMonthDate.setDate(1);
lastMonthDate.setMonth(lastMonthDate.getMonth()-1);
let lastYear = lastMonthDate.getYear();
let lastMonth = lastMonthDate.getMonth();

this.dataUrl = '../../api/v1/query_user_metrics_page';

if (typeof type_val=="undefined" || type_val=="null" || type_val==""){
this.params.startDate= this.formatDate(this.value_time[0].getFullYear(),this.value_time[0].getMonth() + 1,this.value_time[0].getDate());
this.params.endDate = this.formatDate(this.value_time[1].getFullYear(),this.value_time[1].getMonth() + 1,this.value_time[1].getDate());
}else{
switch(type_val){
case "yesterday_usr":{
this.value_time=[]
this.dataUrl = '../../api/v1/query_metrics_yesterday';
break
}
case "current_week_usr":{
this.value_time=[]
this.dataUrl = '../../api/v1/query_metrics_current_week';
break
}
case "current_month_usr":{
this.value_time=[]
this.dataUrl = '../../api/v1/query_metrics_current_month';
break
}
case "last_month_usr":{
this.value_time=[]
this.dataUrl = '../../api/v1/query_metrics_last_month';
break
}
case "monthly_usr":{
this.value_time=[]
this.dataUrl = '../../api/v1/query_metrics_last30_day';
break
}
case "current_year_usr":{
this.value_time=[]
this.dataUrl = '../../api/v1/query_metrics_current_year';
break
}
case "all_usr":{
this.value_time=[]
this.dataUrl = '../../api/v1/query_metrics_all';
break
}
}
};

this.$axios.get(this.dataUrl,{
params:this.params
}).then((res)=>{
this.tableData = res.data.data
// console.log("res.data:"+res.data.data)
this.totalNum = res.data.count
this.drawSelectData()
})

},
getYesterdayUser(){
this.$axios.get(this.dataYesterdayUrl,{
}).then((res)=>{
this.ys_count = res.data.count
this.tableDataYesterday = res.data.data[0]
if(this.ys_count>0){
this.drawYesterdayUser()
this.drawSumUser()
}else{
document.getElementById("isShow").style.display='none'
}
})
},
drawYesterdayUser(){
this.optionYesterdayUser = {
tooltip: {
trigger: 'item',
show:false
},
legend: {
top: '5%',
left: 'center',
show:false
},
// graphic:{
// type:'text',
// left:'center',
// top:'center',
// style:{
// text:this.tableDataYesterday.TotalRegistUser,
// fontSize:18,
// fontWeight:'bold',
// color:'#101010'
// }
// },
color:['#5087Ec','#DBDBDB'],
series: [
{
name: '',
type: 'pie',
radius: ['65%', '70%'],
center:['50%','50%'],
avoidLabelOverlap: false,
label: {
normal:{
show: true,
position: 'center',
formatter:''+this.tableDataYesterday.TotalRegistUser,
fontSize:18,
fontWeight:'bold',
color:'#101010'
}
},
emphasis: {
label: {
show: false,
fontSize: '40',
fontWeight: 'bold'
}
},
labelLine: {
normal:{
show:false
}
},
data: [
{ value: this.tableDataYesterday.ActivateRegistUser, name: '已激活' },
{ value: this.tableDataYesterday.NotActivateRegistUser, name: '未激活'},
],
hoverAnimation:false,
}
]
};
this.echartsYsAddUser.setOption(this.optionYesterdayUser)
},
drawSumUser(){
this.optionYesterdaAllUser = {
tooltip: {
trigger: 'item',
show:false
},
legend: {
top: '5%',
left: 'center',
show:false
},
// graphic:{
// type:'text',
// left:'center',
// top:'center',
// style:{
// text:this.tableDataYesterday.TotalRegistUser,
// fontSize:18,
// fontWeight:'bold',
// color:'#101010'
// }
// },
color:['#5087Ec','#DBDBDB'],
series: [
{
name: '',
type: 'pie',
radius: ['65%', '70%'],
center:['50%','50%'],
avoidLabelOverlap: false,
label: {
normal:{
show: true,
position: 'center',
formatter:''+this.tableDataYesterday.TotalUser,
fontSize:18,
fontWeight:'bold',
color:'#101010'
}
},
emphasis: {
label: {
show: false,
fontSize: '40',
fontWeight: 'bold'
}
},
labelLine: {
normal:{
show:false
}
},
data: [
{ value: this.tableDataYesterday.TotalActivateRegistUser, name: '已激活' },
{ value: this.tableDataYesterday.TotalNotActivateRegistUser, name: '未激活'},
],
hoverAnimation:false,
}
]
};
this.echartsYsAllUser.setOption(this.optionYesterdaAllUser)

},
// searchName(){
// this.params.userName = this.search
// this.params.page = 1
// this.page=1
// this.getUserList(this.type_val, this.dynamic)

// },
tableHeaderStyle({row,column,rowIndex,columnIndex}){
if(rowIndex===0){
return 'background:#f5f5f6;color:#606266'
}
},
cellStyle({row,column,rowIndex,columnIndex}){
if(rowIndex%2 === 1){
return 'background:#f5f5f6;color:#606266'
}
},
drawSelectData(){
// $("#selectData").removeAttr("selectData").empty();
var xdata=[]
var ydata_TotalRegistUser=[]
var ydata_ActivateRegistUser=[]
var ydata_NotActivateRegistUser=[]
var ydata_RegistActivityUser=[]
var ydata_TotalUser=[]
var ydata_TotalActivateRegistUser=[]
var ydata_TotalHasActivityUser=[]
// if ()
for(var i =0;i<this.tableData.length;i++){
xdata.push(this.tableData[this.tableData.length-1-i].DisplayDate);
ydata_TotalRegistUser.push(this.tableData[this.tableData.length-1-i].TotalRegistUser)
ydata_ActivateRegistUser.push(this.tableData[this.tableData.length-1-i].ActivateRegistUser)
ydata_RegistActivityUser.push(this.tableData[this.tableData.length-1-i].HasActivityUser)
ydata_NotActivateRegistUser.push(this.tableData[this.tableData.length-1-i].NotActivateRegistUser)
ydata_TotalUser.push(this.tableData[this.tableData.length-1-i].TotalUser)
ydata_TotalActivateRegistUser.push(this.tableData[this.tableData.length-1-i].TotalActivateRegistUser)
ydata_TotalHasActivityUser.push(this.tableData[this.tableData.length-1-i].TotalHasActivityUser)
}

this.option = {
title : {
text: '',


textStyle: {
                fontSize: 12,
            },
left:'center',
top:'bottom',

subtext: '',

},
tooltip : {
trigger: 'axis',
backgroundColor:'rgba(255,255,255,0.8)',
color:'black',
borderWidth:'1',
borderColor:'gray',
textStyle:{
color:'black'
},
},
legend: {
data:['新增注册用户','新增已激活','新增有贡献活动','新增未激活','累计注册用户','累计已激活','累计有贡献活动'],
selected:{
// '新增注册用户':true,
// '新增已激活':true,
// '新增有贡献活动':true,
// '新增未激活':false,
// '累计注册用户':false,
// '累计已激活':false,
// '累计有贡献活动':false
}
// orient: 'vertical',
// top:'top',  
},
toolbox: {
show : false,
feature : {
mark : {show: true},
dataView : {show: false, readOnly: false},
magicType : {show: true, type: ['line', 'bar']},
restore : {show: false},
saveAsImage : {show: true}
}
},
calculable : true,
xAxis : [
{
type : 'category',
data : xdata,
axisLine: {
show: false, //x轴线消失
},
axisTick:{
show:false//刻度隐藏
}
}
],
yAxis : [
{
type : 'value',
axisLine: {
show: false, //y轴线消失
},
axisTick:{
show:false//刻度隐藏
}
}
],
series : [
{ name:"新增注册用户",
data: ydata_TotalRegistUser,
type: 'line',
areaStyle: {},
itemStyle:{
normal:{
lineStyle:{
color:"#3894FF ",
},
color:"#3894FF ",
}
},
},
{
name:"新增已激活",
data: ydata_ActivateRegistUser,
type: 'line',
areaStyle: {},
itemStyle:{
normal:{
lineStyle:{
color:"#67B3BB",
},
color:"#67B3BB",
}
},
},
{
name:"新增有贡献活动",
data: ydata_RegistActivityUser,
type: 'line',
areaStyle: {},
itemStyle:{
normal:{
lineStyle:{
color:"#58A55C",
},
color:"#58A55C",
}
},
},
{
name:"新增未激活",
data: ydata_NotActivateRegistUser,
type: 'line',
areaStyle: {},
itemStyle:{
normal:{
lineStyle:{
color:"#F2BD42",
},
color:"#F2BD42",
}
},
},
{
name:"累计注册用户",
data: ydata_TotalUser,
type: 'line',
areaStyle: {},
itemStyle:{
normal:{
lineStyle:{
color:"#2E4552",
},
color:"#2E4552",
}
},
},
{
name:"累计已激活",
data: ydata_TotalActivateRegistUser,
type: 'line',
areaStyle: {},
itemStyle:{
normal:{
lineStyle:{
color:"#4786B4",
},
color:"#4786B4",
}
},
},
{
name:"累计有贡献活动",
data: ydata_TotalHasActivityUser,
type: 'line',
areaStyle: {},
itemStyle:{
normal:{
lineStyle:{
color:"#4E9C8F",
},
color:"#4E9C8F",
}
},
},

]
};
// this.echartsSelectData.resize()
var checkboxs=document.getElementsByName('checkboxchart');
// $(".checkboxchart").click(function(){
for(var i=0; i<checkboxs.length; i++){
// console.log("selectArr[i]:",this.option.legend.data[i])
if(checkboxs[i].checked){
this.option.legend.selected[this.option.legend.data[i]]=true;
}else{
this.option.legend.selected[this.option.legend.data[i]]=false;
}
}
this.echartsSelectData.setOption(this.option)
// this.clickCheckBox()
// setTimeout(function (){
// window.onresize = function () {
// this.echartsSelectData.resize;
// }
// },200)

// // 使用刚指定的选择项数据显示图表。
// var selectArr = this.echartsSelectData.getOption().legend[0].data;//legend所有值
// var checkboxs=document.getElementsByName('checkboxchart');
// $(".checkboxchart").click(function(){
// var obj = {};
// for(var i=0; i<checkboxs.length; i++){
// if(checkboxs[i].checked){
// obj[selectArr[i]] = true;
// }else{
// obj[selectArr[i]] = false;
// }
// }
// option.legend.selected = obj;
// this.echartsSelectData.setOption(option);
// });


},
clickCheckBox(){
// 使用刚指定的选择项数据显示图表。
var selectArr = this.echartsSelectData.getOption().legend[0].data;//legend所有值
var checkboxs=document.getElementsByName('checkboxchart');
// $(".checkboxchart").click(function(){
var obj = {};
for(var i=0; i<checkboxs.length; i++){
if(checkboxs[i].checked){
obj[selectArr[i]] = true;
}else{
obj[selectArr[i]] = false;
}
}
// console.log("obj:",obj)
this.option.legend.selected = obj;
this.echartsSelectData.setOption(this.option);
// });

},

},
filters:{
rounding (value) {
if(value>=1){
return "100%"
}else if(value==0){
return "-"
}else{
return Number(value*100).toFixed(2) + "%"
}
},
transformTimestamp(timestamp){
let a = new Date(timestamp*1000);
const date = new Date(a);
const Y = date.getFullYear() + '/';
const M = (date.getMonth() + 1 < 10 ? '0' + (date.getMonth() + 1) : date.getMonth() + 1) + '/';
const D = (date.getDate() < 10 ? '0'+date.getDate() : date.getDate()) + ' ';
const h = (date.getHours() < 10 ? '0'+date.getHours() : date.getHours()) + ':';
const m = (date.getMinutes() <10 ? '0'+date.getMinutes() : date.getMinutes());// + ':' ;
// const s = (date.getSeconds() <10 ? '0'+date.getSeconds() : date.getSeconds()) ; // 秒
const dateString = Y + M + D + h + m ;//+ s;
return dateString;
},
addUser(val1,val2){
return val1+val2
}
},
mounted() {
// document.getElementById("all_usr").style.outline="none"
// document.getElementById("all_usr").focus()
this.getUpdateTime()
this.getUserList("monthly_usr",4)
this.getYesterdayUser()

document.getElementById('selectData').style.width = document.getElementById('user_tend').offsetWidth*0.8+'px'
this.echartsSelectData = this.$echarts.init(document.getElementById('selectData'))
this.echartsYsAddUser = this.$echarts.init(document.getElementById('ys_add_user'))
this.echartsYsAllUser = this.$echarts.init(document.getElementById('ys_all_user'))
},
created() {
this.getUserList("monthly_usr",4)
this.getYesterdayUser()
},
watch:{
// search(val){
// if(!val){
// this.params.userName = this.search
// this.params.page = 1
// this.page=1
// this.getUserList(this.type_val, this.dynamic)
// }
// }
},
}
</script>

<style scoped>
.pro_item{
font-size: 16px;
color: rgba(16, 16, 16, 100);
font-family: SourceHanSansSC-bold;
}
.sta_item{
font-size: 14px;
color: rgb(0 0 0);
font-family: SourceHanSansSC-bold;
}
.update_time{
line-height: 17px;
font-size: 12px;
color:rgba(187, 187, 187, 100);
margin-left: 10px;
}
/* .btn{
line-height: 1.5;
margin: -3px;
border: 1px solid #409effd6;
background: #FFFF;
color: #409eff;
width: 60px;
height: 30px;
border-radius:4px ;
} */
.btnFirst{
line-height: 1.5;
margin: -3.5px;
border: 1px solid rgba(22, 132, 252, 100);
border-right: none;
background: #FFFF;
color: #1684FC;
width: 60px;
height: 30px;
border-radius:4px 0px 0px 4px;
}
.btn{
line-height: 1.5;
margin: -3.5px;
border: 1px solid rgba(22, 132, 252, 100);
border-right: none;
background: #FFFF;
color: #1684FC;
width: 60px;
height: 30px;
}
.btnLast{
line-height: 1.5;
margin: -3.5px;
border: 1px solid rgba(22, 132, 252, 100);
/* border-right: none; */
background: #FFFF;
color: #1684FC;
width: 60px;
height: 30px;
border-radius:0px 4px 4px 0px;
}
.btnFirst,.btn,.btnLast {
cursor: pointer;
}


/* .btn:focus,
.btn:active{
background-color:#409effd6 ;
} */
/* /deep/ .el-date-picker {
width: 220px;
} */
/deep/ .el-table {
font-size: 12px;
}
/deep/ .el-table tbody tr:hover>td {
background-color:#D3D3D3!important;
opacity:1
}
/deep/ .el-range-separator{
width: 20% !important;
}
/deep/ .el-pagination {
padding-bottom: 30px;
}
.colorChange {
background-color: #1684FC;
color: #FFFF;
cursor: default;
}
.item_echart{
margin-top: 10px;
margin-right: 5px;
border:1px solid rgba(219, 219, 219, 100);
height: 350px;
width: 100%;
}
.yesterday_blk{
display: block;
margin-top:40px
}
.yesterday_pdrt{
padding-left: 10px;
}
.yesterday_color1{
border-left: 3px solid #DBDBDB;
}
.yesterday_color2{
border-left: 3px solid #5087Ec;
}
.yesterday_title{
font-size: 14px;
font-weight: bold;
}
.yesterday_text{
font-size: 12px;
line-height: 12px;
color: #888888;
margin-top: 10px;
}
.bold_num{
font-weight: bold;
}
.draw_region{
width: 180px;
height: 180px;
}
</style>

+ 14
- 2
web_src/js/components/images/Images.vue View File

@@ -77,9 +77,11 @@
align="center"
>
<template slot-scope="scope">
<a :href="'/' + scope.row.userName" :title="scope.row.userName">
<a v-if="scope.row.userName||scope.row.relAvatarLink" :href="'/' + scope.row.userName" :title="scope.row.userName">
<img :src="scope.row.relAvatarLink" class="ui avatar image">
</a>
<a v-else><img class="ui avatar image" title="Ghost" src="/user/avatar/ghost/-1"></a>
</template>
</el-table-column>
<el-table-column
@@ -368,9 +370,10 @@
align="center"
>
<template slot-scope="scope">
<a :href="'/' + scope.row.userName" :title="scope.row.userName">
<a v-if="scope.row.userName||scope.row.relAvatarLink" :href="'/' + scope.row.userName" :title="scope.row.userName">
<img :src="scope.row.relAvatarLink" class="ui avatar image">
</a>
<a v-else><img class="ui avatar image" title="Ghost" src="/user/avatar/ghost/-1"></a>
</template>
</el-table-column>
<el-table-column
@@ -638,6 +641,15 @@ export default {
cInput.select()
document.execCommand('Copy')
cInput.remove()
$('body')
.toast({
message: '复制成功!',
showProgress: 'bottom',
showIcon:'check circle',
class: 'info',
position: 'top right',
})
;
},
searchName(){
if(this.activeName=='first'){


+ 355
- 363
web_src/js/components/images/adminImages.vue View File

@@ -1,395 +1,387 @@
<template>
<div >
<div class="ui container" style="width: 80%;">
<div class="ui grid">
<div class="row" style="border: 1px solid #d4d4d5;margin-top: 15px;padding-top: 0;">
<div class="ui attached segment">
<div class="ui form ignore-dirty">
<div class="ui fluid action input">
<input type="text" placeholder="搜镜像Tag/描述/标签..." v-model="search" @keyup.enter="searchName()">
<button class="ui blue button" @click="searchName()">搜索</button>
</div>
</div>
</div>
<div>
<div class="ui container" style="width: 80%;">
<div class="ui grid">
<div class="row" style="border: 1px solid #d4d4d5;margin-top: 15px;padding-top: 0;">

<div class="ui ten wide column" style="margin: 1rem 0;">
<el-checkbox v-model="checked" style="padding: 0.5rem 1rem;">仅显示平台推荐</el-checkbox>
<el-dropdown @command="handleCommand" trigger="click" style="border: 1px solid rgba(34,36,38,.15);border-radius: 4px;padding: 0.5rem 1rem;">
<span class="el-dropdown-link">
{{dropdownPrivate}}<i class="el-icon-caret-bottom el-icon--right"></i>
</span>
<el-dropdown-menu slot="dropdown">
<el-dropdown-item :command="{label:'全部',private:''}">全部</el-dropdown-item>
<el-dropdown-item :command="{label:'公开',private:false}">公开</el-dropdown-item>
<el-dropdown-item :command="{label:'私有',private:true}">私有</el-dropdown-item>
</el-dropdown-menu>
</el-dropdown>
</div>
<div class="ui six wide column right aligned" style="margin: 1rem 0;">
<a class="ui blue small button" href="/admin/images/commit_image">创建云脑镜像</a>
</div>
<div class="ui sixteen wide column" style="padding: 0;">
<el-table
:data="tableDataCustom"
style="width: 100%"
:header-cell-style="tableHeaderStyle"
>
<el-table-column
label="镜像Tag"
min-width="19%"
align="left"
prop="tag"
>
<template slot-scope="scope">
<div style="display: flex;align-items: center;">
<a class="text-over image_title" :title="scope.row.tag">{{ scope.row.tag }}</a>
<i class="ri-lock-2-line" style="color: #fa8c16;padding: 0 1rem;" v-if="scope.row.isPrivate"></i>
<img v-if="scope.row.type==5" src="/img/jian.svg" style="margin-left: 0.5rem;">
</div>
</template>
</el-table-column>
<el-table-column
label="镜像描述"
min-width="28%"
align="left"
prop="description"
>
<template slot-scope="scope">
<div class="image_desc" :title="scope.row.description">{{ scope.row.description}}</div>
<div v-if="!!scope.row.topics">
<span v-for="(topic,index) in scope.row.topics" class="ui repo-topic label topic" style="cursor: default;">{{topic}}</span>
<div class="ui attached segment">
<div class="ui form ignore-dirty">
<div class="ui fluid action input">
<input type="text" placeholder="搜镜像Tag/描述/标签..." v-model="search"
@keyup.enter="searchName()">
<button class="ui blue button" @click="searchName()">搜索</button>
</div>
</template>
</el-table-column>
<el-table-column
prop="cloudbrainType"
label="可用集群"
min-width="10%"
align="center"
>
<template slot-scope="scope">
{{scope.row.cloudbrainType | transformType}}
</template>
</el-table-column>
<el-table-column
prop="isPrivate"
label="状态"
min-width="8%"
align="center"
>
<template slot-scope="scope">
<span v-if="scope.row.isPrivate" style="color: rgb(250, 140, 22);">私有</span>
<span v-else style="color: rgb(19, 194, 141);">公开</span>
</template>
</el-table-column>
<el-table-column
prop="creator"
label="创建者"
min-width="7%"
align="center"
>
<template slot-scope="scope">
<a :href="'/' + scope.row.userName" :title="scope.row.userName">
<img :src="scope.row.relAvatarLink" class="ui avatar image">
</a>
</template>
</el-table-column>
<el-table-column
prop="createdUnix"
label="创建时间"
align="center"
min-width="13%"
>
<template slot-scope="scope">
{{scope.row.createdUnix | transformTimestamp}}
</template>
</el-table-column>
<el-table-column
align="center"
min-width="23%"
label="操作"
>
<template slot-scope="scope">
<div style="display: flex;justify-content: flex-end;align-items: center;">
<div style="display: flex;align-items: center;cursor: default;;padding: 0 1rem;">
<svg width="1.4em" height="1.4em" viewBox="0 0 32 32" class="heart-stroke"><path d="M4.4 6.54c-1.761 1.643-2.6 3.793-2.36 6.056.24 2.263 1.507 4.521 3.663 6.534a29110.9 29110.9 0 0010.296 9.633l10.297-9.633c2.157-2.013 3.424-4.273 3.664-6.536.24-2.264-.599-4.412-2.36-6.056-1.73-1.613-3.84-2.29-6.097-1.955-1.689.25-3.454 1.078-5.105 2.394l-.4.319-.398-.319c-1.649-1.316-3.414-2.143-5.105-2.394a7.612 7.612 0 00-1.113-.081c-1.838 0-3.541.694-4.983 2.038z"></path></svg>
<span style="line-height: 2;margin-left:0.3rem;">{{scope.row.numStars}}</span>
</div>
</div>

<div class="ui ten wide column" style="margin: 1rem 0;">
<el-checkbox v-model="checked" style="padding: 0.5rem 1rem;">仅显示平台推荐</el-checkbox>
<el-dropdown @command="handleCommand" trigger="click"
style="border: 1px solid rgba(34,36,38,.15);border-radius: 4px;padding: 0.5rem 1rem;">
<span class="el-dropdown-link">
{{dropdownPrivate}}<i class="el-icon-caret-bottom el-icon--right"></i>
</span>
<el-dropdown-menu slot="dropdown">
<el-dropdown-item :command="{label:'全部',private:''}">全部</el-dropdown-item>
<el-dropdown-item :command="{label:'公开',private:false}">公开</el-dropdown-item>
<el-dropdown-item :command="{label:'私有',private:true}">私有</el-dropdown-item>
</el-dropdown-menu>
</el-dropdown>
</div>
<div class="ui six wide column right aligned" style="margin: 1rem 0;">
<a class="ui blue small button" href="/admin/images/commit_image">创建云脑镜像</a>
</div>
<div class="ui sixteen wide column" style="padding: 0;">
<el-table :data="tableDataCustom" style="width: 100%" :header-cell-style="tableHeaderStyle">
<el-table-column label="镜像Tag" min-width="19%" align="left" prop="tag">
<template slot-scope="scope">
<div style="display: flex;align-items: center;">
<a class="text-over image_title" :title="scope.row.tag">{{ scope.row.tag }}</a>
<i class="ri-lock-2-line" style="color: #fa8c16;padding: 0 1rem;"
v-if="scope.row.isPrivate"></i>
<img v-if="scope.row.type==5" src="/img/jian.svg" style="margin-left: 0.5rem;">
</div>
<span style="padding: 0 1rem;color: rgb(250, 140, 22);cursor:pointer;" v-if="scope.row.type==5" @click="unSetRecommend(scope.$index,scope.row.id)">取消推荐</span>
<span style="padding: 0 1rem;color: rgb(19, 194, 141);cursor:pointer;" v-if="scope.row.type!==5 && !scope.row.isPrivate" @click="setRecommend(scope.$index,scope.row.id)">设为推荐</span>
<span style="padding: 0 1rem;color:#0366d6;cursor:pointer;" @click="copyUrl(scope.row.place)">复制地址</span>
<div style="padding-left:1rem;cursor:pointer;">
<el-dropdown size="medium">
<span class="el-dropdown-link">
更多<i class="el-icon-arrow-down el-icon--right"></i>
</span>
<el-dropdown-menu slot="dropdown">
<el-dropdown-item @click.native="eidtImage(scope.row.id)">编辑</el-dropdown-item>
<el-dropdown-item style="color: red;" @click.native="deleteImage(scope.row.id)">删除</el-dropdown-item>
</el-dropdown-menu>
</el-dropdown>
</template>
</el-table-column>
<el-table-column label="镜像描述" min-width="28%" align="left" prop="description">
<template slot-scope="scope">
<div class="image_desc" :title="scope.row.description">{{ scope.row.description}}
</div>
</div>
</template>
</el-table-column>
</el-table>
</div>
<div class="ui container" style="padding:2rem 0;text-align:center">
<el-pagination
background
@size-change="handleSizeChangeCustom"
@current-change="handleCurrentChangeCustom"
:current-page="currentPageCustom"
:page-size="pageSizeCustom"
:page-sizes="[5,15,20]"
layout="total, sizes, prev, pager, next, jumper"
:total="totalNumCustom">
</el-pagination>
<div v-if="!!scope.row.topics">
<span v-for="(topic,index) in scope.row.topics"
class="ui repo-topic label topic" style="cursor: default;">{{topic}}</span>
</div>

</template>
</el-table-column>
<el-table-column prop="cloudbrainType" label="可用集群" min-width="10%" align="center">
<template slot-scope="scope">
{{scope.row.cloudbrainType | transformType}}
</template>
</el-table-column>
<el-table-column prop="isPrivate" label="状态" min-width="8%" align="center">
<template slot-scope="scope">
<span v-if="scope.row.isPrivate" style="color: rgb(250, 140, 22);">私有</span>
<span v-else style="color: rgb(19, 194, 141);">公开</span>
</template>
</el-table-column>
<el-table-column prop="creator" label="创建者" min-width="7%" align="center">
<template slot-scope="scope">
<a v-if="scope.row.userName||scope.row.relAvatarLink"
:href="'/' + scope.row.userName" :title="scope.row.userName">
<img :src="scope.row.relAvatarLink" class="ui avatar image">
</a>
<a v-else>
<img class="ui avatar image" title="Ghost" src="/user/avatar/ghost/-1">
</a>
</template>
</el-table-column>
<el-table-column prop="createdUnix" label="创建时间" align="center" min-width="13%">
<template slot-scope="scope">
{{scope.row.createdUnix | transformTimestamp}}
</template>
</el-table-column>
<el-table-column align="center" min-width="23%" label="操作">
<template slot-scope="scope">
<div style="display: flex;justify-content: flex-end;align-items: center;">
<div
style="display: flex;align-items: center;cursor: default;;padding: 0 1rem;">
<svg width="1.4em" height="1.4em" viewBox="0 0 32 32" class="heart-stroke">
<path
d="M4.4 6.54c-1.761 1.643-2.6 3.793-2.36 6.056.24 2.263 1.507 4.521 3.663 6.534a29110.9 29110.9 0 0010.296 9.633l10.297-9.633c2.157-2.013 3.424-4.273 3.664-6.536.24-2.264-.599-4.412-2.36-6.056-1.73-1.613-3.84-2.29-6.097-1.955-1.689.25-3.454 1.078-5.105 2.394l-.4.319-.398-.319c-1.649-1.316-3.414-2.143-5.105-2.394a7.612 7.612 0 00-1.113-.081c-1.838 0-3.541.694-4.983 2.038z">
</path>
</svg>
<span
style="line-height: 2;margin-left:0.3rem;">{{scope.row.numStars}}</span>
</div>
<span style="padding: 0 1rem;color: rgb(250, 140, 22);cursor:pointer;"
v-if="scope.row.type==5"
@click="unSetRecommend(scope.$index,scope.row.id)">取消推荐</span>
<span style="padding: 0 1rem;color: rgb(19, 194, 141);cursor:pointer;"
v-if="scope.row.type!==5 && !scope.row.isPrivate"
@click="setRecommend(scope.$index,scope.row.id)">设为推荐</span>
<span style="padding: 0 1rem;color:#0366d6;cursor:pointer;"
@click="copyUrl(scope.row.place)">复制地址</span>
<div style="padding-left:1rem;cursor:pointer;">
<el-dropdown size="medium">
<span class="el-dropdown-link">
更多<i class="el-icon-arrow-down el-icon--right"></i>
</span>
<el-dropdown-menu slot="dropdown">
<el-dropdown-item @click.native="eidtImage(scope.row.id)">编辑
</el-dropdown-item>
<el-dropdown-item style="color: red;"
@click.native="deleteImage(scope.row.id)">删除</el-dropdown-item>
</el-dropdown-menu>
</el-dropdown>
</div>
</div>
</template>
</el-table-column>
</el-table>
</div>
<div class="ui container" style="padding:2rem 0;text-align:center">
<el-pagination background @size-change="handleSizeChangeCustom"
@current-change="handleCurrentChangeCustom" :current-page="currentPageCustom"
:page-size="pageSizeCustom" :page-sizes="[5,15,20]"
layout="total, sizes, prev, pager, next, jumper" :total="totalNumCustom">
</el-pagination>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>


</template>

<script>

const {_AppSubUrl, _StaticUrlPrefix, csrf} = window.config;
const { _AppSubUrl, _StaticUrlPrefix, csrf } = window.config;




export default {
components: {
},
data() {
return {
search:'',
dropdownPrivate:'全部',
checked:false,
currentPageCustom:1,
pageSizeCustom:15,
totalNumCustom:0,
paramsCustom:{page:1,pageSize:15,q:'',recommend:false},
tableDataCustom: [],
starCustom:[],
loadingCustom:false,
};
},
methods: {
tableHeaderStyle({row,column,rowIndex,columnIndex}){
if(rowIndex===0){
return 'background:#f5f5f6;color:#606266'
}
},

handleSizeChangeCustom(val){
this.paramsCustom.pageSize = val
this.getImageListCustom()
},
handleCurrentChangeCustom(val){
this.paramsCustom.page = val
this.getImageListCustom()
},

getImageListCustom(){
this.loadingCustom = true
this.$axios.get('/admin/images/data',{
params:this.paramsCustom
}).then((res)=>{
this.totalNumCustom = res.data.count
this.tableDataCustom = res.data.images
this.tableDataCustom.forEach(element => {
this.starCustom.push({id:element.id,})
});
this.loadingCustom = false
})
},
deleteImage(id){
let flag=1
let _this = this
$('.ui.basic.modal.images')
.modal({
onDeny: function() {
flag = false
export default {
components: {

},
data() {
return {
search: '',
dropdownPrivate: '全部',
checked: false,
currentPageCustom: 1,
pageSizeCustom: 15,
totalNumCustom: 0,
paramsCustom: { page: 1, pageSize: 15, q: '', recommend: false },
tableDataCustom: [],
starCustom: [],
loadingCustom: false,
};
},
methods: {
tableHeaderStyle({ row, column, rowIndex, columnIndex }) {
if (rowIndex === 0) {
return 'background:#f5f5f6;color:#606266'
}
},

handleSizeChangeCustom(val) {
this.paramsCustom.pageSize = val
this.getImageListCustom()
},
onApprove: function() {
_this.$axios.delete('/image/'+id).then((res)=>{
_this.getImageListCustom()
handleCurrentChangeCustom(val) {
this.paramsCustom.page = val
this.getImageListCustom()
},

getImageListCustom() {
this.loadingCustom = true
this.$axios.get('/admin/images/data', {
params: this.paramsCustom
}).then((res) => {
this.totalNumCustom = res.data.count
this.tableDataCustom = res.data.images
this.tableDataCustom.forEach(element => {
this.starCustom.push({ id: element.id, })

});
this.loadingCustom = false
})
flag = true
},
onHidden: function() {
if (flag == false) {
$('.alert').html('您已取消操作').removeClass('alert-success').addClass('alert-danger').show().delay(1500).fadeOut();
}else{
$('.alert').html('删除成功').removeClass('alert-danger').addClass('alert-success').show().delay(1500).fadeOut();
deleteImage(id) {
let flag = 1
let _this = this
$('.ui.basic.modal.images')
.modal({
onDeny: function () {
flag = false
},
onApprove: function () {
_this.$axios.delete('/image/' + id).then((res) => {
_this.getImageListCustom()
})
flag = true
},
onHidden: function () {
if (flag == false) {
$('.alert').html('您已取消操作').removeClass('alert-success').addClass('alert-danger').show().delay(1500).fadeOut();
} else {
$('.alert').html('删除成功').removeClass('alert-danger').addClass('alert-success').show().delay(1500).fadeOut();
}
}
})
.modal('show')
},
eidtImage(id) {
location.href = `/image/${id}/imageAdmin`
},
imageStar(index, id, isStar) {
if (isStar) {
this.$axios.put(`/image/${id}/action/unstar`).then((res) => {
this.tableDataPublic[index].numStars = this.tableDataPublic[index].numStars - 1
this.tableDataPublic[index].isStar = false
})
} else {
this.$axios.put(`/image/${id}/action/star`).then((res) => {
this.tableDataPublic[index].numStars = this.tableDataPublic[index].numStars + 1
this.tableDataPublic[index].isStar = true
})
}
}
})
.modal('show')
},
eidtImage(id){
location.href = `/image/${id}/imageAdmin`
},
imageStar(index,id,isStar){
if(isStar){
this.$axios.put(`/image/${id}/action/unstar`).then((res)=>{
this.tableDataPublic[index].numStars = this.tableDataPublic[index].numStars - 1
this.tableDataPublic[index].isStar = false
})
}else{
this.$axios.put(`/image/${id}/action/star`).then((res)=>{
this.tableDataPublic[index].numStars = this.tableDataPublic[index].numStars + 1
this.tableDataPublic[index].isStar = true
})
}
},
copyUrl(url){
const cInput = document.createElement('input')
cInput.value = url
document.body.appendChild(cInput)
cInput.select()
document.execCommand('Copy')
cInput.remove()
},
searchName(){
this.paramsCustom.q = this.search
this.paramsCustom.page = 1
this.getImageListCustom()
},
setRecommend(index,id){
this.$axios.put(`/admin/image/${id}/action/recommend`).then((res)=>{
this.tableDataCustom[index].type = 5
})
},
unSetRecommend(index,id){
this.$axios.put(`/admin/image/${id}/action/unrecommend`).then((res)=>{
this.tableDataCustom[index].type = 0
})
},
handleCommand(command){
this.dropdownPrivate = command.label
this.paramsCustom.private = command.private
this.getImageListCustom()

}
},
filters:{
transformType(val){
if(val==0){
return "GPU"
}
},
transformPravite(val){
if(val){
return "私有"
}else{
return "公开"
}
},
transformTimestamp(timestamp){
},
copyUrl(url) {
const cInput = document.createElement('input')
cInput.value = url
document.body.appendChild(cInput)
cInput.select()
document.execCommand('Copy')
cInput.remove()
},
searchName() {
this.paramsCustom.q = this.search
this.paramsCustom.page = 1
this.getImageListCustom()

},
setRecommend(index, id) {
this.$axios.put(`/admin/image/${id}/action/recommend`).then((res) => {
this.tableDataCustom[index].type = 5
})
},
unSetRecommend(index, id) {
this.$axios.put(`/admin/image/${id}/action/unrecommend`).then((res) => {
this.tableDataCustom[index].type = 0
})
},
handleCommand(command) {
this.dropdownPrivate = command.label
this.paramsCustom.private = command.private
this.getImageListCustom()

}
},
filters: {
transformType(val) {
if (val == 0) {
return "GPU"
}
},
transformPravite(val) {
if (val) {
return "私有"
} else {
return "公开"
}
},
transformTimestamp(timestamp) {
const date = new Date(parseInt(timestamp) * 1000);
const Y = date.getFullYear() + '-';
const M = (date.getMonth() + 1 < 10 ? '0' + (date.getMonth() + 1) : date.getMonth() + 1) + '-';
const D = (date.getDate() < 10 ? '0'+date.getDate() : date.getDate()) + ' ';
const h = (date.getHours() < 10 ? '0'+date.getHours() : date.getHours()) + ':';
const m = (date.getMinutes() <10 ? '0'+date.getMinutes() : date.getMinutes()) + ':' ;
const s = (date.getSeconds() <10 ? '0'+date.getSeconds() : date.getSeconds()) ; // 秒
const D = (date.getDate() < 10 ? '0' + date.getDate() : date.getDate()) + ' ';
const h = (date.getHours() < 10 ? '0' + date.getHours() : date.getHours()) + ':';
const m = (date.getMinutes() < 10 ? '0' + date.getMinutes() : date.getMinutes()) + ':';
const s = (date.getSeconds() < 10 ? '0' + date.getSeconds() : date.getSeconds()); // 秒
const dateString = Y + M + D + h + m + s;
return dateString;
},
},
watch:{
checked(val){
this.paramsCustom.page = 1
this.paramsCustom.recommend = val
this.getImageListCustom()
}
},
watch: {
checked(val) {
this.paramsCustom.page = 1
this.paramsCustom.recommend = val
this.getImageListCustom()
}

},
mounted() {
this.getImageListCustom()
},
created() {
}
},
mounted() {
this.getImageListCustom()
},
created() {

};
}

};
</script>

<style scoped>
.header-wrapper {
background-color: #f5f5f6;
padding-top: 15px;
}
.image_text{
padding:25px 0 55px 0 ;
}
#header{
position: relative;
top:-40px;
}
.el-dropdown-menu__item--divided{
border-top: 1px solid blue;
}
.el-table thead{
background-color: #f5f5f6;
}
/deep/ .el-tabs__item:hover{
color: #000;
font-weight: 500;
}
/deep/ .el-tabs__item.is-active {
color: #000;
font-weight: 500;
}
/deep/ .el-tabs__active-bar{
background-color:#000
}

#success{
background-color: #5bb973;
color: white;
}
.text-over{
overflow: hidden;
text-overflow: ellipsis;
vertical-align: middle;
white-space: nowrap;
}
.image_title{
display: inline-block;
cursor: default;
color: rgb(66, 98, 144);
}
.image_desc{
-webkit-line-clamp: 2;
-webkit-box-orient: vertical;
display: -webkit-box;
text-overflow: ellipsis;
overflow: hidden;
}
.heart-stroke{
stroke: #FA8C16;
stroke-width: 2;
fill: #fff
}
.stars_active{
fill: #FA8C16 !important;
stroke:#FA8C16 !important
}
.header-new-drop{
width: 100%;
}
</style>
.header-wrapper {
background-color: #f5f5f6;
padding-top: 15px;
}

.image_text {
padding: 25px 0 55px 0;
}

#header {
position: relative;
top: -40px;
}

.el-dropdown-menu__item--divided {
border-top: 1px solid blue;
}

.el-table thead {
background-color: #f5f5f6;
}

/deep/ .el-tabs__item:hover {
color: #000;
font-weight: 500;

}

/deep/ .el-tabs__item.is-active {
color: #000;
font-weight: 500;
}

/deep/ .el-tabs__active-bar {
background-color: #000
}

#success {
background-color: #5bb973;
color: white;
}

.text-over {
overflow: hidden;
text-overflow: ellipsis;
vertical-align: middle;
white-space: nowrap;
}

.image_title {
display: inline-block;

cursor: default;
color: rgb(66, 98, 144);
}

.image_desc {
-webkit-line-clamp: 2;
-webkit-box-orient: vertical;
display: -webkit-box;
text-overflow: ellipsis;
overflow: hidden;
}

.heart-stroke {
stroke: #FA8C16;
stroke-width: 2;
fill: #fff
}

.stars_active {
fill: #FA8C16 !important;
stroke: #FA8C16 !important
}

.header-new-drop {
width: 100%;
}
</style>

+ 296
- 277
web_src/js/components/images/selectImages.vue View File

@@ -1,76 +1,87 @@
<template>

<div class="inline required field" :class="{ 'unite': benchmarkNew, 'min_title': benchmarkNew}">
<label v-if="benchmarkNew" style="font-weight: normal;">镜像</label>
<label v-else>镜像</label>
<span v-if="benchmarkNew">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span>
<input v-if="benchmarkNew" type="text" name="image" :value="imageAddress" style="width: 48.5%;" placeholder="选择镜像或输入镜像地址">
<input v-else type="text" name="image" :value="imageAddress" placeholder="选择镜像或输入镜像地址">
<el-button type="text" @click="dialogVisible = true" icon="el-icon-plus" style="color: #0366d6;">选择镜像</el-button>
<el-dialog
title="选择镜像"
:visible.sync="dialogVisible"
width="50%"
>
<div class="ui icon input" style="z-index: 9999;position: absolute;right: 50px;height:30px;">
<i class="search icon" style="cursor: pointer;pointer-events:auto"></i>
<input type="text" placeholder="搜镜像Tag/描述/标签..." v-model="search">
</div>
<el-tabs v-model="activeName" @tab-click="handleClick">
<div class="inline required field" :class="{ 'unite': benchmarkNew, 'min_title': benchmarkNew}">
<label v-if="benchmarkNew" style="font-weight: normal;">镜像</label>
<label v-else>镜像</label>
<span v-if="benchmarkNew">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span>
<input v-if="benchmarkNew" type="text" name="image" :value="imageAddress" style="width: 48.5%;"
placeholder="选择镜像或输入镜像地址">
<input v-else type="text" name="image" :value="imageAddress" placeholder="选择镜像或输入镜像地址">
<el-button type="text" @click="dialogVisible = true" icon="el-icon-plus" style="color: #0366d6;">选择镜像
</el-button>
<el-dialog title="选择镜像" :visible.sync="dialogVisible" width="50%">
<div class="ui icon input" style="z-index: 9999;position: absolute;right: 50px;height:30px;">
<i class="search icon" style="cursor: pointer;pointer-events:auto"></i>
<input type="text" placeholder="搜镜像Tag/描述/标签..." v-model="search">
</div>
<el-tabs v-model="activeName" @tab-click="handleClick">
<el-tab-pane label="公开镜像" name="first" v-loading="loadingPublic">
<div style="display: flex;align-items: center;justify-content: space-between;padding: 1rem 0;border-bottom:1px solid #F5F5F5" v-for="(publicData,index) in tableDataPublic" :key="index">
<div style="display: flex;align-items: center;justify-content: space-between;padding: 1rem 0;border-bottom:1px solid #F5F5F5"
v-for="(publicData,index) in tableDataPublic" :key="index">
<div style="width: 90%;">
<div style="display: flex;align-items: center;justify-content: space-between;">
<div style="display: flex;align-items: center;">
<span class="panel_dataset_name text-over" style="margin-left: 0;">{{publicData.tag}} </span>
<img v-if="publicData.type==5" src="/img/jian.svg" style="margin-left: 0.5rem;">
<span class="panel_dataset_name text-over"
style="margin-left: 0;">{{publicData.tag}} </span>
<img v-if="publicData.type==5" src="/img/jian.svg" style="margin-left: 0.5rem;">
</div>
<div v-if="!!publicData.topics" class="text-over">
<span v-for="(topic,index) in publicData.topics" class="ui repo-topic label topic">{{topic}}</span>
<span v-for="(topic,index) in publicData.topics"
class="ui repo-topic label topic">{{topic}}</span>
</div>
</div>
<div style="margin-top: 8px;display: flex;">
<a :title="publicData.userName" style="cursor: default;">
<img class="ui avatar mini image" style="width: 20px;height: 20px;" :src="publicData.relAvatarLink">
<a v-if="publicData.relAvatarLink||publicData.userName" :title="publicData.userName"
style="cursor: default;">
<img class="ui avatar mini image" style="width: 20px;height: 20px;"
:src="publicData.relAvatarLink">
</a>
<a v-else><img class="ui avatar mini image" title="Ghost" src="/user/avatar/ghost/-1"
style="width: 20px;height: 20px;"></a>
<span class="panel_datset_desc">{{publicData.description}}</span>
</div>
</div>
<div>
<button class="ui primary basic button mini" @click.stop.prevent="selectImages(publicData.place,publicData.tag)">使用</button>
<button class="ui primary basic button mini"
@click.stop.prevent="selectImages(publicData.place,publicData.tag)">使用</button>
</div>
</div>
<div class="ui container" style="margin-top:50px;text-align:center">
<el-pagination
background
@current-change="handleCurrentChangePublic"
:current-page="currentPagePublic"
:page-size="pageSizePublic"
layout="total, prev, pager, next"
:total="totalNumPublic">
<el-pagination background @current-change="handleCurrentChangePublic"
:current-page="currentPagePublic" :page-size="pageSizePublic"
layout="total, prev, pager, next" :total="totalNumPublic">
</el-pagination>
</div>
</el-tab-pane>

<el-tab-pane label="我的镜像" name="second" v-loading="loadingCustom">
<div style="display: flex;align-items: center;justify-content: space-between;padding: 1rem 0;border-bottom:1px solid #F5F5F5" v-for="(customData,index) in tableDataCustom" :key="index">
<div style="display: flex;align-items: center;justify-content: space-between;padding: 1rem 0;border-bottom:1px solid #F5F5F5"
v-for="(customData,index) in tableDataCustom" :key="index">
<div style="width: 90%;">
<div style="display: flex;align-items: center;justify-content: space-between;">
<span class="panel_dataset_name text-over" style="margin-left: 0;">{{customData.tag}} </span>
<span class="panel_dataset_name text-over" style="margin-left: 0;">{{customData.tag}}
</span>
<div v-if="!!customData.topics" class="text-over">
<span v-for="(topic,index) in customData.topics" class="ui repo-topic label topic">{{topic}}</span>
<span v-for="(topic,index) in customData.topics"
class="ui repo-topic label topic">{{topic}}</span>
</div>
</div>
<div style="margin-top: 8px;display: flex;">
<a :title="customData.userName" style="cursor: default;">
<img class="ui avatar mini image" style="width: 20px;height: 20px;" :src="customData.relAvatarLink">
<a v-if="customData.relAvatarLink||customData.userName" :title="customData.userName"
style="cursor: default;">
<img class="ui avatar mini image" style="width: 20px;height: 20px;"
:src="customData.relAvatarLink">
</a>
<a v-else><img class="ui avatar mini image" title="Ghost" src="/user/avatar/ghost/-1"
style="width: 20px;height: 20px;"></a>

<span class="panel_datset_desc">{{customData.description}}</span>
</div>
</div>
<div>
<button v-if="customData.status===1" class="ui primary basic button mini" @click.stop.prevent="selectImages(customData.place,customData.tag)">使用</button>
<button v-if="customData.status===1" class="ui primary basic button mini"
@click.stop.prevent="selectImages(customData.place,customData.tag)">使用</button>
<span v-if="customData.status===0" style="display: flex;align-items: center;">
<i class="CREATING"></i>
<span style="margin-left: 0.4em;font-size: 12px;color: #5A5A5A;">提交中</span>
@@ -80,278 +91,286 @@
<el-tooltip class="item" effect="dark" content="检测提交镜像是否大小超过20G!" placement="left">
<span style="margin-left: 0.4em;font-size: 12px;color:red;">提交失败</span>
</el-tooltip>
</span>
</div>
</div>
<div class="ui container" style="margin-top:50px;text-align:center">
<el-pagination
background
@current-change="handleCurrentChangeCustom"
:current-page="currentPageCustom"
:page-size="pageSizeCustom"
layout="total, prev, pager, next"
:total="totalNumCustom">
</el-pagination>
<el-pagination background @current-change="handleCurrentChangeCustom"
:current-page="currentPageCustom" :page-size="pageSizeCustom"
layout="total, prev, pager, next" :total="totalNumCustom">
</el-pagination>
</div>
</el-tab-pane>

<el-tab-pane label="我收藏的镜像" name="third">
<div style="display: flex;align-items: center;justify-content: space-between;padding: 1rem 0;border-bottom:1px solid #F5F5F5" v-for="(starData,index) in tableDataStar" :key="index">
<div style="display: flex;align-items: center;justify-content: space-between;padding: 1rem 0;border-bottom:1px solid #F5F5F5"
v-for="(starData,index) in tableDataStar" :key="index">
<div style="width: 90%;">
<div style="display: flex;align-items: center;justify-content: space-between;">
<div style="display: flex;align-items: center;">
<span class="panel_dataset_name text-over" style="margin-left: 0;">{{starData.tag}} </span>
<img v-if="starData.type==5" src="/img/jian.svg" style="margin-left: 0.5rem;">
<span class="panel_dataset_name text-over" style="margin-left: 0;">{{starData.tag}}
</span>
<img v-if="starData.type==5" src="/img/jian.svg" style="margin-left: 0.5rem;">
</div>
<div v-if="!!starData.topics" class="text-over">
<span v-for="(topic,index) in starData.topics" class="ui repo-topic label topic">{{topic}}</span>
<span v-for="(topic,index) in starData.topics"
class="ui repo-topic label topic">{{topic}}</span>
</div>
</div>
<div style="margin-top: 8px;display: flex;">
<a :title="starData.userName" style="cursor: default;">
<img class="ui avatar mini image" style="width: 20px;height: 20px;" :src="starData.relAvatarLink">
<a v-if="starData.relAvatarLink||starData.userName" :title="starData.userName"
style="cursor: default;">
<img class="ui avatar mini image" style="width: 20px;height: 20px;"
:src="starData.relAvatarLink">
</a>
<a v-else><img class="ui avatar mini image" title="Ghost" src="/user/avatar/ghost/-1"
style="width: 20px;height: 20px;"></a>
<span class="panel_datset_desc">{{starData.description}}</span>
</div>
</div>
<div>
<button class="ui primary basic button mini" @click.stop.prevent="selectImages(starData.place,starData.tag)">使用</button>
<button class="ui primary basic button mini"
@click.stop.prevent="selectImages(starData.place,starData.tag)">使用</button>
</div>
</div>
<div class="ui container" style="margin-top:50px;text-align:center">
<el-pagination
background
@current-change="handleCurrentChangeStar"
:current-page="currentPageStar"
:page-size="pageSizeStar"
layout="total, prev, pager, next"
:total="totalNumStar">
</el-pagination>
<el-pagination background @current-change="handleCurrentChangeStar"
:current-page="currentPageStar" :page-size="pageSizeStar" layout="total, prev, pager, next"
:total="totalNumStar">
</el-pagination>
</div>
</el-tab-pane>
</el-tabs>
</el-dialog>
</div>
</el-tabs>
</el-dialog>
</div>



</template>

<script>

const {_AppSubUrl, _StaticUrlPrefix, csrf} = window.config;




export default {
components: {
},
data() {
return {
dialogVisible:false,
benchmarkNew:false,
imageAddress:'',
activeName: 'first',
search:'',
checked:false,
currentPagePublic:1,
pageSizePublic:5,
totalNumPublic:0,
paramsPublic:{page:1,pageSize:5,q:'',recommend:false},
tableDataPublic: [],
loadingPublic:false,

currentPageCustom:1,
pageSizeCustom:5,
totalNumCustom:0,
paramsCustom:{page:1,pageSize:5,q:''},
tableDataCustom: [],
starCustom:[],
loadingCustom:false,

currentPageStar:1,
pageSizeStar:5,
totalNumStar:0,
paramsStar:{page:1,pageSize:5,q:''},
tableDataStar: [],
loadingStar:false
};
},
methods: {
handleClick(tab, event) {
this.search = ''
if(tab.name=="first"){
this.paramsPublic.q = ''
this.getImageListPublic()
}
if(tab.name=="second"){
this.getImageListCustom()
}
if(tab.name=="third"){
this.getImageListStar()
}
},
tableHeaderStyle({row,column,rowIndex,columnIndex}){
if(rowIndex===0){
return 'background:#f5f5f6;color:#606266'
}
},

handleCurrentChangePublic(val){
this.paramsPublic.page = val
this.getImageListPublic()

},

handleCurrentChangeCustom(val){
this.paramsCustom.page = val
this.getImageListCustom()

},
handleCurrentChangeStar(val){
this.paramsStar.page = val
this.getImageListStar()

},
getImageListPublic(){
this.loadingPublic = true
this.$axios.get('/explore/images/public',{
params:this.paramsPublic
}).then((res)=>{
this.totalNumPublic = res.data.count
this.tableDataPublic = res.data.images
this.loadingPublic = false
})
},

getImageListCustom(){
this.loadingCustom = true
this.$axios.get('/explore/images/custom',{
params:this.paramsCustom
}).then((res)=>{
this.totalNumCustom = res.data.count
this.tableDataCustom = res.data.images
this.tableDataCustom.forEach(element => {
this.starCustom.push({id:element.id,})
});
this.loadingCustom = false
})
},

getImageListStar(){
this.loadingStar = true
this.$axios.get('/explore/images/star',{
params:this.paramsStar
}).then((res)=>{
this.totalNumStar = res.data.count
this.tableDataStar = res.data.images
this.loadingStar = false
})
},
searchName(){
if(this.activeName=='first'){
this.paramsPublic.q = this.search
this.paramsPublic.page = 1
const { _AppSubUrl, _StaticUrlPrefix, csrf } = window.config;




export default {
components: {

},
data() {
return {
dialogVisible: false,
benchmarkNew: false,
imageAddress: '',
activeName: 'first',
search: '',
checked: false,
currentPagePublic: 1,
pageSizePublic: 5,
totalNumPublic: 0,
paramsPublic: { page: 1, pageSize: 5, q: '', recommend: false },
tableDataPublic: [],
loadingPublic: false,

currentPageCustom: 1,
pageSizeCustom: 5,
totalNumCustom: 0,
paramsCustom: { page: 1, pageSize: 5, q: '' },
tableDataCustom: [],
starCustom: [],
loadingCustom: false,

currentPageStar: 1,
pageSizeStar: 5,
totalNumStar: 0,
paramsStar: { page: 1, pageSize: 5, q: '' },
tableDataStar: [],
loadingStar: false
};
},
methods: {
handleClick(tab, event) {
this.search = ''
if (tab.name == "first") {
this.paramsPublic.q = ''
this.getImageListPublic()
}
if (tab.name == "second") {
this.getImageListCustom()
}
if (tab.name == "third") {
this.getImageListStar()
}

},
tableHeaderStyle({ row, column, rowIndex, columnIndex }) {

if (rowIndex === 0) {
return 'background:#f5f5f6;color:#606266'
}

},

handleCurrentChangePublic(val) {
this.paramsPublic.page = val
this.getImageListPublic()

},

handleCurrentChangeCustom(val) {
this.paramsCustom.page = val
this.getImageListCustom()

},
handleCurrentChangeStar(val) {
this.paramsStar.page = val
this.getImageListStar()

},
getImageListPublic() {
this.loadingPublic = true
this.$axios.get('/explore/images/public', {
params: this.paramsPublic
}).then((res) => {
this.totalNumPublic = res.data.count
this.tableDataPublic = res.data.images
this.loadingPublic = false
})
},

getImageListCustom() {
this.loadingCustom = true
this.$axios.get('/explore/images/custom', {
params: this.paramsCustom
}).then((res) => {
this.totalNumCustom = res.data.count
this.tableDataCustom = res.data.images
this.tableDataCustom.forEach(element => {
this.starCustom.push({ id: element.id, })

});
this.loadingCustom = false
})
},

getImageListStar() {
this.loadingStar = true
this.$axios.get('/explore/images/star', {
params: this.paramsStar
}).then((res) => {
this.totalNumStar = res.data.count
this.tableDataStar = res.data.images
this.loadingStar = false
})
},
searchName() {
if (this.activeName == 'first') {
this.paramsPublic.q = this.search
this.paramsPublic.page = 1
this.getImageListPublic()
}
if (this.activeName == 'second') {
this.paramsCustom.q = this.search
this.paramsCustom.page = 1
this.getImageListCustom()
}
if (this.activeName == 'third') {
this.paramsStar.q = this.search
this.paramsStar.page = 1
this.getImageListStar()
}

},
selectImages(place) {
this.imageAddress = place
this.dialogVisible = false
},

},
watch: {
search(val) {
if (this.activeName == 'first') {
this.paramsPublic.q = val
this.getImageListPublic()
}
if (this.activeName == 'second') {
this.paramsCustom.q = val
this.getImageListCustom()
}
if (this.activeName == 'third') {
this.paramsStar.q = val
this.getImageListStar()
}
}

},
mounted() {
this.getImageListPublic()
if (location.href.indexOf('benchmark') !== -1 || location.href.indexOf('train-job') !== -1) {
this.benchmarkNew = true
}
},
created() {

}
if(this.activeName=='second'){
this.paramsCustom.q = this.search
this.paramsCustom.page = 1
this.getImageListCustom()
}
if(this.activeName=='third'){
this.paramsStar.q = this.search
this.paramsStar.page = 1
this.getImageListStar()
}
},
selectImages(place){
this.imageAddress = place
this.dialogVisible = false
},

},
watch:{
search(val){
if(this.activeName=='first'){
this.paramsPublic.q = val
this.getImageListPublic()
}
if(this.activeName=='second'){
this.paramsCustom.q = val
this.getImageListCustom()
}
if(this.activeName=='third'){
this.paramsStar.q = val
this.getImageListStar()
}
}

},
mounted() {
this.getImageListPublic()
if(location.href.indexOf('benchmark')!==-1 || location.href.indexOf('train-job')!==-1){
this.benchmarkNew = true
}
},
created() {
}

};

};
</script>

<style scoped>
.header-wrapper {
background-color: #f5f5f6;
padding-top: 15px;
}
.image_text{
padding:25px 0 55px 0 ;
}
#header{
position: relative;
top:-40px;
}
#success{
background-color: #5bb973;
color: white;
}
.text-over{
overflow: hidden;
text-overflow: ellipsis;
vertical-align: middle;
white-space: nowrap;
}
.image_title{
display: inline-block;
width: 80%;
cursor: default;
color: rgb(66, 98, 144);
}
.image_desc{
-webkit-line-clamp: 2;
-webkit-box-orient: vertical;
display: -webkit-box;
text-overflow: ellipsis;
overflow: hidden;
}
.heart-stroke{
stroke: #666;
stroke-width: 2;
fill: #fff
}
.stars_active{
fill: #FA8C16 !important;
stroke:#FA8C16 !important
}
</style>
.header-wrapper {
background-color: #f5f5f6;
padding-top: 15px;
}

.image_text {
padding: 25px 0 55px 0;
}

#header {
position: relative;
top: -40px;
}

#success {
background-color: #5bb973;
color: white;
}

.text-over {
overflow: hidden;
text-overflow: ellipsis;
vertical-align: middle;
white-space: nowrap;
}

.image_title {
display: inline-block;
width: 80%;
cursor: default;
color: rgb(66, 98, 144);
}

.image_desc {
-webkit-line-clamp: 2;
-webkit-box-orient: vertical;
display: -webkit-box;
text-overflow: ellipsis;
overflow: hidden;
}

.heart-stroke {
stroke: #666;
stroke-width: 2;
fill: #fff
}

.stars_active {
fill: #FA8C16 !important;
stroke: #FA8C16 !important
}
</style>

+ 1
- 1
web_src/js/features/clipboard.js View File

@@ -2,7 +2,7 @@ export default async function initClipboard() {
const els = document.querySelectorAll('.clipboard');
if (!els || !els.length) return;

const {default: ClipboardJS} = await import(/* webpackChunkName: "clipboard" */'clipboard');
const { default: ClipboardJS } = await import(/* webpackChunkName: "clipboard" */'clipboard');

const clipboard = new ClipboardJS(els);
clipboard.on('success', (e) => {


+ 200
- 113
web_src/js/features/cloudrbanin.js View File

@@ -2,7 +2,9 @@ export default async function initCloudrain() {
let debug_button = $('.cloudbrain_debug').data('debug')
let debug_again_button = $('.cloudbrain_debug').data('debug-again')
let timeid = window.setInterval(loadJobStatus, 15000);
let timeidShow = window.setInterval(loadShowJobStatus, 15000);
$(document).ready(loadJobStatus);
$(document).ready(loadShowJobStatus);
function loadJobStatus() {
$(".job-status").each((index, job) => {
const ID = job.dataset.jobid;
@@ -10,7 +12,7 @@ export default async function initCloudrain() {
// const computeResource = job.dataset.resource
const versionname = job.dataset.version
const status_text = $(`#${ID}-text`).text()
const finalState = ['STOPPED','CREATE_FAILED','UNAVAILABLE','DELETED','RESIZE_FAILED','SUCCEEDED','IMAGE_FAILED','SUBMIT_FAILED','DELETE_FAILED','KILLED','COMPLETED','FAILED','CANCELED','LOST','START_FAILED','SUBMIT_MODEL_FAILED','DEPLOY_SERVICE_FAILED','CHECK_FAILED']
const finalState = ['STOPPED', 'CREATE_FAILED', 'UNAVAILABLE', 'DELETED', 'RESIZE_FAILED', 'SUCCEEDED', 'IMAGE_FAILED', 'SUBMIT_FAILED', 'DELETE_FAILED', 'KILLED', 'COMPLETED', 'FAILED', 'CANCELED', 'LOST', 'START_FAILED', 'SUBMIT_MODEL_FAILED', 'DEPLOY_SERVICE_FAILED', 'CHECK_FAILED']
if (finalState.includes(status_text)) {
return
}
@@ -19,46 +21,83 @@ export default async function initCloudrain() {
const ID = data.ID || data.JobID
const status = data.JobStatus
const duration = data.JobDuration
$('#duration-'+ID).text(duration)
console.log(status,["STOPPED"].includes(status))
$('#duration-' + ID).text(duration)
if (status != status_text) {
$('#' + ID+'-icon').removeClass().addClass(status)
$('#' + ID+ '-text').text(status)
$('#' + ID + '-icon').removeClass().addClass(status)
$('#' + ID + '-text').text(status)
finalState.includes(status) && $('#' + ID + '-stop').removeClass('blue').addClass('disabled')
}
if(status==="RUNNING"){
$('#ai-debug-'+ID).removeClass('disabled').addClass('blue').text(debug_button).css("margin","0 1rem")
$('#model-image-'+ID).removeClass('disabled').addClass('blue')
if (status === "RUNNING") {
$('#ai-debug-' + ID).removeClass('disabled').addClass('blue').text(debug_button).css("margin", "0 1rem")
$('#model-image-' + ID).removeClass('disabled').addClass('blue')
}
if(status!=="RUNNING"){
if (status !== "RUNNING") {
// $('#model-debug-'+ID).removeClass('blue')
// $('#model-debug-'+ID).addClass('disabled')
$('#model-image-'+ID).removeClass('blue').addClass('disabled')
$('#model-image-' + ID).removeClass('blue').addClass('disabled')
}
if(["CREATING","STOPPING","WAITING","STARTING"].includes(status)){
$('#ai-debug-'+ID).removeClass('blue').addClass('disabled')
if (["CREATING", "STOPPING", "WAITING", "STARTING"].includes(status)) {
$('#ai-debug-' + ID).removeClass('blue').addClass('disabled')
}
if(['STOPPED','FAILED','START_FAILED','CREATE_FAILED','SUCCEEDED'].includes(status)){
$('#ai-debug-'+ID).removeClass('disabled').addClass('blue').text(debug_again_button).css("margin","0")
}
if(["RUNNING","WAITING"].includes(status)){
$('#ai-stop-'+ID).removeClass('disabled').addClass('blue')
if (['STOPPED', 'FAILED', 'START_FAILED', 'CREATE_FAILED', 'SUCCEEDED'].includes(status)) {
$('#ai-debug-' + ID).removeClass('disabled').addClass('blue').text(debug_again_button).css("margin", "0")
}
if(["CREATING","STOPPING","STARTING","STOPPED","FAILED","START_FAILED","SUCCEEDED","COMPLETED","CREATE_FAILED"].includes(status)){
$('#ai-stop-'+ID).removeClass('blue').addClass('disabled')
if (["RUNNING", "WAITING"].includes(status)) {
$('#ai-stop-' + ID).removeClass('disabled').addClass('blue')
}
if(["STOPPED","FAILED","START_FAILED","KILLED","COMPLETED","SUCCEEDED"].includes(status)){
$('#ai-delete-'+ID).removeClass('disabled').addClass('blue')
}else{
$('#ai-delete-'+ID).removeClass('blue').addClass('disabled')
if (["CREATING", "STOPPING", "STARTING", "STOPPED", "FAILED", "START_FAILED", "SUCCEEDED", "COMPLETED", "CREATE_FAILED"].includes(status)) {
$('#ai-stop-' + ID).removeClass('blue').addClass('disabled')
}
}).fail(function(err) {

if (["STOPPED", "FAILED", "START_FAILED", "KILLED", "COMPLETED", "SUCCEEDED"].includes(status)) {
$('#ai-delete-' + ID).removeClass('disabled').addClass('blue')
} else {
$('#ai-delete-' + ID).removeClass('blue').addClass('disabled')
}
}).fail(function (err) {
console.log(err);
});
});
};
function assertDelete(obj,versionName,repoPath) {

function loadShowJobStatus() {
$(".ui.accordion.border-according").each((index, job) => {
const jobID = job.dataset.jobid;
const repoPath = job.dataset.repopath;
const versionname = job.dataset.version
// ['IMAGE_FAILED','SUBMIT_FAILED','DELETE_FAILED','KILLED','COMPLETED','FAILED','CANCELED','LOST','START_FAILED']
// if (job.textContent.trim() == 'IMAGE_FAILED' || job.textContent.trim() == 'SUBMIT_FAILED' || job.textContent.trim() == 'DELETE_FAILED'
// || job.textContent.trim() == 'KILLED' || job.textContent.trim() == 'COMPLETED' || job.textContent.trim() == 'FAILED'
// || job.textContent.trim() == 'CANCELED' || job.textContent.trim() == 'LOST') {
// return
// }
let status = $(`#${versionname}-status-span`).text()

if (['IMAGE_FAILED', 'SUBMIT_FAILED', 'DELETE_FAILED', 'KILLED', 'COMPLETED', 'FAILED', 'CANCELED', 'LOST', 'START_FAILED', 'SUCCEEDED', 'STOPPED'].includes(status)) {
return
}
let stopArray = ["KILLED", "FAILED", "START_FAILED", "KILLING", "COMPLETED", "SUCCEEDED", "STOPPED"]
$.get(`/api/v1/repos/${repoPath}/${jobID}?version_name=${versionname}`, (data) => {
//$(`#${versionname}-duration-span`).text(data.JobDuration)
$(`#${versionname}-status-span span`).text(data.JobStatus)
$(`#${versionname}-status-span i`).attr("class", data.JobStatus)
// detail status and duration
//$('#'+versionname+'-duration').text(data.JobDuration)
$('#' + versionname + '-status').text(data.JobStatus)
if (stopArray.includes(data.JobStatus)) {
$('#' + versionname + '-stop').addClass('disabled')
}
if (data.JobStatus === "COMPLETED") {
$('#' + versionname + '-create-model').removeClass('disabled').addClass('blue')
}
}).fail(function (err) {
console.log(err);
});
});
};


function assertDelete(obj, versionName, repoPath) {
if (obj.style.color == "rgb(204, 204, 204)") {
return
} else {
@@ -66,19 +105,19 @@ export default async function initCloudrain() {
let flag = 1;
$('.ui.basic.modal')
.modal({
onDeny: function() {
onDeny: function () {
flag = false
},
onApprove: function() {
if(!versionName){
onApprove: function () {
if (!versionName) {
document.getElementById(delId).submit()
}
else{
deleteVersion(versionName,repoPath)
else {
deleteVersion(versionName, repoPath)
}
flag = true
},
onHidden: function() {
onHidden: function () {
if (flag == false) {
$('.alert').html('您已取消操作').removeClass('alert-success').addClass('alert-danger').show().delay(1500).fadeOut();
}
@@ -87,157 +126,205 @@ export default async function initCloudrain() {
.modal('show')
}
}
function deleteVersion(versionName,repoPath){
function deleteVersion(versionName, repoPath) {
const url = `/api/v1/repos/${repoPath}`
$.post(url,{version_name:versionName},(data)=>{
if(data.StatusOK===0){
$.post(url, { version_name: versionName }, (data) => {
if (data.StatusOK === 0) {
location.reload()
}
}).fail(function(err) {
console.log(err);
}).fail(function (err) {
console.log(err);
});
}
$('.ui.basic.ai_delete').click(function() {
$('.ui.basic.ai_delete').click(function () {
const repoPath = this.dataset.repopath
const versionName = this.dataset.version
if(repoPath && versionName){
assertDelete(this,versionName,repoPath)
if (repoPath && versionName) {
assertDelete(this, versionName, repoPath)
}
else{
else {
assertDelete(this)
}
})
function stopDebug(ID,stopUrl){
function stopDebug(ID, stopUrl) {
$.ajax({
type:"POST",
url:stopUrl,
data:$('#stopForm-'+ID).serialize(),
success:function(res){
if(res.result_code==="0"){
$('#' + ID+'-icon').removeClass().addClass(res.status)
$('#' + ID+ '-text').text(res.status)
if(res.status==="STOPPED"){
$('#ai-debug-'+ID).removeClass('disabled').addClass('blue').text(debug_again_button).css("margin","0")
$('#ai-image-'+ID).removeClass('blue').addClass('disabled')
$('#ai-model-debug-'+ID).removeClass('blue').addClass('disabled')
$('#ai-delete-'+ID).removeClass('disabled').addClass('blue')
$('#ai-stop-'+ID).removeClass('blue').addClass('disabled')
type: "POST",
url: stopUrl,
data: $('#stopForm-' + ID).serialize(),
success: function (res) {
if (res.result_code === "0") {
$('#' + ID + '-icon').removeClass().addClass(res.status)
$('#' + ID + '-text').text(res.status)
if (res.status === "STOPPED") {
$('#ai-debug-' + ID).removeClass('disabled').addClass('blue').text(debug_again_button).css("margin", "0")
$('#ai-image-' + ID).removeClass('blue').addClass('disabled')
$('#ai-model-debug-' + ID).removeClass('blue').addClass('disabled')
$('#ai-delete-' + ID).removeClass('disabled').addClass('blue')
$('#ai-stop-' + ID).removeClass('blue').addClass('disabled')
}
else{
$('#ai-debug-'+ID).removeClass('blue').addClass('disabled')
$('#ai-stop-'+ID).removeClass('blue').addClass('disabled')
else {
$('#ai-debug-' + ID).removeClass('blue').addClass('disabled')
$('#ai-stop-' + ID).removeClass('blue').addClass('disabled')
}
}else{
} else {
$('.alert').html(res.error_msg).removeClass('alert-success').addClass('alert-danger').show().delay(2000).fadeOut();
}
},
error :function(res){
error: function (res) {
console.log(res)
}
})
}
$('.ui.basic.ai_stop').click(function() {
$('.ui.basic.ai_stop').click(function () {
const ID = this.dataset.jobid
const repoPath = this.dataset.repopath
stopDebug(ID,repoPath)
stopDebug(ID, repoPath)
})

function stopVersion(version_name,ID,repoPath){
function stopVersion(version_name, ID, repoPath) {
const url = `/api/v1/repos/${repoPath}/${ID}/stop_version`
$.post(url,{version_name:version_name},(data)=>{
if(data.StatusOK===0){
$('#ai-stop-'+ID).removeClass('blue')
$('#ai-stop-'+ID).addClass('disabled')
refreshStatus(version_name,ID,repoPath)
$.post(url, { version_name: version_name }, (data) => {
if (data.StatusOK === 0) {
$('#ai-stop-' + ID).removeClass('blue')
$('#ai-stop-' + ID).addClass('disabled')
refreshStatus(version_name, ID, repoPath)
}
}).fail(function(err) {
console.log(err);
}).fail(function (err) {
console.log(err);
});
}
function refreshStatus(version_name,ID,repoPath){
function refreshStatus(version_name, ID, repoPath) {
const url = `/api/v1/repos/${repoPath}/${ID}/?version_name${version_name}`
$.get(url,(data)=>{
$(`#${ID}-icon`).attr("class",data.JobStatus)
$.get(url, (data) => {
$(`#${ID}-icon`).attr("class", data.JobStatus)
// detail status and duration
$(`#${ID}-text`).text(data.JobStatus)
if(["STOPPED","FAILED","START_FAILED","KILLED","COMPLETED","SUCCEEDED"].includes(data.JobStatus)){
$('#ai-delete-'+ID).removeClass('disabled').addClass('blue')
if (["STOPPED", "FAILED", "START_FAILED", "KILLED", "COMPLETED", "SUCCEEDED"].includes(data.JobStatus)) {
$('#ai-delete-' + ID).removeClass('disabled').addClass('blue')
}
}).fail(function(err) {
}).fail(function (err) {
console.log(err);
});
}
$('.ui.basic.ai_stop_version').click(function() {
$('.ui.basic.ai_stop_version').click(function () {
const ID = this.dataset.jobid
const repoPath = this.dataset.repopath
const versionName = this.dataset.version
stopVersion(versionName,ID,repoPath)
stopVersion(versionName, ID, repoPath)
})
function getModelInfo(repoPath,modelName,versionName,jobName){
$.get(`${repoPath}/modelmanage/show_model_info_api?name=${modelName}`,(data)=>{
if(data.length===0){
function getModelInfo(repoPath, modelName, versionName, jobName) {
$.get(`${repoPath}/modelmanage/show_model_info_api?name=${modelName}`, (data) => {
if (data.length === 0) {
$(`#${jobName}`).popup('toggle')
}else{
let versionData = data.filter((item)=>{
} else {
let versionData = data.filter((item) => {
return item.Version === versionName
})
if(versionData.length==0){
if (versionData.length == 0) {
$(`#${jobName}`).popup('toggle')
}
else{
else {
location.href = `${repoPath}/modelmanage/show_model_info?name=${modelName}`
}
}
})
}
$('.goto_modelmanage').click(function() {
$('.goto_modelmanage').click(function () {
const repoPath = this.dataset.repopath
const modelName = this.dataset.modelname
const versionName = this.dataset.version
const jobName = this.dataset.jobname
getModelInfo(repoPath,modelName,versionName,jobName)
getModelInfo(repoPath, modelName, versionName, jobName)
})
function debugAgain(ID,debugUrl,redirect_to){
if($('#' + ID+ '-text').text()==="RUNNING"){
window.open(debugUrl+'debug')
}else{
function debugAgain(ID, debugUrl, redirect_to) {
if ($('#' + ID + '-text').text() === "RUNNING") {
window.open(debugUrl + 'debug')
} else {
$.ajax({
type:"POST",
url:debugUrl+'restart?redirect_to='+redirect_to,
data:$('#debugAgainForm-'+ID).serialize(),
success:function(res){
if(res['WechatRedirectUrl']){
window.location.href=res['WechatRedirectUrl']
type: "POST",
url: debugUrl + 'restart?redirect_to=' + redirect_to,
data: $('#debugAgainForm-' + ID).serialize(),
success: function (res) {
if (res['WechatRedirectUrl']) {
window.location.href = res['WechatRedirectUrl']
}
else if(res.result_code==="0"){
if(res.id!==ID){
else if (res.result_code === "0") {
if (res.id !== ID) {
location.reload()
}else{
$('#' + ID+'-icon').removeClass().addClass(res.status)
$('#' + ID+ '-text').text(res.status)
$('#ai-debug-'+ID).removeClass('blue').addClass('disabled')
$('#ai-delete-'+ID).removeClass('blue').addClass('disabled')
$('#ai-debug-'+ID).text(debug_button).css("margin","0 1rem")
} else {
$('#' + ID + '-icon').removeClass().addClass(res.status)
$('#' + ID + '-text').text(res.status)
$('#ai-debug-' + ID).removeClass('blue').addClass('disabled')
$('#ai-delete-' + ID).removeClass('blue').addClass('disabled')
$('#ai-debug-' + ID).text(debug_button).css("margin", "0 1rem")
}
}else{
} else {
$('.alert').html(res.error_msg).removeClass('alert-success').addClass('alert-danger').show().delay(2000).fadeOut();
}
},
error :function(res){
error: function (res) {
console.log(res)
}
})
}
}
$('.ui.basic.ai_debug').click(function() {
$('.ui.basic.ai_debug').click(function () {
const ID = this.dataset.jobid
const repoPath = this.dataset.repopath
const redirect_to = this.dataset.linkpath
debugAgain(ID,repoPath,redirect_to)
debugAgain(ID, repoPath, redirect_to)
})
}

function userSearchControll() {
if ($('#userCloud').length === 0) {
return
}
const params = new URLSearchParams(window.location.search)
let jobType
if ($('.cloudbrain_debug').length === 1) {
if (!params.get('jobType')) {
jobType = $('.cloudbrain_debug').data('allTask')
} else {
if (params.get('jobType') === 'DEBUG') {
jobType = $('.cloudbrain_debug').data('debug-task')
} else if (params.get('jobType') === 'TRAIN') {
jobType = $('.cloudbrain_debug').data('train-task')
}
else if (params.get('jobType') === 'INFERENCE') {
jobType = $('.cloudbrain_debug').data('inference-task')
}
else {
jobType = $('.cloudbrain_debug').data('benchmark-task')
}
}
}
let listType = !params.get('listType') ? $('.cloudbrain_debug').data('all-compute') : params.get('listType')
let jobStatus = !params.get('jobStatus') ? $('.cloudbrain_debug').data('all-status') : params.get('jobStatus').toUpperCase()
const dropdownValueArray = [jobType, listType, jobStatus]
$('#userCloud .default.text ').each(function (index, e) {
$(e).text(dropdownValueArray[index])
})
}

function AdaminSearchControll() {
if ($('#adminCloud').length === 0) {
return
}
const params = new URLSearchParams(window.location.search)
let jobType = !params.get('jobType') ? $('.cloudbrain_debug').data('all-task') : params.get('jobType')
let listType = !params.get('listType') ? $('.cloudbrain_debug').data('all-compute') : params.get('listType')
let jobStatus = !params.get('jobStatus') ? $('.cloudbrain_debug').data('all-status') : params.get('jobStatus').toUpperCase()
const dropdownValueArray = [jobType, listType, jobStatus]
$('#adminCloud .default.text ').each(function (index, e) {
$(e).text(dropdownValueArray[index])
})
}
userSearchControll()
AdaminSearchControll()




+ 156
- 0
web_src/js/features/contexmenu.js View File

@@ -0,0 +1,156 @@

export default async function initContextMenu() {
$('.popup-close').on('click', function (e) {
$(this).parents('tr').prev().css('display', 'table-row')
$(this).closest('tr').css('cssText', 'display:none !important')
})
function contextMenu() {
let canContextMenu = $('.ui.single.line.table.can-context-menu').data('can-editfile')
if (canContextMenu) {
$('.name.four.wide').on('contextmenu', function (e) {
let ev = window.event || e;
ev.preventDefault();
menu.show(e)
})
} else {
return
}
}
contextMenu()
const menu = new Menu({
data: [
{
label: '新标签打开',
icon: "file outline icon context-menu-icon",
active: (e, a) => {
window.open(a.currentTarget.getElementsByTagName("a")[0].getAttribute('href'))
}
},
{
label: '重命名',
icon: "edit icon context-menu-icon",
active: (e, a) => {
document.querySelectorAll(".context-menu-one").forEach((ele) => {
if (ele.style.display === 'table-row') {

ele.style.display = 'none'
ele.previousElementSibling.style.display = 'table-row'
}
})
if (a.currentTarget.parentNode.nextElementSibling) {
a.currentTarget.parentNode.style.setProperty('display', 'none', 'important')
a.currentTarget.parentNode.nextElementSibling.style.display = 'table-row'
const renameFile = a.currentTarget.getElementsByTagName("a")[0].getAttribute('title')
let renameFileValue = renameFile.indexOf('/') !== -1 ? renameFile.substr(0, renameFile.indexOf('/')) : renameFile
a.currentTarget.parentNode.nextElementSibling.getElementsByTagName("input")[0].setAttribute("value", renameFileValue)

}
let btn = a.currentTarget.parentNode.nextElementSibling.getElementsByTagName("button")[0]
btn.addEventListener('click', function (e) {
let postUrl = btn.getAttribute('data-postbasepath')
const postUrlArr = postUrl.split('/')
postUrlArr[postUrlArr.length - 1] = encodeURIComponent(postUrlArr[postUrlArr.length - 1])
postUrl = postUrlArr.join('/')
console.log(postUrl)
let last_commit = btn.getAttribute('data-commit')
let tree_path = btn.getAttribute('data-treepath') + e.target.parentNode.previousElementSibling.getElementsByTagName("input")[0].value
let csrf = $("input[name='_csrf']").val()
$.ajax({
url: postUrl,
type: "POST",
contentType: "application/x-www-form-urlencoded",
data: { last_commit: last_commit, tree_path: tree_path, _csrf: csrf },
success: function (res) {
if (res.Code === 0) {
document.getElementById("mask").style.display = "block"
location.reload()
}
else {
$('.ui.negative.message').text(res.Msg).show().delay(10000).fadeOut();
}
}

})

})
},
},
// {
// label: '删除',
// icon: "trash icon context-menu-icon",
// active: (e, a) => {
// console.dir(a)
// $('.context-menu-delete.modal')
// .modal({
// onApprove() {
// }
// })
// .modal('show');
// }
// },

]
})
}
class Menu {
constructor(param) {
this.target = document.createElement('div')
this.target.classList.add("ui", "menu", "compact", "vertical", "context-menu-click")
this.data = param.data
this.active = false
this.clickZ = this.click.bind(this)
this.closeZ = this.close2.bind(this)
document.addEventListener('click', this.closeZ)
for (let i = 0; i < this.data.length; i++) {
let div = document.createElement('a')
div.classList.add('item', 'context-menu-operation')
if (this.data[i].disabled) {
div.classList.add('disabled')
}
div.dataset.index = i.toString()
div.innerHTML = `<i class="${this.data[i].icon}"></i>${this.data[i].label}`
div.addEventListener('click', this.clickZ)
this.target.append(div)
}
document.body.append(this.target)
}
click(e) {
let index = parseInt(e.target.dataset.index)
if (this.data[index].active) {
this.data[index].active(e, this.acEvent)
}
this.close()
}
show(e) {
this.active = true
this.nodeList = this.target.querySelectorAll('.item')
for (let i = 0; i < this.data.length; i++) {
if (this.data[i].beforeDisabled) {
let t = this.data[i].beforeDisabled(e)
this.data[i].disabled = t
if (t) {
this.nodeList[i].classList.add('disabled')
} else {
this.nodeList[i].classList.remove('disabled')
}
}
}
this.acEvent = e
this.target.style.top = `${e.pageY}px`
this.target.style.left = `${e.pageX}px`
this.target.style.minWidth = '90px'
this.target.classList.add('active')
}

close() {
this.active = false
this.target.classList.remove('active')
}

close2(e) {
if (!this.target.contains(e.target) && this.active) {
this.active = false
this.target.classList.remove('active')
}
}
}

+ 537
- 515
web_src/js/index.js
File diff suppressed because it is too large
View File


+ 64
- 0
web_src/js/router/index.js View File

@@ -0,0 +1,64 @@
import Vue from 'vue'
import Router from 'vue-router'
import DataAnalysis from '../components/DataAnalysis.vue'
import ProAnalysis from '../components/ProAnalysis.vue'
import ProTrend from '../components/ProTrend.vue'
import UserTrend from '../components/UserTrend.vue'
import UserAnalysis from '../components/UserAnalysis.vue'
import BrainAnalysis from '../components/BrainAnalysis.vue'
import Overview from '../components/Overview.vue'

const originalPush = Router.prototype.push

Router.prototype.push = function push(location) {
return originalPush.call(this, location).catch(err => err)
}
Vue.use(Router)

export default new Router({
mode: 'history',
base: '/explore/data_analysis/', //添加根目录
scrollBehavior: () => ({ y: 0 }),
routes:[
{
path:'/',redirect:'/ProAnalysis',
name:'ProAnalysis',
component:ProAnalysis,
},

{
path:'/Overview',
name:'Overview',
component:Overview,
},
{
path:'/ProTrend',
name:'ProTrend',
component:ProTrend,
},
{
path:'/ProAnalysis',
name:'ProAnalysis',
component:ProAnalysis,
},
{
path:'/UserAnalysis',
name:'UserAnalysis',
component:UserAnalysis,
},
{
path:'/UserTrend',
name:'UserTrend',
component:UserTrend,
},

{
path:'/BrainAnalysis',
name:'BrainAnalysis',
component:BrainAnalysis,
},

],


})

+ 30
- 1
web_src/less/openi.less View File

@@ -1025,4 +1025,33 @@ display: block;
z-index: 9999;
width:150;
height: 80;
}
}

.ui.toast-container .toast-box.compact, .ui.toast-container .toast-box>.compact {
width: 250px !important;
}
.context-menu-click {
z-index: 99;
position: absolute;
padding: 0;
border-radius: 4px;
border: 1px solid #e3e9ed;
-webkit-box-shadow: none;
box-shadow: none;
background: #fff;
display: none !important;
}

.context-menu-click.active {
display: block !important;
}

.context-menu-operation {
padding: 5px !important;
line-height: 1.78 !important;
}

.context-menu-icon {
float: left !important;
margin: 0px 5px 0px 0px !important;
}

Loading…
Cancel
Save