Browse Source

Merge branch 'V20220926' into point-v2

pull/2975/head^2
chenyifan01 2 years ago
parent
commit
932ac68f26
45 changed files with 2257 additions and 564 deletions
  1. +24
    -0
      models/ai_model_manage.go
  2. +1
    -0
      models/models.go
  3. +72
    -5
      models/user_business_analysis.go
  4. +14
    -7
      models/user_business_struct.go
  5. +102
    -0
      models/user_invitation.go
  6. +1
    -1
      modules/auth/user_form.go
  7. +6
    -5
      modules/grampus/resty.go
  8. +6
    -5
      modules/setting/setting.go
  9. +9
    -0
      options/locale/locale_en-US.ini
  10. +9
    -0
      options/locale/locale_zh-CN.ini
  11. +14
    -0
      routers/api/v1/api.go
  12. +5
    -1
      routers/api/v1/repo/cloudbrain.go
  13. +15
    -0
      routers/home.go
  14. +49
    -24
      routers/repo/ai_model_manage.go
  15. +30
    -3
      routers/repo/grampus.go
  16. +2
    -1
      routers/repo/modelarts.go
  17. +440
    -0
      routers/repo/user_invitation.go
  18. +3
    -0
      routers/routes/routes.go
  19. +107
    -0
      routers/user/Invitation.go
  20. +28
    -24
      routers/user/auth.go
  21. +22
    -0
      services/repository/repository.go
  22. +11
    -1
      templates/base/footer.tmpl
  23. +4
    -0
      templates/base/head_navbar.tmpl
  24. +4
    -0
      templates/base/head_navbar_fluid.tmpl
  25. +4
    -0
      templates/base/head_navbar_home.tmpl
  26. +4
    -0
      templates/base/head_navbar_pro.tmpl
  27. +1
    -2
      templates/repo/cloudbrain/trainjob/show.tmpl
  28. +10
    -1
      templates/repo/grampus/trainjob/show.tmpl
  29. +9
    -2
      templates/repo/modelmanage/convertIndex.tmpl
  30. +2
    -2
      templates/repo/modelmanage/index.tmpl
  31. +38
    -0
      templates/user/auth/signup_inner.tmpl
  32. +5
    -0
      templates/user/dashboard/repolist.tmpl
  33. +34
    -1
      templates/user/profile.tmpl
  34. +7
    -0
      templates/user/settings/invite.tmpl
  35. +624
    -473
      web_src/js/components/Model.vue
  36. +140
    -0
      web_src/js/features/ad.js
  37. +8
    -0
      web_src/js/features/i18nVue.js
  38. +1
    -0
      web_src/js/index.js
  39. +15
    -5
      web_src/js/standalone/phoneverify.js
  40. +2
    -1
      web_src/less/standalone/_phoneverify.less
  41. +11
    -0
      web_src/vuepages/apis/modules/userinvite.js
  42. +14
    -0
      web_src/vuepages/langs/config/en-US.js
  43. +14
    -0
      web_src/vuepages/langs/config/zh-CN.js
  44. +319
    -0
      web_src/vuepages/pages/user/invite/index.vue
  45. +17
    -0
      web_src/vuepages/pages/user/invite/vp-user-invite.js

+ 24
- 0
models/ai_model_manage.go View File

@@ -25,6 +25,7 @@ type AiModelManage struct {
DownloadCount int `xorm:"NOT NULL DEFAULT 0"` DownloadCount int `xorm:"NOT NULL DEFAULT 0"`
Engine int64 `xorm:"NOT NULL DEFAULT 0"` Engine int64 `xorm:"NOT NULL DEFAULT 0"`
Status int `xorm:"NOT NULL DEFAULT 0"` Status int `xorm:"NOT NULL DEFAULT 0"`
StatusDesc string `xorm:"varchar(500)"`
Accuracy string `xorm:"varchar(1000)"` Accuracy string `xorm:"varchar(1000)"`
AttachmentId string `xorm:"NULL"` AttachmentId string `xorm:"NULL"`
RepoId int64 `xorm:"INDEX NULL"` RepoId int64 `xorm:"INDEX NULL"`
@@ -286,6 +287,23 @@ func ModifyModelDescription(id string, description string) error {
return nil return nil
} }


func ModifyModelStatus(id string, modelSize int64, status int, modelPath string, statusDesc string) error {
var sess *xorm.Session
sess = x.ID(id)
defer sess.Close()
re, err := sess.Cols("size", "status", "path", "status_desc").Update(&AiModelManage{
Size: modelSize,
Status: status,
Path: modelPath,
StatusDesc: statusDesc,
})
if err != nil {
return err
}
log.Info("success to update ModelStatus from db.re=" + fmt.Sprint((re)))
return nil
}

func ModifyModelNewProperty(id string, new int, versioncount int) error { func ModifyModelNewProperty(id string, new int, versioncount int) error {
var sess *xorm.Session var sess *xorm.Session
sess = x.ID(id) sess = x.ID(id)
@@ -356,6 +374,12 @@ func QueryModel(opts *AiModelQueryOptions) ([]*AiModelManage, int64, error) {
) )
} }


if (opts.Status) >= 0 {
cond = cond.And(
builder.Eq{"ai_model_manage.status": opts.Status},
)
}

count, err := sess.Where(cond).Count(new(AiModelManage)) count, err := sess.Where(cond).Count(new(AiModelManage))
if err != nil { if err != nil {
return nil, 0, fmt.Errorf("Count: %v", err) return nil, 0, fmt.Errorf("Count: %v", err)


+ 1
- 0
models/models.go View File

@@ -178,6 +178,7 @@ func init() {
new(UserLoginLog), new(UserLoginLog),
new(UserMetrics), new(UserMetrics),
new(UserAnalysisPara), new(UserAnalysisPara),
new(Invitation),
) )


gonicNames := []string{"SSL", "UID"} gonicNames := []string{"SSL", "UID"}


+ 72
- 5
models/user_business_analysis.go View File

@@ -106,7 +106,8 @@ type UserBusinessAnalysisAll struct {
CollectedImage int `xorm:"NOT NULL DEFAULT 0"` CollectedImage int `xorm:"NOT NULL DEFAULT 0"`
RecommendImage int `xorm:"NOT NULL DEFAULT 0"` RecommendImage int `xorm:"NOT NULL DEFAULT 0"`


Phone string `xorm:"NULL"`
Phone string `xorm:"NULL"`
InvitationUserNum int `xorm:"NOT NULL DEFAULT 0"`
} }


type UserBusinessAnalysis struct { type UserBusinessAnalysis struct {
@@ -193,7 +194,8 @@ type UserBusinessAnalysis struct {
CollectedImage int `xorm:"NOT NULL DEFAULT 0"` CollectedImage int `xorm:"NOT NULL DEFAULT 0"`
RecommendImage int `xorm:"NOT NULL DEFAULT 0"` RecommendImage int `xorm:"NOT NULL DEFAULT 0"`


Phone string `xorm:"NULL"`
Phone string `xorm:"NULL"`
InvitationUserNum int `xorm:"NOT NULL DEFAULT 0"`
} }


type UserBusinessAnalysisQueryOptions struct { type UserBusinessAnalysisQueryOptions struct {
@@ -354,6 +356,33 @@ func QueryRankList(key string, tableName string, limit int) ([]*UserBusinessAnal
return userBusinessAnalysisAllList, int64(len(userBusinessAnalysisAllList)) return userBusinessAnalysisAllList, int64(len(userBusinessAnalysisAllList))
} }


func QueryUserInvitationDataByTableName(start int, pageSize int, tableName string, queryObj interface{}, userName string, invitationNum int) ([]*UserBusinessAnalysisAll, int64) {
statictisSess := xStatistic.NewSession()
defer statictisSess.Close()
var cond = builder.NewCond()
if len(userName) > 0 {
cond = cond.And(
builder.Like{"lower(name)", strings.ToLower(userName)},
)
}
cond = cond.And(
builder.Gte{"invitation_user_num": invitationNum},
)

allCount, err := statictisSess.Where(cond).Count(queryObj)
if err != nil {
log.Info("query error." + err.Error())
return nil, 0
}
log.Info("query return total:" + fmt.Sprint(allCount))
userBusinessAnalysisAllList := make([]*UserBusinessAnalysisAll, 0)
if err := statictisSess.Table(tableName).Where(cond).OrderBy("invitation_user_num desc,id asc").Limit(pageSize, start).
Find(&userBusinessAnalysisAllList); err != nil {
return nil, 0
}
return userBusinessAnalysisAllList, allCount
}

func QueryUserStaticDataByTableName(start int, pageSize int, tableName string, queryObj interface{}, userName string) ([]*UserBusinessAnalysisAll, int64) { func QueryUserStaticDataByTableName(start int, pageSize int, tableName string, queryObj interface{}, userName string) ([]*UserBusinessAnalysisAll, int64) {
statictisSess := xStatistic.NewSession() statictisSess := xStatistic.NewSession()
defer statictisSess.Close() defer statictisSess.Close()
@@ -363,6 +392,7 @@ func QueryUserStaticDataByTableName(start int, pageSize int, tableName string, q
builder.Like{"lower(name)", strings.ToLower(userName)}, builder.Like{"lower(name)", strings.ToLower(userName)},
) )
} }

allCount, err := statictisSess.Where(cond).Count(queryObj) allCount, err := statictisSess.Where(cond).Count(queryObj)
if err != nil { if err != nil {
log.Info("query error." + err.Error()) log.Info("query error." + err.Error())
@@ -752,6 +782,8 @@ func refreshUserStaticTable(wikiCountMap map[string]int, tableName string, pageS
CollectImage, CollectedImage := queryImageStars(start_unix, end_unix) CollectImage, CollectedImage := queryImageStars(start_unix, end_unix)
RecommendImage := queryRecommedImage(start_unix, end_unix) RecommendImage := queryRecommedImage(start_unix, end_unix)


InvitationMap := queryUserInvitationCount(start_unix, end_unix)

DataDate := currentTimeNow.Format("2006-01-02") + " 00:01" DataDate := currentTimeNow.Format("2006-01-02") + " 00:01"


cond := "type != 1 and is_active=true" cond := "type != 1 and is_active=true"
@@ -825,7 +857,7 @@ func refreshUserStaticTable(wikiCountMap map[string]int, tableName string, pageS
dateRecordAll.CollectImage = getMapValue(dateRecordAll.ID, CollectImage) dateRecordAll.CollectImage = getMapValue(dateRecordAll.ID, CollectImage)
dateRecordAll.CollectedImage = getMapValue(dateRecordAll.ID, CollectedImage) dateRecordAll.CollectedImage = getMapValue(dateRecordAll.ID, CollectedImage)
dateRecordAll.RecommendImage = getMapValue(dateRecordAll.ID, RecommendImage) dateRecordAll.RecommendImage = getMapValue(dateRecordAll.ID, RecommendImage)
dateRecordAll.InvitationUserNum = getMapValue(dateRecordAll.ID, InvitationMap)
dateRecordAll.UserIndexPrimitive = getUserIndexFromAnalysisAll(dateRecordAll, ParaWeight) dateRecordAll.UserIndexPrimitive = getUserIndexFromAnalysisAll(dateRecordAll, ParaWeight)
userIndexMap[dateRecordAll.ID] = dateRecordAll.UserIndexPrimitive userIndexMap[dateRecordAll.ID] = dateRecordAll.UserIndexPrimitive
if maxUserIndex < dateRecordAll.UserIndexPrimitive { if maxUserIndex < dateRecordAll.UserIndexPrimitive {
@@ -888,7 +920,7 @@ func insertTable(dateRecords []UserBusinessAnalysisAll, tableName string, static


insertBatchSql := "INSERT INTO public." + tableName + insertBatchSql := "INSERT INTO public." + tableName +
"(id, count_date, code_merge_count, commit_count, issue_count, comment_count, focus_repo_count, star_repo_count, watched_count, gitea_age_month, commit_code_size, commit_dataset_size, " + "(id, count_date, code_merge_count, commit_count, issue_count, comment_count, focus_repo_count, star_repo_count, watched_count, gitea_age_month, commit_code_size, commit_dataset_size, " +
"commit_model_count, solve_issue_count, encyclopedias_count, regist_date, create_repo_count, login_count, open_i_index, email, name, data_date,cloud_brain_task_num,gpu_debug_job,npu_debug_job,gpu_train_job,npu_train_job,npu_inference_job,gpu_bench_mark_job,cloud_brain_run_time,commit_dataset_num,user_index,user_location,focus_other_user,collect_dataset,collected_dataset,recommend_dataset,collect_image,collected_image,recommend_image,user_index_primitive,phone) " +
"commit_model_count, solve_issue_count, encyclopedias_count, regist_date, create_repo_count, login_count, open_i_index, email, name, data_date,cloud_brain_task_num,gpu_debug_job,npu_debug_job,gpu_train_job,npu_train_job,npu_inference_job,gpu_bench_mark_job,cloud_brain_run_time,commit_dataset_num,user_index,user_location,focus_other_user,collect_dataset,collected_dataset,recommend_dataset,collect_image,collected_image,recommend_image,user_index_primitive,phone,invitation_user_num) " +
"VALUES" "VALUES"


for i, record := range dateRecords { for i, record := range dateRecords {
@@ -897,7 +929,7 @@ func insertTable(dateRecords []UserBusinessAnalysisAll, tableName string, static
", " + fmt.Sprint(record.WatchedCount) + ", " + fmt.Sprint(record.GiteaAgeMonth) + ", " + fmt.Sprint(record.CommitCodeSize) + ", " + fmt.Sprint(record.CommitDatasetSize) + ", " + fmt.Sprint(record.WatchedCount) + ", " + fmt.Sprint(record.GiteaAgeMonth) + ", " + fmt.Sprint(record.CommitCodeSize) + ", " + fmt.Sprint(record.CommitDatasetSize) +
", " + fmt.Sprint(record.CommitModelCount) + ", " + fmt.Sprint(record.SolveIssueCount) + ", " + fmt.Sprint(record.EncyclopediasCount) + ", " + fmt.Sprint(record.RegistDate) + ", " + fmt.Sprint(record.CommitModelCount) + ", " + fmt.Sprint(record.SolveIssueCount) + ", " + fmt.Sprint(record.EncyclopediasCount) + ", " + fmt.Sprint(record.RegistDate) +
", " + fmt.Sprint(record.CreateRepoCount) + ", " + fmt.Sprint(record.LoginCount) + ", " + fmt.Sprint(record.OpenIIndex) + ", '" + record.Email + "', '" + record.Name + "', '" + record.DataDate + "'," + fmt.Sprint(record.CloudBrainTaskNum) + "," + fmt.Sprint(record.GpuDebugJob) + "," + fmt.Sprint(record.NpuDebugJob) + "," + fmt.Sprint(record.GpuTrainJob) + "," + fmt.Sprint(record.NpuTrainJob) + "," + fmt.Sprint(record.NpuInferenceJob) + "," + fmt.Sprint(record.GpuBenchMarkJob) + "," + fmt.Sprint(record.CloudBrainRunTime) + "," + fmt.Sprint(record.CommitDatasetNum) + "," + fmt.Sprint(record.UserIndex) + ",'" + record.UserLocation + "'," + ", " + fmt.Sprint(record.CreateRepoCount) + ", " + fmt.Sprint(record.LoginCount) + ", " + fmt.Sprint(record.OpenIIndex) + ", '" + record.Email + "', '" + record.Name + "', '" + record.DataDate + "'," + fmt.Sprint(record.CloudBrainTaskNum) + "," + fmt.Sprint(record.GpuDebugJob) + "," + fmt.Sprint(record.NpuDebugJob) + "," + fmt.Sprint(record.GpuTrainJob) + "," + fmt.Sprint(record.NpuTrainJob) + "," + fmt.Sprint(record.NpuInferenceJob) + "," + fmt.Sprint(record.GpuBenchMarkJob) + "," + fmt.Sprint(record.CloudBrainRunTime) + "," + fmt.Sprint(record.CommitDatasetNum) + "," + fmt.Sprint(record.UserIndex) + ",'" + record.UserLocation + "'," +
fmt.Sprint(record.FocusOtherUser) + "," + fmt.Sprint(record.CollectDataset) + "," + fmt.Sprint(record.CollectedDataset) + "," + fmt.Sprint(record.RecommendDataset) + "," + fmt.Sprint(record.CollectImage) + "," + fmt.Sprint(record.CollectedImage) + "," + fmt.Sprint(record.RecommendImage) + "," + fmt.Sprint(record.UserIndexPrimitive) + ",'" + record.Phone + "')"
fmt.Sprint(record.FocusOtherUser) + "," + fmt.Sprint(record.CollectDataset) + "," + fmt.Sprint(record.CollectedDataset) + "," + fmt.Sprint(record.RecommendDataset) + "," + fmt.Sprint(record.CollectImage) + "," + fmt.Sprint(record.CollectedImage) + "," + fmt.Sprint(record.RecommendImage) + "," + fmt.Sprint(record.UserIndexPrimitive) + ",'" + record.Phone + "'" + "," + fmt.Sprint(record.InvitationUserNum) + ")"
if i < (len(dateRecords) - 1) { if i < (len(dateRecords) - 1) {
insertBatchSql += "," insertBatchSql += ","
} }
@@ -2173,6 +2205,41 @@ func queryCloudBrainTask(start_unix int64, end_unix int64) (map[int64]int, map[s


return resultMap, resultItemMap return resultMap, resultItemMap
} }

func queryUserInvitationCount(start_unix int64, end_unix int64) map[int64]int {
statictisSess := xStatistic.NewSession()
defer statictisSess.Close()

resultMap := make(map[int64]int)
cond := "created_unix>=" + fmt.Sprint(start_unix) + " and created_unix<=" + fmt.Sprint(end_unix)
count, err := statictisSess.Where(cond).Count(new(Invitation))
if err != nil {
log.Info("query queryUserInvitationCount error. return.")
return resultMap
}
var indexTotal int64
indexTotal = 0
for {
statictisSess.Select("id,src_user_id,user_id").Table("invitation").Where(cond).OrderBy("id asc").Limit(PAGE_SIZE, int(indexTotal))
invitationList := make([]*Invitation, 0)
statictisSess.Find(&invitationList)
log.Info("query invitationList size=" + fmt.Sprint(len(invitationList)))
for _, invitationRecord := range invitationList {
if _, ok := resultMap[invitationRecord.SrcUserID]; !ok {
resultMap[invitationRecord.SrcUserID] = 1
} else {
resultMap[invitationRecord.SrcUserID] += 1
}
}
indexTotal += PAGE_SIZE
if indexTotal >= count {
break
}
}
log.Info("invitationList size=" + fmt.Sprint(len(resultMap)))
return resultMap
}

func setMapKey(key string, userId int64, value int, resultItemMap map[string]int) { func setMapKey(key string, userId int64, value int, resultItemMap map[string]int) {
newKey := fmt.Sprint(userId) + "_" + key newKey := fmt.Sprint(userId) + "_" + key
if _, ok := resultItemMap[newKey]; !ok { if _, ok := resultItemMap[newKey]; !ok {


+ 14
- 7
models/user_business_struct.go View File

@@ -66,7 +66,8 @@ type UserBusinessAnalysisCurrentYear struct {
CollectedImage int `xorm:"NOT NULL DEFAULT 0"` CollectedImage int `xorm:"NOT NULL DEFAULT 0"`
RecommendImage int `xorm:"NOT NULL DEFAULT 0"` RecommendImage int `xorm:"NOT NULL DEFAULT 0"`


Phone string `xorm:"NULL"`
Phone string `xorm:"NULL"`
InvitationUserNum int `xorm:"NOT NULL DEFAULT 0"`
} }


type UserBusinessAnalysisLast30Day struct { type UserBusinessAnalysisLast30Day struct {
@@ -133,7 +134,8 @@ type UserBusinessAnalysisLast30Day struct {
CollectedImage int `xorm:"NOT NULL DEFAULT 0"` CollectedImage int `xorm:"NOT NULL DEFAULT 0"`
RecommendImage int `xorm:"NOT NULL DEFAULT 0"` RecommendImage int `xorm:"NOT NULL DEFAULT 0"`


Phone string `xorm:"NULL"`
Phone string `xorm:"NULL"`
InvitationUserNum int `xorm:"NOT NULL DEFAULT 0"`
} }


type UserBusinessAnalysisLastMonth struct { type UserBusinessAnalysisLastMonth struct {
@@ -200,7 +202,8 @@ type UserBusinessAnalysisLastMonth struct {
CollectedImage int `xorm:"NOT NULL DEFAULT 0"` CollectedImage int `xorm:"NOT NULL DEFAULT 0"`
RecommendImage int `xorm:"NOT NULL DEFAULT 0"` RecommendImage int `xorm:"NOT NULL DEFAULT 0"`


Phone string `xorm:"NULL"`
Phone string `xorm:"NULL"`
InvitationUserNum int `xorm:"NOT NULL DEFAULT 0"`
} }


type UserBusinessAnalysisCurrentMonth struct { type UserBusinessAnalysisCurrentMonth struct {
@@ -267,7 +270,8 @@ type UserBusinessAnalysisCurrentMonth struct {
CollectedImage int `xorm:"NOT NULL DEFAULT 0"` CollectedImage int `xorm:"NOT NULL DEFAULT 0"`
RecommendImage int `xorm:"NOT NULL DEFAULT 0"` RecommendImage int `xorm:"NOT NULL DEFAULT 0"`


Phone string `xorm:"NULL"`
Phone string `xorm:"NULL"`
InvitationUserNum int `xorm:"NOT NULL DEFAULT 0"`
} }


type UserBusinessAnalysisCurrentWeek struct { type UserBusinessAnalysisCurrentWeek struct {
@@ -335,7 +339,8 @@ type UserBusinessAnalysisCurrentWeek struct {
CollectedImage int `xorm:"NOT NULL DEFAULT 0"` CollectedImage int `xorm:"NOT NULL DEFAULT 0"`
RecommendImage int `xorm:"NOT NULL DEFAULT 0"` RecommendImage int `xorm:"NOT NULL DEFAULT 0"`


Phone string `xorm:"NULL"`
Phone string `xorm:"NULL"`
InvitationUserNum int `xorm:"NOT NULL DEFAULT 0"`
} }


type UserBusinessAnalysisYesterday struct { type UserBusinessAnalysisYesterday struct {
@@ -403,7 +408,8 @@ type UserBusinessAnalysisYesterday struct {
CollectedImage int `xorm:"NOT NULL DEFAULT 0"` CollectedImage int `xorm:"NOT NULL DEFAULT 0"`
RecommendImage int `xorm:"NOT NULL DEFAULT 0"` RecommendImage int `xorm:"NOT NULL DEFAULT 0"`


Phone string `xorm:"NULL"`
Phone string `xorm:"NULL"`
InvitationUserNum int `xorm:"NOT NULL DEFAULT 0"`
} }


type UserBusinessAnalysisLastWeek struct { type UserBusinessAnalysisLastWeek struct {
@@ -471,7 +477,8 @@ type UserBusinessAnalysisLastWeek struct {
CollectedImage int `xorm:"NOT NULL DEFAULT 0"` CollectedImage int `xorm:"NOT NULL DEFAULT 0"`
RecommendImage int `xorm:"NOT NULL DEFAULT 0"` RecommendImage int `xorm:"NOT NULL DEFAULT 0"`


Phone string `xorm:"NULL"`
Phone string `xorm:"NULL"`
InvitationUserNum int `xorm:"NOT NULL DEFAULT 0"`
} }


type UserAnalysisPara struct { type UserAnalysisPara struct {


+ 102
- 0
models/user_invitation.go View File

@@ -0,0 +1,102 @@
package models

import (
"fmt"

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

// Follow represents relations of user and his/her followers.
type Invitation struct {
ID int64 `xorm:"pk autoincr"`
SrcUserID int64 `xorm:"NOT NULL DEFAULT 0"`
UserID int64 `xorm:"NOT NULL DEFAULT 0"`
Phone string `xorm:"INDEX"`
Avatar string `xorm:"-"`
Name string `xorm:"-"`
InvitationUserNum int `xorm:"-"`
IsActive bool `xorm:"-"`
CreatedUnix timeutil.TimeStamp `xorm:"created"`
}

func QueryInvitaionByPhone(phone string) []*Invitation {
statictisSess := xStatistic.NewSession()
defer statictisSess.Close()
cond := "phone ='" + phone + "'"
invitationList := make([]*Invitation, 0)
if err := statictisSess.Table(new(Invitation)).Where(cond).
Find(&invitationList); err != nil {
return nil
} else {
return invitationList
}
}

func GetAllUserName() map[int64]string {
sess := x.NewSession()
defer sess.Close()
sess.Select("id,name").Table("user")
userList := make([]*User, 0)
reMap := make(map[int64]string)
sess.Find(&userList)
for _, user := range userList {
reMap[user.ID] = user.Name
}
return reMap
}

func QueryInvitaionPage(start int, pageSize int) ([]*Invitation, int64) {
statictisSess := xStatistic.NewSession()
defer statictisSess.Close()
//cond := "created_unix >=" + fmt.Sprint(startTime) + " and created_unix <=" + fmt.Sprint(endTime)

allCount, err := statictisSess.Count(new(Invitation))
if err != nil {
log.Info("query error." + err.Error())
return nil, 0
}
invitationList := make([]*Invitation, 0)
if err := statictisSess.Table(new(Invitation)).OrderBy("created_unix desc").Limit(pageSize, start).
Find(&invitationList); err != nil {
return nil, 0
}
return invitationList, allCount
}

func QueryInvitaionByTime(startTime int64, endTime int64) []*Invitation {
statictisSess := xStatistic.NewSession()
defer statictisSess.Close()
cond := "created_unix >=" + fmt.Sprint(startTime) + " and created_unix <=" + fmt.Sprint(endTime)
invitationList := make([]*Invitation, 0)
if err := statictisSess.Table(new(Invitation)).Where(cond).OrderBy("created_unix desc").
Find(&invitationList); err != nil {
return nil
}
return invitationList
}

func InsertInvitaion(invitationUser *Invitation) error {
statictisSess := xStatistic.NewSession()
defer statictisSess.Close()
_, err := statictisSess.Insert(invitationUser)
return err
}

func QueryInvitaionBySrcUserId(srcUserId int64, start int, pageSize int) ([]*Invitation, int64) {
statictisSess := xStatistic.NewSession()
defer statictisSess.Close()
cond := "src_user_id =" + fmt.Sprint(srcUserId)
allCount, err := statictisSess.Where(cond).Count(new(Invitation))
if err != nil {
log.Info("query error." + err.Error())
return nil, 0
}
invitationList := make([]*Invitation, 0)

if err := statictisSess.Table(new(Invitation)).Where(cond).OrderBy("created_unix desc").Limit(pageSize, start).
Find(&invitationList); err != nil {
return nil, 0
}
return invitationList, allCount
}

+ 1
- 1
modules/auth/user_form.go View File

@@ -372,7 +372,7 @@ func (f *U2FDeleteForm) Validate(ctx *macaron.Context, errs binding.Errors) bind


type PhoneNumberForm struct { type PhoneNumberForm struct {
PhoneNumber string `binding:"Required;MaxSize(20)"` PhoneNumber string `binding:"Required;MaxSize(20)"`
Mode int `binding:"Required"`
Mode int `binding:"Required"`
SlideID string `binding:"Required;MaxSize(100)"` SlideID string `binding:"Required;MaxSize(100)"`
} }




+ 6
- 5
modules/grampus/resty.go View File

@@ -1,14 +1,15 @@
package grampus package grampus


import ( import (
"code.gitea.io/gitea/models"
"code.gitea.io/gitea/modules/log"
"code.gitea.io/gitea/modules/setting"
"crypto/tls" "crypto/tls"
"encoding/json" "encoding/json"
"fmt" "fmt"
"github.com/go-resty/resty/v2"
"net/http" "net/http"

"code.gitea.io/gitea/models"
"code.gitea.io/gitea/modules/log"
"code.gitea.io/gitea/modules/setting"
"github.com/go-resty/resty/v2"
) )


var ( var (
@@ -236,7 +237,7 @@ func GetTrainJobLog(jobID string) (string, error) {
return logContent, fmt.Errorf("json.Unmarshal failed(%s): %v", res.String(), err.Error()) return logContent, fmt.Errorf("json.Unmarshal failed(%s): %v", res.String(), err.Error())
} }
log.Error("GetTrainJobLog failed(%d):%s(%s)", res.StatusCode(), temp.ErrorCode, temp.ErrorMsg) log.Error("GetTrainJobLog failed(%d):%s(%s)", res.StatusCode(), temp.ErrorCode, temp.ErrorMsg)
return logContent, fmt.Errorf("GetTrainJobLog failed(%d):%s(%s)", res.StatusCode(), temp.ErrorCode, temp.ErrorMsg)
return logContent, fmt.Errorf("GetTrainJobLog failed(%d):%d(%s)", res.StatusCode(), temp.ErrorCode, temp.ErrorMsg)
} }


logContent = res.String() logContent = res.String()


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

@@ -66,9 +66,10 @@ const (
) )


type C2NetSequenceInfo struct { type C2NetSequenceInfo struct {
ID int `json:"id"`
Name string `json:"name"`
Content string `json:"content"`
ID int `json:"id"`
Name string `json:"name"`
Content string `json:"content"`
ContentEN string `json:"content_en"`
} }


type C2NetSqInfos struct { type C2NetSqInfos struct {
@@ -1475,7 +1476,7 @@ func NewContext() {
FlavorInfos = sec.Key("FLAVOR_INFOS").MustString("") FlavorInfos = sec.Key("FLAVOR_INFOS").MustString("")
TrainJobFLAVORINFOS = sec.Key("TrainJob_FLAVOR_INFOS").MustString("") TrainJobFLAVORINFOS = sec.Key("TrainJob_FLAVOR_INFOS").MustString("")
ModelArtsSpecialPools = sec.Key("SPECIAL_POOL").MustString("") ModelArtsSpecialPools = sec.Key("SPECIAL_POOL").MustString("")
ModelArtsMultiNode=sec.Key("MULTI_NODE").MustString("")
ModelArtsMultiNode = sec.Key("MULTI_NODE").MustString("")


sec = Cfg.Section("elk") sec = Cfg.Section("elk")
ElkUrl = sec.Key("ELKURL").MustString("") ElkUrl = sec.Key("ELKURL").MustString("")
@@ -1570,7 +1571,7 @@ func getGrampusConfig() {
Grampus.UserName = sec.Key("USERNAME").MustString("") Grampus.UserName = sec.Key("USERNAME").MustString("")
Grampus.Password = sec.Key("PASSWORD").MustString("") Grampus.Password = sec.Key("PASSWORD").MustString("")
Grampus.SpecialPools = sec.Key("SPECIAL_POOL").MustString("") Grampus.SpecialPools = sec.Key("SPECIAL_POOL").MustString("")
Grampus.C2NetSequence = sec.Key("C2NET_SEQUENCE").MustString("{\"sequence\":[{\"id\":1,\"name\":\"cloudbrain_one\",\"content\":\"鹏城云脑一号\"},{\"id\":2,\"name\":\"cloudbrain_two\",\"content\":\"鹏城云脑二号\"},{\"id\":3,\"name\":\"beida\",\"content\":\"北大人工智能集群系统\"},{\"id\":4,\"name\":\"hefei\",\"content\":\"合肥类脑智能开放平台\"},{\"id\":5,\"name\":\"wuhan\",\"content\":\"武汉人工智能计算中心\"},{\"id\":6,\"name\":\"xian\",\"content\":\"西安未来人工智能计算中心\"},{\"id\":7,\"pclcci\":\"more\",\"content\":\"鹏城云计算所\"},{\"id\":8,\"name\":\"xuchang\",\"content\":\"中原人工智能计算中心\"},{\"id\":9,\"name\":\"chengdu\",\"content\":\"成都人工智能计算中心\"},{\"id\":10,\"name\":\"more\",\"content\":\"横琴先进智能计算中心\"},{\"id\":11,\"name\":\"more\",\"content\":\"国家超级计算济南中心\"}]}")
Grampus.C2NetSequence = sec.Key("C2NET_SEQUENCE").MustString("{\"sequence\":[{\"id\":1,\"name\":\"cloudbrain_one\",\"content\":\"鹏城云脑一号\",\"content_en\":\"Pencheng Cloudbrain Ⅰ\"},{\"id\":2,\"name\":\"cloudbrain_two\",\"content\":\"鹏城云脑二号\",\"content_en\":\"Pencheng Cloudbrain Ⅱ\"},{\"id\":3,\"name\":\"beida\",\"content\":\"北大人工智能集群系统\",\"content_en\":\"Peking University AI Center\"},{\"id\":4,\"name\":\"hefei\",\"content\":\"合肥类脑智能开放平台\",\"content_en\":\"Hefei AI Center\"},{\"id\":5,\"name\":\"wuhan\",\"content\":\"武汉人工智能计算中心\",\"content_en\":\"Wuhan AI Center\"},{\"id\":6,\"name\":\"xian\",\"content\":\"西安未来人工智能计算中心\",\"content_en\":\"Xi'an AI Center\"},{\"id\":7,\"pclcci\":\"more\",\"content\":\"鹏城云计算所\",\"content_en\":\"Pengcheng Cloud Computing Institute\"},{\"id\":8,\"name\":\"xuchang\",\"content\":\"中原人工智能计算中心\",\"content_en\":\"Zhongyuan AI Center\"},{\"id\":9,\"name\":\"chengdu\",\"content\":\"成都人工智能计算中心\",\"content_en\":\"Chengdu AI Center\"},{\"id\":10,\"name\":\"more\",\"content\":\"横琴先进智能计算中心\",\"content_en\":\"Hengqin AI Center\"},{\"id\":11,\"name\":\"more\",\"content\":\"国家超级计算济南中心\",\"content_en\":\"HPC & AI Center\"}]}")
if Grampus.C2NetSequence != "" { if Grampus.C2NetSequence != "" {
if err := json.Unmarshal([]byte(Grampus.C2NetSequence), &C2NetInfos); err != nil { if err := json.Unmarshal([]byte(Grampus.C2NetSequence), &C2NetInfos); err != nil {
log.Error("Unmarshal(C2NetSequence) failed:%v", err) log.Error("Unmarshal(C2NetSequence) failed:%v", err)


+ 9
- 0
options/locale/locale_en-US.ini View File

@@ -70,6 +70,10 @@ your_dashboard = Dashboard
your_profile = Profile your_profile = Profile
your_starred = Starred your_starred = Starred
your_settings = Settings your_settings = Settings
invite_friends = Invite Friends
your_friend=Your friend
invite_you_to_join_the_OpenI_AI_Collaboration_Platform_and_enjoy_abundant_free_computing_resources=invite you to join the OpenI AI Collaboration Platform and enjoy abundant free computing resources!
recommender=Recommender


all = All all = All
sources = Sources sources = Sources
@@ -532,6 +536,10 @@ form.name_reserved = The username '%s' is reserved.
form.name_pattern_not_allowed = The pattern '%s' is not allowed in a username. form.name_pattern_not_allowed = The pattern '%s' is not allowed in a username.
form.name_chars_not_allowed = User name '%s' contains invalid characters. form.name_chars_not_allowed = User name '%s' contains invalid characters.


static.invitationdetailsheetname=User Invitation Detail
static.invitationNum=User Invitation Count
static.invitationsheetname=User Invitation
static.srcUserId=Recommended User ID
static.sheetname=User Analysis static.sheetname=User Analysis
static.id=ID static.id=ID
static.name=User Name static.name=User Name
@@ -1293,6 +1301,7 @@ modelconvert.taskurlname=Model transformation task
log_scroll_start=Scroll to top log_scroll_start=Scroll to top
log_scroll_end=Scroll to bottom log_scroll_end=Scroll to bottom
modelconvert.tasknameempty=Please enter a task name. modelconvert.tasknameempty=Please enter a task name.
modelconvert.modelfileempty=Please choose a model file.
modelconvert.inputshapeerror=Format input error, please input such as: 1,1,32,32, corresponding to the input data format. modelconvert.inputshapeerror=Format input error, please input such as: 1,1,32,32, corresponding to the input data format.


modelconvert.manage.create_error1=A model transformation task with the same name already exists. modelconvert.manage.create_error1=A model transformation task with the same name already exists.


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

@@ -70,6 +70,10 @@ your_dashboard=个人中心
your_profile=个人信息 your_profile=个人信息
your_starred=已点赞 your_starred=已点赞
your_settings=设置 your_settings=设置
invite_friends=邀请好友
your_friend=您的好友
invite_you_to_join_the_OpenI_AI_Collaboration_Platform_and_enjoy_abundant_free_computing_resources=邀请您加入启智社区AI协作平台,畅享充沛的免费算力资源!
recommender=推荐人


all=所有 all=所有
sources=自建 sources=自建
@@ -537,7 +541,11 @@ form.name_reserved='%s' 用户名被保留。
form.name_pattern_not_allowed=用户名中不允许使用 "%s"。 form.name_pattern_not_allowed=用户名中不允许使用 "%s"。
form.name_chars_not_allowed=用户名 '%s' 包含无效字符。 form.name_chars_not_allowed=用户名 '%s' 包含无效字符。


static.invitationdetailsheetname=用户邀请详细数据
static.invitationNum=邀请用户数
static.sheetname=用户分析 static.sheetname=用户分析
static.srcUserId=推荐用户ID
static.invitationsheetname=用户邀请分析
static.id=ID static.id=ID
static.name=用户名 static.name=用户名
static.codemergecount=PR数 static.codemergecount=PR数
@@ -1309,6 +1317,7 @@ log_scroll_start=滚动到顶部
log_scroll_end=滚动到底部 log_scroll_end=滚动到底部
modelconvert.tasknameempty=请输入任务名称。 modelconvert.tasknameempty=请输入任务名称。
modelconvert.inputshapeerror=格式输入错误,请输入如:1,1,32,32,与输入数据格式对应。 modelconvert.inputshapeerror=格式输入错误,请输入如:1,1,32,32,与输入数据格式对应。
modelconvert.modelfileempty=请选择模型文件。


modelconvert.manage.create_error1=相同的名称模型转换任务已经存在。 modelconvert.manage.create_error1=相同的名称模型转换任务已经存在。
modelconvert.manage.create_error2=只能创建一个正在运行的模型转换任务。 modelconvert.manage.create_error2=只能创建一个正在运行的模型转换任务。


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

@@ -572,6 +572,19 @@ func RegisterRoutes(m *macaron.Macaron) {
m.Get("/query_user_all", operationReq, repo_ext.QueryUserStaticAll) m.Get("/query_user_all", operationReq, repo_ext.QueryUserStaticAll)
m.Get("/query_user_activity", operationReq, repo_ext.QueryUserActivity) m.Get("/query_user_activity", operationReq, repo_ext.QueryUserActivity)
m.Get("/query_user_login", operationReq, repo_ext.QueryUserLoginInfo) m.Get("/query_user_login", operationReq, repo_ext.QueryUserLoginInfo)

m.Get("/query_invitation_current_month", operationReq, repo_ext.QueryInvitationCurrentMonth)
m.Get("/query_invitation_current_week", operationReq, repo_ext.QueryInvitationCurrentWeek)
m.Get("/query_invitation_last_week", operationReq, repo_ext.QueryInvitationLastWeek)
m.Get("/query_invitation_current_year", operationReq, repo_ext.QueryInvitationCurrentYear)
m.Get("/query_invitation_last30_day", operationReq, repo_ext.QueryInvitationLast30Day)
m.Get("/query_invitation_last_month", operationReq, repo_ext.QueryInvitationLastMonth)
m.Get("/query_invitation_yesterday", operationReq, repo_ext.QueryInvitationYesterday)
m.Get("/query_invitation_all", operationReq, repo_ext.QueryInvitationAll)
m.Get("/query_invitation_userdefine", operationReq, repo_ext.QueryUserDefineInvitationPage)

m.Get("/download_invitation_detail", operationReq, repo_ext.DownloadInvitationDetail)

//cloudbrain board //cloudbrain board
m.Group("/cloudbrainboard", func() { m.Group("/cloudbrainboard", func() {
m.Get("/downloadAll", repo.DownloadCloudBrainBoard) m.Get("/downloadAll", repo.DownloadCloudBrainBoard)
@@ -969,6 +982,7 @@ func RegisterRoutes(m *macaron.Macaron) {
m.Get("", repo.GetModelArtsTrainJobVersion) m.Get("", repo.GetModelArtsTrainJobVersion)
m.Post("/stop_version", cloudbrain.AdminOrOwnerOrJobCreaterRightForTrain, repo_ext.GrampusStopJob) m.Post("/stop_version", cloudbrain.AdminOrOwnerOrJobCreaterRightForTrain, repo_ext.GrampusStopJob)
m.Get("/log", repo_ext.GrampusGetLog) m.Get("/log", repo_ext.GrampusGetLog)
m.Get("/download_log", cloudbrain.AdminOrJobCreaterRightForTrain, repo_ext.GrampusDownloadLog)
}) })
}) })
}, reqRepoReader(models.UnitTypeCloudBrain)) }, reqRepoReader(models.UnitTypeCloudBrain))


+ 5
- 1
routers/api/v1/repo/cloudbrain.go View File

@@ -379,7 +379,11 @@ func CloudbrainDownloadLogFile(ctx *context.Context) {
return return
} }


prefix := "/" + setting.CBCodePathPrefix + job.JobName + "/model"
logDir := "/model"
if job.JobType == string(models.JobTypeInference) {
logDir = cloudbrain.ResultPath
}
prefix := "/" + setting.CBCodePathPrefix + job.JobName + logDir
files, err := storage.GetOneLevelAllObjectUnderDirMinio(setting.Attachment.Minio.Bucket, prefix, "") files, err := storage.GetOneLevelAllObjectUnderDirMinio(setting.Attachment.Minio.Bucket, prefix, "")
if err != nil { if err != nil {
log.Error("query cloudbrain model failed: %v", err) log.Error("query cloudbrain model failed: %v", err)


+ 15
- 0
routers/home.go View File

@@ -106,6 +106,11 @@ func Dashboard(ctx *context.Context) {
log.Info("set image info=" + pictureInfo[0]["url"]) log.Info("set image info=" + pictureInfo[0]["url"])
ctx.Data["image_url"] = pictureInfo[0]["url"] ctx.Data["image_url"] = pictureInfo[0]["url"]
ctx.Data["image_link"] = pictureInfo[0]["image_link"] ctx.Data["image_link"] = pictureInfo[0]["image_link"]

if len(pictureInfo) > 1 {
ctx.Data["invite_image_url"] = pictureInfo[1]["url"]
ctx.Data["invite_image_link"] = pictureInfo[1]["image_link"]
}
} }
if !ctx.User.IsActive && setting.Service.RegisterEmailConfirm { if !ctx.User.IsActive && setting.Service.RegisterEmailConfirm {
ctx.Data["Title"] = ctx.Tr("auth.active_your_account") ctx.Data["Title"] = ctx.Tr("auth.active_your_account")
@@ -728,6 +733,16 @@ func getImageInfo(filename string) ([]map[string]string, error) {
return imageInfo, nil return imageInfo, nil
} }


func GetMapInfo(ctx *context.Context) {
filename := ctx.Query("filename")
url := setting.RecommentRepoAddr + filename
result, err := repository.RecommendContentFromPromote(url)
if err != nil {
log.Info("get file error:" + err.Error())
}
ctx.JSON(http.StatusOK, result)
}

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


+ 49
- 24
routers/repo/ai_model_manage.go View File

@@ -27,6 +27,9 @@ const (
MODEL_LATEST = 1 MODEL_LATEST = 1
MODEL_NOT_LATEST = 0 MODEL_NOT_LATEST = 0
MODEL_MAX_SIZE = 1024 * 1024 * 1024 MODEL_MAX_SIZE = 1024 * 1024 * 1024
STATUS_COPY_MODEL = 1
STATUS_FINISHED = 0
STATUS_ERROR = 2
) )


func saveModelByParameters(jobId string, versionName string, name string, version string, label string, description string, engine int, ctx *context.Context) error { func saveModelByParameters(jobId string, versionName string, name string, version string, label string, description string, engine int, ctx *context.Context) error {
@@ -62,13 +65,9 @@ func saveModelByParameters(jobId string, versionName string, name string, versio
modelSelectedFile := ctx.Query("modelSelectedFile") modelSelectedFile := ctx.Query("modelSelectedFile")
//download model zip //train type //download model zip //train type
if aiTask.ComputeResource == models.NPUResource { if aiTask.ComputeResource == models.NPUResource {
modelPath, modelSize, err = downloadModelFromCloudBrainTwo(id, aiTask.JobName, "", aiTask.TrainUrl, modelSelectedFile)
if err != nil {
log.Info("download model from CloudBrainTwo faild." + err.Error())
return err
}
cloudType = models.TypeCloudBrainTwo cloudType = models.TypeCloudBrainTwo
} else if aiTask.ComputeResource == models.GPUResource { } else if aiTask.ComputeResource == models.GPUResource {
cloudType = models.TypeCloudBrainOne
var ResourceSpecs *models.ResourceSpecs var ResourceSpecs *models.ResourceSpecs
json.Unmarshal([]byte(setting.ResourceSpecs), &ResourceSpecs) json.Unmarshal([]byte(setting.ResourceSpecs), &ResourceSpecs)
for _, tmp := range ResourceSpecs.ResourceSpec { for _, tmp := range ResourceSpecs.ResourceSpec {
@@ -77,24 +76,8 @@ func saveModelByParameters(jobId string, versionName string, name string, versio
aiTask.FlavorName = flaverName aiTask.FlavorName = flaverName
} }
} }
modelPath, modelSize, err = downloadModelFromCloudBrainOne(id, aiTask.JobName, "", aiTask.TrainUrl, modelSelectedFile)
if err != nil {
log.Info("download model from CloudBrainOne faild." + err.Error())
return err
}
cloudType = models.TypeCloudBrainOne
} }
// else if cloudType == models.TypeC2Net {
// if aiTask.ComputeResource == models.NPUResource {
// modelPath, modelSize, err = downloadModelFromCloudBrainTwo(id, aiTask.JobName, "", aiTask.TrainUrl, modelSelectedFile)
// if err != nil {
// log.Info("download model from CloudBrainTwo faild." + err.Error())
// return err
// }
// } else if aiTask.ComputeResource == models.GPUResource {

// }
// }

accuracy := make(map[string]string) accuracy := make(map[string]string)
accuracy["F1"] = "" accuracy["F1"] = ""
accuracy["Recall"] = "" accuracy["Recall"] = ""
@@ -123,6 +106,7 @@ func saveModelByParameters(jobId string, versionName string, name string, versio
Engine: int64(engine), Engine: int64(engine),
TrainTaskInfo: string(aiTaskJson), TrainTaskInfo: string(aiTaskJson),
Accuracy: string(accuracyJson), Accuracy: string(accuracyJson),
Status: STATUS_COPY_MODEL,
} }


err = models.SaveModelToDb(model) err = models.SaveModelToDb(model)
@@ -146,11 +130,44 @@ func saveModelByParameters(jobId string, versionName string, name string, versio


models.UpdateRepositoryUnits(ctx.Repo.Repository, units, deleteUnitTypes) models.UpdateRepositoryUnits(ctx.Repo.Repository, units, deleteUnitTypes)


go asyncToCopyModel(aiTask, id, modelSelectedFile)

log.Info("save model end.") log.Info("save model end.")
notification.NotifyOtherTask(ctx.User, ctx.Repo.Repository, id, name, models.ActionCreateNewModelTask) notification.NotifyOtherTask(ctx.User, ctx.Repo.Repository, id, name, models.ActionCreateNewModelTask)
return nil return nil
} }


func asyncToCopyModel(aiTask *models.Cloudbrain, id string, modelSelectedFile string) {
if aiTask.ComputeResource == models.NPUResource {
modelPath, modelSize, err := downloadModelFromCloudBrainTwo(id, aiTask.JobName, "", aiTask.TrainUrl, modelSelectedFile)
if err != nil {
updateStatus(id, 0, STATUS_ERROR, modelPath, err.Error())
log.Info("download model from CloudBrainTwo faild." + err.Error())
} else {
updateStatus(id, modelSize, STATUS_FINISHED, modelPath, "")
}
} else if aiTask.ComputeResource == models.GPUResource {

modelPath, modelSize, err := downloadModelFromCloudBrainOne(id, aiTask.JobName, "", aiTask.TrainUrl, modelSelectedFile)
if err != nil {
updateStatus(id, 0, STATUS_ERROR, modelPath, err.Error())
log.Info("download model from CloudBrainOne faild." + err.Error())
} else {
updateStatus(id, modelSize, STATUS_FINISHED, modelPath, "")
}
}
}

func updateStatus(id string, modelSize int64, status int, modelPath string, statusDesc string) {
if len(statusDesc) > 400 {
statusDesc = statusDesc[0:400]
}
err := models.ModifyModelStatus(id, modelSize, status, modelPath, statusDesc)
if err != nil {
log.Info("update status error." + err.Error())
}
}

func SaveNewNameModel(ctx *context.Context) { func SaveNewNameModel(ctx *context.Context) {
if !ctx.Repo.CanWrite(models.UnitTypeModelManage) { if !ctx.Repo.CanWrite(models.UnitTypeModelManage) {
ctx.Error(403, ctx.Tr("repo.model_noright")) ctx.Error(403, ctx.Tr("repo.model_noright"))
@@ -331,6 +348,7 @@ func QueryModelByParameters(repoId int64, page int) ([]*models.AiModelManage, in
RepoID: repoId, RepoID: repoId,
Type: -1, Type: -1,
New: MODEL_LATEST, New: MODEL_LATEST,
Status: -1,
}) })
} }


@@ -642,7 +660,6 @@ func queryUserName(intSlice []int64) map[int64]*models.User {
result[user.ID] = user result[user.ID] = user
} }
} }

return result return result
} }


@@ -685,6 +702,7 @@ func SetModelCount(ctx *context.Context) {
RepoID: repoId, RepoID: repoId,
Type: Type, Type: Type,
New: MODEL_LATEST, New: MODEL_LATEST,
Status: -1,
}) })
ctx.Data["MODEL_COUNT"] = count ctx.Data["MODEL_COUNT"] = count
} }
@@ -758,6 +776,7 @@ func ShowModelPageInfo(ctx *context.Context) {
RepoID: repoId, RepoID: repoId,
Type: Type, Type: Type,
New: MODEL_LATEST, New: MODEL_LATEST,
Status: -1,
}) })
if err != nil { if err != nil {
ctx.ServerError("Cloudbrain", err) ctx.ServerError("Cloudbrain", err)
@@ -835,6 +854,7 @@ func QueryModelListForPredict(ctx *context.Context) {
RepoID: repoId, RepoID: repoId,
Type: ctx.QueryInt("type"), Type: ctx.QueryInt("type"),
New: -1, New: -1,
Status: 0,
}) })
if err != nil { if err != nil {
ctx.ServerError("Cloudbrain", err) ctx.ServerError("Cloudbrain", err)
@@ -896,12 +916,17 @@ func QueryOneLevelModelFile(ctx *context.Context) {
log.Info("TypeCloudBrainTwo list model file.") log.Info("TypeCloudBrainTwo list model file.")
prefix := model.Path[len(setting.Bucket)+1:] prefix := model.Path[len(setting.Bucket)+1:]
fileinfos, _ := storage.GetOneLevelAllObjectUnderDir(setting.Bucket, prefix, parentDir) fileinfos, _ := storage.GetOneLevelAllObjectUnderDir(setting.Bucket, prefix, parentDir)
if fileinfos == nil {
fileinfos = make([]storage.FileInfo, 0)
}
ctx.JSON(http.StatusOK, fileinfos) ctx.JSON(http.StatusOK, fileinfos)
} else if model.Type == models.TypeCloudBrainOne { } else if model.Type == models.TypeCloudBrainOne {
log.Info("TypeCloudBrainOne list model file.") log.Info("TypeCloudBrainOne list model file.")
prefix := model.Path[len(setting.Attachment.Minio.Bucket)+1:] prefix := model.Path[len(setting.Attachment.Minio.Bucket)+1:]
fileinfos, _ := storage.GetOneLevelAllObjectUnderDirMinio(setting.Attachment.Minio.Bucket, prefix, parentDir) fileinfos, _ := storage.GetOneLevelAllObjectUnderDirMinio(setting.Attachment.Minio.Bucket, prefix, parentDir)
if fileinfos == nil {
fileinfos = make([]storage.FileInfo, 0)
}
ctx.JSON(http.StatusOK, fileinfos) ctx.JSON(http.StatusOK, fileinfos)
} }

} }

+ 30
- 3
routers/repo/grampus.go View File

@@ -914,7 +914,7 @@ func GrampusTrainJobShow(ctx *context.Context) {
ctx.HTML(http.StatusOK, tplGrampusTrainJobShow) ctx.HTML(http.StatusOK, tplGrampusTrainJobShow)
} }


func GrampusGetLog(ctx *context.Context) {
func GrampusDownloadLog(ctx *context.Context) {
jobID := ctx.Params(":jobid") jobID := ctx.Params(":jobid")
job, err := models.GetCloudbrainByJobID(jobID) job, err := models.GetCloudbrainByJobID(jobID)
if err != nil { if err != nil {
@@ -926,13 +926,40 @@ func GrampusGetLog(ctx *context.Context) {
content, err := grampus.GetTrainJobLog(job.JobID) content, err := grampus.GetTrainJobLog(job.JobID)
if err != nil { if err != nil {
log.Error("GetTrainJobLog failed: %v", err, ctx.Data["MsgID"]) log.Error("GetTrainJobLog failed: %v", err, ctx.Data["MsgID"])
content = ""
}
fileName := job.JobName + "-log.txt"
ctx.Resp.Header().Set("Content-Disposition", "attachment; filename="+fileName)
ctx.Resp.Header().Set("Content-Type", "application/octet-stream")
var b []byte = []byte(content)
ctx.Resp.Write(b)
}

func GrampusGetLog(ctx *context.Context) {
jobID := ctx.Params(":jobid")
job, err := models.GetCloudbrainByJobID(jobID)
if err != nil {
log.Error("GetCloudbrainByJobID failed: %v", err, ctx.Data["MsgID"])
ctx.ServerError(err.Error(), err) ctx.ServerError(err.Error(), err)
return return
} }


content, err := grampus.GetTrainJobLog(job.JobID)
if err != nil {
log.Error("GetTrainJobLog failed: %v", err, ctx.Data["MsgID"])
ctx.ServerError(err.Error(), err)
return
}
var canLogDownload bool
if err != nil {
canLogDownload = false
} else {
canLogDownload = true
}
ctx.JSON(http.StatusOK, map[string]interface{}{ ctx.JSON(http.StatusOK, map[string]interface{}{
"JobName": job.JobName,
"Content": content,
"JobName": job.JobName,
"Content": content,
"CanLogDownload": canLogDownload,
}) })


return return


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

@@ -1551,7 +1551,6 @@ func TrainJobCreateVersion(ctx *context.Context, form auth.CreateModelArtsTrainJ
}) })
} }



task, err := models.GetCloudbrainByJobIDAndVersionName(jobID, PreVersionName) task, err := models.GetCloudbrainByJobIDAndVersionName(jobID, PreVersionName)
if err != nil { if err != nil {
log.Error("GetCloudbrainByJobIDAndVersionName(%s) failed:%v", jobID, err.Error()) log.Error("GetCloudbrainByJobIDAndVersionName(%s) failed:%v", jobID, err.Error())
@@ -2322,6 +2321,7 @@ func InferenceJobIndex(ctx *context.Context) {
RepoID: repoId, RepoID: repoId,
Type: Type, Type: Type,
New: MODEL_LATEST, New: MODEL_LATEST,
Status: 0,
}) })
ctx.Data["MODEL_COUNT"] = model_count ctx.Data["MODEL_COUNT"] = model_count


@@ -2402,6 +2402,7 @@ func inferenceJobNewDataPrepare(ctx *context.Context) error {
RepoID: repoId, RepoID: repoId,
Type: Type, Type: Type,
New: MODEL_LATEST, New: MODEL_LATEST,
Status: 0,
}) })
ctx.Data["MODEL_COUNT"] = model_count ctx.Data["MODEL_COUNT"] = model_count
ctx.Data["datasetType"] = models.TypeCloudBrainTwo ctx.Data["datasetType"] = models.TypeCloudBrainTwo


+ 440
- 0
routers/repo/user_invitation.go View File

@@ -0,0 +1,440 @@
package repo

import (
"fmt"
"net/http"
"net/url"
"sort"
"time"

"code.gitea.io/gitea/models"
"code.gitea.io/gitea/modules/context"
"code.gitea.io/gitea/modules/log"
"code.gitea.io/gitea/modules/setting"
"github.com/360EntSecGroup-Skylar/excelize/v2"
)

func QueryInvitationCurrentMonth(ctx *context.Context) {
// userName := ctx.Query("userName")
// currentTimeNow := time.Now()
// pageEndTime := time.Date(currentTimeNow.Year(), currentTimeNow.Month(), currentTimeNow.Day(), 0, 0, 0, 0, currentTimeNow.Location())
// pageStartTime := time.Date(currentTimeNow.Year(), currentTimeNow.Month(), 1, 0, 0, 0, 0, currentTimeNow.Location())

//queryUserDataPage(ctx, "public.user_business_analysis_current_month", new(models.UserBusinessAnalysisCurrentMonth))
//_, count := models.QueryUserStaticDataByTableName(1, 1, "public.user_business_analysis_current_month", new(models.UserBusinessAnalysisCurrentMonth), userName, 1)

queryDataFromStaticTable(ctx, "public.user_business_analysis_current_month", new(models.UserBusinessAnalysisCurrentMonth))
}

func getInvitationExcelHeader(ctx *context.Context) map[string]string {
excelHeader := make([]string, 0)
excelHeader = append(excelHeader, ctx.Tr("user.static.id"))
excelHeader = append(excelHeader, ctx.Tr("user.static.name"))
excelHeader = append(excelHeader, ctx.Tr("user.static.invitationNum"))
excelHeader = append(excelHeader, ctx.Tr("user.static.phone"))
excelHeader = append(excelHeader, ctx.Tr("user.static.registdate"))

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 getInvitationDetailExcelHeader(ctx *context.Context) map[string]string {
excelHeader := make([]string, 0)
excelHeader = append(excelHeader, ctx.Tr("user.static.id"))
excelHeader = append(excelHeader, ctx.Tr("user.static.name"))
excelHeader = append(excelHeader, ctx.Tr("user.static.srcUserId"))
excelHeader = append(excelHeader, ctx.Tr("user.static.phone"))
excelHeader = append(excelHeader, ctx.Tr("user.static.registdate"))

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 writeInvitationExcel(row int, xlsx *excelize.File, sheetName string, userRecord *models.UserBusinessAnalysisAll) {
rows := fmt.Sprint(row)
var tmp byte
tmp = 0
xlsx.SetCellValue(sheetName, getColumn(tmp)+rows, userRecord.ID)
tmp = tmp + 1
xlsx.SetCellValue(sheetName, getColumn(tmp)+rows, userRecord.Name)
tmp = tmp + 1

xlsx.SetCellValue(sheetName, getColumn(tmp)+rows, userRecord.InvitationUserNum)
tmp = tmp + 1

xlsx.SetCellValue(sheetName, getColumn(tmp)+rows, userRecord.Phone)
tmp = tmp + 1

formatTime := userRecord.RegistDate.Format("2006-01-02 15:04:05")
xlsx.SetCellValue(sheetName, getColumn(tmp)+rows, formatTime[0:len(formatTime)-3])

}

func writeInvitationDetailExcel(row int, xlsx *excelize.File, sheetName string, userRecord *models.Invitation) {
rows := fmt.Sprint(row)
var tmp byte
tmp = 0
xlsx.SetCellValue(sheetName, getColumn(tmp)+rows, userRecord.UserID)
tmp = tmp + 1
xlsx.SetCellValue(sheetName, getColumn(tmp)+rows, userRecord.Name)
tmp = tmp + 1

xlsx.SetCellValue(sheetName, getColumn(tmp)+rows, userRecord.SrcUserID)
tmp = tmp + 1

xlsx.SetCellValue(sheetName, getColumn(tmp)+rows, userRecord.Phone)
tmp = tmp + 1

formatTime := userRecord.CreatedUnix.Format("2006-01-02 15:04:05")
xlsx.SetCellValue(sheetName, getColumn(tmp)+rows, formatTime[0:len(formatTime)-3])

}

func DownloadInvitationDetail(ctx *context.Context) {
xlsx := excelize.NewFile()
sheetName := ctx.Tr("user.static.invitationdetailsheetname")
index := xlsx.NewSheet(sheetName)
xlsx.DeleteSheet("Sheet1")
excelHeader := getInvitationDetailExcelHeader(ctx)
for k, v := range excelHeader {
//设置单元格的值
xlsx.SetCellValue(sheetName, k, v)
}
userNameMap := models.GetAllUserName()
_, count := models.QueryInvitaionPage(1, 1)
var indexTotal int64
indexTotal = 0
row := 1
for {
re, _ := models.QueryInvitaionPage(int(indexTotal), PAGE_SIZE)
log.Info("return count=" + fmt.Sprint(count))
for _, userRecord := range re {
row++
userRecord.Name = userNameMap[userRecord.UserID]
if userRecord.Name == "" {
userRecord.Name = "已注销"
}
writeInvitationDetailExcel(row, xlsx, sheetName, userRecord)
}
indexTotal += PAGE_SIZE
if indexTotal >= count {
break
}
}
//设置默认打开的表单
xlsx.SetActiveSheet(index)
filename := sheetName + ".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())
}
}

func queryDataFromStaticTable(ctx *context.Context, tableName string, queryObj interface{}) {
page, pageSize := getPageInfo(ctx)
userName := ctx.Query("userName")
IsReturnFile := ctx.QueryBool("IsReturnFile")

if IsReturnFile {
//writer exec file.
xlsx := excelize.NewFile()
sheetName := ctx.Tr("user.static.invitationsheetname")
index := xlsx.NewSheet(sheetName)
xlsx.DeleteSheet("Sheet1")
excelHeader := getInvitationExcelHeader(ctx)
for k, v := range excelHeader {
//设置单元格的值
xlsx.SetCellValue(sheetName, k, v)
}
_, count := models.QueryUserInvitationDataByTableName(1, 1, tableName, queryObj, "", 1)
var indexTotal int64
indexTotal = 0
row := 1
for {
re, _ := models.QueryUserInvitationDataByTableName(int(indexTotal), PAGE_SIZE, tableName, queryObj, "", 1)
log.Info("return count=" + fmt.Sprint(count))
for _, userRecord := range re {
row++
writeInvitationExcel(row, xlsx, sheetName, userRecord)
}
indexTotal += PAGE_SIZE
if indexTotal >= count {
break
}
}
//设置默认打开的表单
xlsx.SetActiveSheet(index)
filename := sheetName + "_" + ctx.Tr("user.static."+tableName) + ".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 {
resultRecord, count := models.QueryUserInvitationDataByTableName((page-1)*pageSize, pageSize, tableName, queryObj, userName, 1)
result := make([]models.Invitation, 0)
for _, record := range resultRecord {
invi := models.Invitation{
SrcUserID: record.ID,
Name: record.Name,
InvitationUserNum: record.InvitationUserNum,
Phone: record.Phone,
CreatedUnix: record.RegistDate,
}
result = append(result, invi)
}
mapInterface := make(map[string]interface{})
mapInterface["data"] = result
mapInterface["count"] = count
ctx.JSON(http.StatusOK, mapInterface)
}
}

func QueryInvitationCurrentWeek(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)
// pageEndTime := time.Date(currentTimeNow.Year(), currentTimeNow.Month(), currentTimeNow.Day(), 0, 0, 0, 0, currentTimeNow.Location())
// queryData(ctx, pageStartTime.Unix(), pageEndTime.Unix())
queryDataFromStaticTable(ctx, "public.user_business_analysis_current_week", new(models.UserBusinessAnalysisCurrentWeek))
}

func QueryInvitationLastWeek(ctx *context.Context) {
// currentTimeNow := time.Now()
// offset := int(time.Monday - currentTimeNow.Weekday())
// if offset > 0 {
// offset = -6
// }
// pageEndTime := time.Date(currentTimeNow.Year(), currentTimeNow.Month(), currentTimeNow.Day(), 0, 0, 0, 0, time.Local).AddDate(0, 0, offset)
// pageStartTime := pageEndTime.AddDate(0, 0, -7)
// queryData(ctx, pageStartTime.Unix(), pageEndTime.Unix())

queryDataFromStaticTable(ctx, "public.user_business_analysis_last_week", new(models.UserBusinessAnalysisLastWeek))
}

func QueryInvitationCurrentYear(ctx *context.Context) {
// currentTimeNow := time.Now()
// pageStartTime := time.Date(currentTimeNow.Year(), 1, 1, 0, 0, 0, 0, currentTimeNow.Location())
// pageEndTime := time.Date(currentTimeNow.Year(), currentTimeNow.Month(), currentTimeNow.Day(), 0, 0, 0, 0, currentTimeNow.Location())
// queryData(ctx, pageStartTime.Unix(), pageEndTime.Unix())

queryDataFromStaticTable(ctx, "public.user_business_analysis_current_year", new(models.UserBusinessAnalysisCurrentYear))
}

func QueryInvitationLast30Day(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)
// pageEndTime := time.Date(currentTimeNow.Year(), currentTimeNow.Month(), currentTimeNow.Day(), 0, 0, 0, 0, currentTimeNow.Location())
// queryData(ctx, pageStartTime.Unix(), pageEndTime.Unix())

queryDataFromStaticTable(ctx, "public.user_business_analysis_last30_day", new(models.UserBusinessAnalysisLast30Day))
}

func QueryInvitationLastMonth(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)
// pageEndTime := time.Date(currentTimeNow.Year(), currentTimeNow.Month(), 1, 23, 59, 59, 0, currentTimeNow.Location()).AddDate(0, 0, -1)
// queryData(ctx, pageStartTime.Unix(), pageEndTime.Unix())

queryDataFromStaticTable(ctx, "public.user_business_analysis_last_month", new(models.UserBusinessAnalysisLastMonth))
}

func QueryInvitationYesterday(ctx *context.Context) {
// currentTimeNow := time.Now().AddDate(0, 0, -1)
// pageStartTime := time.Date(currentTimeNow.Year(), currentTimeNow.Month(), currentTimeNow.Day(), 0, 0, 0, 0, time.Local)
// pageEndTime := time.Date(currentTimeNow.Year(), currentTimeNow.Month(), currentTimeNow.Day(), 23, 59, 59, 0, currentTimeNow.Location())
// queryData(ctx, pageStartTime.Unix(), pageEndTime.Unix())

queryDataFromStaticTable(ctx, "public.user_business_analysis_yesterday", new(models.UserBusinessAnalysisYesterday))
}

func QueryInvitationAll(ctx *context.Context) {
// currentTimeNow := time.Now()
// pageStartTime := time.Date(2022, 8, 5, 0, 0, 0, 0, currentTimeNow.Location())
// pageEndTime := time.Date(currentTimeNow.Year(), currentTimeNow.Month(), currentTimeNow.Day(), 0, 0, 0, 0, currentTimeNow.Location())
// queryData(ctx, pageStartTime.Unix(), pageEndTime.Unix())

queryDataFromStaticTable(ctx, "public.user_business_analysis_all", new(models.UserBusinessAnalysisAll))
}

func QueryUserDefineInvitationPage(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)

queryData(ctx, startTime, endTime)
}

func queryData(ctx *context.Context, startTime time.Time, endTime time.Time) {
page, pageSize := getPageInfo(ctx)
IsReturnFile := ctx.QueryBool("IsReturnFile")

dbResult := models.QueryInvitaionByTime(startTime.Unix(), endTime.Unix())

invitaionNumMap := make(map[int64]int, 0)
allUserIds := make([]int64, 0)
for _, record := range dbResult {
if _, ok := invitaionNumMap[record.SrcUserID]; !ok {
invitaionNumMap[record.SrcUserID] = 1
} else {
invitaionNumMap[record.SrcUserID] = invitaionNumMap[record.SrcUserID] + 1
}
}
invitaionNumList := make([]models.Invitation, 0)
for key, value := range invitaionNumMap {
invi := models.Invitation{
SrcUserID: key,
InvitationUserNum: value,
}
invitaionNumList = append(invitaionNumList, invi)
allUserIds = append(allUserIds, key)
}
sort.Slice(invitaionNumList, func(i, j int) bool {
return invitaionNumList[i].InvitationUserNum > invitaionNumList[j].InvitationUserNum
})
if IsReturnFile {
xlsx := excelize.NewFile()
sheetName := ctx.Tr("user.static.invitationsheetname")
index := xlsx.NewSheet(sheetName)
xlsx.DeleteSheet("Sheet1")
excelHeader := getInvitationExcelHeader(ctx)
for k, v := range excelHeader {
//设置单元格的值
xlsx.SetCellValue(sheetName, k, v)
}
end := 100
userMap := make(map[int64]*models.User, 0)
log.Info("len(allUserIds)=" + fmt.Sprint(len(allUserIds)))
for i := 0; i < len(allUserIds); i += 100 {
if end >= len(allUserIds) {
end = len(allUserIds)
}
log.Info("i=" + fmt.Sprint(i) + " end=" + fmt.Sprint(end))
if i == end {
break
}
userList, err := models.GetUsersByIDs(allUserIds[i:end])
if err == nil {
for _, tmp := range userList {
userMap[tmp.ID] = tmp
}
} else {

}
end = end + 100
}
row := 1
log.Info("len(userMap)=" + fmt.Sprint(len(userMap)))
for _, userRecord := range invitaionNumList {
row++
rows := fmt.Sprint(row)
var tmp byte
tmp = 0

xlsx.SetCellValue(sheetName, getColumn(tmp)+rows, userRecord.SrcUserID)
tmp = tmp + 1
name := "已注销"
if userMap[userRecord.SrcUserID] != nil {
name = userMap[userRecord.SrcUserID].Name
}
xlsx.SetCellValue(sheetName, getColumn(tmp)+rows, name)
tmp = tmp + 1

xlsx.SetCellValue(sheetName, getColumn(tmp)+rows, userRecord.InvitationUserNum)
tmp = tmp + 1
Phone := ""
if userMap[userRecord.SrcUserID] != nil {
Phone = userMap[userRecord.SrcUserID].PhoneNumber
}
xlsx.SetCellValue(sheetName, getColumn(tmp)+rows, Phone)
tmp = tmp + 1

formatTime := ""
if userMap[userRecord.SrcUserID] != nil {
formatTime = userMap[userRecord.SrcUserID].CreatedUnix.Format("2006-01-02 15:04:05")
formatTime = formatTime[0 : len(formatTime)-3]
}
xlsx.SetCellValue(sheetName, getColumn(tmp)+rows, formatTime)
}
//设置默认打开的表单
xlsx.SetActiveSheet(index)
filename := sheetName + "_" + getTimeFileName(startTime) + "_" + getTimeFileName(endTime) + ".xlsx"
//filename := sheetName + "_" + ctx.Tr("user.static."+tableName) + ".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 {
result := make([]*models.Invitation, 0)
userIds := make([]int64, 0)
end := len(invitaionNumList) - 1
for start := (page - 1) * pageSize; start <= end; start++ {
invi := invitaionNumList[start]
//todo name phone,createunix
result = append(result, &invi)
userIds = append(userIds, invi.SrcUserID)
if len(result) == pageSize {
break
}
}
userList, err := models.GetUsersByIDs(userIds)
if err == nil {
for _, invi := range result {
tmpUser := userList[0]
for _, tmp := range userList {
if tmp.ID == invi.SrcUserID {
tmpUser = tmp
break
}
}
if invi.SrcUserID == tmpUser.ID {
invi.Name = tmpUser.Name
invi.Phone = tmpUser.PhoneNumber
invi.CreatedUnix = tmpUser.CreatedUnix
} else {
invi.Name = "已注销"
}
}
} else {
log.Info("query user error." + err.Error())
}
mapInterface := make(map[string]interface{})
mapInterface["data"] = result
mapInterface["count"] = len(invitaionNumList)
ctx.JSON(http.StatusOK, mapInterface)
}
}

func getPageInfo(ctx *context.Context) (int, int) {
page := ctx.QueryInt("page")
if page <= 0 {
page = 1
}
pageSize := ctx.QueryInt("pageSize")
if pageSize <= 0 {
pageSize = setting.UI.IssuePagingNum
}
return page, pageSize
}

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

@@ -335,6 +335,7 @@ func RegisterRoutes(m *macaron.Macaron) {
go reward.AcceptStatusChangeAction() go reward.AcceptStatusChangeAction()
m.Get("/action/notification", routers.ActionNotification) m.Get("/action/notification", routers.ActionNotification)
m.Get("/recommend/home", routers.RecommendHomeInfo) m.Get("/recommend/home", routers.RecommendHomeInfo)
m.Get("/dashboard/invitation", routers.GetMapInfo)
//m.Get("/recommend/org", routers.RecommendOrgFromPromote) //m.Get("/recommend/org", routers.RecommendOrgFromPromote)
//m.Get("/recommend/repo", routers.RecommendRepoFromPromote) //m.Get("/recommend/repo", routers.RecommendRepoFromPromote)
m.Get("/recommend/userrank/:index", routers.GetUserRankFromPromote) m.Get("/recommend/userrank/:index", routers.GetUserRankFromPromote)
@@ -509,6 +510,8 @@ func RegisterRoutes(m *macaron.Macaron) {
m.Get("/forgot_password", user.ForgotPasswd) m.Get("/forgot_password", user.ForgotPasswd)
m.Post("/forgot_password", user.ForgotPasswdPost) m.Post("/forgot_password", user.ForgotPasswdPost)
m.Post("/logout", user.SignOut) m.Post("/logout", user.SignOut)
m.Get("/invitation_code", reqSignIn, user.GetInvitaionCode)
m.Get("/invitation_tpl", reqSignIn, user.InviationTpl)
}) })
// ***** END: User ***** // ***** END: User *****




+ 107
- 0
routers/user/Invitation.go View File

@@ -0,0 +1,107 @@
package user

import (
"errors"
"strconv"
"strings"

"code.gitea.io/gitea/models"
"code.gitea.io/gitea/modules/base"
"code.gitea.io/gitea/modules/context"
"code.gitea.io/gitea/modules/log"
"code.gitea.io/gitea/modules/setting"
"code.gitea.io/gitea/services/repository"
)

const (
tplInvitation base.TplName = "user/settings/invite"
)

func GetInvitaionCode(ctx *context.Context) {
page := ctx.QueryInt("page")
if page <= 0 {
page = 1
}
pageSize := ctx.QueryInt("pageSize")
if pageSize <= 0 {
pageSize = setting.UI.IssuePagingNum
}

url := setting.RecommentRepoAddr + "invitaion_page"
result, err := repository.RecommendFromPromote(url)
resultJsonMap := make(map[string]interface{}, 0)
if err == nil {
for _, strLine := range result {
tmpIndex := strings.Index(strLine, "=")
if tmpIndex != -1 {
key := strLine[0:tmpIndex]
value := strLine[tmpIndex+1:]
resultJsonMap[key] = value
}
}
}

if ctx.IsSigned {
resultJsonMap["invitation_code"] = getInvitaionCode(ctx)
re, count := models.QueryInvitaionBySrcUserId(ctx.User.ID, (page-1)*pageSize, pageSize)
for _, record := range re {
tmpUser, err := models.GetUserByID(record.UserID)
if err == nil {
record.Avatar = strings.TrimRight(setting.AppSubURL, "/") + "/user/avatar/" + tmpUser.Name + "/" + strconv.Itoa(-1)
record.IsActive = tmpUser.IsActive
record.Name = tmpUser.Name
}
}
resultJsonMap["invitation_users"] = re
resultJsonMap["invitation_users_count"] = count
}

ctx.JSON(200, resultJsonMap)
}

func InviationTpl(ctx *context.Context) {
ctx.HTML(200, tplInvitation)
}

func RegisteUserByInvitaionCode(invitationcode string, newUserId int64, newPhoneNumber string) error {
user := parseInvitaionCode(invitationcode)
if user == nil {
return errors.New("The invitated user not existed.")
}

if newPhoneNumber != "" {
re := models.QueryInvitaionByPhone(newPhoneNumber)
if re != nil {
if len(re) > 0 {
log.Info("The phone has been invitated. so ingore it.")
return errors.New("The phone has been invitated.")
}
}
} else {
log.Info("the phone number is null. user name=" + user.Name)
}

invitation := &models.Invitation{
SrcUserID: user.ID,
UserID: newUserId,
Phone: newPhoneNumber,
}

err := models.InsertInvitaion(invitation)
if err != nil {
log.Info("insert error," + err.Error())
}
return err
}

func getInvitaionCode(ctx *context.Context) string {
return ctx.User.Name
}

func parseInvitaionCode(invitationcode string) *models.User {
user, err := models.GetUserByName(invitationcode)
if err == nil {
return user
}
return nil
}

+ 28
- 24
routers/user/auth.go View File

@@ -8,11 +8,12 @@ package user
import ( import (
"errors" "errors"
"fmt" "fmt"
"github.com/gomodule/redigo/redis"
"net/http" "net/http"
"strconv" "strconv"
"strings" "strings"


"github.com/gomodule/redigo/redis"

"code.gitea.io/gitea/modules/slideimage" "code.gitea.io/gitea/modules/slideimage"


phoneService "code.gitea.io/gitea/services/phone" phoneService "code.gitea.io/gitea/services/phone"
@@ -352,18 +353,17 @@ func SignInPostCommon(ctx *context.Context, form auth.SignInForm) {
ctx.Redirect(setting.AppSubURL + "/user/two_factor") ctx.Redirect(setting.AppSubURL + "/user/two_factor")
} }



func SignInCloudBrainPost(ctx *context.Context, form auth.SignInForm) { func SignInCloudBrainPost(ctx *context.Context, form auth.SignInForm) {
ctx.Data["PageIsCloudBrainLogin"] = true ctx.Data["PageIsCloudBrainLogin"] = true
ctx.Data["SignInLink"] = setting.AppSubURL + "/user/login/cloud_brain" ctx.Data["SignInLink"] = setting.AppSubURL + "/user/login/cloud_brain"
SignInPostCommon(ctx,form)
SignInPostCommon(ctx, form)
} }


// SignInPost response for sign in request // SignInPost response for sign in request
func SignInPost(ctx *context.Context, form auth.SignInForm) { func SignInPost(ctx *context.Context, form auth.SignInForm) {
ctx.Data["PageIsLogin"] = true ctx.Data["PageIsLogin"] = true
ctx.Data["SignInLink"] = setting.AppSubURL + "/user/login" ctx.Data["SignInLink"] = setting.AppSubURL + "/user/login"
SignInPostCommon(ctx,form)
SignInPostCommon(ctx, form)
} }


// TwoFactor shows the user a two-factor authentication page. // TwoFactor shows the user a two-factor authentication page.
@@ -1264,9 +1264,9 @@ func SignUp(ctx *context.Context) {
// SignUpPost response for sign up information submission // SignUpPost response for sign up information submission
func SignUpPost(ctx *context.Context, cpt *captcha.Captcha, form auth.RegisterForm) { func SignUpPost(ctx *context.Context, cpt *captcha.Captcha, form auth.RegisterForm) {
ctx.Data["Title"] = ctx.Tr("sign_up") ctx.Data["Title"] = ctx.Tr("sign_up")
invitationCode := ctx.Query("invitation_code")
ctx.Data["SignUpLink"] = setting.AppSubURL + "/user/sign_up" ctx.Data["SignUpLink"] = setting.AppSubURL + "/user/sign_up"
ctx.Data["invitationCode"] = invitationCode
ctx.Data["EnableCaptcha"] = setting.Service.EnableCaptcha ctx.Data["EnableCaptcha"] = setting.Service.EnableCaptcha
ctx.Data["RecaptchaURL"] = setting.Service.RecaptchaURL ctx.Data["RecaptchaURL"] = setting.Service.RecaptchaURL
ctx.Data["CaptchaType"] = setting.Service.CaptchaType ctx.Data["CaptchaType"] = setting.Service.CaptchaType
@@ -1366,6 +1366,11 @@ func SignUpPost(ctx *context.Context, cpt *captcha.Captcha, form auth.RegisterFo
} }
log.Trace("Account created: %s", u.Name, ctx.Data["MsgID"]) log.Trace("Account created: %s", u.Name, ctx.Data["MsgID"])


log.Info("enter here, and form.InvitaionCode =" + invitationCode)
if invitationCode != "" {
RegisteUserByInvitaionCode(invitationCode, u.ID, u.PhoneNumber)
}

err := models.AddEmailAddress(&models.EmailAddress{ err := models.AddEmailAddress(&models.EmailAddress{
UID: u.ID, UID: u.ID,
Email: form.Email, Email: form.Email,
@@ -1919,7 +1924,7 @@ func SendVerifyCode(ctx *context.Context, slideImage *slideimage.SlideImage, for
return return
} }


if form.Mode==0 { //注册
if form.Mode == 0 { //注册


if has { if has {
ctx.JSON(http.StatusOK, models.BaseErrorMessage(ctx.Tr("phone.already_register"))) ctx.JSON(http.StatusOK, models.BaseErrorMessage(ctx.Tr("phone.already_register")))
@@ -1935,32 +1940,31 @@ func SendVerifyCode(ctx *context.Context, slideImage *slideimage.SlideImage, for


} else { } else {
//修改手机号 mode=2 绑定手机 //修改手机号 mode=2 绑定手机
u, err := models.GetUserByPhoneNumber(phoneNumber)
if err != nil && !models.IsErrUserNotExist(err) {
log.Warn("sql err", err)
ctx.JSON(http.StatusOK, models.BaseErrorMessage(ctx.Tr("phone.query_err")))
return
}

if u != nil {
u, err := models.GetUserByPhoneNumber(phoneNumber)
if err != nil && !models.IsErrUserNotExist(err) {
log.Warn("sql err", err)
ctx.JSON(http.StatusOK, models.BaseErrorMessage(ctx.Tr("phone.query_err")))
return
}


if u.ID == ctx.User.ID { //没有修改手机号
ctx.JSON(http.StatusOK, models.BaseErrorMessage(ctx.Tr("phone.not_modify")))
return
} else { //修改的手机已经被别的用户注册
ctx.JSON(http.StatusOK, models.BaseErrorMessage(ctx.Tr("phone.already_register")))
return
}
if u != nil {


if u.ID == ctx.User.ID { //没有修改手机号
ctx.JSON(http.StatusOK, models.BaseErrorMessage(ctx.Tr("phone.not_modify")))
return
} else { //修改的手机已经被别的用户注册
ctx.JSON(http.StatusOK, models.BaseErrorMessage(ctx.Tr("phone.already_register")))
return
} }
}


}
}


redisConn := labelmsg.Get() redisConn := labelmsg.Get()
defer redisConn.Close() defer redisConn.Close()


sendTimes, err := phoneService.GetPhoneNumberSendTimes(redisConn, phoneNumber) sendTimes, err := phoneService.GetPhoneNumberSendTimes(redisConn, phoneNumber)
if err != nil && err!=redis.ErrNil {
if err != nil && err != redis.ErrNil {
log.Warn("redis err", err) log.Warn("redis err", err)
ctx.JSON(http.StatusOK, models.BaseErrorMessage(ctx.Tr("phone.query_err"))) ctx.JSON(http.StatusOK, models.BaseErrorMessage(ctx.Tr("phone.query_err")))
return return


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

@@ -148,6 +148,28 @@ func GetRecommendRepoFromPromote(filename string) ([]map[string]interface{}, err
return resultRepo, nil return resultRepo, nil
} }


func RecommendContentFromPromote(url string) (string, error) {
defer func() {
if err := recover(); err != nil {
log.Info("not error.", err)
return
}
}()
resp, err := http.Get(url)
if err != nil || resp.StatusCode != 200 {
log.Info("Get organizations url error=" + err.Error())
return "", err
}
bytes, err := ioutil.ReadAll(resp.Body)
resp.Body.Close()
if err != nil {
log.Info("Get organizations url error=" + err.Error())
return "", err
}
allLineStr := string(bytes)
return allLineStr, nil
}

func RecommendFromPromote(url string) ([]string, error) { func RecommendFromPromote(url string) ([]string, error) {
defer func() { defer func() {
if err := recover(); err != nil { if err := recover(); err != nil {


+ 11
- 1
templates/base/footer.tmpl View File

@@ -52,6 +52,12 @@
<script src="/rotation3D/rotation3D.js?v={{MD5 AppVer}}"></script> <script src="/rotation3D/rotation3D.js?v={{MD5 AppVer}}"></script>
<script> <script>
var jobTask={}; var jobTask={};
var html =document.documentElement;
var lang = html.attributes["lang"]
var isZh = true;
if(lang != null && lang.nodeValue =="en-US" ){
isZh=false;
}
function queryAiCenterInfo(){ function queryAiCenterInfo(){
$.ajax({ $.ajax({
type:"GET", type:"GET",
@@ -96,7 +102,11 @@
tmp["type"]="green"; tmp["type"]="green";
} }
tmp["icon"]=""; tmp["icon"]="";
tmp["content"]=json[i].content;
if(isZh){
tmp["content"]=json[i].content;
}else{
tmp["content"]=json[i].content_en;
}
serverItemList.push(tmp); serverItemList.push(tmp);
} }
} }


+ 4
- 0
templates/base/head_navbar.tmpl View File

@@ -182,6 +182,10 @@
</i> </i>
{{.i18n.Tr "custom.Platform_Tutorial"}} {{.i18n.Tr "custom.Platform_Tutorial"}}
</a> </a>
<a class="item" href="{{AppSubUrl}}/user/invitation_tpl">
<i class="icon users"></i>
{{.i18n.Tr "invite_friends"}}
</a>
{{if .IsAdmin}} {{if .IsAdmin}}
<div class="divider"></div> <div class="divider"></div>




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

@@ -179,6 +179,10 @@
</svg> </svg>
</i> </i>
{{.i18n.Tr "custom.Platform_Tutorial"}} {{.i18n.Tr "custom.Platform_Tutorial"}}
</a>
<a class="item" href="{{AppSubUrl}}/user/invitation_tpl">
<i class="icon users"></i>
{{.i18n.Tr "invite_friends"}}
</a> </a>
{{if .IsAdmin}} {{if .IsAdmin}}
<div class="divider"></div> <div class="divider"></div>


+ 4
- 0
templates/base/head_navbar_home.tmpl View File

@@ -162,6 +162,10 @@
</i> </i>
{{.i18n.Tr "custom.Platform_Tutorial"}} {{.i18n.Tr "custom.Platform_Tutorial"}}
</a> </a>
<a class="item" href="{{AppSubUrl}}/user/invitation_tpl">
<i class="icon users"></i>
{{.i18n.Tr "invite_friends"}}
</a>
{{if .IsAdmin}} {{if .IsAdmin}}
<div class="divider"></div> <div class="divider"></div>




+ 4
- 0
templates/base/head_navbar_pro.tmpl View File

@@ -183,6 +183,10 @@
</i> </i>
{{.i18n.Tr "custom.Platform_Tutorial"}} {{.i18n.Tr "custom.Platform_Tutorial"}}
</a> </a>
<a class="item" href="{{AppSubUrl}}/user/invitation_tpl">
<i class="icon users"></i>
{{.i18n.Tr "invite_friends"}}
</a>
{{if .IsAdmin}} {{if .IsAdmin}}
<div class="divider"></div> <div class="divider"></div>




+ 1
- 2
templates/repo/cloudbrain/trainjob/show.tmpl View File

@@ -533,8 +533,7 @@
</a> </a>


</div> </div>
<div
style="position: relative;border: 1px solid rgba(0,0,0,.2);padding: 0 10px;margin-top: 10px;">
<div style="position: relative;border: 1px solid rgba(0,0,0,.2);padding: 0 10px;margin-top: 10px;">
<span> <span>
<a title="滚动到顶部" style="position: absolute; right: -32px;cursor: pointer;" <a title="滚动到顶部" style="position: absolute; right: -32px;cursor: pointer;"
class="log_top" data-version="{{.VersionName}}"><i class="icon-to-top"></i></a> class="log_top" data-version="{{.VersionName}}"><i class="icon-to-top"></i></a>


+ 10
- 1
templates/repo/grampus/trainjob/show.tmpl View File

@@ -499,7 +499,16 @@
</div> </div>
</div> </div>
<div class="ui tab" data-tab="second{{$k}}"> <div class="ui tab" data-tab="second{{$k}}">
<div style="position: relative;">
<div>
<a id="{{.VersionName}}-log-down"
class='{{if $.canDownload}}ti-download-file{{else}}disabled{{end}}'
href="/api/v1/repos/{{$.RepoRelPath}}/grampus/train-job/{{.JobID}}/download_log">
<i class="ri-download-cloud-2-line"></i>
<span style="margin-left: 0.3rem;">{{$.i18n.Tr "repo.modelarts.download_log"}}</span>
</a>

</div>
<div style="position: relative;border: 1px solid rgba(0,0,0,.2);padding: 0 10px;margin-top: 10px;">
<span> <span>
<a title="{{$.i18n.Tr "repo.log_scroll_start"}}" style="position: absolute; right: -32px;cursor: pointer;" <a title="{{$.i18n.Tr "repo.log_scroll_start"}}" style="position: absolute; right: -32px;cursor: pointer;"
class="log_top" data-version="{{.VersionName}}"><i class="icon-to-top"></i></a> class="log_top" data-version="{{.VersionName}}"><i class="icon-to-top"></i></a>


+ 9
- 2
templates/repo/modelmanage/convertIndex.tmpl View File

@@ -241,7 +241,7 @@
</div> </div>
</div> </div>
</div> </div>
<div class="unite min_title inline fields required">
<div class="unite min_title inline fields required" id="ModelFile_Div">
<div class="three wide field right aligned"> <div class="three wide field right aligned">
<label for="choice_file">{{$.i18n.Tr "repo.model.manage.modelfile"}}</label> <label for="choice_file">{{$.i18n.Tr "repo.model.manage.modelfile"}}</label>
</div> </div>
@@ -382,7 +382,14 @@
data['DestFormat'] = $('#DestFormat').val(); data['DestFormat'] = $('#DestFormat').val();
data['NetOutputFormat']= $('#NetOutputFormat').val(); data['NetOutputFormat']= $('#NetOutputFormat').val();
data['ModelFile'] = $('#ModelFile').val(); data['ModelFile'] = $('#ModelFile').val();

if(data['ModelFile']==""){
$('.ui.error.message').text("{{.i18n.Tr "repo.modelconvert.modelfileempty"}}")
$('.ui.error.message').css('display','block')
$("#ModelFile_Div").addClass("error")
return false
}else{
$("#ModelFile_Div").removeClass("error")
}
$.post(`${repolink}/modelmanage/create_model_convert`,data,(result) => { $.post(`${repolink}/modelmanage/create_model_convert`,data,(result) => {
console.log("result=" + result); console.log("result=" + result);
if(result.result_code ==0){ if(result.result_code ==0){


+ 2
- 2
templates/repo/modelmanage/index.tmpl View File

@@ -46,9 +46,9 @@
<div class="repository release dataset-list view"> <div class="repository release dataset-list view">
{{template "repo/header" .}} {{template "repo/header" .}}
<!-- 列表容器 --> <!-- 列表容器 -->
<div class="ui container {{if ne $.MODEL_COUNT 0}}active loader {{end}}" id="loadContainer">
<div class="ui container {{if ne $.MODEL_COUNT 0}}active loader {{end}}" id="loadContainer" >
{{template "base/alert" .}} {{template "base/alert" .}}
<div class="ui two column stackable grid">
<div class="ui two column stackable grid" style="display: none;">
<div class="column"> <div class="column">
<div class="ui blue small menu compact selectcloudbrain"> <div class="ui blue small menu compact selectcloudbrain">
<a class="active item" href="{{.RepoLink}}/modelmanage/show_model">{{$.i18n.Tr "repo.model.list"}}</a> <a class="active item" href="{{.RepoLink}}/modelmanage/show_model">{{$.i18n.Tr "repo.model.list"}}</a>


+ 38
- 0
templates/user/auth/signup_inner.tmpl View File

@@ -35,6 +35,9 @@
{{if .DisableRegistration}} {{if .DisableRegistration}}
<p>{{.i18n.Tr "auth.disable_register_prompt"}}</p> <p>{{.i18n.Tr "auth.disable_register_prompt"}}</p>
{{else}} {{else}}
<div class="field invitation_tips" style="font-weight:400;font-size:14px;color:rgba(250,140,22,1);{{if not .invitationCode}}display:none;{{end}}">
<span>{{.i18n.Tr "your_friend"}} <span class="__invitation_code__">{{.invitationCode}}</span> {{.i18n.Tr "invite_you_to_join_the_OpenI_AI_Collaboration_Platform_and_enjoy_abundant_free_computing_resources"}}</span>
</div>
<div class="field {{if and (.Err_UserName) (or (not .LinkAccountMode) (and .LinkAccountMode .LinkAccountModeRegister))}}error{{end}}"> <div class="field {{if and (.Err_UserName) (or (not .LinkAccountMode) (and .LinkAccountMode .LinkAccountModeRegister))}}error{{end}}">
<input id="user_name" name="user_name" value="{{.user_name}}" placeholder="{{.i18n.Tr "username"}}" autofocus required> <input id="user_name" name="user_name" value="{{.user_name}}" placeholder="{{.i18n.Tr "username"}}" autofocus required>
</div> </div>
@@ -71,6 +74,16 @@
{{template "user/auth/phone_verify" .}} {{template "user/auth/phone_verify" .}}
</div> </div>
{{end}} {{end}}
<div class="field">
<div style="display:flex;">
<div style="display:flex;align-items:center;">
<span>{{.i18n.Tr "recommender"}}</span>
</div>
<input style="flex:1;margin-left:12px;" id="invitation_code" name="invitation_code" value="{{.invitationCode}}" {{if .invitationCode}}readonly="true"{{end}} autocomplete="off" />
</div>
</div>

<div class="field"> <div class="field">
<div class="ui checkbox"> <div class="ui checkbox">
<input name="agree" type="checkbox" tabindex="0" class="hidden" {{if .agree}}checked{{end}}><label>{{.i18n.Tr "use_and_privacy_agree" "/home/term" "/home/privacy" | Safe}}</label> <input name="agree" type="checkbox" tabindex="0" class="hidden" {{if .agree}}checked{{end}}><label>{{.i18n.Tr "use_and_privacy_agree" "/home/term" "/home/privacy" | Safe}}</label>
@@ -94,3 +107,28 @@
</div> </div>
</div> </div>
</div> </div>
<script>
; (function() {
var getUrlParams = function() {
var url = window.location.search;
var index = url.indexOf('?');
var obj = {};
if (index !== -1) {
var str = url.substr(1);
var arr = str.split('&');
for (var i = 0, iLen = arr.length; i < iLen; i++) {
var list = arr[i].split('=');
obj[list[0]] = list[1];
}
}
return obj;
};
var sharedUser = getUrlParams()['sharedUser'];
if (sharedUser) {
setTimeout(function() {
$('.invitation_tips').show().find('.__invitation_code__').text(sharedUser);
$('input#invitation_code').val(sharedUser).attr('readonly', true);
}, 20);
}
})();
</script>

+ 5
- 0
templates/user/dashboard/repolist.tmpl View File

@@ -18,6 +18,11 @@
v-cloak v-cloak
> >
<div> <div>
{{if .invite_image_url}}
<div style="height:60px;">
<a href="{{.invite_image_link}}" target="_blank"><img src="{{.invite_image_url}}" style="width:100%;height:100%" /></a>
</div>
{{end}}
<div v-if="!isOrganization" class="ui two item tabable menu"> <div v-if="!isOrganization" class="ui two item tabable menu">
<a :class="{item: true, active: tab === 'repos'}" @click="changeTab('repos')">{{.i18n.Tr "repository"}}</a> <a :class="{item: true, active: tab === 'repos'}" @click="changeTab('repos')">{{.i18n.Tr "repository"}}</a>
<a :class="{item: true, active: tab === 'organizations'}" @click="changeTab('organizations')">{{.i18n.Tr "organization"}}</a> <a :class="{item: true, active: tab === 'organizations'}" @click="changeTab('organizations')">{{.i18n.Tr "organization"}}</a>


+ 34
- 1
templates/user/profile.tmpl View File

@@ -48,7 +48,40 @@
</li> </li>
{{end}} {{end}}
{{end}} {{end}}
<li>{{svg "octicon-clock" 16}} {{.i18n.Tr "user.join_on"}} {{.Owner.CreatedUnix.FormatShort}}</li>
<li>
{{svg "octicon-clock" 16}} {{.i18n.Tr "user.join_on"}} {{.Owner.CreatedUnix.FormatShort}}
{{if and .IsSigned (eq .SignedUserName .Owner.Name)}}
<div class=__ad_profile_c__ style="margin-top:6px;height:50px;display:none;">
<a class="__ad_profile__" href="" target="_blank"><img src="" style="width:100%;height:100%" /></a>
</div>
<script>
;(function(){
document.addEventListener("DOMContentLoaded", function() {
$.ajax({
type: "GET",
url: "/dashboard/invitation",
dataType: "json",
data: { filename: 'ad-profile.json' },
success: function (res) {
try {
var data = JSON.parse(res);
$('.__ad_profile__').attr('href', data.url).find('img').attr('src', data.src);
$('.__ad_profile_c__').show();
} catch (err) {
console.log(err);
}
},
error: function (err) {
console.log(err);
}
});
});
})();
</script>
{{end}}
</li>
{{if and .Orgs .HasOrgsVisible}} {{if and .Orgs .HasOrgsVisible}}
<li style="border-bottom: none;padding-bottom: 0;"><div style="border-bottom: 1px solid #eaeaea;padding-top: 5px;padding-bottom:5px"> <b>{{.i18n.Tr "organization"}} </b></div></li> <li style="border-bottom: none;padding-bottom: 0;"><div style="border-bottom: 1px solid #eaeaea;padding-top: 5px;padding-bottom:5px"> <b>{{.i18n.Tr "organization"}} </b></div></li>


+ 7
- 0
templates/user/settings/invite.tmpl View File

@@ -0,0 +1,7 @@
{{template "base/head" .}}
<link rel="stylesheet" href="{{StaticUrlPrefix}}/css/vp-user-invite.css?v={{MD5 AppVer}}" />
<div class="user settings invite">
<div id="__vue-root"></div>
</div>
<script src="{{StaticUrlPrefix}}/js/vp-user-invite.js?v={{MD5 AppVer}}"></script>
{{template "base/footer" .}}

+ 624
- 473
web_src/js/components/Model.vue
File diff suppressed because it is too large
View File


+ 140
- 0
web_src/js/features/ad.js View File

@@ -0,0 +1,140 @@
; (function () {
/*const adList = [
{
"width": 144,
"height": 108,
"pos": {
"left": 50,
"bottom": 50
},
"src": "https://git.openi.org.cn/OpenIOSSG/promote/raw/branch/master/imgs/invitation/pic-01.png",
"url": "/user/invitation_tpl",
"show": true
},
{
"width": 144,
"height": 108,
"pos": {
"right": 50,
"bottom": 50
},
"src": "https://git.openi.org.cn/OpenIOSSG/promote/raw/branch/master/imgs/invitation/pic-01.png",
"url": "/user/invitation_tpl",
"show": false
}
];*/
const exceptPages = [
// '/user/invitation_tpl'
];

function initAd() {
$.ajax({
type: "GET",
url: "/dashboard/invitation",
dataType: "json",
data: { filename: 'ad-pop-up.json' },
success: function (res) {
try {
var data = JSON.parse(res);
createAd(data);
} catch (err) {
console.log(err);
}
},
error: function (err) {
console.log(err);
}
});
}

function createAd(adList) {
const adInfoStr = window.localStorage.getItem('ads') || '{}';
let adInfoObj = JSON.parse(adInfoStr);
const today = new Date();
const timeTodayEnd = new Date(today.getFullYear(), today.getMonth(), today.getDate() + 1).getTime();
const now = Date.now();
const expTime = now + 4 * 60 * 60 * 1000;
if (!adInfoObj.expires || adInfoObj.expires <= now) {
adInfoObj = {
expires: Math.min(timeTodayEnd, expTime),
};
}
for (var i = 0, iLen = adList.length; i < iLen; i++) {
var adI = adList[i];
if (adI.show === false) continue;
var showOr = adInfoObj[i] === false ? false : true;
adInfoObj[i] = showOr;
if (!showOr) continue;
var adEl = $(`<div class="__ad_c__" _id="${i}" style="position:fixed;z-index:99999999;
width:${adI.width}px;height:${adI.height}px;
left:${adI.pos.left !== undefined ? adI.pos.left + 'px' : ''};
top:${adI.pos.top !== undefined ? adI.pos.top + 'px' : ''};
right:${adI.pos.right !== undefined ? adI.pos.right + 'px' : ''};
bottom:${adI.pos.bottom !== undefined ? adI.pos.bottom + 'px' : ''};">
<a style="" href="${adI.url}" target="_blank">
<img style="height:100%;width:100%;" src="${adI.src}" />
</a>
<div class="__ad_close_c__" style="position:absolute;top:6px;right:6px;">
<i class="ri-close-circle-line __ad_close__" style="color:white;font-size:18px;cursor:pointer;"></i>
</div>
</div>`);
adEl.data('data', adI);
$('body').append(adEl);
}
window.localStorage.setItem('ads', JSON.stringify(adInfoObj));
}

function initAdEvent() {
$('body').on('click', '.__ad_c__ .__ad_close__', function () {
var self = $(this);
var adEl = self.closest('.__ad_c__');
var adId = adEl.attr('_id');
const adInfoStr = window.localStorage.getItem('ads') || '{}';
const adInfoObj = JSON.parse(adInfoStr);
adInfoObj[adId] = false;
window.localStorage.setItem('ads', JSON.stringify(adInfoObj));
adEl.remove();
});
var scrollTopOld = $(document).scrollTop();
var timeHandler = null;
$(window).scroll(function (e) {
var scrollTop = $(document).scrollTop();
var offSet = scrollTop - scrollTopOld;
scrollTopOld = scrollTop;
timeHandler && clearTimeout(timeHandler);
$('.__ad_c__').each(function (_, item) {
var self = $(item);
var adData = self.data('data');
if (adData.pos.bottom !== undefined) {
self.animate({ bottom: adData.pos.bottom + offSet + 'px' }, 0);
}
if (adData.pos.top !== undefined) {
self.animate({ top: adData.pos.top - offSet + 'px' }, 0);
}
})
timeHandler = setTimeout(function () {
$('.__ad_c__').each(function (_, item) {
var self = $(item);
var adData = self.data('data');
if (adData.pos.bottom !== undefined) {
self.animate({ bottom: adData.pos.bottom + 'px' }, 0);
}
if (adData.pos.top !== undefined) {
self.animate({ top: adData.pos.top + 'px' }, 0);
}
})
}, 20);
});
}

setTimeout(function () {
if (!$('meta[name="_uid"]').length) { // 未登录,不显示
window.localStorage.removeItem('ads');
return;
}
var pathName = window.location.pathname;
if (exceptPages.indexOf(pathName) > -1) return; // 排除页,不显示
initAd();
initAdEvent();
}, 0);
})();

+ 8
- 0
web_src/js/features/i18nVue.js View File

@@ -97,6 +97,10 @@ export const i18nVue = {
model_delete: "删除", model_delete: "删除",
model_create_title: "导入新模型", model_create_title: "导入新模型",
model_create_version_title: "创建模型新版本", model_create_version_title: "创建模型新版本",
model_status:"状态",
model_wait:"模型加载中",
model_success:"模型加载成功",
model_failed:"模型加载失败",
}, },
US: { US: {
computer_vision: "computer vision", computer_vision: "computer vision",
@@ -200,5 +204,9 @@ export const i18nVue = {
model_delete: "Delete", model_delete: "Delete",
model_create_title: "Import new model", model_create_title: "Import new model",
model_create_version_title: "Create a new version of the model", model_create_version_title: "Create a new version of the model",
model_status: "Status",
model_wait:"Loading",
model_success:"Success",
model_failed:"Failed",
}, },
}; };

+ 1
- 0
web_src/js/index.js View File

@@ -52,6 +52,7 @@ import router from "./router/index.js";
import { Message } from "element-ui"; import { Message } from "element-ui";


import { i18nVue } from "./features/i18nVue.js"; import { i18nVue } from "./features/i18nVue.js";
import './features/ad.js';


Vue.use(ElementUI); Vue.use(ElementUI);
Vue.prototype.$axios = axios; Vue.prototype.$axios = axios;


+ 15
- 5
web_src/js/standalone/phoneverify.js View File

@@ -77,7 +77,7 @@
}); });


function mouseMove(e) { function mouseMove(e) {
var _clientX = e.clientX;
var _clientX = e.clientX !== undefined ? e.clientX : e.targetTouches[0].clientX;
var offset = _clientX - clientX; var offset = _clientX - clientX;
var triggerEl = self.dom.find('.slide-trigger'); var triggerEl = self.dom.find('.slide-trigger');
var triggerWidth = triggerEl.width(); var triggerWidth = triggerEl.width();
@@ -99,6 +99,8 @@
function mouseUp(e) { function mouseUp(e) {
$(document).off('mousemove', mouseMove); $(document).off('mousemove', mouseMove);
$(document).off('mouseup', mouseUp); $(document).off('mouseup', mouseUp);
$(document).off('touchmove', mouseMove);
$(document).off('touchend', mouseUp);
self.isMoving = false; self.isMoving = false;
$.ajax({ $.ajax({
url: '/verifySlideImage', url: '/verifySlideImage',
@@ -106,7 +108,7 @@
dataType: 'json', dataType: 'json',
data: { data: {
slide_id: self.imgID, slide_id: self.imgID,
x: parseInt(self.dom.find('.slide-image-small').position().left)
x: parseInt(self.dom.find('.slide-image-small').position().left / self.dom.find('.slide-image-big').attr('scale'))
}, },
success: function (res) { success: function (res) {
if (res && res.Code === 0) { if (res && res.Code === 0) {
@@ -138,13 +140,18 @@
}); });
} }


this.dom.find('.slide-trigger').on('mousedown', function (e) {
function mouseDown(e) {
if (self.verifySucess) return; if (self.verifySucess) return;
clientX = e.clientX;
clientX = e.clientX !== undefined ? e.clientX : e.targetTouches[0].clientX;
oLeft = $(this).position().left; oLeft = $(this).position().left;
$(document).on('mousemove', mouseMove); $(document).on('mousemove', mouseMove);
$(document).on('mouseup', mouseUp); $(document).on('mouseup', mouseUp);
});
$(document).on('touchmove', mouseMove);
$(document).on('touchend', mouseUp);
}

this.dom.find('.slide-trigger').on('mousedown', mouseDown);
this.dom.find('.slide-trigger').on('touchstart', mouseDown);


this.dom.find('.verify-code-send-btn').on('click', function () { this.dom.find('.verify-code-send-btn').on('click', function () {
if (!self.canSendCode) return; if (!self.canSendCode) return;
@@ -199,6 +206,7 @@
self.dom.find('.slide-bar-wrap').css('display', 'flex'); self.dom.find('.slide-bar-wrap').css('display', 'flex');
self.dom.find('.verify-code-c').css('display', 'flex'); self.dom.find('.verify-code-c').css('display', 'flex');
self.dom.find('.modify-phone-number').hide(); self.dom.find('.modify-phone-number').hide();
self.refreshImages();
}); });
}; };


@@ -210,6 +218,8 @@
this.imgID = ''; this.imgID = '';
this.dom.find('.slide-bar').removeClass('sucess error').css('width', '30px'); this.dom.find('.slide-bar').removeClass('sucess error').css('width', '30px');
this.dom.find('.slide-trigger').removeClass('sucess error').css('left', '0px'); this.dom.find('.slide-trigger').removeClass('sucess error').css('left', '0px');
var scale = this.dom.find('.slide-bar-bg').width() / 391;
this.dom.find('.slide-image-big').css('transform', `scale(${scale})`).attr('scale', scale);
this.dom.find('.slide-trigger .icon').hide(); this.dom.find('.slide-trigger .icon').hide();
this.dom.find('.slide-trigger .icon.arrow').show(); this.dom.find('.slide-trigger .icon.arrow').show();
this.dom.find('.slide-txt').show(); this.dom.find('.slide-txt').show();


+ 2
- 1
web_src/less/standalone/_phoneverify.less View File

@@ -174,10 +174,11 @@
width: 391px; width: 391px;
height: 196px; height: 196px;
top: 36px; top: 36px;
left: 0;
left: 1px;
border-radius: 2px; border-radius: 2px;
z-index: 100; z-index: 100;
display: none; display: none;
transform-origin: 0 0;
} }


.__phone-verify-code .slide-bar-c .slide-image-small { .__phone-verify-code .slide-bar-c .slide-image-small {


+ 11
- 0
web_src/vuepages/apis/modules/userinvite.js View File

@@ -0,0 +1,11 @@
import service from '../service';

// 邀请好友页面数据
export const getUserInvitationCode = (params) => { // page pageSize
return service({
url: '/user/invitation_code',
method: 'get',
params: params,
data: {},
});
}

+ 14
- 0
web_src/vuepages/langs/config/en-US.js View File

@@ -162,6 +162,20 @@ const en = {
available: 'Available', available: 'Available',
notAvailable: 'Not Available', notAvailable: 'Not Available',
}, },
user: {
inviteFriends: 'Invite Friends',
inviteFriendsTips: 'Copy QR code or invite registration link to share with friends',
clickToViewTheEventDetails: 'Click to view the event details',
copyRegistrationInvitationLink: 'Copy registration invitation link',
registrationAdress: 'Registration Adress: ',
recommender: 'Recommender: ',
invitedFriends: 'Invited friends',
registrationTime: 'Registration time',
theSharedContentHasBeenCopiedToTheClipboard: 'The shared content has been copied to the clipboard',
copyError: 'Copy error',
Activated: 'Activated',
notActive: 'Not active',
},
} }


export default en; export default en;

+ 14
- 0
web_src/vuepages/langs/config/zh-CN.js View File

@@ -162,6 +162,20 @@ const zh = {
available: '可用', available: '可用',
notAvailable: '不可用', notAvailable: '不可用',
}, },
user: {
inviteFriends: '邀请好友',
inviteFriendsTips: '复制二维码或者注册邀请链接分享给好友',
clickToViewTheEventDetails: '点击查看活动详情',
copyRegistrationInvitationLink: '复制注册邀请链接',
registrationAdress: '注册地址:',
recommender: '推荐人:',
invitedFriends: '已邀请好友',
registrationTime: '注册时间',
theSharedContentHasBeenCopiedToTheClipboard: '分享内容已复制到剪切板',
copyError: '复制错误',
Activated: '已激活',
notActive: '未激活',
},
} }


export default zh; export default zh;

+ 319
- 0
web_src/vuepages/pages/user/invite/index.vue View File

@@ -0,0 +1,319 @@
<template>
<div class="ui container">
<div class="title">
<div class="title-1"><span>{{ $t('user.inviteFriends') }}</span></div>
<div class="title-2"><span>{{ $t('user.inviteFriendsTips') }}</span></div>
</div>
<div class="content-1">
<div class="img-c">
<img class="img" :src="bannerImg" />
<div class="txt">{{ bannerTitle }}</div>
</div>
<div class="descr">
<span>{{ pageLinkDesc }}</span>
<a :href="pageLink" target="_blank">{{ $t('user.clickToViewTheEventDetails') }}</a>
</div>
</div>
<div class="content-2">
<div class="txt-c">
<div class="txt-1">
<span>{{ pageOpeniDesc }}</span>
</div>
<div class="txt-2"><span>{{ $t('user.registrationAdress') }}</span><span>{{ invitationLink + invitationCode
}}</span></div>
<div class="txt-3"><span>{{ $t('user.recommender') }}</span><span>{{ invitationCode }}</span></div>
<el-button class="__copy_link_btn__" type="primary">{{ $t('user.copyRegistrationInvitationLink') }}</el-button>
</div>
<div class="qr-code">
<div id="__qr-code__" style="width:120px;height:120px;"></div>
</div>
</div>
<div class="table-container">
<div>
<el-table border :data="tableData" style="width:100%" v-loading="loading" stripe>
<el-table-column prop="ID" :label="$t('user.invitedFriends')" align="left" header-align="center">
<template slot-scope="scope">
<div style="display:flex;align-items:center;padding-left:20px;">
<img :src="scope.row.avatarSrc" alt="" style="height:45px;width:45px;margin-right:10px;" />
<a :href="scope.row.userLink" style="font-weight:500;font-size:15px;">{{ scope.row.userName }}</a>
</div>
</template>
</el-table-column>
<el-table-column prop="statusStr" :label="$t('status')" align="center" header-align="center">
<template slot-scope="scope">
<span :style="{ color: scope.row.statusColor }">{{ scope.row.statusStr }}</span>
</template>
</el-table-column>
<el-table-column prop="regTime" :label="$t('user.registrationTime')" align="center" header-align="center">
</el-table-column>
<template slot="empty">
<span>{{
loading ? $t('loading') : $t('noData')
}}</span>
</template>
</el-table>
</div>
<div class="__r_p_pagination">
<div style="margin-top: 2rem">
<div class="center">
<el-pagination background @current-change="currentChange" :current-page="pageInfo.curpage"
:page-sizes="pageInfo.pageSizes" :page-size="pageInfo.pageSize"
layout="total, sizes, prev, pager, next, jumper" :total="pageInfo.total">
</el-pagination>
</div>
</div>
</div>
</div>
</div>
</template>

<script>
import Clipboard from 'clipboard';
import QRCode from 'qrcodejs2';
import { formatDate } from 'element-ui/lib/utils/date-util';
import { getUserInvitationCode } from '~/apis/modules/userinvite';

export default {
data() {
return {
bannerImg: '',
bannerTitle: '',
pageLink: '',
pageLinkDesc: '',
invitationLink: window.origin + '/user/sign_up?sharedUser=',
invitationCode: '',
pageOpeniDesc: '',

loading: false,
tableData: [],
pageInfo: {
curpage: 1,
pageSize: 10,
pageSizes: [10],
total: 0,
},
};
},
components: {},
methods: {
initCopy() {
const clipboard = new Clipboard('.__copy_link_btn__', {
text: () => {
return `${this.pageOpeniDesc}\n${this.$t('user.registrationAdress')}${this.invitationLink + this.invitationCode}\n${this.$t('user.recommender')}${this.invitationCode}`;
},
});
clipboard.on('success', (e) => {
this.$message({
type: 'success',
message: this.$t('user.theSharedContentHasBeenCopiedToTheClipboard')
});
});
clipboard.on('error', (e) => {
this.$message({
type: 'error',
message: this.$t('user.copyError')
});
});
},
transRowData(item) {
return {
userName: item.Name,
avatarSrc: item.Avatar,
userLink: window.origin + '/' + item.Name,
statusStr: item.IsActive ? this.$t('user.Activated') : this.$t('user.notActive'),
statusColor: item.IsActive ? 'rgb(82, 196, 26)' : 'rgb(245, 34, 45)',
regTime: formatDate(new Date(item.CreatedUnix * 1000), 'yyyy-MM-dd HH:mm:ss'),
}
},
initData() {
getUserInvitationCode({ page: this.pageInfo.curpage, pageSize: this.pageInfo.pageSize }).then(res => {
res = res.data;
if (res) {
this.bannerImg = res.page_banner_img;
this.bannerTitle = res.page_banner_title;
this.pageLink = res.page_link;
this.pageLinkDesc = res.page_link_desc;
this.invitationCode = res.invitation_code;
this.pageOpeniDesc = res.page_openi_desc;
this.tableData = (res.invitation_users || []).map((item, index) => {
return this.transRowData(item);
});
this.pageInfo.total = res.invitation_users_count;
const qrCode = new QRCode("__qr-code__", {
text: this.invitationLink + this.invitationCode,
width: 120,
height: 120,
colorDark: '#000000',
colorLight: '#ffffff',
correctLevel: QRCode.CorrectLevel.H
});
}
}).catch(err => {
console.log(err);
});
},
getTableData() {
const params = {
page: this.pageInfo.curpage,
pageSize: this.pageInfo.pageSize,
};
this.loading = true;
getUserInvitationCode(params).then(res => {
this.loading = false;
res = res.data;
const data = (res.invitation_users || []).map((item, index) => {
return this.transRowData(item);
});
this.tableData = data;
this.pageInfo.total = res.invitation_users_count;
}).catch(err => {
console.log(err);
this.loading = false;
});
},
currentChange(val) {
this.pageInfo.curpage = val;
this.getTableData();
},
},
mounted() {
this.initData();
this.initCopy();
},
beforeDestroy() {
},
};
</script>

<style scoped lang="less">
.title {
margin-top: 15px;
margin-bottom: 15px;

.title-1 {
font-weight: 500;
font-size: 20px;
color: rgba(16, 16, 16, 1);
margin-bottom: 10px;
}

.title-2 {
font-weight: 400;
font-size: 14px;
color: rgba(136, 136, 136, 1);
}
}

.content-1 {
margin-bottom: 32px;

.img-c {
height: 80px;
position: relative;

.img {
width: 100%;
height: 100%;
}

.txt {
position: absolute;
width: 100%;
height: 100%;
left: 0;
top: 0;
line-height: 80px;
padding-left: 25px;
font-weight: 500;
font-size: 24px;
color: rgb(255, 255, 255);
}
}

.descr {
font-weight: 300;
font-size: 16px;
color: rgb(16, 16, 16);
padding: 25px;
border-left: 1px solid rgba(0, 0, 0, 0.1);
border-right: 1px solid rgba(0, 0, 0, 0.1);
border-bottom: 1px solid rgba(0, 0, 0, 0.1);
border-radius: 0px 0px 4px 4px;
}
}

.content-2 {
display: flex;
background-color: rgb(228, 242, 255);
border-color: rgb(228, 242, 255);
border-width: 1px;
border-style: solid;
border-radius: 5px;
padding: 25px;
margin-bottom: 32px;

.txt-c {
flex: 1;
font-weight: 300;
font-size: 16px;
color: rgb(16, 16, 16);

span {
line-height: 24px;
}

div {
margin-bottom: 6px;
}

.txt-3 {
margin-bottom: 15px;
}
}

.__copy_link_btn__ {
font-size: 14px;
padding: 11px 15px;
background: rgb(21, 114, 255);
border-radius: 0;
}

.qr-code {
width: 150px;
display: flex;
flex-direction: column;
align-items: end;
}
}

.table-container {
margin-bottom: 16px;

/deep/ .el-table__header {
th {
background: rgb(245, 245, 246);
font-size: 14px;
color: rgb(36, 36, 36);
font-weight: 400;
}
}

/deep/ .el-table__body {
td {
font-size: 14px;
}
}

.op-btn {
cursor: pointer;
font-size: 12px;
color: rgb(25, 103, 252);
margin: 0 5px;
}
}

.center {
display: flex;
justify-content: center;
}
</style>

+ 17
- 0
web_src/vuepages/pages/user/invite/vp-user-invite.js View File

@@ -0,0 +1,17 @@
import Vue from 'vue';
import ElementUI from 'element-ui';
import 'element-ui/lib/theme-chalk/index.css';
import localeEn from 'element-ui/lib/locale/lang/en';
import localeZh from 'element-ui/lib/locale/lang/zh-CN';
import { i18n, lang } from '~/langs';
import App from './index.vue';

Vue.use(ElementUI, {
locale: lang === 'zh-CN' ? localeZh : localeEn,
size: 'small',
});

new Vue({
i18n,
render: (h) => h(App),
}).$mount('#__vue-root');

Loading…
Cancel
Save