Reviewed-on: https://git.openi.org.cn/OpenI/aiforge/pulls/1850 Reviewed-by: lewis <747342561@qq.com>tags/v1.22.4.1^2
| @@ -1,13 +1,14 @@ | |||||
| package models | package models | ||||
| import ( | import ( | ||||
| "code.gitea.io/gitea/modules/util" | |||||
| "encoding/json" | "encoding/json" | ||||
| "fmt" | "fmt" | ||||
| "strconv" | "strconv" | ||||
| "strings" | "strings" | ||||
| "time" | "time" | ||||
| "code.gitea.io/gitea/modules/util" | |||||
| "xorm.io/builder" | "xorm.io/builder" | ||||
| "xorm.io/xorm" | "xorm.io/xorm" | ||||
| @@ -1580,3 +1581,64 @@ func RestartCloudbrain(old *Cloudbrain, new *Cloudbrain) (err error) { | |||||
| return nil | return nil | ||||
| } | } | ||||
| func CloudbrainAll(opts *CloudbrainsOptions) ([]*CloudbrainInfo, int64, error) { | |||||
| sess := x.NewSession() | |||||
| defer sess.Close() | |||||
| var cond = builder.NewCond() | |||||
| if (opts.Type) >= 0 { | |||||
| cond = cond.And( | |||||
| builder.Eq{"cloudbrain.type": opts.Type}, | |||||
| ) | |||||
| } | |||||
| var count int64 | |||||
| var err error | |||||
| condition := "cloudbrain.user_id = `user`.id" | |||||
| if len(opts.Keyword) == 0 { | |||||
| count, err = sess.Where(cond).Count(new(Cloudbrain)) | |||||
| } else { | |||||
| lowerKeyWord := strings.ToLower(opts.Keyword) | |||||
| cond = cond.And(builder.Or(builder.Like{"LOWER(cloudbrain.job_name)", lowerKeyWord}, builder.Like{"LOWER(cloudbrain.display_job_name)", lowerKeyWord}, builder.Like{"`user`.lower_name", lowerKeyWord})) | |||||
| count, err = sess.Table(&Cloudbrain{}).Where(cond). | |||||
| Join("left", "`user`", condition).Count(new(CloudbrainInfo)) | |||||
| } | |||||
| if err != nil { | |||||
| return nil, 0, fmt.Errorf("Count: %v", err) | |||||
| } | |||||
| if opts.Page >= 0 && opts.PageSize > 0 { | |||||
| var start int | |||||
| if opts.Page == 0 { | |||||
| start = 0 | |||||
| } else { | |||||
| start = (opts.Page - 1) * opts.PageSize | |||||
| } | |||||
| sess.Limit(opts.PageSize, start) | |||||
| } | |||||
| sess.OrderBy("cloudbrain.created_unix DESC") | |||||
| cloudbrains := make([]*CloudbrainInfo, 0, setting.UI.IssuePagingNum) | |||||
| if err := sess.Table(&Cloudbrain{}).Unscoped().Where(cond). | |||||
| Join("left", "`user`", condition). | |||||
| Find(&cloudbrains); err != nil { | |||||
| return nil, 0, fmt.Errorf("Find: %v", err) | |||||
| } | |||||
| if opts.NeedRepoInfo { | |||||
| var ids []int64 | |||||
| for _, task := range cloudbrains { | |||||
| ids = append(ids, task.RepoID) | |||||
| } | |||||
| repositoryMap, err := GetRepositoriesMapByIDs(ids) | |||||
| if err == nil { | |||||
| for _, task := range cloudbrains { | |||||
| task.Repo = repositoryMap[task.RepoID] | |||||
| } | |||||
| } | |||||
| } | |||||
| return cloudbrains, count, nil | |||||
| } | |||||
| @@ -1015,7 +1015,9 @@ modelarts.train_job.basic_info=基本信息 | |||||
| modelarts.train_job.job_status=任务状态 | modelarts.train_job.job_status=任务状态 | ||||
| modelarts.train_job.job_name=任务名称 | modelarts.train_job.job_name=任务名称 | ||||
| modelarts.train_job.version=任务版本 | modelarts.train_job.version=任务版本 | ||||
| modelarts.train_job.start_time=开始时间 | |||||
| modelarts.train_job.start_time=开始运行时间 | |||||
| modelarts.train_job.end_time=运行结束时间 | |||||
| modelarts.train_job.wait_time=等待时间 | |||||
| modelarts.train_job.dura_time=运行时长 | modelarts.train_job.dura_time=运行时长 | ||||
| modelarts.train_job.description=任务描述 | modelarts.train_job.description=任务描述 | ||||
| modelarts.train_job.parameter_setting=参数设置 | modelarts.train_job.parameter_setting=参数设置 | ||||
| @@ -557,6 +557,10 @@ func RegisterRoutes(m *macaron.Macaron) { | |||||
| m.Get("/query_user_last_month", operationReq, repo_ext.QueryUserStaticLastMonth) | m.Get("/query_user_last_month", operationReq, repo_ext.QueryUserStaticLastMonth) | ||||
| m.Get("/query_user_yesterday", operationReq, repo_ext.QueryUserStaticYesterday) | m.Get("/query_user_yesterday", operationReq, repo_ext.QueryUserStaticYesterday) | ||||
| m.Get("/query_user_all", operationReq, repo_ext.QueryUserStaticAll) | m.Get("/query_user_all", operationReq, repo_ext.QueryUserStaticAll) | ||||
| //cloudbrain board | |||||
| m.Group("/cloudbrainboard", func() { | |||||
| m.Get("/downloadAll", repo.DownloadCloudBrainBoard) | |||||
| }, operationReq) | |||||
| // Users | // Users | ||||
| m.Group("/users", func() { | m.Group("/users", func() { | ||||
| m.Get("/search", user.Search) | m.Get("/search", user.Search) | ||||
| @@ -0,0 +1,135 @@ | |||||
| package repo | |||||
| import ( | |||||
| "net/http" | |||||
| "net/url" | |||||
| "time" | |||||
| "code.gitea.io/gitea/models" | |||||
| "code.gitea.io/gitea/modules/context" | |||||
| "code.gitea.io/gitea/modules/log" | |||||
| "github.com/360EntSecGroup-Skylar/excelize/v2" | |||||
| ) | |||||
| func DownloadCloudBrainBoard(ctx *context.Context) { | |||||
| page := 1 | |||||
| pageSize := 300 | |||||
| var cloudBrain = ctx.Tr("repo.cloudbrain") | |||||
| fileName := getCloudbrainFileName(cloudBrain) | |||||
| _, total, err := models.CloudbrainAll(&models.CloudbrainsOptions{ | |||||
| ListOptions: models.ListOptions{ | |||||
| Page: page, | |||||
| PageSize: 1, | |||||
| }, | |||||
| Type: models.TypeCloudBrainAll, | |||||
| NeedRepoInfo: false, | |||||
| }) | |||||
| if err != nil { | |||||
| log.Warn("Can not get cloud brain info", err) | |||||
| ctx.Error(http.StatusBadRequest, ctx.Tr("repo.cloudbrain_query_fail")) | |||||
| return | |||||
| } | |||||
| totalPage := getTotalPage(total, pageSize) | |||||
| f := excelize.NewFile() | |||||
| index := f.NewSheet(cloudBrain) | |||||
| f.DeleteSheet("Sheet1") | |||||
| for k, v := range allCloudbrainHeader(ctx) { | |||||
| f.SetCellValue(cloudBrain, k, v) | |||||
| } | |||||
| var row = 2 | |||||
| for i := 0; i < totalPage; i++ { | |||||
| pageRecords, _, err := models.CloudbrainAll(&models.CloudbrainsOptions{ | |||||
| ListOptions: models.ListOptions{ | |||||
| Page: page, | |||||
| PageSize: pageSize, | |||||
| }, | |||||
| Type: models.TypeCloudBrainAll, | |||||
| NeedRepoInfo: true, | |||||
| }) | |||||
| if err != nil { | |||||
| log.Warn("Can not get cloud brain info", err) | |||||
| continue | |||||
| } | |||||
| for _, record := range pageRecords { | |||||
| for k, v := range allCloudbrainValues(row, record, ctx) { | |||||
| f.SetCellValue(cloudBrain, k, v) | |||||
| } | |||||
| row++ | |||||
| } | |||||
| page++ | |||||
| } | |||||
| f.SetActiveSheet(index) | |||||
| ctx.Resp.Header().Set("Content-Disposition", "attachment; filename="+url.QueryEscape(fileName)) | |||||
| ctx.Resp.Header().Set("Content-Type", "application/octet-stream") | |||||
| f.WriteTo(ctx.Resp) | |||||
| } | |||||
| func getCloudbrainFileName(baseName string) string { | |||||
| return baseName + "_" + time.Now().Format(EXCEL_DATE_FORMAT) + ".xlsx" | |||||
| } | |||||
| func allCloudbrainHeader(ctx *context.Context) map[string]string { | |||||
| return map[string]string{"A1": ctx.Tr("repo.cloudbrain_task"), "B1": ctx.Tr("repo.cloudbrain_task_type"), "C1": ctx.Tr("repo.modelarts.status"), | |||||
| "D1": ctx.Tr("repo.modelarts.createtime"), "E1": ctx.Tr("repo.modelarts.train_job.wait_time"), "F1": ctx.Tr("repo.modelarts.train_job.dura_time"), | |||||
| "G1": ctx.Tr("repo.modelarts.train_job.start_time"), | |||||
| "H1": ctx.Tr("repo.modelarts.train_job.end_time"), "I1": ctx.Tr("repo.modelarts.computing_resources"), | |||||
| "J1": ctx.Tr("repo.cloudbrain_creator"), "K1": ctx.Tr("repo.repo_name"), "L1": ctx.Tr("repo.cloudbrain_task_name")} | |||||
| } | |||||
| func allCloudbrainValues(row int, rs *models.CloudbrainInfo, ctx *context.Context) map[string]string { | |||||
| return map[string]string{getCellName("A", row): rs.DisplayJobName, getCellName("B", row): rs.JobType, getCellName("C", row): rs.Status, | |||||
| getCellName("D", row): time.Unix(int64(rs.Cloudbrain.CreatedUnix), 0).Format(CREATE_TIME_FORMAT), getCellName("E", row): getBrainWaitTime(rs), | |||||
| getCellName("F", row): rs.TrainJobDuration, getCellName("G", row): getBrainStartTime(rs), | |||||
| getCellName("H", row): getBrainEndTime(rs), | |||||
| getCellName("I", row): rs.ComputeResource, getCellName("J", row): rs.Name, getCellName("K", row): getBrainRepo(rs), | |||||
| getCellName("L", row): rs.JobName, | |||||
| } | |||||
| } | |||||
| func getBrainRepo(rs *models.CloudbrainInfo) string { | |||||
| if rs.Repo != nil { | |||||
| return rs.Repo.OwnerName + "/" + rs.Repo.Alias | |||||
| } | |||||
| return "" | |||||
| } | |||||
| func getBrainStartTime(rs *models.CloudbrainInfo) string { | |||||
| timeString := time.Unix(int64(rs.Cloudbrain.StartTime), 0).Format(CREATE_TIME_FORMAT) | |||||
| if timeString != "1970/01/01 08:00:00" { | |||||
| return timeString | |||||
| } else { | |||||
| return "0" | |||||
| } | |||||
| } | |||||
| func getBrainEndTime(rs *models.CloudbrainInfo) string { | |||||
| timeString := time.Unix(int64(rs.Cloudbrain.EndTime), 0).Format(CREATE_TIME_FORMAT) | |||||
| if timeString != "1970/01/01 08:00:00" { | |||||
| return timeString | |||||
| } else { | |||||
| return "0" | |||||
| } | |||||
| } | |||||
| func getBrainWaitTime(rs *models.CloudbrainInfo) string { | |||||
| waitTime := rs.Cloudbrain.StartTime - rs.Cloudbrain.CreatedUnix | |||||
| if waitTime <= 0 { | |||||
| return "0" | |||||
| } else { | |||||
| return models.ConvertDurationToStr(int64(waitTime)) | |||||
| } | |||||
| } | |||||
| @@ -0,0 +1,86 @@ | |||||
| <template> | |||||
| <div style="width: 100%;"> | |||||
| <div id = "pro_main"> | |||||
| <div style="margin-top: 10px;"> | |||||
| <b class="pro_item">云脑分析</b> <span class="update_time">数据更新时间:</span> <span style="font-size: 12px;">{{lastUpdatedTime}} / 从有记录起开始统计</span> | |||||
| </div> | |||||
| <bar-label :width="'95%'" :height="'500px'"></bar-label> | |||||
| <div style="margin-top: 20px;"> | |||||
| <span class="sta_iterm">统计周期:</span> | |||||
| <button type="button" class='btnLast' id = "all" v-bind:class="{colorChange:7==dynamic}" @click="resetPage(),getAllProList('all',7)">所有</button> | |||||
| <span style="float:right; margin-right: 20px;"> | |||||
| <div style="display:inline-block;margin-left: 40px; "> | |||||
| <a class="el-icon-download" v-if="tableData!=''" :href= "'../api/v1/cloudbrainboard/downloadAll'"></a> | |||||
| <i class="el-icon-download" v-else="tableData=''" href="#" style="color:rgba(187, 187, 187, 100);" @click='popMark()'></i> | |||||
| <!-- <span ><a id = "download_file" :href= "'../api/v1/projectboard/downloadAll'" >下载报告</a> </span> --> | |||||
| <span > | |||||
| <a id = "download_file" v-if="tableData!=''" :href= "'../api/v1/cloudbrainboard/downloadAll'">下载报告</a> | |||||
| <a id = "download_file" v-else="tableData=''" href= "#" style="color:rgba(187, 187, 187, 100);" @click='popMark()'>下载报告</a> | |||||
| </span> | |||||
| </div> | |||||
| </span> | |||||
| </div> | |||||
| </div> | |||||
| </div> | |||||
| </template> | |||||
| <script> | |||||
| // import barLabel from './basic/barLabel.vue'; | |||||
| const {AppSubUrl, StaticUrlPrefix, csrf} = window.config; | |||||
| import { export2Excel } from '../excel/util.js' | |||||
| export default{ | |||||
| name:'ProAnalysis', | |||||
| components: { | |||||
| // barLabel, | |||||
| }, | |||||
| methods: { | |||||
| popMark(){ | |||||
| alert("数据为空时,不能下载!") | |||||
| }, | |||||
| exportData(){ | |||||
| // this.getOneProList(this.pro_id,'all',true,7) | |||||
| // this.getOneProList(this.pro_id,'all',false,7) | |||||
| // this.fileName() | |||||
| if (this.tableDataID!=''){ | |||||
| this.currentPage=1 | |||||
| var saveFileName = this.getFileName() | |||||
| export2Excel(this.columns,this.tableDataID,saveFileName) | |||||
| }else{ | |||||
| alert("数据为空时,不能下载!") | |||||
| } | |||||
| }, | |||||
| }, | |||||
| } | |||||
| </script> | |||||
| <style scoped> | |||||
| .pro_item{ | |||||
| font-size: 16px; | |||||
| color: rgba(16, 16, 16, 100); | |||||
| font-family: SourceHanSansSC-bold; | |||||
| } | |||||
| .update_time{ | |||||
| line-height: 17px; | |||||
| font-size: 12px; | |||||
| color:rgba(187, 187, 187, 100); | |||||
| margin-left: 10px; | |||||
| } | |||||
| .btnLast{ | |||||
| line-height: 1.5; | |||||
| margin: -3.5px; | |||||
| border: 1px solid rgba(22, 132, 252, 100); | |||||
| /* border-right: none; */ | |||||
| background: #FFFF; | |||||
| color: #1684FC; | |||||
| width: 60px; | |||||
| height: 30px; | |||||
| border-radius:0px 4px 4px 0px; | |||||
| } | |||||
| </style> | |||||
| @@ -26,6 +26,14 @@ | |||||
| </span> | </span> | ||||
| <UserAnalysis ref='UserAnalysis' v-if="isRouterAlive1" id ="usr"></UserAnalysis> | <UserAnalysis ref='UserAnalysis' v-if="isRouterAlive1" id ="usr"></UserAnalysis> | ||||
| </el-tab-pane> | </el-tab-pane> | ||||
| <el-tab-pane name="four" id='four' > | |||||
| <BrainAnalysis ref='BrainAnalysis'id="brain" v-if="isRouterAlive"></BrainAnalysis> | |||||
| <span slot="label"> | |||||
| <el-image style="width: 13px; height: 13px" src="/img/pro_rgb.svg"> | |||||
| </el-image> | |||||
| 云脑分析 | |||||
| </span> | |||||
| </el-tab-pane> | |||||
| </el-tabs> | </el-tabs> | ||||
| </div> | </div> | ||||
| </template> | </template> | ||||
| @@ -33,12 +41,14 @@ | |||||
| <script> | <script> | ||||
| import ProAnalysis from './ProAnalysis.vue' | import ProAnalysis from './ProAnalysis.vue' | ||||
| import UserAnalysis from './UserAnalysis.vue' | import UserAnalysis from './UserAnalysis.vue' | ||||
| import BrainAnalysis from './BrainAnalysis.vue' | |||||
| export default { | export default { | ||||
| components:{ | components:{ | ||||
| 'ProAnalysis':ProAnalysis, | 'ProAnalysis':ProAnalysis, | ||||
| 'UserAnalysis':UserAnalysis, | 'UserAnalysis':UserAnalysis, | ||||
| 'BrainAnalysis':BrainAnalysis, | |||||
| }, | }, | ||||
| data() { | data() { | ||||
| return { | return { | ||||