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