Reviewed-on: https://git.openi.org.cn/OpenI/aiforge/pulls/2469 Reviewed-by: ychao_1983 <ychao_1983@sina.com>tags/v1.22.7.1
| @@ -29,51 +29,22 @@ | |||
| } | |||
| .rotation3D__item .scale{ position: absolute; top: 0; width: 100%; height: 100%; } | |||
| .rotation3D__item .cont{ position: relative; z-index: 2; } | |||
| .rotation3D__item .cont .iconfont { font-size: 28px; margin-top: 30px; margin-bottom: 96px; display: block; } | |||
| .rotation3D__item .cont .iconfont { font-size: 28px; margin-top: 30px; margin-bottom: 96px; display: block; height: 35px;} | |||
| .rotation3D__item .cont p{ color: #101010; } | |||
| .itemList .rotation3D__item .cont p::after{ | |||
| font-size: 12px; | |||
| content: ''; | |||
| position: absolute; | |||
| left: 0; | |||
| right: 0; | |||
| margin-top: 60px; | |||
| color: #101010; | |||
| } | |||
| .itemList .rotation3D__item:nth-child(1) .cont p::after{ | |||
| content: "鹏城云脑一号"; | |||
| } | |||
| .itemList .rotation3D__item:nth-child(2) .cont p::after{ | |||
| content: "鹏城云脑二号"; | |||
| } | |||
| .itemList .rotation3D__item:nth-child(3) .cont p::after{ | |||
| content: "北大人工智能集群系统"; | |||
| } | |||
| .itemList .rotation3D__item:nth-child(4) .cont p::after{ | |||
| content: "合肥类脑智能开放平台"; | |||
| .lineList .rotation3D__line:nth-child(5n+0) .dot{ | |||
| } | |||
| .itemList .rotation3D__item:nth-child(5) .cont p::after{ | |||
| content: "武汉人工智能计算中心"; | |||
| .lineList .rotation3D__line:nth-child(5n+1) .dot{ | |||
| animation-delay: 1s; | |||
| } | |||
| .itemList .rotation3D__item:nth-child(6) .cont p::after{ | |||
| content: "西安未来人工智能计算中心"; | |||
| .lineList .rotation3D__line:nth-child(5n+2) .dot{ | |||
| animation-delay: 3s; | |||
| } | |||
| .itemList .rotation3D__item:nth-child(7) .cont p::after{ | |||
| content: "更多接入中…"; | |||
| .lineList .rotation3D__line:nth-child(5n+3) .dot{ | |||
| animation-delay: 2s; | |||
| } | |||
| .itemList .rotation3D__item:nth-child(8) .cont p::after{ | |||
| content: "中原人工智能计算中心"; | |||
| .lineList .rotation3D__line:nth-child(5n+3) .dot{ | |||
| animation-delay: 4s; | |||
| } | |||
| .itemList .rotation3D__item:nth-child(9) .cont p::after{ | |||
| content: "成都人工智能计算中心"; | |||
| } | |||
| .itemList .rotation3D__item:nth-child(10) .cont p::after{ | |||
| content: "横琴先进智能计算中心"; | |||
| } | |||
| .itemList .rotation3D__item:nth-child(11) .cont p::after{ | |||
| content: "国家超级计算济南中心"; | |||
| } | |||
| .rotation3D__item.blue{ color: #01e9fc; } | |||
| .rotation3D__item.green{ color: #b4b3ca; } | |||
| .rotation3D__item.yellow{ color: #ffd200; } | |||
| @@ -90,14 +61,17 @@ | |||
| ---------------------------*/ | |||
| .rotation3D__line{ | |||
| position: absolute; left: 50%; top: 50%; | |||
| display: block; width: 1px; height: 50%; | |||
| display: block; | |||
| width: 30px; | |||
| height: 50%; | |||
| padding-top: 60px; color: #fff; font-size: 50px; | |||
| /*background: #fff;*/ | |||
| /*原点设置在中间*/ | |||
| transform-origin: 50% 0; | |||
| transform-style: preserve-3d; | |||
| } | |||
| .rotation3D__line .pos{ position: absolute; top: 0; } | |||
| overflow: hidden; | |||
| } | |||
| .rotation3D__line .pos{ position: absolute; top: 0; left: 15px;} | |||
| .rotation3D__line svg { position: absolute; top: 0; } | |||
| .rotation3D__line svg path { | |||
| stroke: #fff; fill: none; | |||
| @@ -139,8 +113,10 @@ | |||
| position: absolute; | |||
| font-size: 12px; | |||
| color: #888; | |||
| transform: rotate(180deg)scale(0.80); | |||
| } | |||
| transform:scale(0.80); | |||
| transform-origin:left; | |||
| white-space: nowrap; | |||
| } | |||
| /*颜色*/ | |||
| .rotation3D__line.blue { color: #07b2f9; } | |||
| @@ -134,7 +134,7 @@ type Cloudbrain struct { | |||
| CanDebug bool `xorm:"-"` | |||
| CanDel bool `xorm:"-"` | |||
| CanModify bool `xorm:"-"` | |||
| Type int | |||
| Type int `xorm:"INDEX"` | |||
| BenchmarkTypeID int | |||
| BenchmarkChildTypeID int | |||
| @@ -2019,3 +2019,30 @@ func GetDatasetInfo(uuidStr string) (map[string]DatasetInfo, string, error) { | |||
| return datasetInfos, datasetNames, nil | |||
| } | |||
| func GetNewestJobsByAiCenter() ([]int64, error) { | |||
| ids := make([]int64, 0) | |||
| return ids, x. | |||
| Select("max(id) as id"). | |||
| Where("type=? and ai_center!='' and ai_center is not null", TypeC2Net). | |||
| GroupBy("ai_center"). | |||
| Table(Cloudbrain{}). | |||
| Find(&ids) | |||
| } | |||
| func GetNewestJobsByType() ([]int64, error) { | |||
| ids := make([]int64, 0) | |||
| return ids, x. | |||
| Select("max(id) as id"). | |||
| In("type", TypeCloudBrainOne, TypeCloudBrainTwo). | |||
| GroupBy("type"). | |||
| Table(Cloudbrain{}). | |||
| Find(&ids) | |||
| } | |||
| func GetCloudbrainByIDs(ids []int64) ([]*Cloudbrain, error) { | |||
| cloudbrains := make([]*Cloudbrain, 0) | |||
| return cloudbrains, x. | |||
| In("id", ids). | |||
| Find(&cloudbrains) | |||
| } | |||
| @@ -7,6 +7,7 @@ package setting | |||
| import ( | |||
| "encoding/base64" | |||
| "encoding/json" | |||
| "fmt" | |||
| "io" | |||
| "io/ioutil" | |||
| @@ -64,7 +65,16 @@ const ( | |||
| ReCaptcha = "recaptcha" | |||
| ) | |||
| // settings | |||
| type C2NetSequenceInfo struct { | |||
| ID int `json:"id"` | |||
| Name string `json:"name"` | |||
| Content string `json:"content"` | |||
| } | |||
| type C2NetSqInfos struct { | |||
| C2NetSqInfo []*C2NetSequenceInfo `json:"sequence"` | |||
| } | |||
| var ( | |||
| // AppVer settings | |||
| AppVer string | |||
| @@ -534,13 +544,16 @@ var ( | |||
| //grampus config | |||
| Grampus = struct { | |||
| Env string | |||
| Host string | |||
| UserName string | |||
| Password string | |||
| SpecialPools string | |||
| Env string | |||
| Host string | |||
| UserName string | |||
| Password string | |||
| SpecialPools string | |||
| C2NetSequence string | |||
| }{} | |||
| C2NetInfos *C2NetSqInfos | |||
| //elk config | |||
| ElkUrl string | |||
| ElkUser string | |||
| @@ -1423,7 +1436,12 @@ 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\":\"国家超级计算济南中心\"}]}") | |||
| if Grampus.C2NetSequence != "" { | |||
| if err := json.Unmarshal([]byte(Grampus.C2NetSequence), &C2NetInfos); err != nil { | |||
| log.Error("Unmarshal(C2NetSequence) failed:%v", err) | |||
| } | |||
| } | |||
| } | |||
| func SetRadarMapConfig() { | |||
| @@ -119,7 +119,6 @@ document.onreadystatechange = function () { | |||
| continue; | |||
| } | |||
| } | |||
| refresh3DInfo(record); | |||
| var recordPrefix = getMsg(record); | |||
| if(record.OpType == "6" || record.OpType == "10" || record.OpType == "12" || record.OpType == "13"){ | |||
| html += recordPrefix + actionName; | |||
| @@ -208,29 +207,6 @@ function getTaskLink(record){ | |||
| return re; | |||
| } | |||
| function refresh3DInfo(record){ | |||
| if(record.OpType == "25" || record.OpType == "29" || record.OpType == "31"){ | |||
| //cloudbrain one | |||
| var lines = $('.rotation3D__line'); | |||
| var span = $('.rotation3D__line').find("span")[0]; | |||
| //console.log(span); | |||
| span.innerText =record.RefName; | |||
| //$('.rotation3D__line').find("span").eq(0).text(record.RefName) | |||
| //console.log("cloudbrain one line length=" + lines.length); | |||
| //lines[0].find("span").text(record.RefName); | |||
| }else if(record.OpType == "26" || record.OpType == "27" || record.OpType == "28"){ | |||
| //cloudbrain two | |||
| var lines = $('.rotation3D__line'); | |||
| //console.log("cloudbrain two line length=" + lines.length); | |||
| var span = $('.rotation3D__line').find("span")[1]; | |||
| //console.log(span); | |||
| if(span != null){ | |||
| span.innerText =record.RefName; | |||
| } | |||
| } | |||
| } | |||
| function getMsg(record){ | |||
| var html =""; | |||
| html += "<div class=\"swiper-slide item\">"; | |||
| @@ -1057,6 +1057,8 @@ func RegisterRoutes(m *macaron.Macaron) { | |||
| m.Post("/prd/event", authentication.AcceptWechatEvent) | |||
| }) | |||
| m.Get("/wechat/material", authentication.GetMaterial) | |||
| m.Get("/cloudbrain/get_newest_job", repo.GetNewestJobs) | |||
| m.Get("/cloudbrain/get_center_info", repo.GetAICenterInfo) | |||
| }, securityHeaders(), context.APIContexter(), sudo()) | |||
| } | |||
| @@ -6,6 +6,7 @@ | |||
| package repo | |||
| import ( | |||
| "code.gitea.io/gitea/modules/setting" | |||
| "encoding/json" | |||
| "net/http" | |||
| "sort" | |||
| @@ -207,3 +208,92 @@ func CloudBrainModelList(ctx *context.APIContext) { | |||
| "PageIsCloudBrain": true, | |||
| }) | |||
| } | |||
| type JobInfo struct { | |||
| JobName string `json:"job_name"` | |||
| AiCenterId int `json:"ai_center_id"` | |||
| } | |||
| func GetNewestJobs(ctx *context.APIContext) { | |||
| idsC2Net, err := models.GetNewestJobsByAiCenter() | |||
| if err != nil { | |||
| log.Error("GetNewestJobsByAiCenter(%s) failed:%v", err.Error()) | |||
| return | |||
| } | |||
| idsCloudbrain, err := models.GetNewestJobsByType() | |||
| if err != nil { | |||
| log.Error("GetNewestJobsByType(%s) failed:%v", err.Error()) | |||
| return | |||
| } | |||
| ids := make([]int64, len(idsC2Net), cap(idsC2Net)*2) | |||
| copy(ids, idsC2Net) | |||
| copy(ids, idsCloudbrain) | |||
| jobs, err := models.GetCloudbrainByIDs(ids) | |||
| if err != nil { | |||
| log.Error("GetCloudbrainByIDs(%s) failed:%v", err.Error()) | |||
| return | |||
| } | |||
| jobInfos := make([]JobInfo, 0) | |||
| for _, job := range jobs { | |||
| var id int | |||
| var content string | |||
| switch job.Type { | |||
| case models.TypeCloudBrainOne: | |||
| id, content = getAICenterID("cloudbrain_one") | |||
| if content == "" { | |||
| log.Error("job(%s) has no match config info", job.DisplayJobName) | |||
| continue | |||
| } | |||
| case models.TypeCloudBrainTwo: | |||
| id, content = getAICenterID("cloudbrain_two") | |||
| if content == "" { | |||
| log.Error("job(%s) has no match config info", job.DisplayJobName) | |||
| continue | |||
| } | |||
| case models.TypeC2Net: | |||
| centerInfo := strings.Split(job.AiCenter, "+") | |||
| if len(centerInfo) != 2 { | |||
| log.Error("job(%s):ai_center(%s) is wrong", job.DisplayJobName, job.AiCenter) | |||
| continue | |||
| } | |||
| id, content = getAICenterID(centerInfo[0]) | |||
| if content == "" { | |||
| log.Error("job(%s) has no match config info", job.DisplayJobName) | |||
| continue | |||
| } | |||
| default: | |||
| log.Error("no match info") | |||
| continue | |||
| } | |||
| jobInfos = append(jobInfos, JobInfo{ | |||
| JobName: job.DisplayJobName, | |||
| AiCenterId: id, | |||
| }) | |||
| } | |||
| ctx.JSON(http.StatusOK, jobInfos) | |||
| } | |||
| func GetAICenterInfo(ctx *context.APIContext) { | |||
| if setting.C2NetInfos == nil { | |||
| log.Error("C2NET_SEQUENCE is incorrect") | |||
| return | |||
| } | |||
| ctx.JSON(http.StatusOK, setting.C2NetInfos.C2NetSqInfo) | |||
| } | |||
| func getAICenterID(name string) (int, string) { | |||
| for _, info := range setting.C2NetInfos.C2NetSqInfo { | |||
| if name == info.Name { | |||
| return info.ID, info.Content | |||
| } | |||
| } | |||
| return 0, "" | |||
| } | |||
| @@ -51,23 +51,63 @@ | |||
| <script src="/rotation3D/vue-2.6.10.min.js"></script> | |||
| <script src="/rotation3D/rotation3D.js?v={{MD5 AppVer}}"></script> | |||
| <script> | |||
| var jobTask={}; | |||
| function queryAiCenterInfo(){ | |||
| $.ajax({ | |||
| type:"GET", | |||
| url:"/api/v1/cloudbrain/get_newest_job", | |||
| headers: { | |||
| authorization:token, | |||
| }, | |||
| dataType:"json", | |||
| async:false, | |||
| success:function(json){ | |||
| for(var i=0;i < json.length;i++){ | |||
| jobTask[json[i].ai_center_id] =json[i].job_name; | |||
| } | |||
| }, | |||
| error:function(response) { | |||
| console.log("query task info error."); | |||
| } | |||
| }); | |||
| $.ajax({ | |||
| type:"GET", | |||
| url:"/api/v1/cloudbrain/get_center_info", | |||
| headers: { | |||
| authorization:token, | |||
| }, | |||
| dataType:"json", | |||
| async:false, | |||
| success:function(json){ | |||
| displayAiCenterInfo(json); | |||
| }, | |||
| error:function(response) { | |||
| } | |||
| }); | |||
| } | |||
| function displayAiCenterInfo(json){ | |||
| for(var i=0;i<json.length;i++){ | |||
| var tmp ={}; | |||
| tmp["name"]=json[i].name; | |||
| if(jobTask[json[i].id] != null){ | |||
| tmp["type"]="blue"; | |||
| }else{ | |||
| tmp["type"]="green"; | |||
| } | |||
| tmp["icon"]=""; | |||
| tmp["content"]=json[i].content; | |||
| serverItemList.push(tmp); | |||
| } | |||
| } | |||
| var serverItemList=[]; | |||
| queryAiCenterInfo(); | |||
| var app = new Vue({ | |||
| el: "#app", | |||
| //数据 blue, green, yellow | |||
| data: { | |||
| itemList: [ | |||
| { name:'鹏城云脑一号', type:'blue', icon:'', }, | |||
| { name:'鹏城云脑二号', type:'blue', icon:'', }, | |||
| { name:'北大人工智能集群系统', type:'green', icon:'', }, | |||
| { name:'合肥类脑智能开放平台', type:'green', icon:'', }, | |||
| { name:'武汉人工智能计算中心', type:'green', icon:'', }, | |||
| { name:'西安未来人工智能计算中心', type:'green', icon:'', }, | |||
| { name:'……', type:'yellow', icon:'', }, | |||
| { name:'中原人工智能计算中心', type:'green', icon:'', }, | |||
| { name:'成都人工智能计算中心', type:'green', icon:'', }, | |||
| { name:'横琴先进智能计算中心', type:'green', icon:'', }, | |||
| { name:'国家超级计算济南中心', type:'green', icon:'', }, | |||
| ], | |||
| itemList:serverItemList, | |||
| }, | |||
| mounted: function () { | |||
| new Rotation3D({ | |||
| @@ -84,6 +124,19 @@ | |||
| }, | |||
| methods: {}, | |||
| }); | |||
| $(document).ready(function(){ | |||
| var pArrays=$('.itemList').find("p"); | |||
| for(var i=0;i<pArrays.length;i++){ | |||
| var p = pArrays[i]; | |||
| p.innerText=serverItemList[i].content; | |||
| } | |||
| var lines=$('.lineList').find("span"); | |||
| for(var i=0; i< lines.length;i++){ | |||
| if(jobTask[i+1] != null){ | |||
| lines[i].innerText = jobTask[i+1]; | |||
| } | |||
| } | |||
| }); | |||
| </script> | |||
| {{end}} | |||
| @@ -94,12 +94,6 @@ | |||
| </div> | |||
| <div id="app" v-cloak> | |||
| <!--数据 | |||
| <div class="aiData"> | |||
| <p>完成AI任务<br><strong id="completed_task">1716</strong></p> | |||
| <p>运行AI任务<br><strong id="running_task">120</strong></p> | |||
| <p>等待AI任务<br><strong id="wait_task">80</strong></p> | |||
| </div>--> | |||
| <!--底座--> | |||
| <div class="rotation3D-baseMap"></div> | |||
| <!--旋转3D--> | |||
| @@ -129,13 +123,13 @@ | |||
| <svg width="10" height="400"> | |||
| <path id="path2" d="M0 400, 0 0" stroke-dasharray="5,10"/> | |||
| </svg> | |||
| <div class="dot dot2"><i class="el-icon-close"></i></div> | |||
| <div class="dot dot2"><i class="el-icon-close"></i><span></span></div> | |||
| </div> | |||
| <div v-if="item.type=='green'" class="pos"> | |||
| <svg width="50" height="400"> | |||
| <path id="path1" d="M0 400, 0 0" stroke-dasharray="5,10"/> | |||
| </svg> | |||
| <div class="dot dot1 ri-arrow-left-s-line"></div> | |||
| <div class="dot dot1 ri-arrow-left-s-line"><span></span></div> | |||
| </div> | |||
| </div> | |||
| </div> | |||