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 | |||
| import ( | |||
| "code.gitea.io/gitea/modules/util" | |||
| "encoding/json" | |||
| "fmt" | |||
| "strconv" | |||
| "strings" | |||
| "time" | |||
| "code.gitea.io/gitea/modules/util" | |||
| "xorm.io/builder" | |||
| "xorm.io/xorm" | |||
| @@ -1580,3 +1581,64 @@ func RestartCloudbrain(old *Cloudbrain, new *Cloudbrain) (err error) { | |||
| 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_name=任务名称 | |||
| 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.description=任务描述 | |||
| 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_yesterday", operationReq, repo_ext.QueryUserStaticYesterday) | |||
| m.Get("/query_user_all", operationReq, repo_ext.QueryUserStaticAll) | |||
| //cloudbrain board | |||
| m.Group("/cloudbrainboard", func() { | |||
| m.Get("/downloadAll", repo.DownloadCloudBrainBoard) | |||
| }, operationReq) | |||
| // Users | |||
| m.Group("/users", func() { | |||
| 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> | |||
| <UserAnalysis ref='UserAnalysis' v-if="isRouterAlive1" id ="usr"></UserAnalysis> | |||
| </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> | |||
| </div> | |||
| </template> | |||
| @@ -33,12 +41,14 @@ | |||
| <script> | |||
| import ProAnalysis from './ProAnalysis.vue' | |||
| import UserAnalysis from './UserAnalysis.vue' | |||
| import BrainAnalysis from './BrainAnalysis.vue' | |||
| export default { | |||
| components:{ | |||
| 'ProAnalysis':ProAnalysis, | |||
| 'UserAnalysis':UserAnalysis, | |||
| 'BrainAnalysis':BrainAnalysis, | |||
| }, | |||
| data() { | |||
| return { | |||