Browse Source

Merge remote-tracking branch 'origin/V20220616' into fix-2208

pull/2291/head
liuzx 3 years ago
parent
commit
88c2b52ce4
66 changed files with 3262 additions and 199 deletions
  1. +76
    -5
      custom/public/css/git.openi.css
  2. BIN
      custom/public/img/i-pic-01.jpg
  3. BIN
      custom/public/img/i-pic-02.jpg
  4. BIN
      custom/public/img/i-pic-03.jpg
  5. BIN
      custom/public/img/i-pic-04.jpg
  6. BIN
      custom/public/rotation3D/img/baseLogo.png
  7. +1250
    -0
      custom/public/rotation3D/img/baseLogo.svg
  8. BIN
      custom/public/rotation3D/img/baseMap.png
  9. +1
    -0
      custom/public/rotation3D/img/brain.svg
  10. BIN
      custom/public/rotation3D/img/idc-green.png
  11. BIN
      custom/public/rotation3D/img/idc-red.png
  12. BIN
      custom/public/rotation3D/img/idc-yellow.png
  13. +2
    -0
      custom/public/rotation3D/jquery-3.5.0.min.js
  14. +152
    -0
      custom/public/rotation3D/rotation3D.css
  15. +380
    -0
      custom/public/rotation3D/rotation3D.js
  16. +6
    -0
      custom/public/rotation3D/vue-2.6.10.min.js
  17. +14
    -2
      models/cloudbrain.go
  18. +22
    -0
      models/cloudbrain_static.go
  19. +16
    -13
      models/user_business_analysis.go
  20. +1
    -0
      modules/auth/repo_form.go
  21. +41
    -0
      modules/modelarts/resty.go
  22. +8
    -0
      modules/storage/local.go
  23. +10
    -0
      modules/storage/minio.go
  24. +134
    -0
      modules/storage/minio_ext.go
  25. +14
    -0
      modules/storage/obs.go
  26. +1
    -0
      modules/storage/storage.go
  27. +5
    -1
      options/locale/locale_en-US.ini
  28. +7
    -2
      options/locale/locale_zh-CN.ini
  29. +66
    -5
      public/home/home.js
  30. +1
    -0
      public/self/css/notebook/katex.min.css
  31. +86
    -0
      public/self/css/notebook/notebook.css
  32. +142
    -0
      public/self/css/notebook/prism.css
  33. +6
    -0
      public/self/js/notebook/ansi_up.min.js
  34. +7
    -0
      public/self/js/notebook/es5-shim.min.js
  35. +1
    -0
      public/self/js/notebook/katex-auto-render.min.js
  36. +1
    -0
      public/self/js/notebook/katex.min.js
  37. +1
    -0
      public/self/js/notebook/marked.min.js
  38. +1
    -0
      public/self/js/notebook/notebook.min.js
  39. +7
    -0
      public/self/js/notebook/prism.min.js
  40. +3
    -0
      public/self/js/notebook/purify.min.js
  41. +4
    -0
      routers/api/v1/api.go
  42. +16
    -0
      routers/api/v1/repo/cloudbrain_dashboard.go
  43. +43
    -0
      routers/api/v1/repo/modelarts.go
  44. +33
    -0
      routers/home.go
  45. +201
    -78
      routers/repo/ai_model_manage.go
  46. +1
    -1
      routers/repo/dataset.go
  47. +34
    -4
      routers/repo/modelarts.go
  48. +6
    -2
      routers/repo/repo.go
  49. +4
    -0
      routers/repo/view.go
  50. +7
    -3
      routers/routes/routes.go
  51. +44
    -0
      templates/base/footer.tmpl
  52. +2
    -0
      templates/base/head_home.tmpl
  53. +4
    -4
      templates/base/head_navbar.tmpl
  54. +5
    -5
      templates/explore/datasets.tmpl
  55. +80
    -25
      templates/home.tmpl
  56. +39
    -19
      templates/repo/create.tmpl
  57. +4
    -4
      templates/repo/datasets/index.tmpl
  58. +12
    -0
      templates/repo/header.tmpl
  59. +32
    -1
      templates/repo/modelarts/trainjob/show.tmpl
  60. +85
    -8
      templates/repo/modelmanage/index.tmpl
  61. +14
    -0
      templates/repo/view_file.tmpl
  62. +4
    -11
      templates/user/dashboard/dashboard.tmpl
  63. +1
    -1
      templates/user/dashboard/feeds.tmpl
  64. +15
    -2
      web_src/js/components/Model.vue
  65. +106
    -3
      web_src/js/index.js
  66. +4
    -0
      web_src/less/_dashboard.less

+ 76
- 5
custom/public/css/git.openi.css View File

@@ -71,6 +71,19 @@
.ui.secondary.hometop.segment #navbar{ .ui.secondary.hometop.segment #navbar{
z-index: 10; z-index: 10;
} }
.ui.secondary.c2net.segment{
/* background: #f8faff;
border: none;*/
margin-bottom: 5em;
padding-top: 2em;
color: rgba(0,0,0,.87);
background-image: linear-gradient(to bottom left,var(--tw-gradient-stops));
--tw-gradient-from: #f5f3ff;
--tw-gradient-stops: var(--tw-gradient-from),#fff,var(--tw-gradient-to,hsla(0,0%,100%,0));
--tw-gradient-to: rgba(219,234,254,0.4);
border-top: 1px solid rgba(243,244,246,1)!important;
border-bottom: 1px solid rgba(243,244,246,1)!important;
}


.hometop .ui.secondary.menu .active.item{ .hometop .ui.secondary.menu .active.item{
color: #000; color: #000;
@@ -134,8 +147,13 @@
.i-code-pic > img{ .i-code-pic > img{
margin-bottom: -3.0rem; margin-bottom: -3.0rem;
} }
.i-env .ui.cards>.card{
box-shadow:none;
}
.i-env .ui.cards>.card>.image{ .i-env .ui.cards>.card>.image{
background: none; background: none;
width: 60%;
margin: auto;
} }
.i-env .ui.cards>.card>.content{ .i-env .ui.cards>.card>.content{
border-top: none; border-top: none;
@@ -168,7 +186,7 @@
bottom: 0; bottom: 0;
background-color: rgba(105, 192, 255, .4); background-color: rgba(105, 192, 255, .4);
width: 2px; width: 2px;
}
}
.homenews .time-since{ .homenews .time-since{
padding-left: 1em; padding-left: 1em;
color: #888888; color: #888888;
@@ -185,7 +203,7 @@
padding: 0; padding: 0;
} }
.newslist{ .newslist{
height: 325px;
height: 300px;
overflow: hidden; overflow: hidden;
} }


@@ -208,14 +226,25 @@
height: auto; height: auto;
border-top: 2px solid #3291F8; border-top: 2px solid #3291F8;
border-right: 2px solid #3291F8; border-right: 2px solid #3291F8;
border-bottom: 2px solid #3291F8;
border-radius: 0 4.0em 4.0em 0;
border-radius: 0 4.0em 0 0;
width: 10em; width: 10em;
z-index: 6; z-index: 6;
} }
.leftline02::after, .leftline02-2::after{
content: '';
position: absolute;
transform: translate(55%,50%);
right: 0;
bottom: 0;
width: 1.0em;
height: 1.0em;
background-color: #FFF;
border: 2px solid #3291F8;
border-radius: 1em;
}
.leftline03{ .leftline03{
border-radius: 4.0em 0 0 0; border-radius: 4.0em 0 0 0;
border-top: 2px solid #3291F8;
border-top: 2px solid #3291F8;
border-bottom:none; border-bottom:none;
top: -2.0em; top: -2.0em;
} }
@@ -224,6 +253,9 @@
width: 7em; width: 7em;
z-index: 5; z-index: 5;
} }
.leftline02-2::after{
border-color: rgba(105, 192, 255, .4);
}
.leftline04{ .leftline04{
border-radius: 0; border-radius: 0;
border-top: none; border-top: none;
@@ -280,6 +312,9 @@
.i-env > div{ .i-env > div{
position: relative; position: relative;
} }
.event-list .ui.card>.image>img{
height: 146px !important;
}


@media only screen and (max-width: 767px) { @media only screen and (max-width: 767px) {
.am-mt-30{ margin-top: 1.5rem !important;} .am-mt-30{ margin-top: 1.5rem !important;}
@@ -376,4 +411,40 @@


@media only screen and (min-width: 1920px) { @media only screen and (min-width: 1920px) {


}

/* rotation3D */
#app{
width: 800px;
margin: 0 auto;
}
.rotation3D-baseMap{
position: absolute; left: 0; right: 0; top: 270px; margin: auto;
width: 800px; height: 516px;
background: url("../rotation3D/img/baseMap.png") no-repeat;
background-size: cover;
}
.rotation3D-baseMap::before{
position: absolute;
margin: auto; z-index: 99;
left:50%; top: -150px;
transform:translate(-50%,0);
width: 342px; height: 470px; display: block; content: '';
background: url("../rotation3D/img/baseLogo.svg");
/*animation: 10s bounceUpDown infinite;*/
}
.rotation3D-baseMap::after{
position: absolute;
margin: auto; z-index: 100;
left:50%; top:0;
transform:translate(-50%,0);
width: 110px; height: 86px; display: block; content: '';
background: url("../rotation3D/img/brain.svg");
animation: 6s bounceUpDown infinite;
mix-blend-mode: color-dodge;
}
@keyframes bounceUpDown{
0% {transform: translate(-50%, 0px);}
50% {transform: translate(-50%, -15px);}
100% {transform: translate(-50%, 0px);}
} }

BIN
custom/public/img/i-pic-01.jpg View File

Before After
Width: 266  |  Height: 178  |  Size: 13 kB

BIN
custom/public/img/i-pic-02.jpg View File

Before After
Width: 266  |  Height: 178  |  Size: 12 kB

BIN
custom/public/img/i-pic-03.jpg View File

Before After
Width: 266  |  Height: 178  |  Size: 14 kB

BIN
custom/public/img/i-pic-04.jpg View File

Before After
Width: 266  |  Height: 178  |  Size: 17 kB

BIN
custom/public/rotation3D/img/baseLogo.png View File

Before After
Width: 342  |  Height: 470  |  Size: 88 kB

+ 1250
- 0
custom/public/rotation3D/img/baseLogo.svg
File diff suppressed because it is too large
View File


BIN
custom/public/rotation3D/img/baseMap.png View File

Before After
Width: 800  |  Height: 516  |  Size: 58 kB

+ 1
- 0
custom/public/rotation3D/img/brain.svg
File diff suppressed because it is too large
View File


BIN
custom/public/rotation3D/img/idc-green.png View File

Before After
Width: 161  |  Height: 188  |  Size: 39 kB

BIN
custom/public/rotation3D/img/idc-red.png View File

Before After
Width: 161  |  Height: 188  |  Size: 39 kB

BIN
custom/public/rotation3D/img/idc-yellow.png View File

Before After
Width: 161  |  Height: 188  |  Size: 39 kB

+ 2
- 0
custom/public/rotation3D/jquery-3.5.0.min.js
File diff suppressed because it is too large
View File


+ 152
- 0
custom/public/rotation3D/rotation3D.css View File

@@ -0,0 +1,152 @@

/*
椭圆会使内部失真 transform: rotateX(50deg);
*/
.rotation3D{
position: relative; width: 800px; height: 600px; user-select: none;
margin: 0 auto;
/* border: 1px solid white; border-radius: 100%; */
/* cursor: move; */
}
.rotation3D .center{
display: none;
position: absolute; left: 50%; top: 50%;
transform: translate(-50%, -50%);
}

.rotation3D .itemList{ position: absolute; width: 100%; height: 100%; z-index: 20; }
.rotation3D .lineList{
position: absolute; width: 100%; height: 100%; z-index: 10;
transform-style: preserve-3d;
}

/*---------------------------点样式---------------------------*/
.rotation3D__item{
position: absolute; display: block; width: 161px; height: 188px;
text-align: center; line-height: 30px; font-size: 16px; color: white;
/*background: #2292ef; border-radius: 4px;*/
/*cursor: pointer; */
}
.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 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: "合肥类脑智能开放平台";
}
.itemList .rotation3D__item:nth-child(5) .cont p::after{
content: "武汉人工智能计算中心";
}
.itemList .rotation3D__item:nth-child(6) .cont p::after{
content: "西安未来人工智能计算中心";
}
.itemList .rotation3D__item:nth-child(7) .cont p::after{
content: "更多接入中…";
}
.itemList .rotation3D__item:nth-child(8) .cont p::after{
content: "中原人工智能计算中心";
}
.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; }

/*底座*/
.rotation3D__item .baseImg{ position: absolute; width: 100%; height: 100%; z-index: 1; }
.rotation3D__item.blue .baseImg{ background: url("img/idc-red.png"); }
.rotation3D__item.green .baseImg{ background: url("img/idc-green.png"); }
.rotation3D__item.yellow .baseImg{ background: url("img/idc-yellow.png"); }

/*---------------------------
线样式
线高为总高的一般
---------------------------*/
.rotation3D__line{
position: absolute; left: 50%; top: 50%;
display: block; width: 1px; 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; }
.rotation3D__line svg { position: absolute; top: 0; }
.rotation3D__line svg path {
stroke: #fff; fill: none;
stroke-width: 2;
animation: path-animation 100s linear 0s infinite normal;
}
@keyframes path-animation {
0% { stroke-dashoffset:500; }
100% { stroke-dashoffset:0; }
}
.rotation3D__line .dot {
position: absolute; top: 0; left: 0; text-align: center;
/*width: 35px; height: 35px; font-size: 35px; */
width: 19px; height: 19px; font-size: 19px;
}
.rotation3D__line .dot1,.rotation3D__line .dot3,.rotation3D__line .dot4{
animation: svg-path-animation 6s ease-in-out 0s infinite normal;
}
.rotation3D__line .dot1{
offset-path: path("M0 400, 0 0"); offset-distance: 0%;
}
.rotation3D__line .dot2{
offset-path: path("M0 200, 0 0"); offset-distance: 0%;
background: #ffd200; border-radius: 100%;
font-size: 22px; color: #000;
}
.rotation3D__line .dot3{
offset-path: path("M20 400 S 0 200, 20 0"); offset-distance: 0%;
}
.rotation3D__line .dot4{
position: relative;
offset-path: path("M20 0 S 40 200, 20 400"); offset-distance: 0%;
}
@keyframes svg-path-animation {
from {offset-distance: 100%;}
to {offset-distance: 0%;}
}
.dot1 > span{
position: absolute;
font-size: 12px;
color: #888;
transform: rotate(180deg)scale(0.80);
}

/*颜色*/
.rotation3D__line.blue { color: #07b2f9; }
.rotation3D__line.green { color: #ac94ee; }
.rotation3D__line.yellow { color: #ffd500; }

.rotation3D__line.blue svg path { stroke: #07b2f9; }
.rotation3D__line.green svg path { stroke: #ac94ee; }
.rotation3D__line.yellow svg path { stroke: #ffd500; }

+ 380
- 0
custom/public/rotation3D/rotation3D.js View File

@@ -0,0 +1,380 @@
var cancelFrame = window.cancelAnimationFrame || window.cancelRequestAnimationFrame;
var requestFrame = window.requestAnimationFrame;
var time = !window.performance || !window.performance.now ?
function () {return +new Date()}:
function () {return performance.now()};

/**
* 计算两点距离
* @param points
* @returns {number}
* distance([{x:0,y:0},{x:1,y:1}]);
*/
var distance = function(points) {
var p1=points[0];
var p2=points[1];
var a = p2.x-p1.x;
var b = p2.y-p1.y;
return Math.sqrt(a*a+b*b);
};

/**
* 圆公式
* @param rotation 弧度
* 计算公式:
* Math.PI; //圆周率
* Math.sin(); //正弦 x -左 +右
* Math.cos; //余弦 y -下 +上
*/
var circleMath = {
/**
* 根据弧度计算角度
* @param rotation 弧度
* rotation, farScale, xs, xr, ys, yr, itemWidth
*/
// parseRotate: function (rotation) {
// return (180 / Math.PI * rotation) - 180;
// },
parseRotate: function (rotation, self) {
var sin = Math.sin(rotation), cos = Math.cos(rotation);
var sin_cos = sin*cos; //得出偏移正负值,从0°向左依次 +-+-
var angle = (180 / Math.PI * rotation) - 180;
var lastAngle = angle;

// console.log('rotation',rotation)
// console.log('sin',sin)
// console.log('cos',cos)
// console.log('sin*cos',sin*cos);
// console.log('统一偏移角度',self.yr * (sin_cos/Math.PI))

lastAngle = angle + (self.yr * (sin_cos/(Math.PI+1)));

return lastAngle;
},
/**
* 计算scale,x,y
* scale 最小尺寸 + ((1 - 最小尺寸) * (sin正弦 + 1) * 0.5)
* x x起点 + (尺寸 * cos余弦 * x半径) - 元素宽度一半
* y y起点 + (尺寸 * sin正弦 * x半径) - 元素宽度一半
* farScale, xs, xr, ys, yr, itemWidth
*/
parseSXY: function (rotation, self) {
var farScale=self.farScale;
var itemWidth=self.itemWidth;
var xs=self.xs; var xr=self.xr; var ys=self.ys; var yr=self.yr;
var sin = Math.sin(rotation), cos = Math.cos(rotation);
var scale = farScale + ((1 - farScale) * (sin + 1) * 0.5); //单个尺寸

// 按设置尺寸
// var x = xs + (scale * cos * xr) - (itemWidth * 0.5);
// var y = ys + (scale * sin * yr) - (itemWidth * 0.5);
// 不使用压缩
// var x = xs + (cos * xs) - (itemWidth * 0.5);
// var y = ys + (sin * ys) - (itemWidth * 0.5);
// 使用压缩
var x = xs + (cos * xr) - (itemWidth * 0.5);
var y = ys + (sin * yr) - (itemWidth * 0.5);
var distanceNumber = distance([
{x:self.$rotation.width()/2 - self.$item.width()/2, y:self.$rotation.height()/2 - self.$item.height()/2},
{x:x,y:y}]
);

// console.log({x:self.$rotation.width()/2, y:self.$rotation.height()/2})
// console.log('x,y',x,y)
// console.log('两点距离',distanceNumber)

return {
x: x,
y: y,
scale: scale,
distanceNumber: distanceNumber,
}
},
}
/**
* 3D旋转
* @param id
*/
var Rotation3D = window.Rotation3D = function (_opts) {
var self=this;
this.$rotation = $(_opts.id)
this.$lineList = this.$rotation.find('.lineList')
this.$item = this.$rotation.find('.rotation3D__item')
this.$line = this.$rotation.find('.rotation3D__line')
this.itemWidth = this.$item.width();
this.itemHeight = this.$item.height();
this.length = this.$item.length;
// 圆计算
this.rotation = Math.PI / 2; //圆周率/2
this.destRotation = this.rotation;

var xr = this.$rotation.width() * 0.5;
var yr = this.$rotation.height() * 0.5;
var xRadius = _opts.xRadius || 0;
var yRadius = _opts.yRadius || 0;

var opts = Object.assign({
farScale: 1, // 最小尺寸
xs: xr, // x起点
ys: yr, // y起点
xr: xr - xRadius, // x半径-压缩
yr: yr - yRadius, // y半径-压缩
// 播放
autoPlay:false,
autoPlayDelay:3000,
currenIndex:-1,
fps:30,
speed:4,
},_opts)
Object.assign(this, opts)

// 遍历子元素
this.$item.each(function (index) {
$(this).click(function () {
$(this).addClass('active').siblings().removeClass('active')
self.goTo(index)
})
})
// 当前控件进入离开
this.$rotation.mouseenter(function () {
clearInterval(self.autoPlayTimer)
})
this.$rotation.mouseleave(function () {
self.onAutoPlay()
})

this.onAutoPlay()
this.onDrag()
this.render()

}
/**
* item样式
* x x起点 + (尺寸 * 余弦 * x压缩) - 元素宽度一半
* y y起点 + (尺寸 * 正弦 * y压缩) - 元素宽度一半
*/
Rotation3D.prototype.itemStyle = function($item, index, rotation) {
//console.log("itemStyle=" + rotation + " index=" + index);
var parseSXY = circleMath.parseSXY(rotation, this);
var scale = parseSXY.scale;
var x = parseSXY.x;
var y = parseSXY.y;
var $line = this.$lineList.find('.rotation3D__line').eq(index);

//设置当前子菜单的位置(left,top) = (x,y)
$item.find('.scale').css({
'transform': `scale(${scale})`,
// 'top': `${this.itemWidth * (1-scale) }`,
})
$item.css({
position: 'absolute',
display: 'inline-block',
// opacity: scale,
'z-index': parseInt(scale * 100),
'transform-origin': '0px 0px',
// 'transform': `translate(${x}px, ${y}px) scale(${scale})`,
'transform': `translate(${x}px, ${y}px)`,
});

/**
* 线样式
*/
$line.css({
height:parseSXY.distanceNumber,
})
$line.find('svg').css({
height:parseSXY.distanceNumber,
})
$line.find('.dot1').css({
'offset-path':`path("M0 ${parseSXY.distanceNumber}, 0 0")`,
})
$line.find('#path1').attr({
'd':`M0 ${parseSXY.distanceNumber}, 0 0`,
})

$line.find('.dot2').css({
'offset-path':`path("M0 ${parseSXY.distanceNumber/2}, 0 0")`,
})
$line.find('#path2').attr({
'd':`M0 ${parseSXY.distanceNumber}, 0 0`,
})

$line.find('.dot3').css({
'offset-path':`path("M20 ${parseSXY.distanceNumber} S 0 ${parseSXY.distanceNumber/2}, 20 0")`,
})
$line.find('#path3').attr({
'd':`M20 ${parseSXY.distanceNumber} S 0 ${parseSXY.distanceNumber/2}, 20 0`,
})

$line.find('.dot4').css({
'offset-path':`path("M20 0 S 40 ${parseSXY.distanceNumber/2}, 20 ${parseSXY.distanceNumber}")`,
})
$line.find('#path4').attr({
'd':`M20 0 S 40 ${parseSXY.distanceNumber/2}, 20 ${parseSXY.distanceNumber}`,
})

}
/**
* line样式
*/
Rotation3D.prototype.lineStyle = function($line, index, rotation) {
var rotate = circleMath.parseRotate(rotation, this)
//console.log("lineStyle=" + rotation + " index=" + index);

$line.css({
transform: 'rotate(' + rotate + 'deg)',
})
this.$lineList.css({
// transform: `rotateX(${this.yRadius / 3}deg)`,
})
}

/**
* 旋转至index
*/
Rotation3D.prototype.goTo = function (index) {
var self = this;
this.currenIndex = index;
//console.log('goTo currenIndex', index);
/**
* 1.计算floatIndex,用于控死amdiff
*/
var itemsRotated = this.length * ((Math.PI / 2) - this.rotation) / (2 * Math.PI);
var floatIndex = itemsRotated % this.length;
if (floatIndex < 0) { floatIndex = floatIndex + this.length; }

/**
* 2.计算diff,判断方向正反
*/
var diff = index - (floatIndex % this.length);
if (2 * Math.abs(diff) > this.length) {
diff -= (diff > 0) ? this.length : -this.length;
}
// 停止任何正在进行的旋转
this.destRotation += (2 * Math.PI / this.length) * -diff;
this.scheduleNextFrame();

}
/**
* 定时器渐近旋转
*/
Rotation3D.prototype.scheduleNextFrame = function () {
var self = this
this.lastTime = time();
// 暂停
var pause = function () {
cancelFrame ? cancelFrame(this.timer) : clearTimeout(self.timer);
self.timer = 0;
}
// 渐进播放
var playFrame = function () {
var rem = self.destRotation - self.rotation;
var now = time(), dt = (now - self.lastTime) * 0.002;
self.lastTime = now;
// console.log('rem',rem)

if (Math.abs(rem) < 0.003) {
self.rotation = self.destRotation;
pause();
} else {
// 渐近地接近目的地
self.rotation = self.destRotation - rem / (1 + (self.speed * dt));
self.scheduleNextFrame();
}
self.render();
}

this.timer = cancelFrame ?
requestFrame(playFrame) :
setTimeout(playFrame, 1000 / this.fps);
}
/**
* 更新
*/
Rotation3D.prototype.render = function () {
var self=this;
// 图形间隔:弧度
var spacing = 2 * Math.PI / this.$item.length;
var itemRotation = this.rotation;
var lineRotation = this.rotation + (Math.PI/2);

this.$item.each(function (index) {
self.itemStyle($(this), index, itemRotation)
itemRotation += spacing;
})
this.$line.each(function (index) {
self.lineStyle($(this), index, lineRotation)
lineRotation += spacing;
})
}
/**
* 自动播放
*/
Rotation3D.prototype.onAutoPlay = function () {
var self = this;

if (this.autoPlay) {
this.autoPlayTimer = setInterval(function () {
if (self.currenIndex < 0) {
self.currenIndex = self.length - 1
}
//console.log("autoPlayTimer....");
self.goTo(self.currenIndex);
self.currenIndex--; //倒叙
}, this.autoPlayDelay)
}
}
/**
* 拖拽
*/
Rotation3D.prototype.onDrag = function () {
var self = this;
var startX, startY, moveX, moveY, endX, endY;
//console.log("onDrag....");
// 拖拽:三个事件-按下 移动 抬起
//按下
this.$rotation.mousedown(function (e) {
startX = e.pageX; startY = e.pageY;
//console.log("mousedown....");
// 移动
$(document).mousemove(function (e) {
// console.log('移动');
endX = e.pageX; endY = e.pageY;
moveX = endX - startX; moveY = endY - startY;
// console.log('x,y',moveX,moveY);
})
// 抬起
$(document).mouseup(function (e) {
endX = e.pageX; endY = e.pageY;
moveX = endX - startX; moveY = endY - startY;
//console.log("mouseup....");
// 每40旋转一步
var moveIndex = parseInt(Math.abs(moveX) / 50)
//console.log('moveIndex',moveIndex)
if (moveIndex > 0) {
// console.log(moveX<0 ? '向左' : '向右')
if (moveX < 0) { //向左
self.currenIndex = self.currenIndex - moveIndex
play(moveIndex)
} else { //向右
self.currenIndex = self.currenIndex + moveIndex
play(moveIndex)
}
}

// 解绑
$(document).unbind("mousemove");
$(document).unbind("mouseup");
})

})

function play() {
if (self.currenIndex == 0) {
self.currenIndex = self.length - 1
}
self.goTo(self.currenIndex % self.length);
}

}

+ 6
- 0
custom/public/rotation3D/vue-2.6.10.min.js
File diff suppressed because it is too large
View File


+ 14
- 2
models/cloudbrain.go View File

@@ -1150,6 +1150,17 @@ type LogFile struct {
Name string Name string
} }


type GetTrainJobMetricStatisticResult struct {
TrainJobResult
Interval int `json:"interval"` //查询的时间间隔,单位为分钟
MetricsInfo []Metrics `json:"metrics"` //监控详情
}

type Metrics struct {
Metric string `json:"metric"` //监控指标项
Value []string `json:"value"` //获取的监控值的序列,元素为String类型
}

func Cloudbrains(opts *CloudbrainsOptions) ([]*CloudbrainInfo, int64, error) { func Cloudbrains(opts *CloudbrainsOptions) ([]*CloudbrainInfo, int64, error) {
sess := x.NewSession() sess := x.NewSession()
defer sess.Close() defer sess.Close()
@@ -1280,7 +1291,8 @@ func QueryModelTrainJobVersionList(jobId string) ([]*CloudbrainInfo, int, error)
builder.Eq{"cloudbrain.job_id": jobId}, builder.Eq{"cloudbrain.job_id": jobId},
) )
cond = cond.And( cond = cond.And(
builder.Eq{"cloudbrain.Status": "COMPLETED"},
builder.In("cloudbrain.Status", "COMPLETED", "SUCCEEDED"),
//builder.Eq{"cloudbrain.Status": "COMPLETED"},
) )


sess.OrderBy("cloudbrain.created_unix DESC") sess.OrderBy("cloudbrain.created_unix DESC")
@@ -1301,7 +1313,7 @@ func QueryModelTrainJobList(repoId int64) ([]*CloudbrainInfo, int, error) {
builder.Eq{"repo_id": repoId}, builder.Eq{"repo_id": repoId},
) )
cond = cond.And( cond = cond.And(
builder.Eq{"Status": "COMPLETED"},
builder.In("Status", "COMPLETED", "SUCCEEDED"),
) )
cond = cond.And( cond = cond.And(
builder.Eq{"job_type": "TRAIN"}, builder.Eq{"job_type": "TRAIN"},


+ 22
- 0
models/cloudbrain_static.go View File

@@ -0,0 +1,22 @@
package models

import "code.gitea.io/gitea/modules/log"

func GetAllStatusCloudBrain() map[string]int {
sess := x.NewSession()
defer sess.Close()
cloudbrains := make([]*CloudbrainInfo, 0)
if err := sess.Table(&Cloudbrain{}).Unscoped().
Find(&cloudbrains); err != nil {
log.Info("find error.")
}
cloudBrainStatusResult := make(map[string]int)
for _, cloudbrain := range cloudbrains {
if _, ok := cloudBrainStatusResult[cloudbrain.Status]; !ok {
cloudBrainStatusResult[cloudbrain.Status] = 1
} else {
cloudBrainStatusResult[cloudbrain.Status] += 1
}
}
return cloudBrainStatusResult
}

+ 16
- 13
models/user_business_analysis.go View File

@@ -719,12 +719,11 @@ func refreshUserStaticTable(wikiCountMap map[string]int, tableName string, pageS
userIndexMap := make(map[int64]float64, 0) userIndexMap := make(map[int64]float64, 0)
maxUserIndex := 0.0 maxUserIndex := 0.0
minUserIndex := 100000000.0 minUserIndex := 100000000.0
dateRecordBatch := make([]UserBusinessAnalysisAll, 0)
for { for {
sess.Select("`user`.*").Table("user").Where(cond).OrderBy("id asc").Limit(PAGE_SIZE, int(indexTotal)) sess.Select("`user`.*").Table("user").Where(cond).OrderBy("id asc").Limit(PAGE_SIZE, int(indexTotal))
userList := make([]*User, 0) userList := make([]*User, 0)
sess.Find(&userList) sess.Find(&userList)
dateRecordBatch := make([]UserBusinessAnalysisAll, 0)
for _, userRecord := range userList { for _, userRecord := range userList {
var dateRecordAll UserBusinessAnalysisAll var dateRecordAll UserBusinessAnalysisAll
dateRecordAll.ID = userRecord.ID dateRecordAll.ID = userRecord.ID
@@ -789,7 +788,7 @@ func refreshUserStaticTable(wikiCountMap map[string]int, tableName string, pageS


dateRecordBatch = append(dateRecordBatch, dateRecordAll) dateRecordBatch = append(dateRecordBatch, dateRecordAll)
if len(dateRecordBatch) >= BATCH_INSERT_SIZE { if len(dateRecordBatch) >= BATCH_INSERT_SIZE {
insertTable(dateRecordBatch, tableName, statictisSess)
err := insertTable(dateRecordBatch, tableName, statictisSess)
insertCount += BATCH_INSERT_SIZE insertCount += BATCH_INSERT_SIZE
if err != nil { if err != nil {
log.Info("insert all data failed." + err.Error()) log.Info("insert all data failed." + err.Error())
@@ -804,18 +803,19 @@ func refreshUserStaticTable(wikiCountMap map[string]int, tableName string, pageS
} }
} }
} }
if len(dateRecordBatch) > 0 {
err := insertTable(dateRecordBatch, tableName, statictisSess)
insertCount += len(dateRecordBatch)
if err != nil {
log.Info("insert all data failed." + err.Error())
}
}
indexTotal += PAGE_SIZE indexTotal += PAGE_SIZE
if indexTotal >= count { if indexTotal >= count {
break break
} }
} }
if len(dateRecordBatch) > 0 {
insertTable(dateRecordBatch, tableName, statictisSess)
insertCount += len(dateRecordBatch)
if err != nil {
log.Info("insert all data failed." + err.Error())
}
}

if tableName == "user_business_analysis_all" { if tableName == "user_business_analysis_all" {
log.Info("TotalHasActivityUser=" + fmt.Sprint(userMetrics["TotalHasActivityUser"])) log.Info("TotalHasActivityUser=" + fmt.Sprint(userMetrics["TotalHasActivityUser"]))
} }
@@ -835,7 +835,7 @@ func updateUserIndex(tableName string, statictisSess *xorm.Session, userId int64
statictisSess.Exec(updateSql) statictisSess.Exec(updateSql)
} }


func insertTable(dateRecords []UserBusinessAnalysisAll, tableName string, statictisSess *xorm.Session) {
func insertTable(dateRecords []UserBusinessAnalysisAll, tableName string, statictisSess *xorm.Session) error {


insertBatchSql := "INSERT INTO public." + tableName + 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, " + "(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, " +
@@ -854,7 +854,8 @@ func insertTable(dateRecords []UserBusinessAnalysisAll, tableName string, static
} }
} }


statictisSess.Exec(insertBatchSql)
_, err := statictisSess.Exec(insertBatchSql)
return err
} }


func RefreshUserStaticAllTabel(wikiCountMap map[string]int, userMetrics map[string]int) { func RefreshUserStaticAllTabel(wikiCountMap map[string]int, userMetrics map[string]int) {
@@ -2057,7 +2058,9 @@ func queryCloudBrainTask(start_unix int64, end_unix int64) (map[int64]int, map[s
} else { } else {
resultMap[cloudTaskRecord.UserID] += 1 resultMap[cloudTaskRecord.UserID] += 1
} }
setMapKey("CloudBrainRunTime", cloudTaskRecord.UserID, int(cloudTaskRecord.Duration), resultItemMap)
if cloudTaskRecord.Duration < 100000000 && cloudTaskRecord.Duration > 0 {
setMapKey("CloudBrainRunTime", cloudTaskRecord.UserID, int(cloudTaskRecord.Duration), resultItemMap)
}
if cloudTaskRecord.Type == 1 { //npu if cloudTaskRecord.Type == 1 { //npu
if cloudTaskRecord.JobType == "TRAIN" { if cloudTaskRecord.JobType == "TRAIN" {
setMapKey("NpuTrainJob", cloudTaskRecord.UserID, 1, resultItemMap) setMapKey("NpuTrainJob", cloudTaskRecord.UserID, 1, resultItemMap)


+ 1
- 0
modules/auth/repo_form.go View File

@@ -46,6 +46,7 @@ type CreateRepoForm struct {
Webhooks bool Webhooks bool
Avatar bool Avatar bool
Labels bool Labels bool
AutoAgree bool
} }


// Validate validates the fields // Validate validates the fields


+ 41
- 0
modules/modelarts/resty.go View File

@@ -1119,3 +1119,44 @@ sendjob:


return &result, nil return &result, nil
} }

func GetTrainJobMetricStatistic(jobID, versionID, podName string) (*models.GetTrainJobMetricStatisticResult, error) {
checkSetting()
client := getRestyClient()
var result models.GetTrainJobMetricStatisticResult

retry := 0

sendjob:
res, err := client.R().
SetAuthToken(TOKEN).
SetResult(&result).
Get(HOST + "/v1/" + setting.ProjectID + urlTrainJob + "/" + jobID + "/versions/" + versionID + "/pod/" + podName + "/metric-statistic")

if err != nil {
return nil, fmt.Errorf("resty GetTrainJobMetricStatistic: %v", err)
}

if res.StatusCode() == http.StatusUnauthorized && retry < 1 {
retry++
_ = getToken()
goto sendjob
}

if res.StatusCode() != http.StatusOK {
var temp models.ErrorResult
if err = json.Unmarshal([]byte(res.String()), &temp); err != nil {
log.Error("json.Unmarshal failed(%s): %v", res.String(), err.Error())
return &result, fmt.Errorf("json.Unmarshal failed(%s): %v", res.String(), err.Error())
}
log.Error("GetTrainJobMetricStatistic failed(%d):%s(%s)", res.StatusCode(), temp.ErrorCode, temp.ErrorMsg)
return &result, fmt.Errorf("GetTrainJobMetricStatistic failed(%d):%s(%s)", res.StatusCode(), temp.ErrorCode, temp.ErrorMsg)
}

if !result.IsSuccess {
log.Error("GetTrainJobMetricStatistic(%s) failed", jobID)
return &result, fmt.Errorf("获取任务资源占用情况失败:%s", result.ErrorMsg)
}

return &result, nil
}

+ 8
- 0
modules/storage/local.go View File

@@ -39,6 +39,14 @@ func (l *LocalStorage) Open(path string) (io.ReadCloser, error) {
return f, nil return f, nil
} }


func (l *LocalStorage) DownloadAFile(bucket string, objectName string) (io.ReadCloser, error) {
f, err := os.Open(filepath.Join(l.dir, objectName))
if err != nil {
return nil, err
}
return f, nil
}

// Save save a file // Save save a file
func (l *LocalStorage) Save(path string, r io.Reader) (int64, error) { func (l *LocalStorage) Save(path string, r io.Reader) (int64, error) {
p := filepath.Join(l.dir, path) p := filepath.Join(l.dir, path)


+ 10
- 0
modules/storage/minio.go View File

@@ -59,6 +59,16 @@ func (m *MinioStorage) buildMinioPath(p string) string {
return strings.TrimPrefix(path.Join(m.basePath, p), "/") return strings.TrimPrefix(path.Join(m.basePath, p), "/")
} }


func (m *MinioStorage) DownloadAFile(bucket string, objectName string) (io.ReadCloser, error) {

var opts = minio.GetObjectOptions{}
object, err := m.client.GetObject(m.bucket, objectName, opts)
if err != nil {
return nil, err
}
return object, nil
}

// Open open a file // Open open a file
func (m *MinioStorage) Open(path string) (io.ReadCloser, error) { func (m *MinioStorage) Open(path string) (io.ReadCloser, error) {
var opts = minio.GetObjectOptions{} var opts = minio.GetObjectOptions{}


+ 134
- 0
modules/storage/minio_ext.go View File

@@ -113,7 +113,141 @@ func GenMultiPartSignedUrl(uuid string, uploadId string, partNumber int, partSiz
objectName := strings.TrimPrefix(path.Join(minio.BasePath, path.Join(uuid[0:1], uuid[1:2], uuid)), "/") objectName := strings.TrimPrefix(path.Join(minio.BasePath, path.Join(uuid[0:1], uuid[1:2], uuid)), "/")


return minioClient.GenUploadPartSignedUrl(uploadId, bucketName, objectName, partNumber, partSize, PresignedUploadPartUrlExpireTime, setting.Attachment.Minio.Location) return minioClient.GenUploadPartSignedUrl(uploadId, bucketName, objectName, partNumber, partSize, PresignedUploadPartUrlExpireTime, setting.Attachment.Minio.Location)
}

func GetAllObjectByBucketAndPrefixMinio(bucket string, prefix string) ([]FileInfo, error) {
_, core, err := getClients()
if err != nil {
log.Error("getClients failed:", err.Error())
return nil, err
}
prefixLen := len(prefix)
delimiter := ""
marker := ""
index := 1
fileInfoList := FileInfoList{}
for {
output, err := core.ListObjects(bucket, prefix, marker, delimiter, 1000)
if err == nil {
log.Info("Page:%d\n", index)
index++
for _, val := range output.Contents {
var isDir bool
if prefixLen == len(val.Key) {
continue
}
if strings.HasSuffix(val.Key, "/") {
isDir = true
} else {
isDir = false
}
fileInfo := FileInfo{
ModTime: val.LastModified.Format("2006-01-02 15:04:05"),
FileName: val.Key[prefixLen:],
Size: val.Size,
IsDir: isDir,
ParenDir: "",
}
fileInfoList = append(fileInfoList, fileInfo)
}
if output.IsTruncated {
marker = output.NextMarker
} else {
break
}
} else {
log.Info("list error." + err.Error())
return nil, err
}
}
sort.Sort(fileInfoList)
return fileInfoList, nil
}

func GetOneLevelAllObjectUnderDirMinio(bucket string, prefixRootPath string, relativePath string) ([]FileInfo, error) {
_, core, err := getClients()
if err != nil {
log.Error("getClients failed:", err.Error())
return nil, err
}


Prefix := prefixRootPath + relativePath
if !strings.HasSuffix(Prefix, "/") {
Prefix += "/"
}
log.Info("bucket=" + bucket + " Prefix=" + Prefix)
output, err := core.ListObjects(bucket, Prefix, "", "", 1000)
fileInfos := make([]FileInfo, 0)
prefixLen := len(Prefix)
if err == nil {
for _, val := range output.Contents {
log.Info("val key=" + val.Key)
var isDir bool
var fileName string
if val.Key == Prefix {
continue
}
if strings.Contains(val.Key[prefixLen:len(val.Key)-1], "/") {
continue
}
if strings.HasSuffix(val.Key, "/") {
isDir = true
fileName = val.Key[prefixLen : len(val.Key)-1]
relativePath += val.Key[prefixLen:]
} else {
isDir = false
fileName = val.Key[prefixLen:]
}
fileInfo := FileInfo{
ModTime: val.LastModified.Local().Format("2006-01-02 15:04:05"),
FileName: fileName,
Size: val.Size,
IsDir: isDir,
ParenDir: relativePath,
}
fileInfos = append(fileInfos, fileInfo)
}
return fileInfos, err
} else {

log.Error("Message:%s", err.Error())

return nil, err
}

}

func MinioPathCopy(bucketName string, srcPath string, destPath string) (int64, error) {
_, core, err := getClients()
var fileTotalSize int64
fileTotalSize = 0
if err != nil {
log.Error("getClients failed:", err.Error())
return fileTotalSize, err
}
delimiter := ""
marker := ""
for {
output, err := core.ListObjects(bucketName, srcPath, marker, delimiter, 1000)
if err == nil {
for _, val := range output.Contents {
srcObjectName := val.Key
destObjectName := destPath + srcObjectName[len(srcPath):]
log.Info("srcObjectName=" + srcObjectName + " destObjectName=" + destObjectName)
core.CopyObject(bucketName, srcObjectName, bucketName, destObjectName, val.UserMetadata)
fileTotalSize += val.Size
}
if output.IsTruncated {
marker = output.NextMarker
} else {
break
}
} else {
log.Info("list error." + err.Error())
return 0, err
}
}
return fileTotalSize, nil
} }


func NewMultiPartUpload(uuid string) (string, error) { func NewMultiPartUpload(uuid string) (string, error) {


+ 14
- 0
modules/storage/obs.go View File

@@ -564,3 +564,17 @@ func ObsCreateObject(path string) error {


return nil return nil
} }

func GetObsLogFileName(prefix string) (string, error) {
input := &obs.ListObjectsInput{}
input.Bucket = setting.Bucket
input.Prefix = prefix

output, err := ObsCli.ListObjects(input)
if err != nil {
log.Error("PutObject failed:", err.Error())
return "", err
}

return output.Contents[0].Key, nil
}

+ 1
- 0
modules/storage/storage.go View File

@@ -22,6 +22,7 @@ const (
type ObjectStorage interface { type ObjectStorage interface {
Save(path string, r io.Reader) (int64, error) Save(path string, r io.Reader) (int64, error)
Open(path string) (io.ReadCloser, error) Open(path string) (io.ReadCloser, error)
DownloadAFile(bucket string, objectName string) (io.ReadCloser, error)
Delete(path string) error Delete(path string) error
DeleteDir(dir string) error DeleteDir(dir string) error
PresignedGetURL(path string, fileName string) (string, error) PresignedGetURL(path string, fileName string) (string, error)


+ 5
- 1
options/locale/locale_en-US.ini View File

@@ -1145,6 +1145,7 @@ modelarts.infer_job.model_version = Model/Version
modelarts.infer_job.select_model = Select Model modelarts.infer_job.select_model = Select Model
modelarts.infer_job.boot_file_helper=The startup file is the entry file for your program execution and must end in.py.Such as inference.py, main.py, example/inference. Py, case/main.py. modelarts.infer_job.boot_file_helper=The startup file is the entry file for your program execution and must end in.py.Such as inference.py, main.py, example/inference. Py, case/main.py.
modelarts.infer_job.tooltip = The model has been deleted and cannot be viewed. modelarts.infer_job.tooltip = The model has been deleted and cannot be viewed.
modelarts.download_log=Download log file




debug_task_not_created = Debug task has not been created debug_task_not_created = Debug task has not been created
@@ -1183,6 +1184,7 @@ template.topics = Topics
template.avatar = Avatar template.avatar = Avatar
template.issue_labels = Issue Labels template.issue_labels = Issue Labels
template.one_item = Must select at least one template item template.one_item = Must select at least one template item
template.one_promise = Must agree to use the agreement!
template.invalid = Must select a template repository template.invalid = Must select a template repository
template.repo_adress=Adress template.repo_adress=Adress
template.repo_path=path template.repo_path=path
@@ -1450,6 +1452,7 @@ issues.filter_sort.feweststars = Fewest stars
issues.filter_sort.mostforks = Most forks issues.filter_sort.mostforks = Most forks
issues.filter_sort.fewestforks = Fewest forks issues.filter_sort.fewestforks = Fewest forks
issues.filter_sort.downloadtimes = Most downloaded issues.filter_sort.downloadtimes = Most downloaded
issues.filter_sort.citations=Citations
issues.filter_sort.mostusecount = Most Quote issues.filter_sort.mostusecount = Most Quote
issues.filter_sort.fewestusecount=Fewest Quote issues.filter_sort.fewestusecount=Fewest Quote
issues.action_open = Open issues.action_open = Open
@@ -2257,7 +2260,8 @@ topic.done = Done
topic.count_prompt = You can not select more than 25 topics topic.count_prompt = You can not select more than 25 topics
topic.format_prompt = Topics must start with a chinese character,a letter or number, can include dashes ('-') and can be up to 35 characters long. topic.format_prompt = Topics must start with a chinese character,a letter or number, can include dashes ('-') and can be up to 35 characters long.
imagetopic.format_prompt = Topics can be up to 35 characters long. imagetopic.format_prompt = Topics can be up to 35 characters long.

use_repo_agreement=I promise that the content of this warehouse does not violate any national laws and regulations. During the use of the warehouse, I will abide by the OpenI community management regulations and platform usage rules, and will not conduct malicious attacks, mining, or any other illegal or disruptive platform order. Information release and related behaviors. For more information please refer to
openi_use_agreement=OpenI Qizhi Community Platform Use Agreement.
[org] [org]
org_name_holder = Organization Name org_name_holder = Organization Name
org_full_name_holder = Organization Full Name org_full_name_holder = Organization Full Name


+ 7
- 2
options/locale/locale_zh-CN.ini View File

@@ -226,7 +226,7 @@ contributors=贡献者
contributor=贡献者 contributor=贡献者


page_title=探索更好的AI page_title=探索更好的AI
page_small_title=启智AI开发协作平台
page_small_title=启智AI协作平台
page_description=面向AI领域的一站式协同开发环境,提供集代码开发、数据管理、模型调试、推理和评测为一体的AI开发流水线 page_description=面向AI领域的一站式协同开发环境,提供集代码开发、数据管理、模型调试、推理和评测为一体的AI开发流水线
page_use=立即使用 page_use=立即使用
page_only_dynamic=仅展示开源项目动态 page_only_dynamic=仅展示开源项目动态
@@ -1155,6 +1155,7 @@ modelarts.infer_job.model_version = 模型/版本
modelarts.infer_job.select_model = 选择模型 modelarts.infer_job.select_model = 选择模型
modelarts.infer_job.boot_file_helper=启动文件是您程序执行的入口文件,必须是以.py结尾的文件。比如inference.py、main.py、example/inference.py、case/main.py。 modelarts.infer_job.boot_file_helper=启动文件是您程序执行的入口文件,必须是以.py结尾的文件。比如inference.py、main.py、example/inference.py、case/main.py。
modelarts.infer_job.tooltip = 该模型已删除,无法查看。 modelarts.infer_job.tooltip = 该模型已删除,无法查看。
modelarts.download_log=下载日志文件




debug_task_not_created = 未创建过调试任务 debug_task_not_created = 未创建过调试任务
@@ -1193,6 +1194,7 @@ template.topics=主题
template.avatar=头像 template.avatar=头像
template.issue_labels=任务标签 template.issue_labels=任务标签
template.one_item=必须至少选择一个模板项 template.one_item=必须至少选择一个模板项
template.one_promise=创建项目时需承诺遵守使用协议
template.invalid=必须选择一个模板项目 template.invalid=必须选择一个模板项目
template.repo_adress=项目地址 template.repo_adress=项目地址
template.repo_path=项目地址 template.repo_path=项目地址
@@ -1460,9 +1462,11 @@ issues.filter_sort.feweststars=点赞由少到多
issues.filter_sort.mostforks=派生由多到少 issues.filter_sort.mostforks=派生由多到少
issues.filter_sort.fewestforks=派生由少到多 issues.filter_sort.fewestforks=派生由少到多
issues.filter_sort.downloadtimes=下载次数 issues.filter_sort.downloadtimes=下载次数
issues.filter_sort.citations=引用次数
issues.filter_sort.moststars=收藏数量 issues.filter_sort.moststars=收藏数量
issues.filter_sort.mostusecount=最多引用 issues.filter_sort.mostusecount=最多引用
issues.filter_sort.fewestusecount=最少引用 issues.filter_sort.fewestusecount=最少引用

issues.action_open=开启 issues.action_open=开启
issues.action_close=关闭 issues.action_close=关闭
issues.action_label=标签 issues.action_label=标签
@@ -2267,7 +2271,8 @@ topic.done=保存
topic.count_prompt=您最多选择25个标签 topic.count_prompt=您最多选择25个标签
topic.format_prompt=标签必须以中文、字母或数字开头,可以包含连字符 (-),并且长度不得超过35个字符 topic.format_prompt=标签必须以中文、字母或数字开头,可以包含连字符 (-),并且长度不得超过35个字符
imagetopic.format_prompt=标签长度不得超过35个字符 imagetopic.format_prompt=标签长度不得超过35个字符

use_repo_agreement=我承诺此仓内容不违反任何国家法律法规,仓库使用过程中遵守OpenI启智社区管理规定和平台使用规则,不进行恶意攻击、挖矿等任何违法或扰乱平台秩序的信息发布和相关行为。更多信息请参考
openi_use_agreement=OpenI启智社区平台使用协议
[org] [org]
org_name_holder=组织名称 org_name_holder=组织名称
org_full_name_holder=组织全名 org_full_name_holder=组织全名


+ 66
- 5
public/home/home.js View File

@@ -9,7 +9,7 @@ if(isEmpty(token)){


var swiperNewMessage = new Swiper(".newslist", { var swiperNewMessage = new Swiper(".newslist", {
direction: "vertical", direction: "vertical",
slidesPerView: 10,
slidesPerView: 9,
loop: true, loop: true,
autoplay: { autoplay: {
delay: 2500, delay: 2500,
@@ -17,7 +17,7 @@ var swiperNewMessage = new Swiper(".newslist", {
}, },
}); });
var swiperEvent = new Swiper(".event-list", { var swiperEvent = new Swiper(".event-list", {
slidesPerView: 2,
slidesPerView: 3,
spaceBetween: 30, spaceBetween: 30,
pagination: { pagination: {
el: ".swiper-pagination", el: ".swiper-pagination",
@@ -117,6 +117,7 @@ socket.onmessage = function (e) {
continue; continue;
} }
} }
refresh3DInfo(record);
var recordPrefix = getMsg(record); var recordPrefix = getMsg(record);
if(record.OpType == "6" || record.OpType == "10" || record.OpType == "12" || record.OpType == "13"){ if(record.OpType == "6" || record.OpType == "10" || record.OpType == "12" || record.OpType == "13"){
html += recordPrefix + actionName; html += recordPrefix + actionName;
@@ -200,6 +201,29 @@ function getTaskLink(record){
return re; 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);
span.innerText =record.RefName;
//$('.rotation3D__line').find("span").eq(1).text(record.RefName)
//lines[1].find("span").text(record.RefName);
}

}

function getMsg(record){ function getMsg(record){
var html =""; var html ="";
html += "<div class=\"swiper-slide item\">"; html += "<div class=\"swiper-slide item\">";
@@ -425,13 +449,50 @@ function queryRecommendData(){
dataType:"json", dataType:"json",
async:false, async:false,
success:function(json){ success:function(json){
displayOrg(json.org);
displayRepo(json.repo);
displayActivity(json.image)
displayOrg(json.org);
displayRepo(json.repo);
displayActivity(json.image);
displayCloudBrain(json.cloudbrain)
}, },
error:function(response) { error:function(response) {
} }
}); });

// $.ajax({
// type:"GET",
// url:"/recommend/repo",
// headers: {
// authorization:token,
// },
// dataType:"json",
// async:false,
// success:function(json){
// displayRepo(json);
// },
// error:function(response) {
// }
// });

// $.ajax({
// type:"GET",
// url:"/recommend/imageinfo",
// headers: {
// authorization:token,
// },
// dataType:"json",
// async:false,
// success:function(json){
// displayActivity(json);
// },
// error:function(response) {
// }
// });
}

function displayCloudBrain(json){
$('#completed_task').text(json.completed_task);
$('#running_task').text(json.running_task);
$('#wait_task').text(json.wait_task);
} }


function displayActivity(json){ function displayActivity(json){


+ 1
- 0
public/self/css/notebook/katex.min.css
File diff suppressed because it is too large
View File


+ 86
- 0
public/self/css/notebook/notebook.css View File

@@ -0,0 +1,86 @@
.nb-notebook {
line-height: 1.5;
margin-left: 7em;
}

.nb-stdout, .nb-stderr {
white-space: pre-wrap;
margin: 1em 0;
padding: 0.1em 0.5em;
}

.nb-stderr {
background-color: #FAA;
}

.nb-cell + .nb-cell {
margin-top: 0.5em;
}

.nb-output table {
border: 1px solid #000;
border-collapse: collapse;
}

.nb-output th {
font-weight: bold;
}

.nb-output th, .nb-output td {
border: 1px solid #000;
padding: 0.25em;
text-align: left;
vertical-align: middle;
border-collapse: collapse;
}

.nb-notebook blockquote {
border-left: 5px solid #CCC;
margin-left: 0;
padding-left: 1em;
}

.nb-cell {
position: relative;
}

.nb-raw-cell {
white-space: pre-wrap;
background-color: #f5f2f0;
font-family: Consolas, Monaco, 'Andale Mono', monospace;
padding: 1em;
margin: .5em 0;
}

.nb-output {
min-height: 1em;
width: 100%;
overflow-x: scroll;
border-right: 1px dotted #CCC;
}

.nb-output img {
max-width: 100%;
}

.nb-output:before, .nb-input:before {
position: absolute;
font-family: monospace;
color: #999;
left: -7em;
width: 7em;
text-align: right;
}

.nb-input:before {
content: "In [" attr(data-prompt-number) "]:";
}
.nb-output:before {
content: "Out [" attr(data-prompt-number) "]:";
}

// Fix pandas dataframe formatting
div[style="max-height:1000px;max-width:1500px;overflow:auto;"] {
max-height: none !important;
}


+ 142
- 0
public/self/css/notebook/prism.css View File

@@ -0,0 +1,142 @@
/* PrismJS 1.21.0
https://prismjs.com/download.html#themes=prism&languages=markup+clike+javascript+julia+python+r */
/**
* prism.js default theme for JavaScript, CSS and HTML
* Based on dabblet (http://dabblet.com)
* @author Lea Verou
*/

code[class*="language-"],
pre[class*="language-"] {
color: black;
background: none;
text-shadow: 0 1px white;
font-family: Consolas, Monaco, 'Andale Mono', 'Ubuntu Mono', monospace;
font-size: 1em;
text-align: left;
white-space: pre;
word-spacing: normal;
word-break: normal;
word-wrap: normal;
line-height: 1.5;

-moz-tab-size: 4;
-o-tab-size: 4;
tab-size: 4;

-webkit-hyphens: none;
-moz-hyphens: none;
-ms-hyphens: none;
hyphens: none;
}

pre[class*="language-"]::-moz-selection, pre[class*="language-"] ::-moz-selection,
code[class*="language-"]::-moz-selection, code[class*="language-"] ::-moz-selection {
text-shadow: none;
background: #b3d4fc;
}

pre[class*="language-"]::selection, pre[class*="language-"] ::selection,
code[class*="language-"]::selection, code[class*="language-"] ::selection {
text-shadow: none;
background: #b3d4fc;
}

@media print {
code[class*="language-"],
pre[class*="language-"] {
text-shadow: none;
}
}

/* Code blocks */
pre[class*="language-"] {
padding: 1em;
margin: .5em 0;
overflow: auto;
}

:not(pre) > code[class*="language-"],
pre[class*="language-"] {
background: #f5f2f0;
}

/* Inline code */
:not(pre) > code[class*="language-"] {
padding: .1em;
border-radius: .3em;
white-space: normal;
}

.token.comment,
.token.prolog,
.token.doctype,
.token.cdata {
color: slategray;
}

.token.punctuation {
color: #999;
}

.token.namespace {
opacity: .7;
}

.token.property,
.token.tag,
.token.boolean,
.token.number,
.token.constant,
.token.symbol,
.token.deleted {
color: #905;
}

.token.selector,
.token.attr-name,
.token.string,
.token.char,
.token.builtin,
.token.inserted {
color: #690;
}

.token.operator,
.token.entity,
.token.url,
.language-css .token.string,
.style .token.string {
color: #9a6e3a;
/* This background color was intended by the author of this theme. */
background: hsla(0, 0%, 100%, .5);
}

.token.atrule,
.token.attr-value,
.token.keyword {
color: #07a;
}

.token.function,
.token.class-name {
color: #DD4A68;
}

.token.regex,
.token.important,
.token.variable {
color: #e90;
}

.token.important,
.token.bold {
font-weight: bold;
}
.token.italic {
font-style: italic;
}

.token.entity {
cursor: help;
}

+ 6
- 0
public/self/js/notebook/ansi_up.min.js View File

@@ -0,0 +1,6 @@
// ansi_up.js
// version : 1.1.0
// author : Dru Nelson
// license : MIT
// http://github.com/drudru/ansi_up
(function(a,b){function g(){this.fg=this.bg=null,this.bright=0}var c,d="1.1.0",e=typeof module!="undefined",f=[[{color:"0, 0, 0","class":"ansi-black"},{color:"187, 0, 0","class":"ansi-red"},{color:"0, 187, 0","class":"ansi-green"},{color:"187, 187, 0","class":"ansi-yellow"},{color:"0, 0, 187","class":"ansi-blue"},{color:"187, 0, 187","class":"ansi-magenta"},{color:"0, 187, 187","class":"ansi-cyan"},{color:"255,255,255","class":"ansi-white"}],[{color:"85, 85, 85","class":"ansi-bright-black"},{color:"255, 85, 85","class":"ansi-bright-red"},{color:"0, 255, 0","class":"ansi-bright-green"},{color:"255, 255, 85","class":"ansi-bright-yellow"},{color:"85, 85, 255","class":"ansi-bright-blue"},{color:"255, 85, 255","class":"ansi-bright-magenta"},{color:"85, 255, 255","class":"ansi-bright-cyan"},{color:"255, 255, 255","class":"ansi-bright-white"}]];g.prototype.escape_for_html=function(a){return a.replace(/[&<>]/gm,function(a){if(a=="&")return"&amp;";if(a=="<")return"&lt;";if(a==">")return"&gt;"})},g.prototype.linkify=function(a){return a.replace(/(https?:\/\/[^\s]+)/gm,function(a){return'<a href="'+a+'">'+a+"</a>"})},g.prototype.ansi_to_html=function(a,b){var c=a.split(/\033\[/),d=c.shift(),e=this,f=c.map(function(a){return e.process_chunk(a,b)});f.unshift(d);var g=f.reduce(function(a,b){return Array.isArray(b)?a.concat(b):(a.push(b),a)},[]),h=g.join("");return h},g.prototype.process_chunk=function(a,b){b=typeof b=="undefined"?{}:b;var c=typeof b.use_classes!="undefined"&&b.use_classes,d=c?"class":"color",e=a.match(/([\d;]*)m([^]*)/m);if(!e)return a;var g=e[2],h=e[1].split(";"),i=this;h.map(function(a){var b=parseInt(a);isNaN(b)||b===0?(i.fg=i.bg=null,i.bright=0):b===1?i.bright=1:b>=30&&b<38?i.fg=f[i.bright][b%10][d]:b>=40&&b<48&&(i.bg=f[0][b%10][d])});if(i.fg===null&&i.bg===null)return g;var j=classes=[];return i.fg&&(c?classes.push(i.fg+"-fg"):j.push("color:rgb("+i.fg+")")),i.bg&&(c?classes.push(i.bg+"-bg"):j.push("background-color:rgb("+i.bg+")")),c?['<span class="'+classes.join(" ")+'">',g,"</span>"]:['<span style="'+j.join(";")+'">',g,"</span>"]},c={escape_for_html:function(a){var b=new g;return b.escape_for_html(a)},linkify:function(a){var b=new g;return b.linkify(a)},ansi_to_html:function(a,b){var c=new g;return c.ansi_to_html(a,b)},ansi_to_html_obj:function(){return new g}},e&&(module.exports=c),typeof window!="undefined"&&typeof ender=="undefined"&&(window.ansi_up=c),typeof define=="function"&&define.amd&&define("ansi_up",[],function(){return c})})(Date);

+ 7
- 0
public/self/js/notebook/es5-shim.min.js
File diff suppressed because it is too large
View File


+ 1
- 0
public/self/js/notebook/katex-auto-render.min.js View File

@@ -0,0 +1 @@
!function(e,t){"object"==typeof exports&&"object"==typeof module?module.exports=t(require("katex")):"function"==typeof define&&define.amd?define(["katex"],t):"object"==typeof exports?exports.renderMathInElement=t(require("katex")):e.renderMathInElement=t(e.katex)}("undefined"!=typeof self?self:this,function(e){return function(e){var t={};function r(n){if(t[n])return t[n].exports;var o=t[n]={i:n,l:!1,exports:{}};return e[n].call(o.exports,o,o.exports,r),o.l=!0,o.exports}return r.m=e,r.c=t,r.d=function(e,t,n){r.o(e,t)||Object.defineProperty(e,t,{enumerable:!0,get:n})},r.r=function(e){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},r.t=function(e,t){if(1&t&&(e=r(e)),8&t)return e;if(4&t&&"object"==typeof e&&e&&e.__esModule)return e;var n=Object.create(null);if(r.r(n),Object.defineProperty(n,"default",{enumerable:!0,value:e}),2&t&&"string"!=typeof e)for(var o in e)r.d(n,o,function(t){return e[t]}.bind(null,o));return n},r.n=function(e){var t=e&&e.__esModule?function(){return e.default}:function(){return e};return r.d(t,"a",t),t},r.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},r.p="",r(r.s=1)}([function(t,r){t.exports=e},function(e,t,r){"use strict";r.r(t);var n=r(0),o=r.n(n),a=function(e,t,r){for(var n=r,o=0,a=e.length;n<t.length;){var i=t[n];if(o<=0&&t.slice(n,n+a)===e)return n;"\\"===i?n++:"{"===i?o++:"}"===i&&o--,n++}return-1},i=function(e,t,r,n){for(var o=[],i=0;i<e.length;i++)if("text"===e[i].type){var l=e[i].data,d=!0,s=0,f=void 0;for(-1!==(f=l.indexOf(t))&&(s=f,o.push({type:"text",data:l.slice(0,s)}),d=!1);;){if(d){if(-1===(f=l.indexOf(t,s)))break;o.push({type:"text",data:l.slice(s,f)}),s=f}else{if(-1===(f=a(r,l,s+t.length)))break;o.push({type:"math",data:l.slice(s+t.length,f),rawData:l.slice(s,f+r.length),display:n}),s=f+r.length}d=!d}o.push({type:"text",data:l.slice(s)})}else o.push(e[i]);return o},l=function(e,t){var r=function(e,t){for(var r=[{type:"text",data:e}],n=0;n<t.length;n++){var o=t[n];r=i(r,o.left,o.right,o.display||!1)}return r}(e,t.delimiters);if(1===r.length&&"text"===r[0].type)return null;for(var n=document.createDocumentFragment(),a=0;a<r.length;a++)if("text"===r[a].type)n.appendChild(document.createTextNode(r[a].data));else{var l=document.createElement("span"),d=r[a].data;t.displayMode=r[a].display;try{t.preProcess&&(d=t.preProcess(d)),o.a.render(d,l,t)}catch(e){if(!(e instanceof o.a.ParseError))throw e;t.errorCallback("KaTeX auto-render: Failed to parse `"+r[a].data+"` with ",e),n.appendChild(document.createTextNode(r[a].rawData));continue}n.appendChild(l)}return n};t.default=function(e,t){if(!e)throw new Error("No element provided to render");var r={};for(var n in t)t.hasOwnProperty(n)&&(r[n]=t[n]);r.delimiters=r.delimiters||[{left:"$$",right:"$$",display:!0},{left:"\\(",right:"\\)",display:!1},{left:"\\[",right:"\\]",display:!0}],r.ignoredTags=r.ignoredTags||["script","noscript","style","textarea","pre","code","option"],r.ignoredClasses=r.ignoredClasses||[],r.errorCallback=r.errorCallback||console.error,r.macros=r.macros||{},function e(t,r){for(var n=0;n<t.childNodes.length;n++){var o=t.childNodes[n];if(3===o.nodeType){var a=l(o.textContent,r);a&&(n+=a.childNodes.length-1,t.replaceChild(a,o))}else 1===o.nodeType&&function(){var t=" "+o.className+" ";-1===r.ignoredTags.indexOf(o.nodeName.toLowerCase())&&r.ignoredClasses.every(function(e){return-1===t.indexOf(" "+e+" ")})&&e(o,r)}()}}(e,r)}}]).default});

+ 1
- 0
public/self/js/notebook/katex.min.js
File diff suppressed because it is too large
View File


+ 1
- 0
public/self/js/notebook/marked.min.js
File diff suppressed because it is too large
View File


+ 1
- 0
public/self/js/notebook/notebook.min.js
File diff suppressed because it is too large
View File


+ 7
- 0
public/self/js/notebook/prism.min.js
File diff suppressed because it is too large
View File


+ 3
- 0
public/self/js/notebook/purify.min.js
File diff suppressed because it is too large
View File


+ 4
- 0
routers/api/v1/api.go View File

@@ -573,6 +573,9 @@ func RegisterRoutes(m *macaron.Macaron) {
//cloudbrain board //cloudbrain board
m.Group("/cloudbrainboard", func() { m.Group("/cloudbrainboard", func() {
m.Get("/downloadAll", repo.DownloadCloudBrainBoard) m.Get("/downloadAll", repo.DownloadCloudBrainBoard)
m.Group("/cloudbrain", func() {
m.Get("/status_analysis", repo.GetCloudbrainsStatusAnalysis)
})
}, operationReq) }, operationReq)
// Users // Users
m.Group("/users", func() { m.Group("/users", func() {
@@ -922,6 +925,7 @@ func RegisterRoutes(m *macaron.Macaron) {
m.Post("/del_version", repo.DelTrainJobVersion) m.Post("/del_version", repo.DelTrainJobVersion)
m.Post("/stop_version", repo.StopTrainJobVersion) m.Post("/stop_version", repo.StopTrainJobVersion)
m.Get("/model_list", repo.ModelList) m.Get("/model_list", repo.ModelList)
m.Get("/metric_statistics", repo.TrainJobGetMetricStatistic)
}) })
}) })
m.Group("/inference-job", func() { m.Group("/inference-job", func() {


+ 16
- 0
routers/api/v1/repo/cloudbrain_dashboard.go View File

@@ -11,6 +11,16 @@ import (
"github.com/360EntSecGroup-Skylar/excelize/v2" "github.com/360EntSecGroup-Skylar/excelize/v2"
) )


type CloudbrainsStatusAnalysis struct {
JobWaitingCount int64 `json:"jobWaitingCount"`
JobRunningCount int64 `json:"jobRunningCount"`
JobStoppedCount int64 `json:"jobStoppedCount"`
JobCompletedCount int64 `json:"jobCompletedCount"`
JobFailedCount int64 `json:"jobFailedCount"`
JobKilledCount int64 `json:"jobKilledCount"`
JobInitCount int64 `json:"jobInitCount"`
}

func DownloadCloudBrainBoard(ctx *context.Context) { func DownloadCloudBrainBoard(ctx *context.Context) {


page := 1 page := 1
@@ -133,3 +143,9 @@ func getBrainWaitTime(rs *models.CloudbrainInfo) string {
return models.ConvertDurationToStr(int64(waitTime)) return models.ConvertDurationToStr(int64(waitTime))
} }
} }
func GetCloudbrainsStatusAnalysis(ctx *context.Context) {
cloudBrainStatusResult := models.GetAllStatusCloudBrain()
ctx.JSON(http.StatusOK, map[string]interface{}{
"cloudBrainStatusResult": cloudBrainStatusResult,
})
}

+ 43
- 0
routers/api/v1/repo/modelarts.go View File

@@ -462,3 +462,46 @@ func ResultList(ctx *context.APIContext) {
"PageIsCloudBrain": true, "PageIsCloudBrain": true,
}) })
} }

func TrainJobGetMetricStatistic(ctx *context.APIContext) {
var (
err error
)

var jobID = ctx.Params(":jobid")
var versionName = ctx.Query("version_name")

result, err := trainJobGetMetricStatistic(jobID, versionName)
if err != nil {
log.Error("trainJobGetMetricStatistic(%s) failed:%v", jobID, err.Error())
return
}

ctx.JSON(http.StatusOK, map[string]interface{}{
"JobID": jobID,
"Interval": result.Interval,
"MetricsInfo": result.MetricsInfo,
})
}

func trainJobGetMetricStatistic(jobID string, versionName string) (*models.GetTrainJobMetricStatisticResult, error) {
task, err := models.GetCloudbrainByJobIDAndVersionName(jobID, versionName)
if err != nil {
log.Error("GetCloudbrainByJobIDAndVersionName(%s) failed:%v", jobID, err.Error())
return nil, err
}

resultLogFile, err := modelarts.GetTrainJobLogFileNames(jobID, strconv.FormatInt(task.VersionID, 10))
if err != nil {
log.Error("GetTrainJobLogFileNames(%s) failed:%v", jobID, err.Error())
return nil, err
}

result, err := modelarts.GetTrainJobMetricStatistic(jobID, strconv.FormatInt(task.VersionID, 10), resultLogFile.LogFileList[0])
if err != nil {
log.Error("GetTrainJobMetricStatistic(%s) failed:%v", jobID, err.Error())
return nil, err
}

return result, err
}

+ 33
- 0
routers/home.go View File

@@ -7,6 +7,7 @@ package routers


import ( import (
"bytes" "bytes"
"fmt"
"net/http" "net/http"
"strconv" "strconv"
"strings" "strings"
@@ -750,6 +751,15 @@ func GetRankUser(index string) ([]map[string]interface{}, error) {
return resultOrg, nil return resultOrg, nil
} }


// func GetImageInfoFromPromote(ctx *context.Context) {
// imageInfo, err := GetImageInfo()
// if err != nil {
// ctx.ServerError("500", err)
// return
// }
// ctx.JSON(200, imageInfo)
// }

func GetUserRankFromPromote(ctx *context.Context) { func GetUserRankFromPromote(ctx *context.Context) {
index := ctx.Params("index") index := ctx.Params("index")
resultUserRank, err := GetRankUser(index) resultUserRank, err := GetRankUser(index)
@@ -773,13 +783,36 @@ func RecommendHomeInfo(ctx *context.Context) {
if err != nil { if err != nil {
log.Info("error." + err.Error()) log.Info("error." + err.Error())
} }
resultCloudBrain, err := getCloudbrainNums()
if err != nil {
log.Info("error." + err.Error())
}
mapInterface := make(map[string]interface{}) mapInterface := make(map[string]interface{})
mapInterface["org"] = resultOrg mapInterface["org"] = resultOrg
mapInterface["repo"] = resultRepo mapInterface["repo"] = resultRepo
mapInterface["image"] = resultImage mapInterface["image"] = resultImage
mapInterface["cloudbrain"] = resultCloudBrain
ctx.JSON(http.StatusOK, mapInterface) ctx.JSON(http.StatusOK, mapInterface)
} }


func getCloudbrainNums() (map[string]string, error) {
result := make(map[string]string)
cloudStatusMap := models.GetAllStatusCloudBrain()
result["completed_task"] = fmt.Sprint(cloudStatusMap["COMPLETED"])
result["running_task"] = fmt.Sprint(cloudStatusMap["RUNNING"])
result["wait_task"] = fmt.Sprint(cloudStatusMap["WAITING"])
return result, nil
}

// func RecommendOrgFromPromote(ctx *context.Context) {
// resultOrg, err := GetRecommendOrg()
// if err != nil {
// ctx.ServerError("500", err)
// return
// }
// ctx.JSON(200, resultOrg)
// }

func RecommendRepoFromPromote(ctx *context.Context) { func RecommendRepoFromPromote(ctx *context.Context) {
result, err := repository.GetRecommendRepoFromPromote("projects") result, err := repository.GetRecommendRepoFromPromote("projects")
if err != nil { if err != nil {


+ 201
- 78
routers/repo/ai_model_manage.go View File

@@ -6,6 +6,7 @@ import (
"errors" "errors"
"fmt" "fmt"
"net/http" "net/http"
"net/url"
"path" "path"
"strings" "strings"


@@ -27,19 +28,22 @@ const (
MODEL_NOT_LATEST = 0 MODEL_NOT_LATEST = 0
) )


func saveModelByParameters(jobId string, versionName string, name string, version string, label string, description string, ctx *context.Context) error {
func saveModelByParameters(jobId string, versionName string, name string, version string, label string, description string, engine int, ctx *context.Context) error {
aiTask, err := models.GetCloudbrainByJobIDAndVersionName(jobId, versionName) aiTask, err := models.GetCloudbrainByJobIDAndVersionName(jobId, versionName)
if err != nil { if err != nil {
log.Info("query task error." + err.Error())
return err
aiTask, err = models.GetRepoCloudBrainByJobID(ctx.Repo.Repository.ID, jobId)
if err != nil {
log.Info("query task error." + err.Error())
return err
} else {
log.Info("query gpu train task.")
}
} }

uuid := uuid.NewV4() uuid := uuid.NewV4()
id := uuid.String() id := uuid.String()
modelPath := id modelPath := id
var lastNewModelId string var lastNewModelId string
var modelSize int64 var modelSize int64
cloudType := models.TypeCloudBrainTwo


log.Info("find task name:" + aiTask.JobName) log.Info("find task name:" + aiTask.JobName)
aimodels := models.QueryModelByName(name, aiTask.RepoID) aimodels := models.QueryModelByName(name, aiTask.RepoID)
@@ -53,7 +57,7 @@ func saveModelByParameters(jobId string, versionName string, name string, versio
} }
} }
} }
cloudType = aiTask.Type
cloudType := aiTask.Type
//download model zip //train type //download model zip //train type
if cloudType == models.TypeCloudBrainTwo { if cloudType == models.TypeCloudBrainTwo {
modelPath, modelSize, err = downloadModelFromCloudBrainTwo(id, aiTask.JobName, "", aiTask.TrainUrl) modelPath, modelSize, err = downloadModelFromCloudBrainTwo(id, aiTask.JobName, "", aiTask.TrainUrl)
@@ -61,6 +65,12 @@ func saveModelByParameters(jobId string, versionName string, name string, versio
log.Info("download model from CloudBrainTwo faild." + err.Error()) log.Info("download model from CloudBrainTwo faild." + err.Error())
return err return err
} }
} else if cloudType == models.TypeCloudBrainOne {
modelPath, modelSize, err = downloadModelFromCloudBrainOne(id, aiTask.JobName, "", aiTask.TrainUrl)
if err != nil {
log.Info("download model from CloudBrainOne faild." + err.Error())
return err
}
} }
accuracy := make(map[string]string) accuracy := make(map[string]string)
accuracy["F1"] = "" accuracy["F1"] = ""
@@ -131,7 +141,7 @@ func SaveNewNameModel(ctx *context.Context) {
return return
} }
SaveModel(ctx) SaveModel(ctx)
ctx.Status(200)
log.Info("save model end.") log.Info("save model end.")
} }


@@ -143,8 +153,9 @@ func SaveModel(ctx *context.Context) {
version := ctx.Query("Version") version := ctx.Query("Version")
label := ctx.Query("Label") label := ctx.Query("Label")
description := ctx.Query("Description") description := ctx.Query("Description")
engine := ctx.QueryInt("Engine")
trainTaskCreate := ctx.QueryBool("trainTaskCreate") trainTaskCreate := ctx.QueryBool("trainTaskCreate")
log.Info("engine=" + fmt.Sprint(engine))
if !trainTaskCreate { if !trainTaskCreate {
if !ctx.Repo.CanWrite(models.UnitTypeModelManage) { if !ctx.Repo.CanWrite(models.UnitTypeModelManage) {
//ctx.NotFound(ctx.Req.URL.RequestURI(), nil) //ctx.NotFound(ctx.Req.URL.RequestURI(), nil)
@@ -163,14 +174,14 @@ func SaveModel(ctx *context.Context) {
return return
} }


err := saveModelByParameters(JobId, VersionName, name, version, label, description, ctx)
err := saveModelByParameters(JobId, VersionName, name, version, label, description, engine, ctx)


if err != nil { if err != nil {
log.Info("save model error." + err.Error()) log.Info("save model error." + err.Error())
ctx.Error(500, fmt.Sprintf("save model error. %v", err)) ctx.Error(500, fmt.Sprintf("save model error. %v", err))
return return
} }
ctx.Status(200)
log.Info("save model end.") log.Info("save model end.")
} }


@@ -199,6 +210,22 @@ func downloadModelFromCloudBrainTwo(modelUUID string, jobName string, parentDir
return dataActualPath, size, nil return dataActualPath, size, nil
} }


func downloadModelFromCloudBrainOne(modelUUID string, jobName string, parentDir string, trainUrl string) (string, int64, error) {
modelActualPath := storage.GetMinioPath(jobName, "/model/")
log.Info("modelActualPath=" + modelActualPath)
modelSrcPrefix := setting.CBCodePathPrefix + jobName + "/model/"
destKeyNamePrefix := Model_prefix + models.AttachmentRelativePath(modelUUID) + "/"
bucketName := setting.Attachment.Minio.Bucket
log.Info("destKeyNamePrefix=" + destKeyNamePrefix + " modelSrcPrefix=" + modelSrcPrefix + " bucket=" + bucketName)
size, err := storage.MinioPathCopy(bucketName, modelSrcPrefix, destKeyNamePrefix)
if err == nil {
dataActualPath := bucketName + "/" + destKeyNamePrefix
return dataActualPath, size, nil
} else {
return "", 0, nil
}
}

func DeleteModel(ctx *context.Context) { func DeleteModel(ctx *context.Context) {
log.Info("delete model start.") log.Info("delete model start.")
id := ctx.Query("ID") id := ctx.Query("ID")
@@ -277,51 +304,117 @@ func DownloadMultiModelFile(ctx *context.Context) {
} }


path := Model_prefix + models.AttachmentRelativePath(id) + "/" path := Model_prefix + models.AttachmentRelativePath(id) + "/"
if task.Type == models.TypeCloudBrainTwo {
downloadFromCloudBrainTwo(path, task, ctx, id)
} else if task.Type == models.TypeCloudBrainOne {
downloadFromCloudBrainOne(path, task, ctx, id)
}
}


allFile, err := storage.GetAllObjectByBucketAndPrefix(setting.Bucket, path)
func MinioDownloadManyFile(path string, ctx *context.Context, returnFileName string, allFile []storage.FileInfo) {
ctx.Resp.Header().Set("Content-Disposition", "attachment; filename="+url.QueryEscape(returnFileName))
ctx.Resp.Header().Set("Content-Type", "application/octet-stream")
w := zip.NewWriter(ctx.Resp)
defer w.Close()
for _, oneFile := range allFile {
if oneFile.IsDir {
log.Info("zip dir name:" + oneFile.FileName)
} else {
log.Info("zip file name:" + oneFile.FileName)
fDest, err := w.Create(oneFile.FileName)
if err != nil {
log.Info("create zip entry error, download file failed: %s\n", err.Error())
ctx.ServerError("download file failed:", err)
return
}
log.Info("minio file path=" + (path + oneFile.FileName))
body, err := storage.Attachments.DownloadAFile(setting.Attachment.Minio.Bucket, path+oneFile.FileName)
if err != nil {
log.Info("download file failed: %s\n", err.Error())
ctx.ServerError("download file failed:", err)
return
} else {
defer body.Close()
p := make([]byte, 1024)
var readErr error
var readCount int
// 读取对象内容
for {
readCount, readErr = body.Read(p)
if readCount > 0 {
fDest.Write(p[:readCount])
}
if readErr != nil {
break
}
}
}
}
}

}

func downloadFromCloudBrainOne(path string, task *models.AiModelManage, ctx *context.Context, id string) {
allFile, err := storage.GetAllObjectByBucketAndPrefixMinio(setting.Attachment.Minio.Bucket, path)
if err == nil { if err == nil {
//count++ //count++
models.ModifyModelDownloadCount(id) models.ModifyModelDownloadCount(id)

returnFileName := task.Name + "_" + task.Version + ".zip" returnFileName := task.Name + "_" + task.Version + ".zip"
ctx.Resp.Header().Set("Content-Disposition", "attachment; filename="+returnFileName)
ctx.Resp.Header().Set("Content-Type", "application/octet-stream")
w := zip.NewWriter(ctx.Resp)
defer w.Close()
for _, oneFile := range allFile {
if oneFile.IsDir {
log.Info("zip dir name:" + oneFile.FileName)
MinioDownloadManyFile(path, ctx, returnFileName, allFile)
} else {
log.Info("error,msg=" + err.Error())
ctx.ServerError("no file to download.", err)
}
}

func ObsDownloadManyFile(path string, ctx *context.Context, returnFileName string, allFile []storage.FileInfo) {
ctx.Resp.Header().Set("Content-Disposition", "attachment; filename="+url.QueryEscape(returnFileName))
ctx.Resp.Header().Set("Content-Type", "application/octet-stream")
w := zip.NewWriter(ctx.Resp)
defer w.Close()
for _, oneFile := range allFile {
if oneFile.IsDir {
log.Info("zip dir name:" + oneFile.FileName)
} else {
log.Info("zip file name:" + oneFile.FileName)
fDest, err := w.Create(oneFile.FileName)
if err != nil {
log.Info("create zip entry error, download file failed: %s\n", err.Error())
ctx.ServerError("download file failed:", err)
return
}
body, err := storage.ObsDownloadAFile(setting.Bucket, path+oneFile.FileName)
if err != nil {
log.Info("download file failed: %s\n", err.Error())
ctx.ServerError("download file failed:", err)
return
} else { } else {
log.Info("zip file name:" + oneFile.FileName)
fDest, err := w.Create(oneFile.FileName)
if err != nil {
log.Info("create zip entry error, download file failed: %s\n", err.Error())
ctx.ServerError("download file failed:", err)
return
}
body, err := storage.ObsDownloadAFile(setting.Bucket, path+oneFile.FileName)
if err != nil {
log.Info("download file failed: %s\n", err.Error())
ctx.ServerError("download file failed:", err)
return
} else {
defer body.Close()
p := make([]byte, 1024)
var readErr error
var readCount int
// 读取对象内容
for {
readCount, readErr = body.Read(p)
if readCount > 0 {
fDest.Write(p[:readCount])
}
if readErr != nil {
break
}
defer body.Close()
p := make([]byte, 1024)
var readErr error
var readCount int
// 读取对象内容
for {
readCount, readErr = body.Read(p)
if readCount > 0 {
fDest.Write(p[:readCount])
}
if readErr != nil {
break
} }
} }
} }
} }
}
}

func downloadFromCloudBrainTwo(path string, task *models.AiModelManage, ctx *context.Context, id string) {
allFile, err := storage.GetAllObjectByBucketAndPrefix(setting.Bucket, path)
if err == nil {
//count++
models.ModifyModelDownloadCount(id)
returnFileName := task.Name + "_" + task.Version + ".zip"
ObsDownloadManyFile(path, ctx, returnFileName, allFile)
} else { } else {
log.Info("error,msg=" + err.Error()) log.Info("error,msg=" + err.Error())
ctx.ServerError("no file to download.", err) ctx.ServerError("no file to download.", err)
@@ -374,42 +467,55 @@ func DownloadSingleModelFile(ctx *context.Context) {
ctx.NotFound(ctx.Req.URL.RequestURI(), nil) ctx.NotFound(ctx.Req.URL.RequestURI(), nil)
return return
} }
if setting.PROXYURL != "" {
body, err := storage.ObsDownloadAFile(setting.Bucket, path)
if err != nil {
log.Info("download error.")
if task.Type == models.TypeCloudBrainTwo {
if setting.PROXYURL != "" {
body, err := storage.ObsDownloadAFile(setting.Bucket, path)
if err != nil {
log.Info("download error.")
} else {
//count++
models.ModifyModelDownloadCount(id)
defer body.Close()
ctx.Resp.Header().Set("Content-Disposition", "attachment; filename="+fileName)
ctx.Resp.Header().Set("Content-Type", "application/octet-stream")
p := make([]byte, 1024)
var readErr error
var readCount int
// 读取对象内容
for {
readCount, readErr = body.Read(p)
if readCount > 0 {
ctx.Resp.Write(p[:readCount])
//fmt.Printf("%s", p[:readCount])
}
if readErr != nil {
break
}
}
}
} else { } else {
url, err := storage.GetObsCreateSignedUrlByBucketAndKey(setting.Bucket, path)
if err != nil {
log.Error("GetObsCreateSignedUrl failed: %v", err.Error(), ctx.Data["msgID"])
ctx.ServerError("GetObsCreateSignedUrl", err)
return
}
//count++ //count++
models.ModifyModelDownloadCount(id) models.ModifyModelDownloadCount(id)
defer body.Close()
ctx.Resp.Header().Set("Content-Disposition", "attachment; filename="+fileName)
ctx.Resp.Header().Set("Content-Type", "application/octet-stream")
p := make([]byte, 1024)
var readErr error
var readCount int
// 读取对象内容
for {
readCount, readErr = body.Read(p)
if readCount > 0 {
ctx.Resp.Write(p[:readCount])
//fmt.Printf("%s", p[:readCount])
}
if readErr != nil {
break
}
}
http.Redirect(ctx.Resp, ctx.Req.Request, url, http.StatusMovedPermanently)
} }
} else {
url, err := storage.GetObsCreateSignedUrlByBucketAndKey(setting.Bucket, path)
} else if task.Type == models.TypeCloudBrainOne {
log.Info("start to down load minio file.")
url, err := storage.Attachments.PresignedGetURL(path, fileName)
if err != nil { if err != nil {
log.Error("GetObsCreateSignedUrl failed: %v", err.Error(), ctx.Data["msgID"])
ctx.ServerError("GetObsCreateSignedUrl", err)
log.Error("Get minio get SignedUrl failed: %v", err.Error(), ctx.Data["msgID"])
ctx.ServerError("Get minio get SignedUrl failed", err)
return return
} }
//count++
models.ModifyModelDownloadCount(id) models.ModifyModelDownloadCount(id)
http.Redirect(ctx.Resp, ctx.Req.Request, url, http.StatusMovedPermanently) http.Redirect(ctx.Resp, ctx.Req.Request, url, http.StatusMovedPermanently)
} }

} }


func ShowModelInfo(ctx *context.Context) { func ShowModelInfo(ctx *context.Context) {
@@ -684,14 +790,22 @@ func QueryModelListForPredict(ctx *context.Context) {
func QueryModelFileForPredict(ctx *context.Context) { func QueryModelFileForPredict(ctx *context.Context) {
id := ctx.Query("ID") id := ctx.Query("ID")
model, err := models.QueryModelById(id) model, err := models.QueryModelById(id)
if err != nil {
if err == nil {
if model.Type == models.TypeCloudBrainTwo {
prefix := model.Path[len(setting.Bucket)+1:]
fileinfos, _ := storage.GetAllObjectByBucketAndPrefix(setting.Bucket, prefix)
ctx.JSON(http.StatusOK, fileinfos)
} else if model.Type == models.TypeCloudBrainOne {
prefix := model.Path[len(setting.Attachment.Minio.Bucket)+1:]
fileinfos, _ := storage.GetAllObjectByBucketAndPrefixMinio(setting.Attachment.Minio.Bucket, prefix)
ctx.JSON(http.StatusOK, fileinfos)
}
} else {
log.Error("no such model!", err.Error()) log.Error("no such model!", err.Error())
ctx.ServerError("no such model:", err) ctx.ServerError("no such model:", err)
return return
} }
prefix := model.Path[len(setting.Bucket)+1:]
fileinfos, err := storage.GetAllObjectByBucketAndPrefix(setting.Bucket, prefix)
ctx.JSON(http.StatusOK, fileinfos)

} }


func QueryOneLevelModelFile(ctx *context.Context) { func QueryOneLevelModelFile(ctx *context.Context) {
@@ -703,7 +817,16 @@ func QueryOneLevelModelFile(ctx *context.Context) {
ctx.ServerError("no such model:", err) ctx.ServerError("no such model:", err)
return return
} }
prefix := model.Path[len(setting.Bucket)+1:]
fileinfos, err := storage.GetOneLevelAllObjectUnderDir(setting.Bucket, prefix, parentDir)
ctx.JSON(http.StatusOK, fileinfos)
if model.Type == models.TypeCloudBrainTwo {
log.Info("TypeCloudBrainTwo list model file.")
prefix := model.Path[len(setting.Bucket)+1:]
fileinfos, _ := storage.GetOneLevelAllObjectUnderDir(setting.Bucket, prefix, parentDir)
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)
ctx.JSON(http.StatusOK, fileinfos)
}

} }

+ 1
- 1
routers/repo/dataset.go View File

@@ -173,7 +173,7 @@ func DatasetIndex(ctx *context.Context) {
uploader, _ := models.GetUserByID(attachment.UploaderID) uploader, _ := models.GetUserByID(attachment.UploaderID)
attachment.Uploader = uploader attachment.Uploader = uploader
if !strings.HasSuffix(attachment.Name, ".zip") { if !strings.HasSuffix(attachment.Name, ".zip") {
attachment.DecompressState = 3 //非zip文件
attachment.DecompressState = -1 //非zip文件
} }


} }


+ 34
- 4
routers/repo/modelarts.go View File

@@ -2251,7 +2251,6 @@ func ModelDownload(ctx *context.Context) {
versionName := ctx.Query("version_name") versionName := ctx.Query("version_name")
parentDir := ctx.Query("parent_dir") parentDir := ctx.Query("parent_dir")
fileName := ctx.Query("file_name") fileName := ctx.Query("file_name")
log.Info("DownloadSingleModelFile start.")
task, err := models.GetCloudbrainByJobIDAndVersionName(jobID, versionName) task, err := models.GetCloudbrainByJobIDAndVersionName(jobID, versionName)
if err != nil { if err != nil {
log.Error("GetCloudbrainByJobID(%s) failed:%v", task.JobName, err.Error()) log.Error("GetCloudbrainByJobID(%s) failed:%v", task.JobName, err.Error())
@@ -2259,7 +2258,6 @@ func ModelDownload(ctx *context.Context) {
} }


path := strings.TrimPrefix(path.Join(setting.TrainJobModelPath, task.JobName, setting.OutPutPath, versionName, parentDir, fileName), "/") path := strings.TrimPrefix(path.Join(setting.TrainJobModelPath, task.JobName, setting.OutPutPath, versionName, parentDir, fileName), "/")
log.Info("Download path is:%s", path)


url, err := storage.GetObsCreateSignedUrlByBucketAndKey(setting.Bucket, path) url, err := storage.GetObsCreateSignedUrlByBucketAndKey(setting.Bucket, path)
if err != nil { if err != nil {
@@ -2267,6 +2265,7 @@ func ModelDownload(ctx *context.Context) {
ctx.ServerError("GetObsCreateSignedUrl", err) ctx.ServerError("GetObsCreateSignedUrl", err)
return return
} }
ctx.Resp.Header().Set("Cache-Control", "max-age=0")
http.Redirect(ctx.Resp, ctx.Req.Request, url, http.StatusMovedPermanently) http.Redirect(ctx.Resp, ctx.Req.Request, url, http.StatusMovedPermanently)
} }


@@ -2278,13 +2277,11 @@ func ResultDownload(ctx *context.Context) {
versionName := ctx.Query("version_name") versionName := ctx.Query("version_name")
parentDir := ctx.Query("parent_dir") parentDir := ctx.Query("parent_dir")
fileName := ctx.Query("file_name") fileName := ctx.Query("file_name")
log.Info("DownloadResult start.")
task := ctx.Cloudbrain task := ctx.Cloudbrain
if err != nil { if err != nil {
ctx.Data["error"] = err.Error() ctx.Data["error"] = err.Error()
} }
path := strings.TrimPrefix(path.Join(setting.TrainJobModelPath, task.JobName, "result/", versionName, parentDir, fileName), "/") path := strings.TrimPrefix(path.Join(setting.TrainJobModelPath, task.JobName, "result/", versionName, parentDir, fileName), "/")
log.Info("Download path is:%s", path)


url, err := storage.GetObsCreateSignedUrlByBucketAndKey(setting.Bucket, path) url, err := storage.GetObsCreateSignedUrlByBucketAndKey(setting.Bucket, path)
if err != nil { if err != nil {
@@ -2292,6 +2289,7 @@ func ResultDownload(ctx *context.Context) {
ctx.ServerError("GetObsCreateSignedUrl", err) ctx.ServerError("GetObsCreateSignedUrl", err)
return return
} }
ctx.Resp.Header().Set("Cache-Control", "max-age=0")
http.Redirect(ctx.Resp, ctx.Req.Request, url, http.StatusMovedPermanently) http.Redirect(ctx.Resp, ctx.Req.Request, url, http.StatusMovedPermanently)
} }
func DeleteJobStorage(jobName string) error { func DeleteJobStorage(jobName string) error {
@@ -2390,3 +2388,35 @@ func SetJobCount(ctx *context.Context) {
} }
ctx.Data["jobCount"] = jobCount ctx.Data["jobCount"] = jobCount
} }

func TrainJobDownloadLogFile(ctx *context.Context) {
var (
err error
)

var jobID = ctx.Params(":jobid")
versionName := ctx.Query("version_name")
task, err := models.GetCloudbrainByJobIDAndVersionName(jobID, versionName)
if err != nil {
log.Error("GetCloudbrainByJobIDAndVersionName(%s) failed:%v", task.JobName, err.Error(), ctx.Data["msgID"])
ctx.ServerError("GetCloudbrainByJobIDAndVersionName", err)
return
}

prefix := strings.TrimPrefix(path.Join(setting.TrainJobModelPath, task.JobName, modelarts.LogPath, versionName), "/") + "/job"
key, err := storage.GetObsLogFileName(prefix)
if err != nil {
log.Error("GetObsLogFileName(%s) failed:%v", jobID, err.Error(), ctx.Data["msgID"])
ctx.ServerError("GetObsLogFileName", err)
return
}

url, err := storage.GetObsCreateSignedUrlByBucketAndKey(setting.Bucket, key)
if err != nil {
log.Error("GetObsCreateSignedUrlByBucketAndKey failed: %v", err.Error(), ctx.Data["msgID"])
ctx.ServerError("GetObsCreateSignedUrlByBucketAndKey", err)
return
}
ctx.Resp.Header().Set("Cache-Control", "max-age=0")
http.Redirect(ctx.Resp, ctx.Req.Request, url, http.StatusMovedPermanently)
}

+ 6
- 2
routers/repo/repo.go View File

@@ -6,7 +6,6 @@
package repo package repo


import ( import (
"code.gitea.io/gitea/modules/validation"
"fmt" "fmt"
"net/url" "net/url"
"os" "os"
@@ -15,6 +14,8 @@ import (
"strings" "strings"
"unicode/utf8" "unicode/utf8"


"code.gitea.io/gitea/modules/validation"

"code.gitea.io/gitea/models" "code.gitea.io/gitea/models"
"code.gitea.io/gitea/modules/auth" "code.gitea.io/gitea/modules/auth"
"code.gitea.io/gitea/modules/base" "code.gitea.io/gitea/modules/base"
@@ -193,7 +194,10 @@ func CreatePost(ctx *context.Context, form auth.CreateRepoForm) {
return return
} }
ctx.Data["ContextUser"] = ctxUser ctx.Data["ContextUser"] = ctxUser

if !form.AutoAgree {
ctx.RenderWithErr(ctx.Tr("repo.template.one_promise"), tplCreate, form)
return
}
if ctx.HasError() { if ctx.HasError() {
ctx.HTML(200, tplCreate) ctx.HTML(200, tplCreate)
return return


+ 4
- 0
routers/repo/view.go View File

@@ -471,6 +471,8 @@ func renderFile(ctx *context.Context, entry *git.TreeEntry, treeLink, rawLink st


readmeExist := markup.IsReadmeFile(blob.Name()) readmeExist := markup.IsReadmeFile(blob.Name())
ctx.Data["ReadmeExist"] = readmeExist ctx.Data["ReadmeExist"] = readmeExist
isNoteBook := strings.HasSuffix(blob.Name(), ".ipynb")
ctx.Data["IsNoteBook"] = isNoteBook
if markupType := markup.Type(blob.Name()); markupType != "" { if markupType := markup.Type(blob.Name()); markupType != "" {
ctx.Data["IsMarkup"] = true ctx.Data["IsMarkup"] = true
ctx.Data["MarkupType"] = markupType ctx.Data["MarkupType"] = markupType
@@ -480,6 +482,8 @@ func renderFile(ctx *context.Context, entry *git.TreeEntry, treeLink, rawLink st
ctx.Data["FileContent"] = strings.Replace( ctx.Data["FileContent"] = strings.Replace(
gotemplate.HTMLEscapeString(string(buf)), "\n", `<br>`, -1, gotemplate.HTMLEscapeString(string(buf)), "\n", `<br>`, -1,
) )
} else if isNoteBook {
ctx.Data["FileContent"] = string(buf)
} else { } else {
// Building code view blocks with line number on server side. // Building code view blocks with line number on server side.
var fileContent string var fileContent string


+ 7
- 3
routers/routes/routes.go View File

@@ -324,7 +324,10 @@ func RegisterRoutes(m *macaron.Macaron) {
go routers.SocketManager.Run() go routers.SocketManager.Run()
m.Get("/action/notification", routers.ActionNotification) m.Get("/action/notification", routers.ActionNotification)
m.Get("/recommend/home", routers.RecommendHomeInfo) m.Get("/recommend/home", routers.RecommendHomeInfo)
//m.Get("/recommend/org", routers.RecommendOrgFromPromote)
//m.Get("/recommend/repo", routers.RecommendRepoFromPromote)
m.Get("/recommend/userrank/:index", routers.GetUserRankFromPromote) m.Get("/recommend/userrank/:index", routers.GetUserRankFromPromote)
//m.Get("/recommend/imageinfo", routers.GetImageInfoFromPromote)
m.Post("/all/search/", routers.Search) m.Post("/all/search/", routers.Search)
m.Get("/all/search/", routers.EmptySearch) m.Get("/all/search/", routers.EmptySearch)
m.Get("/all/dosearch/", routers.SearchApi) m.Get("/all/dosearch/", routers.SearchApi)
@@ -1093,9 +1096,9 @@ func RegisterRoutes(m *macaron.Macaron) {
m.Get("/show_model_child_api", repo.ShowOneVersionOtherModel) m.Get("/show_model_child_api", repo.ShowOneVersionOtherModel)
m.Get("/query_train_job", reqRepoCloudBrainReader, repo.QueryTrainJobList) m.Get("/query_train_job", reqRepoCloudBrainReader, repo.QueryTrainJobList)
m.Get("/query_train_job_version", reqRepoCloudBrainReader, repo.QueryTrainJobVersionList) m.Get("/query_train_job_version", reqRepoCloudBrainReader, repo.QueryTrainJobVersionList)
m.Get("/query_model_for_predict", reqRepoCloudBrainReader, repo.QueryModelListForPredict)
m.Get("/query_modelfile_for_predict", reqRepoCloudBrainReader, repo.QueryModelFileForPredict)
m.Get("/query_onelevel_modelfile", reqRepoCloudBrainReader, repo.QueryOneLevelModelFile)
m.Get("/query_model_for_predict", reqRepoModelManageReader, repo.QueryModelListForPredict)
m.Get("/query_modelfile_for_predict", reqRepoModelManageReader, repo.QueryModelFileForPredict)
m.Get("/query_onelevel_modelfile", reqRepoModelManageReader, repo.QueryOneLevelModelFile)
m.Group("/:ID", func() { m.Group("/:ID", func() {
m.Get("", repo.ShowSingleModel) m.Get("", repo.ShowSingleModel)
m.Get("/downloadsingle", repo.DownloadSingleModelFile) m.Get("/downloadsingle", repo.DownloadSingleModelFile)
@@ -1136,6 +1139,7 @@ func RegisterRoutes(m *macaron.Macaron) {
m.Post("/stop", cloudbrain.AdminOrOwnerOrJobCreaterRightForTrain, repo.TrainJobStop) m.Post("/stop", cloudbrain.AdminOrOwnerOrJobCreaterRightForTrain, repo.TrainJobStop)
m.Post("/del", cloudbrain.AdminOrOwnerOrJobCreaterRightForTrain, repo.TrainJobDel) m.Post("/del", cloudbrain.AdminOrOwnerOrJobCreaterRightForTrain, repo.TrainJobDel)
m.Get("/model_download", cloudbrain.AdminOrJobCreaterRightForTrain, repo.ModelDownload) m.Get("/model_download", cloudbrain.AdminOrJobCreaterRightForTrain, repo.ModelDownload)
m.Get("/download_log_file", cloudbrain.AdminOrJobCreaterRightForTrain, repo.TrainJobDownloadLogFile)
m.Get("/create_version", reqWechatBind, cloudbrain.AdminOrJobCreaterRightForTrain, repo.TrainJobNewVersion) m.Get("/create_version", reqWechatBind, cloudbrain.AdminOrJobCreaterRightForTrain, repo.TrainJobNewVersion)
m.Post("/create_version", reqWechatBind, cloudbrain.AdminOrJobCreaterRightForTrain, bindIgnErr(auth.CreateModelArtsTrainJobForm{}), repo.TrainJobCreateVersion) m.Post("/create_version", reqWechatBind, cloudbrain.AdminOrJobCreaterRightForTrain, bindIgnErr(auth.CreateModelArtsTrainJobForm{}), repo.TrainJobCreateVersion)
}) })


+ 44
- 0
templates/base/footer.tmpl View File

@@ -13,6 +13,9 @@
{{template "base/footer_content" .}} {{template "base/footer_content" .}}


<script src="{{StaticUrlPrefix}}/js/jquery.js?v={{MD5 AppVer}}"></script> <script src="{{StaticUrlPrefix}}/js/jquery.js?v={{MD5 AppVer}}"></script>


{{if .RequireSimpleMDE}} {{if .RequireSimpleMDE}}
<script src="{{StaticUrlPrefix}}/vendor/plugins/simplemde/simplemde.min.js"></script> <script src="{{StaticUrlPrefix}}/vendor/plugins/simplemde/simplemde.min.js"></script>
<script src="{{StaticUrlPrefix}}/vendor/plugins/codemirror/addon/mode/loadmode.js"></script> <script src="{{StaticUrlPrefix}}/vendor/plugins/codemirror/addon/mode/loadmode.js"></script>
@@ -43,5 +46,46 @@
<script src="{{StaticUrlPrefix}}/fomantic/semantic.min.js?v={{MD5 AppVer}}"></script> <script src="{{StaticUrlPrefix}}/fomantic/semantic.min.js?v={{MD5 AppVer}}"></script>
<script src="{{StaticUrlPrefix}}/js/index.js?v={{MD5 AppVer}}"></script> <script src="{{StaticUrlPrefix}}/js/index.js?v={{MD5 AppVer}}"></script>
{{template "custom/footer" .}} {{template "custom/footer" .}}
{{if .PageIsHome}}
<!--script src="https://www.jq22.com/jquery/jquery-1.10.2.js"></script-->
<script src="/rotation3D/vue-2.6.10.min.js"></script>
<script src="/rotation3D/rotation3D.js?v={{MD5 AppVer}}"></script>
<script>
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:'', },
],
},
mounted: function () {
new Rotation3D({
id: '#rotation3D',
farScale: 0.6,
// farScale: 1,
xRadius: 0, //x半径压缩
yRadius: 130, //y半径压缩
// yRadius: 0, //y半径压缩
// autoPlay:true,
// autoPlayDelay:6000,
})
},
methods: {},
});
</script>
{{end}}

</body> </body>
</html> </html>

+ 2
- 0
templates/base/head_home.tmpl View File

@@ -192,6 +192,8 @@ var _hmt = _hmt || [];
<!-- Swiper --> <!-- Swiper -->
<link rel="stylesheet" href="/swiper/swiper-bundle.min.css"> <link rel="stylesheet" href="/swiper/swiper-bundle.min.css">
<script src="/swiper/swiper-bundle.min.js"></script> <script src="/swiper/swiper-bundle.min.js"></script>
<!-- rotation3D -->
<link rel="stylesheet" href="/rotation3D/rotation3D.css">
</head> </head>
<body> <body>
{{template "custom/body_outer_pre" .}} {{template "custom/body_outer_pre" .}}


+ 4
- 4
templates/base/head_navbar.tmpl View File

@@ -34,7 +34,7 @@


<a class="item" href="{{AppSubUrl}}/explore/repos">{{.i18n.Tr "custom.head.project"}}</a> <a class="item" href="{{AppSubUrl}}/explore/repos">{{.i18n.Tr "custom.head.project"}}</a>
<a class="item" href="{{AppSubUrl}}/explore/datasets">{{.i18n.Tr "custom.head.dataset"}}</a> <a class="item" href="{{AppSubUrl}}/explore/datasets">{{.i18n.Tr "custom.head.dataset"}}</a>
<div class="ui dropdown item" id='dropdown_explore'>
<div class="ui simple dropdown item" id='dropdown_explore'>
{{.i18n.Tr "explore"}} {{.i18n.Tr "explore"}}
<i class="dropdown icon"></i> <i class="dropdown icon"></i>
<div class="menu"> <div class="menu">
@@ -65,7 +65,7 @@


<a class="item" href="{{AppSubUrl}}/explore/repos">{{.i18n.Tr "custom.head.project"}}</a> <a class="item" href="{{AppSubUrl}}/explore/repos">{{.i18n.Tr "custom.head.project"}}</a>
<a class="item" href="{{AppSubUrl}}/explore/datasets">{{.i18n.Tr "custom.head.dataset"}}</a> <a class="item" href="{{AppSubUrl}}/explore/datasets">{{.i18n.Tr "custom.head.dataset"}}</a>
<div class="ui dropdown item" id='dropdown_PageHome'>
<div class="ui simple dropdown item" id='dropdown_PageHome'>
{{.i18n.Tr "explore"}} {{.i18n.Tr "explore"}}
<i class="dropdown icon"></i> <i class="dropdown icon"></i>
<div class="menu" > <div class="menu" >
@@ -120,7 +120,7 @@
</span> </span>
</a> </a>


<div class="ui dropdown jump item poping up" data-content="{{.i18n.Tr "create_new"}}" data-variation="tiny inverted">
<div class="ui simple dropdown jump item poping up" data-content="{{.i18n.Tr "create_new"}}" data-variation="tiny inverted">
<span class="text"> <span class="text">
<span class="fitted">{{svg "octicon-plus" 16}}</span> <span class="fitted">{{svg "octicon-plus" 16}}</span>
<span class="sr-mobile-only">{{.i18n.Tr "create_new"}}</span> <span class="sr-mobile-only">{{.i18n.Tr "create_new"}}</span>
@@ -141,7 +141,7 @@
</div><!-- end content create new menu --> </div><!-- end content create new menu -->
</div><!-- end dropdown menu create new --> </div><!-- end dropdown menu create new -->


<div class="ui dropdown jump item poping up" tabindex="-1" data-content="{{.i18n.Tr "user_profile_and_more"}}" data-variation="tiny inverted">
<div class="ui simple dropdown jump item poping up" tabindex="-1" data-content="{{.i18n.Tr "user_profile_and_more"}}" data-variation="tiny inverted">
<span class="text"> <span class="text">
<img class="ui tiny avatar image" width="24" height="24" src="{{.SignedUser.RelAvatarLink}}"> <img class="ui tiny avatar image" width="24" height="24" src="{{.SignedUser.RelAvatarLink}}">
<span class="sr-only">{{.i18n.Tr "user_profile_and_more"}}</span> <span class="sr-only">{{.i18n.Tr "user_profile_and_more"}}</span>


+ 5
- 5
templates/explore/datasets.tmpl View File

@@ -157,8 +157,6 @@
href="{{$.Link}}?sort=moststars&q={{$.Keyword}}&tab={{$.TabName}}&category={{$.Category}}&task={{$.Task}}&license={{$.License}}&recommend={{$.Recommend}}">{{.i18n.Tr "repo.issues.filter_sort.moststars"}}</a> href="{{$.Link}}?sort=moststars&q={{$.Keyword}}&tab={{$.TabName}}&category={{$.Category}}&task={{$.Task}}&license={{$.License}}&recommend={{$.Recommend}}">{{.i18n.Tr "repo.issues.filter_sort.moststars"}}</a>
<a class="{{if eq .SortType "mostusecount"}}active{{end}} item" <a class="{{if eq .SortType "mostusecount"}}active{{end}} item"
href="{{$.Link}}?sort=mostusecount&q={{$.Keyword}}&tab={{$.TabName}}&category={{$.Category}}&task={{$.Task}}&license={{$.License}}&recommend={{$.Recommend}}">{{.i18n.Tr "repo.issues.filter_sort.mostusecount"}}</a> href="{{$.Link}}?sort=mostusecount&q={{$.Keyword}}&tab={{$.TabName}}&category={{$.Category}}&task={{$.Task}}&license={{$.License}}&recommend={{$.Recommend}}">{{.i18n.Tr "repo.issues.filter_sort.mostusecount"}}</a>
<a class="{{if eq .SortType "fewestusecount"}}active{{end}} item"
href="{{$.Link}}?sort=fewestusecount&q={{$.Keyword}}&tab={{$.TabName}}&category={{$.Category}}&task={{$.Task}}&license={{$.License}}&recommend={{$.Recommend}}">{{.i18n.Tr "repo.issues.filter_sort.fewestusecount"}}</a>
</div> </div>
</div> </div>
</div> </div>
@@ -186,7 +184,7 @@
src="/img/jian.svg" style="margin-left: 0.5rem;">{{end}} src="/img/jian.svg" style="margin-left: 0.5rem;">{{end}}
{{if $.IsSigned}} {{if $.IsSigned}}
<span <span
style="display: flex;align-items: center;justify-content: flex-end;cursor: pointer;font-size: 12px;font-weight: normal;flex: 1;"
style="display: flex;align-items: center;justify-content: flex-end;cursor: pointer;font-size: 12px;font-weight: normal;flex: 1;margin-left: 1.5rem;"
@click.stop="postSquareStar({{.ID}},'{{.Repo.Link}}/datasets',{{$k}})"> @click.stop="postSquareStar({{.ID}},'{{.Repo.Link}}/datasets',{{$k}})">


<div style="line-height: 1;margin-right: 4px;margin-bottom: -2px;"> <div style="line-height: 1;margin-right: 4px;margin-bottom: -2px;">
@@ -256,12 +254,14 @@
<span <span
style="color: #999999;font-size: 12px;margin-left: 0.5rem;">{{TimeSinceUnixShort .CreatedUnix}}</span> style="color: #999999;font-size: 12px;margin-left: 0.5rem;">{{TimeSinceUnixShort .CreatedUnix}}</span>
<span <span
style="display: flex;align-items: center;justify-content: center;margin: 0 1rem;">
style="display: flex;align-items: center;justify-content: center;margin: 0 1rem;"
title="{{$.i18n.Tr "repo.issues.filter_sort.citations"}}">
<i class="ri-link"></i> <i class="ri-link"></i>
<span <span
style="color: #101010; font-size: 12px;margin-left: 0.2rem;">{{.UseCount}}</span> style="color: #101010; font-size: 12px;margin-left: 0.2rem;">{{.UseCount}}</span>
</span> </span>
<span style=" display: flex;align-items: center;justify-content: center;">
<span style=" display: flex;align-items: center;justify-content: center;"
title='{{$.i18n.Tr "repo.issues.filter_sort.downloadtimes"}}'>
<i class="ri-download-line"></i> <i class="ri-download-line"></i>
<span <span
style="color: #101010;font-size: 12px;margin-left: 0.2rem;">{{.DownloadTimes}}</span> style="color: #101010;font-size: 12px;margin-left: 0.2rem;">{{.DownloadTimes}}</span>


+ 80
- 25
templates/home.tmpl View File

@@ -1,6 +1,6 @@
{{template "base/head_home" .}} {{template "base/head_home" .}}
<div class="ui vertical masthead secondary hometop segment"> <div class="ui vertical masthead secondary hometop segment">
<div class="ui container" style="position: relative;">
<div class="ui container" style="position: relative;">
<div class="ui center homebanner"> <div class="ui center homebanner">
<h1 class="ui huge header"> <h1 class="ui huge header">
{{.page_title}} {{.page_title}}
@@ -17,7 +17,7 @@
{{end}} {{end}}
</div> </div>
<div class="bannerpic"><img class="ui fluid image" src="/img/gitopeni-index-01.svg"></div> <div class="bannerpic"><img class="ui fluid image" src="/img/gitopeni-index-01.svg"></div>
<div id="homenews" class="ui container">
<div id="homenews">
<p>* {{.page_only_dynamic}}</p> <p>* {{.page_only_dynamic}}</p>
<div class="ui grid"> <div class="ui grid">
<div class="sixteen wide mobile twelve wide tablet ten wide computer column homenews"> <div class="sixteen wide mobile twelve wide tablet ten wide computer column homenews">
@@ -35,33 +35,32 @@


<!--组织--> <!--组织-->
<div class="ui container homeorg"> <div class="ui container homeorg">
<div class="ui stackable grid">
<div class="ui stackable grid">
<div class="sixteen wide tablet four wide computer column homeorg-tit"> <div class="sixteen wide tablet four wide computer column homeorg-tit">
<h2>{{.page_recommend_activity}}</h2>
<p><span class="ui text grey">{{.page_recommend_activity_desc}}</p>
<h2>{{.page_recommend_org}}</h2>
<p><span class="ui text grey">{{.page_recommend_org_desc}}&nbsp;</span><a href="{{.RecommendURL}}">{{.page_recommend_org_commit}}</a></p>
<a href="{{AppSubUrl}}/explore/organizations" class="circular ui primary basic button">{{.page_recommend_org_more}} <i class="arrow circle right icon"></i></a>
</div> </div>
<div class="sixteen wide tablet twelve wide computer column"> <div class="sixteen wide tablet twelve wide computer column">
<div class="event-list">
<div class="swiper-wrapper" id="recommendactivity">
<div class="homeorg-list">
<div class="swiper-wrapper" id="recommendorg">
</div> </div>
<div class="swiper-pagination"></div> <div class="swiper-pagination"></div>
</div> </div>
</div> </div>


<div class="sixteen wide tablet four wide computer column homeorg-tit"> <div class="sixteen wide tablet four wide computer column homeorg-tit">
<h2>{{.page_recommend_org}}</h2>
<p><span class="ui text grey">{{.page_recommend_org_desc}}&nbsp;</span><a href="{{.RecommendURL}}">{{.page_recommend_org_commit}}</a></p>
<a href="{{AppSubUrl}}/explore/organizations" class="circular ui primary basic button">{{.page_recommend_org_more}} <i class="arrow circle right icon"></i></a>
<h2>{{.page_recommend_activity}}</h2>
<p><span class="ui text grey">{{.page_recommend_activity_desc}}</p>
</div> </div>
<div class="sixteen wide tablet twelve wide computer column"> <div class="sixteen wide tablet twelve wide computer column">
<div class="homeorg-list">
<div class="swiper-wrapper" id="recommendorg">
<div class="event-list">
<div class="swiper-wrapper" id="recommendactivity">
</div> </div>
<div class="swiper-pagination"></div> <div class="swiper-pagination"></div>
</div> </div>
</div> </div>
</div> </div>
@@ -87,56 +86,112 @@
</div> </div>


<div class="ui vertical masthead secondary c2net segment">
<div class="ui container">
<div class="ui center am-pt-30 am-pb-30">
<h2>智算网络</h2>
<p><span class="ui text grey">人工智能算力网络推进联盟已接入10家智算中心,算力总规模1542P</p>
</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-->
<div id="rotation3D" class="rotation3D">
<button class="center">中心</button>
<div class="itemList">
<div class="rotation3D__item" :class="item.type" v-for="item in itemList">
<div class="scale">
<div class="baseImg"></div>
<div class="cont">
<i class="iconfont" :class="item.icon"></i>
<p></p>
</div>
</div>
</div>
</div>
<div class="lineList">
<div class="rotation3D__line" v-for="item in itemList" :class="item.type">
<div v-if="item.type=='blue'" 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"><span></span></div>
</div>
<div v-if="item.type=='yellow'" class="pos">
<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>
<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>
</div>
</div>
</div>
</div><!--rotation3D end-->
</div>
</div>


<a name="fourth"></a> <a name="fourth"></a>
<div class="ui container i-env"> <div class="ui container i-env">
<div class="ui center am-pb-30"> <div class="ui center am-pb-30">
<div class="leftline03"></div>
<h2>{{.page_dev_env}}</h2> <h2>{{.page_dev_env}}</h2>
<p><span class="ui text grey">{{.page_dev_env_desc}}</p> <p><span class="ui text grey">{{.page_dev_env_desc}}</p>
</div> </div>
<div class="ui four doubling cards"> <div class="ui four doubling cards">
<div class="card"> <div class="card">
<div class="image"> <div class="image">
<img src="/img/i-pic-01.svg">
<img src="/img/i-pic-01.jpg">
</div> </div>
<div class="content"> <div class="content">
<h3 class="ui centered small header">{{.page_dev_env_desc_title}}</h3> <h3 class="ui centered small header">{{.page_dev_env_desc_title}}</h3>
<div class="description">
<div class="description ui text grey">
{{.page_dev_env_desc_desc}} {{.page_dev_env_desc_desc}}
</div> </div>
</div> </div>
</div> </div>
<div class="card"> <div class="card">
<div class="image"> <div class="image">
<img src="/img/i-pic-02.svg">
<img src="/img/i-pic-02.jpg">
</div> </div>
<div class="content"> <div class="content">
<h3 class="ui centered small header">{{.page_dev_env_desc1_title}}</h3> <h3 class="ui centered small header">{{.page_dev_env_desc1_title}}</h3>
<div class="description">
<div class="description ui text grey">
{{.page_dev_env_desc1_desc}} {{.page_dev_env_desc1_desc}}
</div> </div>
</div> </div>
</div> </div>
<div class="card"> <div class="card">
<div class="image"> <div class="image">
<img src="/img/i-pic-03.svg">
<img src="/img/i-pic-03.jpg">
</div> </div>
<div class="content"> <div class="content">
<h3 class="ui centered small header">{{.page_dev_env_desc2_title}}</h3> <h3 class="ui centered small header">{{.page_dev_env_desc2_title}}</h3>
<div class="description">
<div class="description ui text grey">
{{.page_dev_env_desc2_desc}} {{.page_dev_env_desc2_desc}}
</div> </div>
</div> </div>
</div> </div>
<div class="card"> <div class="card">
<div class="image"> <div class="image">
<img src="/img/i-pic-04.svg">
<img src="/img/i-pic-04.jpg">
</div> </div>
<div class="content"> <div class="content">
<h3 class="ui centered small header">{{.page_dev_env_desc3_title}}</h3> <h3 class="ui centered small header">{{.page_dev_env_desc3_title}}</h3>
<div class="description">
<div class="description ui text grey">
{{.page_dev_env_desc3_desc}} {{.page_dev_env_desc3_desc}}
</div> </div>
</div> </div>
@@ -172,8 +227,8 @@
</div> </div>
</div> </div>
<div class="am-mt-30"></div> <div class="am-mt-30"></div>
<script src="/self/js/jquery.min.js" type="text/javascript"></script>
<script src="/home/home.js?v={{MD5 AppVer}}" type="text/javascript"></script>
<script src="/self/js/jquery.min.js" type="text/javascript"></script>
<script src="/home/home.js?v={{MD5 AppVer}}" type="text/javascript"></script>




{{template "base/footer" .}} {{template "base/footer" .}}

+ 39
- 19
templates/repo/create.tmpl View File

@@ -15,11 +15,11 @@
<label>{{.i18n.Tr "repo.visibility"}}</label> <label>{{.i18n.Tr "repo.visibility"}}</label>
<div class="ui checkbox"> <div class="ui checkbox">
{{if .IsForcedPrivate}} {{if .IsForcedPrivate}}
<input name="private" type="checkbox" checked readonly>
<label>{{.i18n.Tr "repo.visibility_helper_forced" | Safe}}</label>
<input name="private" type="checkbox" checked readonly>
<label>{{.i18n.Tr "repo.visibility_helper_forced" | Safe}}</label>
{{else}} {{else}}
<input name="private" type="checkbox" {{if .private}}checked{{end}}>
<label>{{.i18n.Tr "repo.visibility_helper" | Safe}}</label>
<input name="private" type="checkbox" {{if .private}}checked{{end}}>
<label>{{.i18n.Tr "repo.visibility_helper" | Safe}}</label>
{{end}} {{end}}
</div> </div>
<span class="help">{{.i18n.Tr "repo.visibility_description"}}</span> <span class="help">{{.i18n.Tr "repo.visibility_description"}}</span>
@@ -42,33 +42,41 @@
<div class="inline field"> <div class="inline field">
<label>{{.i18n.Tr "repo.template.items"}}</label> <label>{{.i18n.Tr "repo.template.items"}}</label>
<div class="ui checkbox"> <div class="ui checkbox">
<input class="hidden" name="git_content" type="checkbox" tabindex="0" {{if .git_content}}checked{{end}}>
<input class="hidden" name="git_content" type="checkbox" tabindex="0"
{{if .git_content}}checked{{end}}>
<label>{{.i18n.Tr "repo.template.git_content"}}</label> <label>{{.i18n.Tr "repo.template.git_content"}}</label>
</div> </div>
<div class="ui checkbox" {{if not .SignedUser.CanEditGitHook}}data-tooltip="{{.i18n.Tr "repo.template.git_hooks_tooltip"}}"{{end}}>
<input class="hidden" name="git_hooks" type="checkbox" tabindex="0" {{if .git_hooks}}checked{{end}}>
<div class="ui checkbox"
{{if not .SignedUser.CanEditGitHook}}data-tooltip="{{.i18n.Tr "repo.template.git_hooks_tooltip"}}"
{{end}}>
<input class="hidden" name="git_hooks" type="checkbox" tabindex="0"
{{if .git_hooks}}checked{{end}}>
<label>{{.i18n.Tr "repo.template.git_hooks"}}</label> <label>{{.i18n.Tr "repo.template.git_hooks"}}</label>
</div> </div>
</div> </div>
<div class="inline field"> <div class="inline field">
<label></label> <label></label>
<div class="ui checkbox"> <div class="ui checkbox">
<input class="hidden" name="webhooks" type="checkbox" tabindex="0" {{if .webhooks}}checked{{end}}>
<input class="hidden" name="webhooks" type="checkbox" tabindex="0"
{{if .webhooks}}checked{{end}}>
<label>{{.i18n.Tr "repo.template.webhooks"}}</label> <label>{{.i18n.Tr "repo.template.webhooks"}}</label>
</div> </div>
<div class="ui checkbox"> <div class="ui checkbox">
<input class="hidden" name="topics" type="checkbox" tabindex="0" {{if .topics}}checked{{end}}>
<input class="hidden" name="topics" type="checkbox" tabindex="0"
{{if .topics}}checked{{end}}>
<label>{{.i18n.Tr "repo.template.topics"}}</label> <label>{{.i18n.Tr "repo.template.topics"}}</label>
</div> </div>
</div> </div>
<div class="inline field"> <div class="inline field">
<label></label> <label></label>
<div class="ui checkbox"> <div class="ui checkbox">
<input class="hidden" name="avatar" type="checkbox" tabindex="0" {{if .avatar}}checked{{end}}>
<input class="hidden" name="avatar" type="checkbox" tabindex="0"
{{if .avatar}}checked{{end}}>
<label>{{.i18n.Tr "repo.template.avatar"}}</label> <label>{{.i18n.Tr "repo.template.avatar"}}</label>
</div> </div>
<div class="ui checkbox"> <div class="ui checkbox">
<input class="hidden" name="labels" type="checkbox" tabindex="0" {{if .labels}}checked{{end}}>
<input class="hidden" name="labels" type="checkbox" tabindex="0"
{{if .labels}}checked{{end}}>
<label>{{.i18n.Tr "repo.template.issue_labels"}}</label> <label>{{.i18n.Tr "repo.template.issue_labels"}}</label>
</div> </div>
</div> </div>
@@ -83,7 +91,8 @@
<div class="menu"> <div class="menu">
<div class="item" data-value="">{{.i18n.Tr "repo.issue_labels_helper"}}</div> <div class="item" data-value="">{{.i18n.Tr "repo.issue_labels_helper"}}</div>
{{range $template, $labels := .LabelTemplates}} {{range $template, $labels := .LabelTemplates}}
<div class="item" data-value="{{$template}}">{{$template}}<br/><i>({{$labels}})</i></div>
<div class="item" data-value="{{$template}}">{{$template}}<br /><i>({{$labels}})</i>
</div>
{{end}} {{end}}
</div> </div>
</div> </div>
@@ -98,7 +107,7 @@
<div class="default text">{{.i18n.Tr "repo.repo_gitignore_helper"}}</div> <div class="default text">{{.i18n.Tr "repo.repo_gitignore_helper"}}</div>
<div class="menu"> <div class="menu">
{{range .Gitignores}} {{range .Gitignores}}
<div class="item" data-value="{{.}}">{{.}}</div>
<div class="item" data-value="{{.}}">{{.}}</div>
{{end}} {{end}}
</div> </div>
</div> </div>
@@ -111,7 +120,7 @@
<div class="menu"> <div class="menu">
<div class="item" data-value="">{{.i18n.Tr "repo.license_helper"}}</div> <div class="item" data-value="">{{.i18n.Tr "repo.license_helper"}}</div>
{{range .Licenses}} {{range .Licenses}}
<div class="item" data-value="{{.}}">{{.}}</div>
<div class="item" data-value="{{.}}">{{.}}</div>
{{end}} {{end}}
</div> </div>
</div> </div>
@@ -124,24 +133,35 @@
<div class="default text">{{.i18n.Tr "repo.readme_helper"}}</div> <div class="default text">{{.i18n.Tr "repo.readme_helper"}}</div>
<div class="menu"> <div class="menu">
{{range .Readmes}} {{range .Readmes}}
<div class="item" data-value="{{.}}">{{.}}</div>
<div class="item" data-value="{{.}}">{{.}}</div>
{{end}} {{end}}
</div> </div>
</div> </div>
</div> </div>
<div class="inline field"> <div class="inline field">
<div class="ui checkbox" id="auto-init"> <div class="ui checkbox" id="auto-init">
<input class="hidden" name="auto_init" type="checkbox" tabindex="0" {{if .auto_init}}checked{{end}}>
<input class="hidden" name="auto_init" type="checkbox" tabindex="0"
{{if .auto_init}}checked{{end}}>
<label>{{.i18n.Tr "repo.auto_init"}}</label> <label>{{.i18n.Tr "repo.auto_init"}}</label>
</div> </div>
</div> </div>
<div class="inline field"> <div class="inline field">
<label for="default_branch">{{.i18n.Tr "repo.default_branch"}}</label> <label for="default_branch">{{.i18n.Tr "repo.default_branch"}}</label>
<input id="default_branch" name="default_branch" value="{{.default_branch}}" placeholder="master">
<input id="default_branch" name="default_branch" value="{{.default_branch}}"
placeholder="master">
</div>
<div class="inline field">
<div class="ui checkbox" id="auto-init">
<input class="hidden" name="auto_agree" type="checkbox">
<label
style="width: 76%;text-align: justify;line-height: 1.5;">{{.i18n.Tr "repo.use_repo_agreement"}}
<a target="_blank"
href="/home/term/">{{.i18n.Tr "repo.openi_use_agreement"}}</a></label>
</div>
</div> </div>
</div> </div>


<br/>
<br />
<div class="inline field"> <div class="inline field">
<label></label> <label></label>
<button class="ui green button" id="submit_reponame"> <button class="ui green button" id="submit_reponame">
@@ -154,4 +174,4 @@
</div> </div>
</div> </div>
</div> </div>
{{template "base/footer" .}}
{{template "base/footer" .}}

+ 4
- 4
templates/repo/datasets/index.tmpl View File

@@ -11,7 +11,7 @@


.dataset_title { .dataset_title {
font-size: 14px; font-size: 14px;
max-width: 80%;
/* max-width: 80%; */
display: inline-block !important; display: inline-block !important;
margin-left: 6px !important; margin-left: 6px !important;
padding-right: 0 !important; padding-right: 0 !important;
@@ -279,7 +279,7 @@
<el-tooltip class="item" effect="dark" placement="top" popper-class="diy-popper"> <el-tooltip class="item" effect="dark" placement="top" popper-class="diy-popper">
<div slot="content"><span class="wrap"> <div slot="content"><span class="wrap">


{{if ne .DecompressState 3}}{{$.i18n.Tr "dataset.unzip_status"}}:{{if eq .DecompressState 1}}{{$.i18n.Tr "dataset.unzip_successed"}}{{else if eq .DecompressState 0}}{{$.i18n.Tr "dataset.unzip_stared"}}{{else}}{{$.i18n.Tr "dataset.unzip_failed"}}{{end}}
{{if ne .DecompressState -1}}{{$.i18n.Tr "dataset.unzip_status"}}:{{if eq .DecompressState 1}}{{$.i18n.Tr "dataset.unzip_successed"}}{{else if eq .DecompressState 0 2}}{{$.i18n.Tr "dataset.unzip_stared"}}{{else}}{{$.i18n.Tr "dataset.unzip_failed"}}{{end}}
&nbsp;&nbsp;{{end}}<i &nbsp;&nbsp;{{end}}<i
class="ri-download-line"></i>{{$.i18n.Tr "dataset.download"}}:{{.DownloadCount}} class="ri-download-line"></i>{{$.i18n.Tr "dataset.download"}}:{{.DownloadCount}}
{{if .Description}}&nbsp;&nbsp;{{$.i18n.Tr "dataset.description"}}:{{.Description}}{{end}}</span> {{if .Description}}&nbsp;&nbsp;{{$.i18n.Tr "dataset.description"}}:{{.Description}}{{end}}</span>
@@ -288,10 +288,10 @@
{{if eq .DecompressState 1}} {{if eq .DecompressState 1}}
<i class="ri-folder-open-line" style="color: #5bb973;" <i class="ri-folder-open-line" style="color: #5bb973;"
title='{{$.i18n.Tr "dataset.unzip_successed"}}'></i> title='{{$.i18n.Tr "dataset.unzip_successed"}}'></i>
{{else if eq .DecompressState 0}}
{{else if eq .DecompressState 0 2}}
<i class="ri-folder-chart-2-line" style="color: #888888;" <i class="ri-folder-chart-2-line" style="color: #888888;"
title='{{$.i18n.Tr "dataset.unzip_stared"}}'></i> title='{{$.i18n.Tr "dataset.unzip_stared"}}'></i>
{{else if eq .DecompressState 2}}
{{else if eq .DecompressState 3}}
<i class="ri-folder-forbid-line" style="color: #101010;" <i class="ri-folder-forbid-line" style="color: #101010;"
title='{{$.i18n.Tr "dataset.unzip_failed"}}'></i> title='{{$.i18n.Tr "dataset.unzip_failed"}}'></i>
{{else}} {{else}}


+ 12
- 0
templates/repo/header.tmpl View File

@@ -182,3 +182,15 @@




<script src="{{StaticUrlPrefix}}/js/jquery.js?v={{MD5 AppVer}}"></script> <script src="{{StaticUrlPrefix}}/js/jquery.js?v={{MD5 AppVer}}"></script>
<script src="{{StaticUrlPrefix}}/self/js/notebook/es5-shim.min.js"></script>
<script src="{{StaticUrlPrefix}}/self/js/notebook/marked.min.js"></script>
<script src="{{StaticUrlPrefix}}/self/js/notebook/purify.min.js"></script>
<script src="{{StaticUrlPrefix}}/self/js/notebook/ansi_up.min.js"></script>
<script src="{{StaticUrlPrefix}}/self/js/notebook/prism.min.js"></script>
<script src="{{StaticUrlPrefix}}/self/js/notebook/katex.min.js"></script>
<script src="{{StaticUrlPrefix}}/self/js/notebook/katex-auto-render.min.js"></script>
<script src="{{StaticUrlPrefix}}/self/js/notebook/notebook.min.js"></script>
<script src="{{StaticUrlPrefix}}/self/js/notebook/notebook.min.js"></script>
<link rel="stylesheet" href="{{StaticUrlPrefix}}/self/css/notebook/katex.min.css" />
<link rel="stylesheet" href="{{StaticUrlPrefix}}/self/css/notebook/prism.css" />
<link rel="stylesheet" href="{{StaticUrlPrefix}}/self/css/notebook/notebook.css" />

+ 32
- 1
templates/repo/modelarts/trainjob/show.tmpl View File

@@ -177,6 +177,12 @@
border: 1px solid #dfe1e6; border: 1px solid #dfe1e6;
} }


.ti-download-file {
display: flex;
align-items: center;
margin: 0.5rem 0;
}

.disabled { .disabled {
cursor: default; cursor: default;
pointer-events: none; pointer-events: none;
@@ -220,6 +226,7 @@
<div class="active section">{{.displayJobName}}</div> <div class="active section">{{.displayJobName}}</div>
</div> </div>
</h4> </h4>

{{range $k ,$v := .version_list_task}} {{range $k ,$v := .version_list_task}}
<div class="ui accordion border-according" id="accordion{{.VersionName}}" <div class="ui accordion border-according" id="accordion{{.VersionName}}"
data-repopath="{{$.RepoRelPath}}/modelarts/train-job" data-jobid="{{.JobID}}" data-repopath="{{$.RepoRelPath}}/modelarts/train-job" data-jobid="{{.JobID}}"
@@ -305,6 +312,7 @@
data-tab="first{{$k}}">{{$.i18n.Tr "repo.modelarts.train_job.config"}}</a> data-tab="first{{$k}}">{{$.i18n.Tr "repo.modelarts.train_job.config"}}</a>
<a class="item log_bottom" data-tab="second{{$k}}" <a class="item log_bottom" data-tab="second{{$k}}"
data-version="{{.VersionName}}">{{$.i18n.Tr "repo.modelarts.log"}}</a> data-version="{{.VersionName}}">{{$.i18n.Tr "repo.modelarts.log"}}</a>
<a class="item metric_chart" data-tab="four{{$k}}" data-version="{{.VersionName}}">资源占用情况</a>
<a class="item" data-tab="third{{$k}}" <a class="item" data-tab="third{{$k}}"
onclick="loadModelFile({{.VersionName}},'','','init')">{{$.i18n.Tr "repo.model_download"}}</a> onclick="loadModelFile({{.VersionName}},'','','init')">{{$.i18n.Tr "repo.model_download"}}</a>
</div> </div>
@@ -478,7 +486,17 @@
</div> </div>
</div> </div>
<div class="ui tab" data-tab="second{{$k}}"> <div class="ui tab" data-tab="second{{$k}}">
<div style="position: relative;">
<div>
<a id="{{.VersionName}}-log-down"
class='{{if and (.CanModify) (eq .Status "KILLED" "FAILED" "START_FAILED" "STOPPED" "COMPLETED") }}ti-download-file{{else}}disabled{{end}}'
href="{{$.RepoLink}}/modelarts/train-job/{{.JobID}}/download_log_file?version_name={{.VersionName}}">
<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> <span>
<a title="滚动到顶部" style="position: absolute; right: -32px;cursor: pointer;" <a title="滚动到顶部" style="position: absolute; right: -32px;cursor: pointer;"
class="log_top" data-version="{{.VersionName}}"><i class="icon-to-top"></i></a> class="log_top" data-version="{{.VersionName}}"><i class="icon-to-top"></i></a>
@@ -501,6 +519,13 @@
</div> </div>


</div> </div>
<div class="ui tab" data-tab="four{{$k}}" style="position: relative;">
<i class="ri-refresh-line metric_chart"
style="position: absolute;right: 25%;color:#3291f8;z-index:99;cursor: pointer;"
data-version="{{.VersionName}}"></i>
<div id="metric-{{.VersionName}}" style="height: 260px;width: 870px;">
</div>
</div>
<div class="ui tab" data-tab="third{{$k}}"> <div class="ui tab" data-tab="third{{$k}}">
<input type="hidden" name="model{{.VersionName}}" value="-1"> <input type="hidden" name="model{{.VersionName}}" value="-1">
<input type="hidden" name="modelback{{.VersionName}}" value="-1"> <input type="hidden" name="modelback{{.VersionName}}" value="-1">
@@ -709,6 +734,12 @@
// detail status and duration // detail status and duration
$('#' + version_name + '-duration').text(data.JobDuration) $('#' + version_name + '-duration').text(data.JobDuration)
$('#' + version_name + '-status').text(data.JobStatus) $('#' + version_name + '-status').text(data.JobStatus)
console.log(data)
if (["KILLED", "FAILED", "START_FAILED", "STOPPED", "COMPLETED"].includes(data.JobStatus)) {
$(`#${version_name}-log-down`).removeClass('disabled').addClass('ti-download-file')
$('#' + version_name + '-stop').addClass('disabled')
}

loadLog(version_name) loadLog(version_name)






+ 85
- 8
templates/repo/modelmanage/index.tmpl View File

@@ -130,6 +130,19 @@
<label>模型版本</label> <label>模型版本</label>
<input style="width: 45%;" id="version" name="Version" value="" readonly required maxlength="255"> <input style="width: 45%;" id="version" name="Version" value="" readonly required maxlength="255">
</div> </div>
<div class="unite min_title inline field required">
<label>模型框架</label>
<div class="ui dropdown selection search width70" id="choice_Engine">
<input type="hidden" id="Engine" name="Engine" required>
<div class="default text">选择模型框架</div>
<i class="dropdown icon"></i>
<div class="menu" id="job-Engine">
</div>
</div>
</div>
<div class="inline field"> <div class="inline field">
<label>模型标签</label> <label>模型标签</label>
<input style="width: 83%;margin-left: 7px;" id="label" name="Label" maxlength="255" placeholder='{{.i18n.Tr "repo.modelarts.train_job.label_place"}}'> <input style="width: 83%;margin-left: 7px;" id="label" name="Label" maxlength="255" placeholder='{{.i18n.Tr "repo.modelarts.train_job.label_place"}}'>
@@ -161,7 +174,7 @@
let repoId = {{$repository}} let repoId = {{$repository}}
const {_AppSubUrl, _StaticUrlPrefix, csrf} = window.config; const {_AppSubUrl, _StaticUrlPrefix, csrf} = window.config;
$('input[name="_csrf"]').val(csrf) $('input[name="_csrf"]').val(csrf)
let modelData;
function createModelName(){ function createModelName(){
let repoName = location.pathname.split('/')[2] let repoName = location.pathname.split('/')[2]
let modelName = repoName + '_model_' + Math.random().toString(36).substr(2, 4) let modelName = repoName + '_model_' + Math.random().toString(36).substr(2, 4)
@@ -185,6 +198,7 @@
document.getElementById("formId").reset(); document.getElementById("formId").reset();
$('#choice_model').dropdown('clear') $('#choice_model').dropdown('clear')
$('#choice_version').dropdown('clear') $('#choice_version').dropdown('clear')
$('#choice_Engine').dropdown('clear')
$('.ui.dimmer').css({"background-color":""}) $('.ui.dimmer').css({"background-color":""})
$('.ui.error.message').text() $('.ui.error.message').text()
$('.ui.error.message').css('display','none') $('.ui.error.message').css('display','none')
@@ -197,10 +211,24 @@
$(function(){ $(function(){
$('#choice_model').dropdown({ $('#choice_model').dropdown({
onChange:function(value){ onChange:function(value){
$(".ui.dropdown.selection.search.width70").addClass("loading")
$('#choice_version').dropdown('clear')
$("#job-version").empty()
loadTrainVersion(value)
$(".ui.dropdown.selection.search.width70").addClass("loading")
$('#choice_version').dropdown('clear')
$("#job-version").empty()
loadTrainVersion(value)
}
})

$('#choice_version').dropdown({
onChange:function(value){
console.log("model version:" + value);
if(modelData != null){
for(var i=0; i < modelData.length;i++){
if(modelData[i].VersionName == value){
setEngine(modelData[i])
break;
}
}
}
} }
}) })
}) })
@@ -240,7 +268,8 @@
let JobID = !value ?$('#choice_model input[name="JobId"]').val(): value let JobID = !value ?$('#choice_model input[name="JobId"]').val(): value
$.get(`${repolink}/modelmanage/query_train_job_version?JobID=${JobID}`, (data) => { $.get(`${repolink}/modelmanage/query_train_job_version?JobID=${JobID}`, (data) => {
const n_length = data.length const n_length = data.length
let train_html=''
let train_html='';
modelData = data;
for (let i=0;i<n_length;i++){ for (let i=0;i<n_length;i++){
train_html += `<div class="item" data-value="${data[i].VersionName}">${data[i].VersionName}</div>` train_html += `<div class="item" data-value="${data[i].VersionName}">${data[i].VersionName}</div>`
train_html += '</div>' train_html += '</div>'
@@ -248,11 +277,59 @@
if(data.length){ if(data.length){
$("#job-version").append(train_html) $("#job-version").append(train_html)
$(".ui.dropdown.selection.search.width70").removeClass("loading") $(".ui.dropdown.selection.search.width70").removeClass("loading")
$('#choice_version .default.text').text(data[0].VersionName)
$('#choice_version input[name="VersionName"]').val(data[0].VersionName)
var versionName = data[0].VersionName;
if(versionName==null || versionName==""){
versionName="V0001";
}
$('#choice_version .default.text').text(versionName)
$('#choice_version input[name="VersionName"]').val(versionName)
console.log("1111111111");
setEngine(data[0])
} }


}) })
} }

function setEngine(modelVersion){
console.log("modelVersion=" + modelVersion);
$('#choice_Engine').dropdown('clear')
$("#job-Engine").empty()
if(modelVersion.EngineName != null && modelVersion.EngineName != ""){
srcEngine = modelVersion.EngineName.split('-')[0]
srcEngine = srcEngine.trim();
let selectedText = "Pytorch";
let selectedValue = 0;
let itemHtml = "<option class=\"item\" data-value=\"0\">Pytorch</option>";
if(srcEngine =='TensorFlow'){
selectedText ="TensorFlow";
selectedValue = 1;
itemHtml += "<option class=\"active item\" data-value=\"1\">TensorFlow</option>";
}else{
itemHtml += "<option class=\"item\" data-value=\"1\">TensorFlow</option>";
}
if(srcEngine =='MindSpore'){
selectedText ="MindSpore";
selectedValue = 2;
itemHtml += "<option class=\"active item\" data-value=\"2\">MindSpore</option>";
}else{
itemHtml += "<option class=\"item\" data-value=\"2\">MindSpore</option>";
}
itemHtml += "<option class=\"item\" data-value=\"3\">Other</option>"
$('#choice_Engine .default.text').text(selectedText)
$('#choice_Engine input[name="Engine"]').val(selectedValue)
$("#job-Engine").append(itemHtml);
$("#choice_Engine").addClass('disabled')
}else{
let itemHtml = "<option class=\"active item\" data-value=\"0\">Pytorch</option>";
itemHtml += "<option class=\"item\" data-value=\"1\">TensorFlow</option>"
itemHtml += "<option class=\"item\" data-value=\"2\">MindSpore</option>"
itemHtml += "<option class=\"item\" data-value=\"3\">Other</option>"
$('#choice_Engine .default.text').text("Pytorch");
$('#choice_Engine input[name="Engine"]').val(0)
$("#job-Engine").append(itemHtml);
$("#choice_Engine").removeClass('disabled');
}
}
</script> </script>



+ 14
- 0
templates/repo/view_file.tmpl View File

@@ -108,6 +108,8 @@
<tr> <tr>
{{if .IsFileTooLarge}} {{if .IsFileTooLarge}}
<td><strong>{{.i18n.Tr "repo.file_too_large"}}</strong></td> <td><strong>{{.i18n.Tr "repo.file_too_large"}}</strong></td>
{{else if .IsNoteBook}}
<td id="notebook"></td>
{{else}} {{else}}
<td class="lines-num">{{.LineNums}}</td> <td class="lines-num">{{.LineNums}}</td>
<td class="lines-code"><pre><code class="{{.HighlightClass}}"><ol class="linenums">{{.FileContent}}</ol></code></pre></td> <td class="lines-code"><pre><code class="{{.HighlightClass}}"><ol class="linenums">{{.FileContent}}</ol></code></pre></td>
@@ -128,4 +130,16 @@ function submitDeleteForm() {
$("#delete-file-form").submit() $("#delete-file-form").submit()
} }
} }
function showNoteBook(){
var isNoteBook = {{.IsNoteBook}}
if (isNoteBook) {
var jsonStr = "{{.FileContent}}"
var notebook = nb.parse(JSON.parse(jsonStr));
var rendered = notebook.render();
$("#notebook").append(rendered);
Prism.highlightAll();
}
}
showNoteBook()

</script> </script>

+ 4
- 11
templates/user/dashboard/dashboard.tmpl View File

@@ -10,9 +10,9 @@
{{.i18n.Tr "home.wecome_AI_plt"}} {{.i18n.Tr "home.wecome_AI_plt"}}
</div> </div>
<div class="content"> <div class="content">
<p >{{.i18n.Tr "home.explore_AI"}} <a href="{{AppSubUrl}}/explore/repos"> {{.i18n.Tr "home.repositories"}}</a> {{.i18n.Tr "home.or_t"}} <a href="{{AppSubUrl}}/explore/datasets">{{.i18n.Tr "home.datasets"}}</a></p>
<p >{{.i18n.Tr "home.use_plt__fuction"}}&nbsp;<a class="mini ui blue button" href="{{AppSubUrl}}/repo/create{{if .ContextUser.IsOrganization}}?org={{.ContextUser.ID}}{{end}}" >{{.i18n.Tr "repo.create_repo"}}</a></p>
<p > {{.i18n.Tr "home.provide_resoure"}}</p>
<p class="ui text grey">{{.i18n.Tr "home.explore_AI"}} <a href="{{AppSubUrl}}/explore/repos"> {{.i18n.Tr "home.repositories"}}</a> {{.i18n.Tr "home.or_t"}} <a href="{{AppSubUrl}}/explore/datasets">{{.i18n.Tr "home.datasets"}}</a></p>
<p><span class="ui text grey">{{.i18n.Tr "home.use_plt__fuction"}}</span>&nbsp;<a class="mini ui blue button" href="{{AppSubUrl}}/repo/create{{if .ContextUser.IsOrganization}}?org={{.ContextUser.ID}}{{end}}" >{{.i18n.Tr "repo.create_repo"}}</a></p>
<p class="ui text grey">{{.i18n.Tr "home.provide_resoure"}}</p>
</div> </div>
<div class="guide "> <div class="guide ">
<a class="mini ui blue basic button" style="font-weight:700" href="https://git.openi.org.cn/zeizei/OpenI_Learning" target="_blank">{{.i18n.Tr "custom.Platform_Tutorial"}} <i class="ri-arrow-right-line" ></i></a> <a class="mini ui blue basic button" style="font-weight:700" href="https://git.openi.org.cn/zeizei/OpenI_Learning" target="_blank">{{.i18n.Tr "custom.Platform_Tutorial"}} <i class="ri-arrow-right-line" ></i></a>
@@ -66,19 +66,12 @@
} }
.w_title{ .w_title{
padding-top: 25px; padding-top: 25px;
margin-bottom: 20px;
color: rgba(16, 16, 16, 100); color: rgba(16, 16, 16, 100);
font-size: 20px; font-size: 20px;
text-align: left; text-align: left;
font-weight: 700; font-weight: 700;
} }
.content{
color: rgba(80, 85, 89, 100);
font-size: 14px;
text-align: left;
font-family: SourceHanSansSC-regular;
margin-top: 20px;
}

.guide{ .guide{
margin-top:30px; margin-top:30px;
padding-bottom: 30px; padding-bottom: 30px;


+ 1
- 1
templates/user/dashboard/feeds.tmpl View File

@@ -6,7 +6,7 @@
<div class="ui grid"> <div class="ui grid">
<div class="ui fourteen wide column"> <div class="ui fourteen wide column">
<div class="{{if or (eq .GetOpType 5) (eq .GetOpType 18)}}push news{{end}}"> <div class="{{if or (eq .GetOpType 5) (eq .GetOpType 18)}}push news{{end}}">
<p>
<p class="text truncate">
{{if gt .ActUser.ID 0}} {{if gt .ActUser.ID 0}}
<a href="{{AppSubUrl}}/{{.GetActUserName}}" title="{{.GetDisplayNameTitle}}">{{.GetDisplayName}}</a> <a href="{{AppSubUrl}}/{{.GetActUserName}}" title="{{.GetDisplayNameTitle}}">{{.GetDisplayName}}</a>
{{else}} {{else}}


+ 15
- 2
web_src/js/components/Model.vue View File

@@ -168,7 +168,7 @@ export default {
tableData= res.data tableData= res.data
for(let i=0;i<tableData.length;i++){ for(let i=0;i<tableData.length;i++){
TrainTaskInfo = JSON.parse(tableData[i].TrainTaskInfo) TrainTaskInfo = JSON.parse(tableData[i].TrainTaskInfo)
tableData[i].EngineName = TrainTaskInfo.EngineName.split('-')[0]
tableData[i].EngineName = this.getEngineName(tableData[i])
tableData[i].ComputeResource = TrainTaskInfo.ComputeResource tableData[i].ComputeResource = TrainTaskInfo.ComputeResource
tableData[i].cName=tableData[i].Name tableData[i].cName=tableData[i].Name
tableData[i].Name='' tableData[i].Name=''
@@ -218,6 +218,7 @@ export default {
$('input[name="Name"]').removeAttr('readonly') $('input[name="Name"]').removeAttr('readonly')
$('#choice_model').dropdown('clear') $('#choice_model').dropdown('clear')
$('#choice_version').dropdown('clear') $('#choice_version').dropdown('clear')
$('#choice_Engine').dropdown('clear')
$('.ui.dimmer').css({"background-color":""}) $('.ui.dimmer').css({"background-color":""})
$('.ui.error.message').text() $('.ui.error.message').text()
$('.ui.error.message').css('display','none') $('.ui.error.message').css('display','none')
@@ -347,6 +348,18 @@ export default {
}) })
.modal('show') .modal('show')
}, },
getEngineName(model){
if(model.Engine == 0){
return "Pytorch";
}else if(model.Engine == 1 || model.Engine == 121){
return "TensorFlow";
}else if(model.Engine == 2 || model.Engine == 122){
return "MindSpore";
}else{
return "Other"
}

},
getModelList(){ getModelList(){
try { try {
this.$refs.table.store.states.lazyTreeNodeMap = {} this.$refs.table.store.states.lazyTreeNodeMap = {}
@@ -360,7 +373,7 @@ export default {
for(let i=0;i<this.tableData.length;i++){ for(let i=0;i<this.tableData.length;i++){
TrainTaskInfo = JSON.parse(this.tableData[i].TrainTaskInfo) TrainTaskInfo = JSON.parse(this.tableData[i].TrainTaskInfo)
this.tableData[i].cName=this.tableData[i].Name this.tableData[i].cName=this.tableData[i].Name
this.tableData[i].EngineName = TrainTaskInfo.EngineName.split('-')[0]
this.tableData[i].EngineName = this.getEngineName(this.tableData[i])
this.tableData[i].ComputeResource = TrainTaskInfo.ComputeResource this.tableData[i].ComputeResource = TrainTaskInfo.ComputeResource
this.tableData[i].hasChildren = res.data.data[i].VersionCount===1 ? false : true this.tableData[i].hasChildren = res.data.data[i].VersionCount===1 ? false : true
} }


+ 106
- 3
web_src/js/index.js View File

@@ -1214,7 +1214,7 @@ async function initRepository() {
files: $attachments files: $attachments
}, },
(data) => { (data) => {
if (data.length === 0) {
if (data.length === 0 || data.content === '') {
$renderContent.html($('#no-content').html()); $renderContent.html($('#no-content').html());
} else { } else {
$renderContent.html(data.content); $renderContent.html(data.content);
@@ -1222,10 +1222,18 @@ async function initRepository() {
highlight(this); highlight(this);
}); });
} }
let imageShow = ''
const $content = $segment.parent(); const $content = $segment.parent();
if (!$content.find('.ui.small.images').length) { if (!$content.find('.ui.small.images').length) {
if (data.attachments !== '') {

if (data.attachments !== '' && data.attachments) {
if ($content.find('.ui.middle.aligned').length === 0) {
imageShow += '<div class="ui clearing divider"></div>'
imageShow += '<div class="ui middle aligned padded grid">'
imageShow += data.attachments
imageShow += '</div>'
$content.find('.ui.attached.segment').append(imageShow)
}
else { $content.find('.ui.middle.aligned').html(data.attachments) }
} }
} else if (data.attachments === '') { } else if (data.attachments === '') {
$content $content
@@ -5070,3 +5078,98 @@ function initcreateRepo() {
} }


initcreateRepo() initcreateRepo()


function initChartsNpu() {
const url = window.location.href
const urlArr = url.split('/')
let userName = urlArr.slice(-5)[0]
let repoPath = urlArr.slice(-4)[0]
let jobID = urlArr.slice(-1)[0]


let options = {
legend: {
data: []
},
grid: {
top: '30%',
bottom: '2%',
containLabel: true
},
tooltip: {
trigger: 'axis',
backgroundColor: 'rgb(51, 56, 84)',
borderColor: 'rgb(51, 51, 51)',
borderWidth: 0,
textStyle: {
color: '#fff'
},
axisPointer: {
type: 'line'
}
},
xAxis: {
type: 'category',
data: [],
boundaryGap: false,
axisLabel: {
interval: 'auto'
},
name: '时间(min)'
},
yAxis: {

show: true,
name: '占有率(%)',
axisLine: {
show: true
},
axisTick: { show: true }
},

series: []
};
$('.metric_chart').click(function (e) {
let versionName = $(this).data('version')
let myCharts = echarts.init(document.getElementById(`metric-${versionName}`))
$.get(`${window.config.AppSubUrl}/api/v1/repos/${userName}/${repoPath}/modelarts/train-job/${jobID}/metric_statistics?version_name=${versionName}&statistic_type=each`, (res) => {
let filterDta = res.MetricsInfo.filter((item) => {

return !(['recvBytesRate', 'diskWriteRate', 'sendBytesRate', 'diskReadRate'].includes(item.metric))
})
let legenData = filterDta.map((item) => {
return item.metric
})
let seriesData = filterDta.map((item) => {
let value = item.value.map((item) => { return item > 0 ? item : '0' })
let seriesOption = {
name: item.metric,
type: 'line',
symbol: 'circle',
symbolSize: 10,
smooth: true,
showSymbol: false,
lineStyle: {
width: 2,
shadowColor: 'rgba(0,0,0,0.3)',
shadowBlur: 10,
shadowOffsetY: 8
},
data: value
}
return seriesOption
})
let xLength = res.MetricsInfo[0].value.length
options.xAxis.data = Array.from({ length: xLength }, (_, index) => index)
options.legend.data = legenData
options.series = seriesData
options && myCharts.setOption(options);

})
options && myCharts.setOption(options);

})
}

initChartsNpu()

+ 4
- 0
web_src/less/_dashboard.less View File

@@ -82,6 +82,10 @@


line-height: 1.2; line-height: 1.2;


p {
max-width: 100%;
}
> .ui.grid { > .ui.grid {
margin-left: auto; margin-left: auto;
margin-right: auto; margin-right: auto;


Loading…
Cancel
Save