| @@ -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) | |||
| @@ -178,6 +178,7 @@ func init() { | |||
| new(UserLoginLog), | |||
| new(UserMetrics), | |||
| new(UserAnalysisPara), | |||
| new(Invitation), | |||
| ) | |||
| gonicNames := []string{"SSL", "UID"} | |||
| @@ -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 { | |||
| @@ -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 { | |||
| @@ -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 | |||
| } | |||
| @@ -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)"` | |||
| } | |||
| @@ -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() | |||
| @@ -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) | |||
| @@ -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. | |||
| @@ -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=只能创建一个正在运行的模型转换任务。 | |||
| @@ -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)) | |||
| @@ -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) | |||
| @@ -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) | |||
| @@ -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) | |||
| } | |||
| } | |||
| @@ -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 | |||
| @@ -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 | |||
| @@ -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 | |||
| } | |||
| @@ -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 ***** | |||
| @@ -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 | |||
| } | |||
| @@ -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 | |||
| @@ -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 { | |||
| @@ -52,6 +52,12 @@ | |||
| <script src="/rotation3D/rotation3D.js?v={{MD5 AppVer}}"></script> | |||
| <script> | |||
| 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(){ | |||
| $.ajax({ | |||
| type:"GET", | |||
| @@ -96,7 +102,11 @@ | |||
| tmp["type"]="green"; | |||
| } | |||
| tmp["icon"]=""; | |||
| tmp["content"]=json[i].content; | |||
| if(isZh){ | |||
| tmp["content"]=json[i].content; | |||
| }else{ | |||
| tmp["content"]=json[i].content_en; | |||
| } | |||
| serverItemList.push(tmp); | |||
| } | |||
| } | |||
| @@ -182,6 +182,10 @@ | |||
| </i> | |||
| {{.i18n.Tr "custom.Platform_Tutorial"}} | |||
| </a> | |||
| <a class="item" href="{{AppSubUrl}}/user/invitation_tpl"> | |||
| <i class="icon users"></i> | |||
| {{.i18n.Tr "invite_friends"}} | |||
| </a> | |||
| {{if .IsAdmin}} | |||
| <div class="divider"></div> | |||
| @@ -179,6 +179,10 @@ | |||
| </svg> | |||
| </i> | |||
| {{.i18n.Tr "custom.Platform_Tutorial"}} | |||
| </a> | |||
| <a class="item" href="{{AppSubUrl}}/user/invitation_tpl"> | |||
| <i class="icon users"></i> | |||
| {{.i18n.Tr "invite_friends"}} | |||
| </a> | |||
| {{if .IsAdmin}} | |||
| <div class="divider"></div> | |||
| @@ -162,6 +162,10 @@ | |||
| </i> | |||
| {{.i18n.Tr "custom.Platform_Tutorial"}} | |||
| </a> | |||
| <a class="item" href="{{AppSubUrl}}/user/invitation_tpl"> | |||
| <i class="icon users"></i> | |||
| {{.i18n.Tr "invite_friends"}} | |||
| </a> | |||
| {{if .IsAdmin}} | |||
| <div class="divider"></div> | |||
| @@ -183,6 +183,10 @@ | |||
| </i> | |||
| {{.i18n.Tr "custom.Platform_Tutorial"}} | |||
| </a> | |||
| <a class="item" href="{{AppSubUrl}}/user/invitation_tpl"> | |||
| <i class="icon users"></i> | |||
| {{.i18n.Tr "invite_friends"}} | |||
| </a> | |||
| {{if .IsAdmin}} | |||
| <div class="divider"></div> | |||
| @@ -533,8 +533,7 @@ | |||
| </a> | |||
| </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> | |||
| <a title="滚动到顶部" style="position: absolute; right: -32px;cursor: pointer;" | |||
| class="log_top" data-version="{{.VersionName}}"><i class="icon-to-top"></i></a> | |||
| @@ -499,7 +499,16 @@ | |||
| </div> | |||
| </div> | |||
| <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> | |||
| <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> | |||
| @@ -241,7 +241,7 @@ | |||
| </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"> | |||
| <label for="choice_file">{{$.i18n.Tr "repo.model.manage.modelfile"}}</label> | |||
| </div> | |||
| @@ -382,7 +382,14 @@ | |||
| data['DestFormat'] = $('#DestFormat').val(); | |||
| data['NetOutputFormat']= $('#NetOutputFormat').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) => { | |||
| console.log("result=" + result); | |||
| if(result.result_code ==0){ | |||
| @@ -46,9 +46,9 @@ | |||
| <div class="repository release dataset-list view"> | |||
| {{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" .}} | |||
| <div class="ui two column stackable grid"> | |||
| <div class="ui two column stackable grid" style="display: none;"> | |||
| <div class="column"> | |||
| <div class="ui blue small menu compact selectcloudbrain"> | |||
| <a class="active item" href="{{.RepoLink}}/modelmanage/show_model">{{$.i18n.Tr "repo.model.list"}}</a> | |||
| @@ -35,6 +35,9 @@ | |||
| {{if .DisableRegistration}} | |||
| <p>{{.i18n.Tr "auth.disable_register_prompt"}}</p> | |||
| {{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}}"> | |||
| <input id="user_name" name="user_name" value="{{.user_name}}" placeholder="{{.i18n.Tr "username"}}" autofocus required> | |||
| </div> | |||
| @@ -71,6 +74,16 @@ | |||
| {{template "user/auth/phone_verify" .}} | |||
| </div> | |||
| {{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="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> | |||
| @@ -94,3 +107,28 @@ | |||
| </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> | |||
| @@ -18,6 +18,11 @@ | |||
| v-cloak | |||
| > | |||
| <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"> | |||
| <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> | |||
| @@ -48,7 +48,40 @@ | |||
| </li> | |||
| {{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}} | |||
| <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> | |||
| @@ -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" .}} | |||
| @@ -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); | |||
| })(); | |||
| @@ -97,6 +97,10 @@ export const i18nVue = { | |||
| model_delete: "删除", | |||
| model_create_title: "导入新模型", | |||
| model_create_version_title: "创建模型新版本", | |||
| model_status:"状态", | |||
| model_wait:"模型加载中", | |||
| model_success:"模型加载成功", | |||
| model_failed:"模型加载失败", | |||
| }, | |||
| US: { | |||
| computer_vision: "computer vision", | |||
| @@ -200,5 +204,9 @@ export const i18nVue = { | |||
| model_delete: "Delete", | |||
| model_create_title: "Import new model", | |||
| model_create_version_title: "Create a new version of the model", | |||
| model_status: "Status", | |||
| model_wait:"Loading", | |||
| model_success:"Success", | |||
| model_failed:"Failed", | |||
| }, | |||
| }; | |||
| @@ -52,6 +52,7 @@ import router from "./router/index.js"; | |||
| import { Message } from "element-ui"; | |||
| import { i18nVue } from "./features/i18nVue.js"; | |||
| import './features/ad.js'; | |||
| Vue.use(ElementUI); | |||
| Vue.prototype.$axios = axios; | |||
| @@ -77,7 +77,7 @@ | |||
| }); | |||
| function mouseMove(e) { | |||
| var _clientX = e.clientX; | |||
| var _clientX = e.clientX !== undefined ? e.clientX : e.targetTouches[0].clientX; | |||
| var offset = _clientX - clientX; | |||
| var triggerEl = self.dom.find('.slide-trigger'); | |||
| var triggerWidth = triggerEl.width(); | |||
| @@ -99,6 +99,8 @@ | |||
| function mouseUp(e) { | |||
| $(document).off('mousemove', mouseMove); | |||
| $(document).off('mouseup', mouseUp); | |||
| $(document).off('touchmove', mouseMove); | |||
| $(document).off('touchend', mouseUp); | |||
| self.isMoving = false; | |||
| $.ajax({ | |||
| url: '/verifySlideImage', | |||
| @@ -106,7 +108,7 @@ | |||
| dataType: 'json', | |||
| data: { | |||
| 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) { | |||
| 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; | |||
| clientX = e.clientX; | |||
| clientX = e.clientX !== undefined ? e.clientX : e.targetTouches[0].clientX; | |||
| oLeft = $(this).position().left; | |||
| $(document).on('mousemove', mouseMove); | |||
| $(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 () { | |||
| if (!self.canSendCode) return; | |||
| @@ -199,6 +206,7 @@ | |||
| self.dom.find('.slide-bar-wrap').css('display', 'flex'); | |||
| self.dom.find('.verify-code-c').css('display', 'flex'); | |||
| self.dom.find('.modify-phone-number').hide(); | |||
| self.refreshImages(); | |||
| }); | |||
| }; | |||
| @@ -210,6 +218,8 @@ | |||
| this.imgID = ''; | |||
| this.dom.find('.slide-bar').removeClass('sucess error').css('width', '30px'); | |||
| 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.arrow').show(); | |||
| this.dom.find('.slide-txt').show(); | |||
| @@ -174,10 +174,11 @@ | |||
| width: 391px; | |||
| height: 196px; | |||
| top: 36px; | |||
| left: 0; | |||
| left: 1px; | |||
| border-radius: 2px; | |||
| z-index: 100; | |||
| display: none; | |||
| transform-origin: 0 0; | |||
| } | |||
| .__phone-verify-code .slide-bar-c .slide-image-small { | |||
| @@ -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: {}, | |||
| }); | |||
| } | |||
| @@ -162,6 +162,20 @@ const en = { | |||
| available: '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; | |||
| @@ -162,6 +162,20 @@ const zh = { | |||
| available: '可用', | |||
| notAvailable: '不可用', | |||
| }, | |||
| user: { | |||
| inviteFriends: '邀请好友', | |||
| inviteFriendsTips: '复制二维码或者注册邀请链接分享给好友', | |||
| clickToViewTheEventDetails: '点击查看活动详情', | |||
| copyRegistrationInvitationLink: '复制注册邀请链接', | |||
| registrationAdress: '注册地址:', | |||
| recommender: '推荐人:', | |||
| invitedFriends: '已邀请好友', | |||
| registrationTime: '注册时间', | |||
| theSharedContentHasBeenCopiedToTheClipboard: '分享内容已复制到剪切板', | |||
| copyError: '复制错误', | |||
| Activated: '已激活', | |||
| notActive: '未激活', | |||
| }, | |||
| } | |||
| export default zh; | |||
| @@ -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> | |||
| @@ -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'); | |||