diff --git a/models/ai_model_manage.go b/models/ai_model_manage.go index 0ea01d6e5..a88da8fe5 100644 --- a/models/ai_model_manage.go +++ b/models/ai_model_manage.go @@ -25,6 +25,7 @@ type AiModelManage struct { DownloadCount int `xorm:"NOT NULL DEFAULT 0"` Engine int64 `xorm:"NOT NULL DEFAULT 0"` Status int `xorm:"NOT NULL DEFAULT 0"` + StatusDesc string `xorm:"varchar(500)"` Accuracy string `xorm:"varchar(1000)"` AttachmentId string `xorm:"NULL"` RepoId int64 `xorm:"INDEX NULL"` @@ -286,6 +287,23 @@ func ModifyModelDescription(id string, description string) error { 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 { var sess *xorm.Session 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)) if err != nil { return nil, 0, fmt.Errorf("Count: %v", err) diff --git a/models/models.go b/models/models.go index a4fa8e819..4c2079cd8 100755 --- a/models/models.go +++ b/models/models.go @@ -178,6 +178,7 @@ func init() { new(UserLoginLog), new(UserMetrics), new(UserAnalysisPara), + new(Invitation), ) gonicNames := []string{"SSL", "UID"} diff --git a/models/user_business_analysis.go b/models/user_business_analysis.go index 0c67a569a..e99927e18 100644 --- a/models/user_business_analysis.go +++ b/models/user_business_analysis.go @@ -106,7 +106,8 @@ type UserBusinessAnalysisAll struct { CollectedImage 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 { @@ -193,7 +194,8 @@ type UserBusinessAnalysis struct { CollectedImage 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 { @@ -354,6 +356,33 @@ func QueryRankList(key string, tableName string, limit int) ([]*UserBusinessAnal 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) { statictisSess := xStatistic.NewSession() defer statictisSess.Close() @@ -363,6 +392,7 @@ func QueryUserStaticDataByTableName(start int, pageSize int, tableName string, q builder.Like{"lower(name)", strings.ToLower(userName)}, ) } + allCount, err := statictisSess.Where(cond).Count(queryObj) if err != nil { 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) RecommendImage := queryRecommedImage(start_unix, end_unix) + InvitationMap := queryUserInvitationCount(start_unix, end_unix) + DataDate := currentTimeNow.Format("2006-01-02") + " 00:01" 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.CollectedImage = getMapValue(dateRecordAll.ID, CollectedImage) dateRecordAll.RecommendImage = getMapValue(dateRecordAll.ID, RecommendImage) - + dateRecordAll.InvitationUserNum = getMapValue(dateRecordAll.ID, InvitationMap) dateRecordAll.UserIndexPrimitive = getUserIndexFromAnalysisAll(dateRecordAll, ParaWeight) userIndexMap[dateRecordAll.ID] = dateRecordAll.UserIndexPrimitive if maxUserIndex < dateRecordAll.UserIndexPrimitive { @@ -888,7 +920,7 @@ func insertTable(dateRecords []UserBusinessAnalysisAll, tableName string, static 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, " + - "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" 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.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.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) { insertBatchSql += "," } @@ -2173,6 +2205,41 @@ func queryCloudBrainTask(start_unix int64, end_unix int64) (map[int64]int, map[s 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) { newKey := fmt.Sprint(userId) + "_" + key if _, ok := resultItemMap[newKey]; !ok { diff --git a/models/user_business_struct.go b/models/user_business_struct.go index 36ef077e2..fe98be760 100644 --- a/models/user_business_struct.go +++ b/models/user_business_struct.go @@ -66,7 +66,8 @@ type UserBusinessAnalysisCurrentYear struct { CollectedImage 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 { @@ -133,7 +134,8 @@ type UserBusinessAnalysisLast30Day struct { CollectedImage 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 { @@ -200,7 +202,8 @@ type UserBusinessAnalysisLastMonth struct { CollectedImage 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 { @@ -267,7 +270,8 @@ type UserBusinessAnalysisCurrentMonth struct { CollectedImage 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 { @@ -335,7 +339,8 @@ type UserBusinessAnalysisCurrentWeek struct { CollectedImage 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 { @@ -403,7 +408,8 @@ type UserBusinessAnalysisYesterday struct { CollectedImage 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 { @@ -471,7 +477,8 @@ type UserBusinessAnalysisLastWeek struct { CollectedImage 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 { diff --git a/models/user_invitation.go b/models/user_invitation.go new file mode 100644 index 000000000..2d37bcb23 --- /dev/null +++ b/models/user_invitation.go @@ -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 +} diff --git a/modules/auth/user_form.go b/modules/auth/user_form.go index 130586a5a..ad78607ab 100755 --- a/modules/auth/user_form.go +++ b/modules/auth/user_form.go @@ -372,7 +372,7 @@ func (f *U2FDeleteForm) Validate(ctx *macaron.Context, errs binding.Errors) bind type PhoneNumberForm struct { PhoneNumber string `binding:"Required;MaxSize(20)"` - Mode int `binding:"Required"` + Mode int `binding:"Required"` SlideID string `binding:"Required;MaxSize(100)"` } diff --git a/modules/grampus/resty.go b/modules/grampus/resty.go index 427b801cc..f36721c85 100755 --- a/modules/grampus/resty.go +++ b/modules/grampus/resty.go @@ -1,14 +1,15 @@ package grampus import ( - "code.gitea.io/gitea/models" - "code.gitea.io/gitea/modules/log" - "code.gitea.io/gitea/modules/setting" "crypto/tls" "encoding/json" "fmt" - "github.com/go-resty/resty/v2" "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 ( @@ -236,7 +237,7 @@ func GetTrainJobLog(jobID string) (string, 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) - 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() diff --git a/modules/setting/setting.go b/modules/setting/setting.go index 1a33870b6..d6e4824ef 100755 --- a/modules/setting/setting.go +++ b/modules/setting/setting.go @@ -66,9 +66,10 @@ const ( ) 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 { @@ -1475,7 +1476,7 @@ func NewContext() { FlavorInfos = sec.Key("FLAVOR_INFOS").MustString("") TrainJobFLAVORINFOS = sec.Key("TrainJob_FLAVOR_INFOS").MustString("") ModelArtsSpecialPools = sec.Key("SPECIAL_POOL").MustString("") - ModelArtsMultiNode=sec.Key("MULTI_NODE").MustString("") + ModelArtsMultiNode = sec.Key("MULTI_NODE").MustString("") sec = Cfg.Section("elk") ElkUrl = sec.Key("ELKURL").MustString("") @@ -1570,7 +1571,7 @@ func getGrampusConfig() { Grampus.UserName = sec.Key("USERNAME").MustString("") Grampus.Password = sec.Key("PASSWORD").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 err := json.Unmarshal([]byte(Grampus.C2NetSequence), &C2NetInfos); err != nil { log.Error("Unmarshal(C2NetSequence) failed:%v", err) diff --git a/options/locale/locale_en-US.ini b/options/locale/locale_en-US.ini index 5923dfd5f..34973abcd 100755 --- a/options/locale/locale_en-US.ini +++ b/options/locale/locale_en-US.ini @@ -70,6 +70,10 @@ your_dashboard = Dashboard your_profile = Profile your_starred = Starred 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 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_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.id=ID static.name=User Name @@ -1293,6 +1301,7 @@ modelconvert.taskurlname=Model transformation task log_scroll_start=Scroll to top log_scroll_end=Scroll to bottom 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.manage.create_error1=A model transformation task with the same name already exists. diff --git a/options/locale/locale_zh-CN.ini b/options/locale/locale_zh-CN.ini index 29e9811d5..cdba8c290 100755 --- a/options/locale/locale_zh-CN.ini +++ b/options/locale/locale_zh-CN.ini @@ -70,6 +70,10 @@ your_dashboard=个人中心 your_profile=个人信息 your_starred=已点赞 your_settings=设置 +invite_friends=邀请好友 +your_friend=您的好友 +invite_you_to_join_the_OpenI_AI_Collaboration_Platform_and_enjoy_abundant_free_computing_resources=邀请您加入启智社区AI协作平台,畅享充沛的免费算力资源! +recommender=推荐人 all=所有 sources=自建 @@ -537,7 +541,11 @@ form.name_reserved='%s' 用户名被保留。 form.name_pattern_not_allowed=用户名中不允许使用 "%s"。 form.name_chars_not_allowed=用户名 '%s' 包含无效字符。 +static.invitationdetailsheetname=用户邀请详细数据 +static.invitationNum=邀请用户数 static.sheetname=用户分析 +static.srcUserId=推荐用户ID +static.invitationsheetname=用户邀请分析 static.id=ID static.name=用户名 static.codemergecount=PR数 @@ -1309,6 +1317,7 @@ log_scroll_start=滚动到顶部 log_scroll_end=滚动到底部 modelconvert.tasknameempty=请输入任务名称。 modelconvert.inputshapeerror=格式输入错误,请输入如:1,1,32,32,与输入数据格式对应。 +modelconvert.modelfileempty=请选择模型文件。 modelconvert.manage.create_error1=相同的名称模型转换任务已经存在。 modelconvert.manage.create_error2=只能创建一个正在运行的模型转换任务。 diff --git a/routers/api/v1/api.go b/routers/api/v1/api.go index 0b941b400..6dd1cb32f 100755 --- a/routers/api/v1/api.go +++ b/routers/api/v1/api.go @@ -572,6 +572,19 @@ func RegisterRoutes(m *macaron.Macaron) { m.Get("/query_user_all", operationReq, repo_ext.QueryUserStaticAll) m.Get("/query_user_activity", operationReq, repo_ext.QueryUserActivity) 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 m.Group("/cloudbrainboard", func() { m.Get("/downloadAll", repo.DownloadCloudBrainBoard) @@ -969,6 +982,7 @@ func RegisterRoutes(m *macaron.Macaron) { m.Get("", repo.GetModelArtsTrainJobVersion) m.Post("/stop_version", cloudbrain.AdminOrOwnerOrJobCreaterRightForTrain, repo_ext.GrampusStopJob) m.Get("/log", repo_ext.GrampusGetLog) + m.Get("/download_log", cloudbrain.AdminOrJobCreaterRightForTrain, repo_ext.GrampusDownloadLog) }) }) }, reqRepoReader(models.UnitTypeCloudBrain)) diff --git a/routers/api/v1/repo/cloudbrain.go b/routers/api/v1/repo/cloudbrain.go index d6b7bb076..439190121 100755 --- a/routers/api/v1/repo/cloudbrain.go +++ b/routers/api/v1/repo/cloudbrain.go @@ -379,7 +379,11 @@ func CloudbrainDownloadLogFile(ctx *context.Context) { 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, "") if err != nil { log.Error("query cloudbrain model failed: %v", err) diff --git a/routers/home.go b/routers/home.go index 026491156..ac607b5be 100755 --- a/routers/home.go +++ b/routers/home.go @@ -106,6 +106,11 @@ func Dashboard(ctx *context.Context) { log.Info("set image info=" + pictureInfo[0]["url"]) ctx.Data["image_url"] = pictureInfo[0]["url"] 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 { ctx.Data["Title"] = ctx.Tr("auth.active_your_account") @@ -728,6 +733,16 @@ func getImageInfo(filename string) ([]map[string]string, error) { 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) { url := setting.RecommentRepoAddr + "user_rank_" + index result, err := repository.RecommendFromPromote(url) diff --git a/routers/repo/ai_model_manage.go b/routers/repo/ai_model_manage.go index d01539a75..957028fc6 100644 --- a/routers/repo/ai_model_manage.go +++ b/routers/repo/ai_model_manage.go @@ -27,6 +27,9 @@ const ( MODEL_LATEST = 1 MODEL_NOT_LATEST = 0 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 { @@ -62,13 +65,9 @@ func saveModelByParameters(jobId string, versionName string, name string, versio modelSelectedFile := ctx.Query("modelSelectedFile") //download model zip //train type 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 } else if aiTask.ComputeResource == models.GPUResource { + cloudType = models.TypeCloudBrainOne var ResourceSpecs *models.ResourceSpecs json.Unmarshal([]byte(setting.ResourceSpecs), &ResourceSpecs) for _, tmp := range ResourceSpecs.ResourceSpec { @@ -77,24 +76,8 @@ func saveModelByParameters(jobId string, versionName string, name string, versio 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["F1"] = "" accuracy["Recall"] = "" @@ -123,6 +106,7 @@ func saveModelByParameters(jobId string, versionName string, name string, versio Engine: int64(engine), TrainTaskInfo: string(aiTaskJson), Accuracy: string(accuracyJson), + Status: STATUS_COPY_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) + go asyncToCopyModel(aiTask, id, modelSelectedFile) + log.Info("save model end.") notification.NotifyOtherTask(ctx.User, ctx.Repo.Repository, id, name, models.ActionCreateNewModelTask) 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) { if !ctx.Repo.CanWrite(models.UnitTypeModelManage) { ctx.Error(403, ctx.Tr("repo.model_noright")) @@ -331,6 +348,7 @@ func QueryModelByParameters(repoId int64, page int) ([]*models.AiModelManage, in RepoID: repoId, Type: -1, New: MODEL_LATEST, + Status: -1, }) } @@ -642,7 +660,6 @@ func queryUserName(intSlice []int64) map[int64]*models.User { result[user.ID] = user } } - return result } @@ -685,6 +702,7 @@ func SetModelCount(ctx *context.Context) { RepoID: repoId, Type: Type, New: MODEL_LATEST, + Status: -1, }) ctx.Data["MODEL_COUNT"] = count } @@ -758,6 +776,7 @@ func ShowModelPageInfo(ctx *context.Context) { RepoID: repoId, Type: Type, New: MODEL_LATEST, + Status: -1, }) if err != nil { ctx.ServerError("Cloudbrain", err) @@ -835,6 +854,7 @@ func QueryModelListForPredict(ctx *context.Context) { RepoID: repoId, Type: ctx.QueryInt("type"), New: -1, + Status: 0, }) if err != nil { ctx.ServerError("Cloudbrain", err) @@ -896,12 +916,17 @@ func QueryOneLevelModelFile(ctx *context.Context) { log.Info("TypeCloudBrainTwo list model file.") prefix := model.Path[len(setting.Bucket)+1:] fileinfos, _ := storage.GetOneLevelAllObjectUnderDir(setting.Bucket, prefix, parentDir) + if fileinfos == nil { + fileinfos = make([]storage.FileInfo, 0) + } ctx.JSON(http.StatusOK, fileinfos) } else if model.Type == models.TypeCloudBrainOne { log.Info("TypeCloudBrainOne list model file.") prefix := model.Path[len(setting.Attachment.Minio.Bucket)+1:] fileinfos, _ := storage.GetOneLevelAllObjectUnderDirMinio(setting.Attachment.Minio.Bucket, prefix, parentDir) + if fileinfos == nil { + fileinfos = make([]storage.FileInfo, 0) + } ctx.JSON(http.StatusOK, fileinfos) } - } diff --git a/routers/repo/grampus.go b/routers/repo/grampus.go index ee97d12d6..abf64281a 100755 --- a/routers/repo/grampus.go +++ b/routers/repo/grampus.go @@ -914,7 +914,7 @@ func GrampusTrainJobShow(ctx *context.Context) { ctx.HTML(http.StatusOK, tplGrampusTrainJobShow) } -func GrampusGetLog(ctx *context.Context) { +func GrampusDownloadLog(ctx *context.Context) { jobID := ctx.Params(":jobid") job, err := models.GetCloudbrainByJobID(jobID) if err != nil { @@ -926,13 +926,40 @@ func GrampusGetLog(ctx *context.Context) { content, err := grampus.GetTrainJobLog(job.JobID) if err != nil { 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) 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{}{ - "JobName": job.JobName, - "Content": content, + "JobName": job.JobName, + "Content": content, + "CanLogDownload": canLogDownload, }) return diff --git a/routers/repo/modelarts.go b/routers/repo/modelarts.go index 465442d50..5487231a2 100755 --- a/routers/repo/modelarts.go +++ b/routers/repo/modelarts.go @@ -1551,7 +1551,6 @@ func TrainJobCreateVersion(ctx *context.Context, form auth.CreateModelArtsTrainJ }) } - task, err := models.GetCloudbrainByJobIDAndVersionName(jobID, PreVersionName) if err != nil { log.Error("GetCloudbrainByJobIDAndVersionName(%s) failed:%v", jobID, err.Error()) @@ -2322,6 +2321,7 @@ func InferenceJobIndex(ctx *context.Context) { RepoID: repoId, Type: Type, New: MODEL_LATEST, + Status: 0, }) ctx.Data["MODEL_COUNT"] = model_count @@ -2402,6 +2402,7 @@ func inferenceJobNewDataPrepare(ctx *context.Context) error { RepoID: repoId, Type: Type, New: MODEL_LATEST, + Status: 0, }) ctx.Data["MODEL_COUNT"] = model_count ctx.Data["datasetType"] = models.TypeCloudBrainTwo diff --git a/routers/repo/user_invitation.go b/routers/repo/user_invitation.go new file mode 100644 index 000000000..a2752a481 --- /dev/null +++ b/routers/repo/user_invitation.go @@ -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 +} diff --git a/routers/routes/routes.go b/routers/routes/routes.go index 6d31cfe46..66a357c79 100755 --- a/routers/routes/routes.go +++ b/routers/routes/routes.go @@ -335,6 +335,7 @@ func RegisterRoutes(m *macaron.Macaron) { go reward.AcceptStatusChangeAction() m.Get("/action/notification", routers.ActionNotification) m.Get("/recommend/home", routers.RecommendHomeInfo) + m.Get("/dashboard/invitation", routers.GetMapInfo) //m.Get("/recommend/org", routers.RecommendOrgFromPromote) //m.Get("/recommend/repo", routers.RecommendRepoFromPromote) m.Get("/recommend/userrank/:index", routers.GetUserRankFromPromote) @@ -509,6 +510,8 @@ func RegisterRoutes(m *macaron.Macaron) { m.Get("/forgot_password", user.ForgotPasswd) m.Post("/forgot_password", user.ForgotPasswdPost) m.Post("/logout", user.SignOut) + m.Get("/invitation_code", reqSignIn, user.GetInvitaionCode) + m.Get("/invitation_tpl", reqSignIn, user.InviationTpl) }) // ***** END: User ***** diff --git a/routers/user/Invitation.go b/routers/user/Invitation.go new file mode 100644 index 000000000..8491390b2 --- /dev/null +++ b/routers/user/Invitation.go @@ -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 +} diff --git a/routers/user/auth.go b/routers/user/auth.go index 7cd6472ff..57ffb1710 100755 --- a/routers/user/auth.go +++ b/routers/user/auth.go @@ -8,11 +8,12 @@ package user import ( "errors" "fmt" - "github.com/gomodule/redigo/redis" "net/http" "strconv" "strings" + "github.com/gomodule/redigo/redis" + "code.gitea.io/gitea/modules/slideimage" 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") } - func SignInCloudBrainPost(ctx *context.Context, form auth.SignInForm) { ctx.Data["PageIsCloudBrainLogin"] = true ctx.Data["SignInLink"] = setting.AppSubURL + "/user/login/cloud_brain" - SignInPostCommon(ctx,form) + SignInPostCommon(ctx, form) } // SignInPost response for sign in request func SignInPost(ctx *context.Context, form auth.SignInForm) { ctx.Data["PageIsLogin"] = true ctx.Data["SignInLink"] = setting.AppSubURL + "/user/login" - SignInPostCommon(ctx,form) + SignInPostCommon(ctx, form) } // 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 func SignUpPost(ctx *context.Context, cpt *captcha.Captcha, form auth.RegisterForm) { ctx.Data["Title"] = ctx.Tr("sign_up") - + invitationCode := ctx.Query("invitation_code") ctx.Data["SignUpLink"] = setting.AppSubURL + "/user/sign_up" - + ctx.Data["invitationCode"] = invitationCode ctx.Data["EnableCaptcha"] = setting.Service.EnableCaptcha ctx.Data["RecaptchaURL"] = setting.Service.RecaptchaURL 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.Info("enter here, and form.InvitaionCode =" + invitationCode) + if invitationCode != "" { + RegisteUserByInvitaionCode(invitationCode, u.ID, u.PhoneNumber) + } + err := models.AddEmailAddress(&models.EmailAddress{ UID: u.ID, Email: form.Email, @@ -1919,7 +1924,7 @@ func SendVerifyCode(ctx *context.Context, slideImage *slideimage.SlideImage, for return } - if form.Mode==0 { //注册 + if form.Mode == 0 { //注册 if has { 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 { //修改手机号 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() defer redisConn.Close() sendTimes, err := phoneService.GetPhoneNumberSendTimes(redisConn, phoneNumber) - if err != nil && err!=redis.ErrNil { + if err != nil && err != redis.ErrNil { log.Warn("redis err", err) ctx.JSON(http.StatusOK, models.BaseErrorMessage(ctx.Tr("phone.query_err"))) return diff --git a/services/repository/repository.go b/services/repository/repository.go index 6bf4ab283..b4c047392 100644 --- a/services/repository/repository.go +++ b/services/repository/repository.go @@ -148,6 +148,28 @@ func GetRecommendRepoFromPromote(filename string) ([]map[string]interface{}, err 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) { defer func() { if err := recover(); err != nil { diff --git a/templates/base/footer.tmpl b/templates/base/footer.tmpl index 53f78dc1a..738578a8a 100755 --- a/templates/base/footer.tmpl +++ b/templates/base/footer.tmpl @@ -52,6 +52,12 @@ diff --git a/templates/user/dashboard/repolist.tmpl b/templates/user/dashboard/repolist.tmpl index ff85d72d4..8bc030ef3 100644 --- a/templates/user/dashboard/repolist.tmpl +++ b/templates/user/dashboard/repolist.tmpl @@ -18,6 +18,11 @@ v-cloak >