@@ -71,6 +71,19 @@ | |||
.ui.secondary.hometop.segment #navbar{ | |||
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{ | |||
color: #000; | |||
@@ -134,8 +147,13 @@ | |||
.i-code-pic > img{ | |||
margin-bottom: -3.0rem; | |||
} | |||
.i-env .ui.cards>.card{ | |||
box-shadow:none; | |||
} | |||
.i-env .ui.cards>.card>.image{ | |||
background: none; | |||
width: 60%; | |||
margin: auto; | |||
} | |||
.i-env .ui.cards>.card>.content{ | |||
border-top: none; | |||
@@ -168,7 +186,7 @@ | |||
bottom: 0; | |||
background-color: rgba(105, 192, 255, .4); | |||
width: 2px; | |||
} | |||
} | |||
.homenews .time-since{ | |||
padding-left: 1em; | |||
color: #888888; | |||
@@ -185,7 +203,7 @@ | |||
padding: 0; | |||
} | |||
.newslist{ | |||
height: 325px; | |||
height: 300px; | |||
overflow: hidden; | |||
} | |||
@@ -208,14 +226,25 @@ | |||
height: auto; | |||
border-top: 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; | |||
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{ | |||
border-radius: 4.0em 0 0 0; | |||
border-top: 2px solid #3291F8; | |||
border-top: 2px solid #3291F8; | |||
border-bottom:none; | |||
top: -2.0em; | |||
} | |||
@@ -224,6 +253,9 @@ | |||
width: 7em; | |||
z-index: 5; | |||
} | |||
.leftline02-2::after{ | |||
border-color: rgba(105, 192, 255, .4); | |||
} | |||
.leftline04{ | |||
border-radius: 0; | |||
border-top: none; | |||
@@ -280,6 +312,9 @@ | |||
.i-env > div{ | |||
position: relative; | |||
} | |||
.event-list .ui.card>.image>img{ | |||
height: 146px !important; | |||
} | |||
@media only screen and (max-width: 767px) { | |||
.am-mt-30{ margin-top: 1.5rem !important;} | |||
@@ -376,4 +411,40 @@ | |||
@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);} | |||
} |
@@ -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; } |
@@ -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); | |||
} | |||
} |
@@ -1150,6 +1150,17 @@ type LogFile struct { | |||
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) { | |||
sess := x.NewSession() | |||
defer sess.Close() | |||
@@ -1280,7 +1291,8 @@ func QueryModelTrainJobVersionList(jobId string) ([]*CloudbrainInfo, int, error) | |||
builder.Eq{"cloudbrain.job_id": jobId}, | |||
) | |||
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") | |||
@@ -1301,7 +1313,7 @@ func QueryModelTrainJobList(repoId int64) ([]*CloudbrainInfo, int, error) { | |||
builder.Eq{"repo_id": repoId}, | |||
) | |||
cond = cond.And( | |||
builder.Eq{"Status": "COMPLETED"}, | |||
builder.In("Status", "COMPLETED", "SUCCEEDED"), | |||
) | |||
cond = cond.And( | |||
builder.Eq{"job_type": "TRAIN"}, | |||
@@ -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 | |||
} |
@@ -719,12 +719,11 @@ func refreshUserStaticTable(wikiCountMap map[string]int, tableName string, pageS | |||
userIndexMap := make(map[int64]float64, 0) | |||
maxUserIndex := 0.0 | |||
minUserIndex := 100000000.0 | |||
dateRecordBatch := make([]UserBusinessAnalysisAll, 0) | |||
for { | |||
sess.Select("`user`.*").Table("user").Where(cond).OrderBy("id asc").Limit(PAGE_SIZE, int(indexTotal)) | |||
userList := make([]*User, 0) | |||
sess.Find(&userList) | |||
dateRecordBatch := make([]UserBusinessAnalysisAll, 0) | |||
for _, userRecord := range userList { | |||
var dateRecordAll UserBusinessAnalysisAll | |||
dateRecordAll.ID = userRecord.ID | |||
@@ -789,7 +788,7 @@ func refreshUserStaticTable(wikiCountMap map[string]int, tableName string, pageS | |||
dateRecordBatch = append(dateRecordBatch, dateRecordAll) | |||
if len(dateRecordBatch) >= BATCH_INSERT_SIZE { | |||
insertTable(dateRecordBatch, tableName, statictisSess) | |||
err := insertTable(dateRecordBatch, tableName, statictisSess) | |||
insertCount += BATCH_INSERT_SIZE | |||
if err != nil { | |||
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 | |||
if indexTotal >= count { | |||
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" { | |||
log.Info("TotalHasActivityUser=" + fmt.Sprint(userMetrics["TotalHasActivityUser"])) | |||
} | |||
@@ -835,7 +835,7 @@ func updateUserIndex(tableName string, statictisSess *xorm.Session, userId int64 | |||
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 + | |||
"(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) { | |||
@@ -2057,7 +2058,9 @@ func queryCloudBrainTask(start_unix int64, end_unix int64) (map[int64]int, map[s | |||
} else { | |||
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.JobType == "TRAIN" { | |||
setMapKey("NpuTrainJob", cloudTaskRecord.UserID, 1, resultItemMap) | |||
@@ -46,6 +46,7 @@ type CreateRepoForm struct { | |||
Webhooks bool | |||
Avatar bool | |||
Labels bool | |||
AutoAgree bool | |||
} | |||
// Validate validates the fields | |||
@@ -1119,3 +1119,44 @@ sendjob: | |||
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 | |||
} |
@@ -39,6 +39,14 @@ func (l *LocalStorage) Open(path string) (io.ReadCloser, error) { | |||
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 | |||
func (l *LocalStorage) Save(path string, r io.Reader) (int64, error) { | |||
p := filepath.Join(l.dir, path) | |||
@@ -59,6 +59,16 @@ func (m *MinioStorage) buildMinioPath(p string) string { | |||
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 | |||
func (m *MinioStorage) Open(path string) (io.ReadCloser, error) { | |||
var opts = minio.GetObjectOptions{} | |||
@@ -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)), "/") | |||
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) { | |||
@@ -564,3 +564,17 @@ func ObsCreateObject(path string) error { | |||
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 | |||
} |
@@ -22,6 +22,7 @@ const ( | |||
type ObjectStorage interface { | |||
Save(path string, r io.Reader) (int64, error) | |||
Open(path string) (io.ReadCloser, error) | |||
DownloadAFile(bucket string, objectName string) (io.ReadCloser, error) | |||
Delete(path string) error | |||
DeleteDir(dir string) error | |||
PresignedGetURL(path string, fileName string) (string, error) | |||
@@ -1145,6 +1145,7 @@ modelarts.infer_job.model_version = Model/Version | |||
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.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 | |||
@@ -1183,6 +1184,7 @@ template.topics = Topics | |||
template.avatar = Avatar | |||
template.issue_labels = Issue Labels | |||
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.repo_adress=Adress | |||
template.repo_path=path | |||
@@ -1450,6 +1452,7 @@ issues.filter_sort.feweststars = Fewest stars | |||
issues.filter_sort.mostforks = Most forks | |||
issues.filter_sort.fewestforks = Fewest forks | |||
issues.filter_sort.downloadtimes = Most downloaded | |||
issues.filter_sort.citations=Citations | |||
issues.filter_sort.mostusecount = Most Quote | |||
issues.filter_sort.fewestusecount=Fewest Quote | |||
issues.action_open = Open | |||
@@ -2257,7 +2260,8 @@ topic.done = Done | |||
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. | |||
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_name_holder = Organization Name | |||
org_full_name_holder = Organization Full Name | |||
@@ -226,7 +226,7 @@ contributors=贡献者 | |||
contributor=贡献者 | |||
page_title=探索更好的AI | |||
page_small_title=启智AI开发协作平台 | |||
page_small_title=启智AI协作平台 | |||
page_description=面向AI领域的一站式协同开发环境,提供集代码开发、数据管理、模型调试、推理和评测为一体的AI开发流水线 | |||
page_use=立即使用 | |||
page_only_dynamic=仅展示开源项目动态 | |||
@@ -1155,6 +1155,7 @@ modelarts.infer_job.model_version = 模型/版本 | |||
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.tooltip = 该模型已删除,无法查看。 | |||
modelarts.download_log=下载日志文件 | |||
debug_task_not_created = 未创建过调试任务 | |||
@@ -1193,6 +1194,7 @@ template.topics=主题 | |||
template.avatar=头像 | |||
template.issue_labels=任务标签 | |||
template.one_item=必须至少选择一个模板项 | |||
template.one_promise=创建项目时需承诺遵守使用协议 | |||
template.invalid=必须选择一个模板项目 | |||
template.repo_adress=项目地址 | |||
template.repo_path=项目地址 | |||
@@ -1460,9 +1462,11 @@ issues.filter_sort.feweststars=点赞由少到多 | |||
issues.filter_sort.mostforks=派生由多到少 | |||
issues.filter_sort.fewestforks=派生由少到多 | |||
issues.filter_sort.downloadtimes=下载次数 | |||
issues.filter_sort.citations=引用次数 | |||
issues.filter_sort.moststars=收藏数量 | |||
issues.filter_sort.mostusecount=最多引用 | |||
issues.filter_sort.fewestusecount=最少引用 | |||
issues.action_open=开启 | |||
issues.action_close=关闭 | |||
issues.action_label=标签 | |||
@@ -2267,7 +2271,8 @@ topic.done=保存 | |||
topic.count_prompt=您最多选择25个标签 | |||
topic.format_prompt=标签必须以中文、字母或数字开头,可以包含连字符 (-),并且长度不得超过35个字符 | |||
imagetopic.format_prompt=标签长度不得超过35个字符 | |||
use_repo_agreement=我承诺此仓内容不违反任何国家法律法规,仓库使用过程中遵守OpenI启智社区管理规定和平台使用规则,不进行恶意攻击、挖矿等任何违法或扰乱平台秩序的信息发布和相关行为。更多信息请参考 | |||
openi_use_agreement=OpenI启智社区平台使用协议 | |||
[org] | |||
org_name_holder=组织名称 | |||
org_full_name_holder=组织全名 | |||
@@ -9,7 +9,7 @@ if(isEmpty(token)){ | |||
var swiperNewMessage = new Swiper(".newslist", { | |||
direction: "vertical", | |||
slidesPerView: 10, | |||
slidesPerView: 9, | |||
loop: true, | |||
autoplay: { | |||
delay: 2500, | |||
@@ -17,7 +17,7 @@ var swiperNewMessage = new Swiper(".newslist", { | |||
}, | |||
}); | |||
var swiperEvent = new Swiper(".event-list", { | |||
slidesPerView: 2, | |||
slidesPerView: 3, | |||
spaceBetween: 30, | |||
pagination: { | |||
el: ".swiper-pagination", | |||
@@ -117,6 +117,7 @@ socket.onmessage = function (e) { | |||
continue; | |||
} | |||
} | |||
refresh3DInfo(record); | |||
var recordPrefix = getMsg(record); | |||
if(record.OpType == "6" || record.OpType == "10" || record.OpType == "12" || record.OpType == "13"){ | |||
html += recordPrefix + actionName; | |||
@@ -200,6 +201,29 @@ function getTaskLink(record){ | |||
return re; | |||
} | |||
function refresh3DInfo(record){ | |||
if(record.OpType == "25" || record.OpType == "29" || record.OpType == "31"){ | |||
//cloudbrain one | |||
var lines = $('.rotation3D__line'); | |||
var span = $('.rotation3D__line').find("span")[0]; | |||
//console.log(span); | |||
span.innerText =record.RefName; | |||
//$('.rotation3D__line').find("span").eq(0).text(record.RefName) | |||
//console.log("cloudbrain one line length=" + lines.length); | |||
//lines[0].find("span").text(record.RefName); | |||
}else if(record.OpType == "26" || record.OpType == "27" || record.OpType == "28"){ | |||
//cloudbrain two | |||
var lines = $('.rotation3D__line'); | |||
//console.log("cloudbrain two line length=" + lines.length); | |||
var span = $('.rotation3D__line').find("span")[1]; | |||
//console.log(span); | |||
span.innerText =record.RefName; | |||
//$('.rotation3D__line').find("span").eq(1).text(record.RefName) | |||
//lines[1].find("span").text(record.RefName); | |||
} | |||
} | |||
function getMsg(record){ | |||
var html =""; | |||
html += "<div class=\"swiper-slide item\">"; | |||
@@ -425,13 +449,50 @@ function queryRecommendData(){ | |||
dataType:"json", | |||
async:false, | |||
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) { | |||
} | |||
}); | |||
// $.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){ | |||
@@ -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; | |||
} | |||
@@ -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; | |||
} |
@@ -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"&";if(a=="<")return"<";if(a==">")return">"})},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); |
@@ -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}); |
@@ -573,6 +573,9 @@ func RegisterRoutes(m *macaron.Macaron) { | |||
//cloudbrain board | |||
m.Group("/cloudbrainboard", func() { | |||
m.Get("/downloadAll", repo.DownloadCloudBrainBoard) | |||
m.Group("/cloudbrain", func() { | |||
m.Get("/status_analysis", repo.GetCloudbrainsStatusAnalysis) | |||
}) | |||
}, operationReq) | |||
// Users | |||
m.Group("/users", func() { | |||
@@ -922,6 +925,7 @@ func RegisterRoutes(m *macaron.Macaron) { | |||
m.Post("/del_version", repo.DelTrainJobVersion) | |||
m.Post("/stop_version", repo.StopTrainJobVersion) | |||
m.Get("/model_list", repo.ModelList) | |||
m.Get("/metric_statistics", repo.TrainJobGetMetricStatistic) | |||
}) | |||
}) | |||
m.Group("/inference-job", func() { | |||
@@ -11,6 +11,16 @@ import ( | |||
"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) { | |||
page := 1 | |||
@@ -133,3 +143,9 @@ func getBrainWaitTime(rs *models.CloudbrainInfo) string { | |||
return models.ConvertDurationToStr(int64(waitTime)) | |||
} | |||
} | |||
func GetCloudbrainsStatusAnalysis(ctx *context.Context) { | |||
cloudBrainStatusResult := models.GetAllStatusCloudBrain() | |||
ctx.JSON(http.StatusOK, map[string]interface{}{ | |||
"cloudBrainStatusResult": cloudBrainStatusResult, | |||
}) | |||
} |
@@ -462,3 +462,46 @@ func ResultList(ctx *context.APIContext) { | |||
"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 | |||
} |
@@ -7,6 +7,7 @@ package routers | |||
import ( | |||
"bytes" | |||
"fmt" | |||
"net/http" | |||
"strconv" | |||
"strings" | |||
@@ -750,6 +751,15 @@ func GetRankUser(index string) ([]map[string]interface{}, error) { | |||
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) { | |||
index := ctx.Params("index") | |||
resultUserRank, err := GetRankUser(index) | |||
@@ -773,13 +783,36 @@ func RecommendHomeInfo(ctx *context.Context) { | |||
if err != nil { | |||
log.Info("error." + err.Error()) | |||
} | |||
resultCloudBrain, err := getCloudbrainNums() | |||
if err != nil { | |||
log.Info("error." + err.Error()) | |||
} | |||
mapInterface := make(map[string]interface{}) | |||
mapInterface["org"] = resultOrg | |||
mapInterface["repo"] = resultRepo | |||
mapInterface["image"] = resultImage | |||
mapInterface["cloudbrain"] = resultCloudBrain | |||
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) { | |||
result, err := repository.GetRecommendRepoFromPromote("projects") | |||
if err != nil { | |||
@@ -6,6 +6,7 @@ import ( | |||
"errors" | |||
"fmt" | |||
"net/http" | |||
"net/url" | |||
"path" | |||
"strings" | |||
@@ -27,19 +28,22 @@ const ( | |||
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) | |||
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() | |||
id := uuid.String() | |||
modelPath := id | |||
var lastNewModelId string | |||
var modelSize int64 | |||
cloudType := models.TypeCloudBrainTwo | |||
log.Info("find task name:" + aiTask.JobName) | |||
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 | |||
if cloudType == models.TypeCloudBrainTwo { | |||
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()) | |||
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["F1"] = "" | |||
@@ -131,7 +141,7 @@ func SaveNewNameModel(ctx *context.Context) { | |||
return | |||
} | |||
SaveModel(ctx) | |||
ctx.Status(200) | |||
log.Info("save model end.") | |||
} | |||
@@ -143,8 +153,9 @@ func SaveModel(ctx *context.Context) { | |||
version := ctx.Query("Version") | |||
label := ctx.Query("Label") | |||
description := ctx.Query("Description") | |||
engine := ctx.QueryInt("Engine") | |||
trainTaskCreate := ctx.QueryBool("trainTaskCreate") | |||
log.Info("engine=" + fmt.Sprint(engine)) | |||
if !trainTaskCreate { | |||
if !ctx.Repo.CanWrite(models.UnitTypeModelManage) { | |||
//ctx.NotFound(ctx.Req.URL.RequestURI(), nil) | |||
@@ -163,14 +174,14 @@ func SaveModel(ctx *context.Context) { | |||
return | |||
} | |||
err := saveModelByParameters(JobId, VersionName, name, version, label, description, ctx) | |||
err := saveModelByParameters(JobId, VersionName, name, version, label, description, engine, ctx) | |||
if err != nil { | |||
log.Info("save model error." + err.Error()) | |||
ctx.Error(500, fmt.Sprintf("save model error. %v", err)) | |||
return | |||
} | |||
ctx.Status(200) | |||
log.Info("save model end.") | |||
} | |||
@@ -199,6 +210,22 @@ func downloadModelFromCloudBrainTwo(modelUUID string, jobName string, parentDir | |||
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) { | |||
log.Info("delete model start.") | |||
id := ctx.Query("ID") | |||
@@ -277,51 +304,117 @@ func DownloadMultiModelFile(ctx *context.Context) { | |||
} | |||
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 { | |||
//count++ | |||
models.ModifyModelDownloadCount(id) | |||
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 { | |||
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 { | |||
log.Info("error,msg=" + err.Error()) | |||
ctx.ServerError("no file to download.", err) | |||
@@ -374,42 +467,55 @@ func DownloadSingleModelFile(ctx *context.Context) { | |||
ctx.NotFound(ctx.Req.URL.RequestURI(), nil) | |||
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 { | |||
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++ | |||
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 { | |||
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 | |||
} | |||
//count++ | |||
models.ModifyModelDownloadCount(id) | |||
http.Redirect(ctx.Resp, ctx.Req.Request, url, http.StatusMovedPermanently) | |||
} | |||
} | |||
func ShowModelInfo(ctx *context.Context) { | |||
@@ -684,14 +790,22 @@ func QueryModelListForPredict(ctx *context.Context) { | |||
func QueryModelFileForPredict(ctx *context.Context) { | |||
id := ctx.Query("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()) | |||
ctx.ServerError("no such model:", err) | |||
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) { | |||
@@ -703,7 +817,16 @@ func QueryOneLevelModelFile(ctx *context.Context) { | |||
ctx.ServerError("no such model:", err) | |||
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) | |||
} | |||
} |
@@ -173,7 +173,7 @@ func DatasetIndex(ctx *context.Context) { | |||
uploader, _ := models.GetUserByID(attachment.UploaderID) | |||
attachment.Uploader = uploader | |||
if !strings.HasSuffix(attachment.Name, ".zip") { | |||
attachment.DecompressState = 3 //非zip文件 | |||
attachment.DecompressState = -1 //非zip文件 | |||
} | |||
} | |||
@@ -2251,7 +2251,6 @@ func ModelDownload(ctx *context.Context) { | |||
versionName := ctx.Query("version_name") | |||
parentDir := ctx.Query("parent_dir") | |||
fileName := ctx.Query("file_name") | |||
log.Info("DownloadSingleModelFile start.") | |||
task, err := models.GetCloudbrainByJobIDAndVersionName(jobID, versionName) | |||
if err != nil { | |||
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), "/") | |||
log.Info("Download path is:%s", path) | |||
url, err := storage.GetObsCreateSignedUrlByBucketAndKey(setting.Bucket, path) | |||
if err != nil { | |||
@@ -2267,6 +2265,7 @@ func ModelDownload(ctx *context.Context) { | |||
ctx.ServerError("GetObsCreateSignedUrl", err) | |||
return | |||
} | |||
ctx.Resp.Header().Set("Cache-Control", "max-age=0") | |||
http.Redirect(ctx.Resp, ctx.Req.Request, url, http.StatusMovedPermanently) | |||
} | |||
@@ -2278,13 +2277,11 @@ func ResultDownload(ctx *context.Context) { | |||
versionName := ctx.Query("version_name") | |||
parentDir := ctx.Query("parent_dir") | |||
fileName := ctx.Query("file_name") | |||
log.Info("DownloadResult start.") | |||
task := ctx.Cloudbrain | |||
if err != nil { | |||
ctx.Data["error"] = err.Error() | |||
} | |||
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) | |||
if err != nil { | |||
@@ -2292,6 +2289,7 @@ func ResultDownload(ctx *context.Context) { | |||
ctx.ServerError("GetObsCreateSignedUrl", err) | |||
return | |||
} | |||
ctx.Resp.Header().Set("Cache-Control", "max-age=0") | |||
http.Redirect(ctx.Resp, ctx.Req.Request, url, http.StatusMovedPermanently) | |||
} | |||
func DeleteJobStorage(jobName string) error { | |||
@@ -2390,3 +2388,35 @@ func SetJobCount(ctx *context.Context) { | |||
} | |||
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,7 +6,6 @@ | |||
package repo | |||
import ( | |||
"code.gitea.io/gitea/modules/validation" | |||
"fmt" | |||
"net/url" | |||
"os" | |||
@@ -15,6 +14,8 @@ import ( | |||
"strings" | |||
"unicode/utf8" | |||
"code.gitea.io/gitea/modules/validation" | |||
"code.gitea.io/gitea/models" | |||
"code.gitea.io/gitea/modules/auth" | |||
"code.gitea.io/gitea/modules/base" | |||
@@ -193,7 +194,10 @@ func CreatePost(ctx *context.Context, form auth.CreateRepoForm) { | |||
return | |||
} | |||
ctx.Data["ContextUser"] = ctxUser | |||
if !form.AutoAgree { | |||
ctx.RenderWithErr(ctx.Tr("repo.template.one_promise"), tplCreate, form) | |||
return | |||
} | |||
if ctx.HasError() { | |||
ctx.HTML(200, tplCreate) | |||
return | |||
@@ -471,6 +471,8 @@ func renderFile(ctx *context.Context, entry *git.TreeEntry, treeLink, rawLink st | |||
readmeExist := markup.IsReadmeFile(blob.Name()) | |||
ctx.Data["ReadmeExist"] = readmeExist | |||
isNoteBook := strings.HasSuffix(blob.Name(), ".ipynb") | |||
ctx.Data["IsNoteBook"] = isNoteBook | |||
if markupType := markup.Type(blob.Name()); markupType != "" { | |||
ctx.Data["IsMarkup"] = true | |||
ctx.Data["MarkupType"] = markupType | |||
@@ -480,6 +482,8 @@ func renderFile(ctx *context.Context, entry *git.TreeEntry, treeLink, rawLink st | |||
ctx.Data["FileContent"] = strings.Replace( | |||
gotemplate.HTMLEscapeString(string(buf)), "\n", `<br>`, -1, | |||
) | |||
} else if isNoteBook { | |||
ctx.Data["FileContent"] = string(buf) | |||
} else { | |||
// Building code view blocks with line number on server side. | |||
var fileContent string | |||
@@ -324,7 +324,10 @@ func RegisterRoutes(m *macaron.Macaron) { | |||
go routers.SocketManager.Run() | |||
m.Get("/action/notification", routers.ActionNotification) | |||
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/imageinfo", routers.GetImageInfoFromPromote) | |||
m.Post("/all/search/", routers.Search) | |||
m.Get("/all/search/", routers.EmptySearch) | |||
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("/query_train_job", reqRepoCloudBrainReader, repo.QueryTrainJobList) | |||
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.Get("", repo.ShowSingleModel) | |||
m.Get("/downloadsingle", repo.DownloadSingleModelFile) | |||
@@ -1136,6 +1139,7 @@ func RegisterRoutes(m *macaron.Macaron) { | |||
m.Post("/stop", cloudbrain.AdminOrOwnerOrJobCreaterRightForTrain, repo.TrainJobStop) | |||
m.Post("/del", cloudbrain.AdminOrOwnerOrJobCreaterRightForTrain, repo.TrainJobDel) | |||
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.Post("/create_version", reqWechatBind, cloudbrain.AdminOrJobCreaterRightForTrain, bindIgnErr(auth.CreateModelArtsTrainJobForm{}), repo.TrainJobCreateVersion) | |||
}) | |||
@@ -13,6 +13,9 @@ | |||
{{template "base/footer_content" .}} | |||
<script src="{{StaticUrlPrefix}}/js/jquery.js?v={{MD5 AppVer}}"></script> | |||
{{if .RequireSimpleMDE}} | |||
<script src="{{StaticUrlPrefix}}/vendor/plugins/simplemde/simplemde.min.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}}/js/index.js?v={{MD5 AppVer}}"></script> | |||
{{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> | |||
</html> |
@@ -192,6 +192,8 @@ var _hmt = _hmt || []; | |||
<!-- Swiper --> | |||
<link rel="stylesheet" href="/swiper/swiper-bundle.min.css"> | |||
<script src="/swiper/swiper-bundle.min.js"></script> | |||
<!-- rotation3D --> | |||
<link rel="stylesheet" href="/rotation3D/rotation3D.css"> | |||
</head> | |||
<body> | |||
{{template "custom/body_outer_pre" .}} | |||
@@ -34,7 +34,7 @@ | |||
<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> | |||
<div class="ui dropdown item" id='dropdown_explore'> | |||
<div class="ui simple dropdown item" id='dropdown_explore'> | |||
{{.i18n.Tr "explore"}} | |||
<i class="dropdown icon"></i> | |||
<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/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"}} | |||
<i class="dropdown icon"></i> | |||
<div class="menu" > | |||
@@ -120,7 +120,7 @@ | |||
</span> | |||
</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="fitted">{{svg "octicon-plus" 16}}</span> | |||
<span class="sr-mobile-only">{{.i18n.Tr "create_new"}}</span> | |||
@@ -141,7 +141,7 @@ | |||
</div><!-- end content create new menu --> | |||
</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"> | |||
<img class="ui tiny avatar image" width="24" height="24" src="{{.SignedUser.RelAvatarLink}}"> | |||
<span class="sr-only">{{.i18n.Tr "user_profile_and_more"}}</span> | |||
@@ -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> | |||
<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> | |||
<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> | |||
@@ -186,7 +184,7 @@ | |||
src="/img/jian.svg" style="margin-left: 0.5rem;">{{end}} | |||
{{if $.IsSigned}} | |||
<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}})"> | |||
<div style="line-height: 1;margin-right: 4px;margin-bottom: -2px;"> | |||
@@ -256,12 +254,14 @@ | |||
<span | |||
style="color: #999999;font-size: 12px;margin-left: 0.5rem;">{{TimeSinceUnixShort .CreatedUnix}}</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> | |||
<span | |||
style="color: #101010; font-size: 12px;margin-left: 0.2rem;">{{.UseCount}}</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> | |||
<span | |||
style="color: #101010;font-size: 12px;margin-left: 0.2rem;">{{.DownloadTimes}}</span> | |||
@@ -1,6 +1,6 @@ | |||
{{template "base/head_home" .}} | |||
<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"> | |||
<h1 class="ui huge header"> | |||
{{.page_title}} | |||
@@ -17,7 +17,7 @@ | |||
{{end}} | |||
</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> | |||
<div class="ui grid"> | |||
<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 stackable grid"> | |||
<div class="ui stackable grid"> | |||
<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}} </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 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 class="swiper-pagination"></div> | |||
</div> | |||
</div> | |||
<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}} </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 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 class="swiper-pagination"></div> | |||
</div> | |||
</div> | |||
</div> | |||
@@ -87,56 +86,112 @@ | |||
</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> | |||
<div class="ui container i-env"> | |||
<div class="ui center am-pb-30"> | |||
<div class="leftline03"></div> | |||
<h2>{{.page_dev_env}}</h2> | |||
<p><span class="ui text grey">{{.page_dev_env_desc}}</p> | |||
</div> | |||
<div class="ui four doubling cards"> | |||
<div class="card"> | |||
<div class="image"> | |||
<img src="/img/i-pic-01.svg"> | |||
<img src="/img/i-pic-01.jpg"> | |||
</div> | |||
<div class="content"> | |||
<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}} | |||
</div> | |||
</div> | |||
</div> | |||
<div class="card"> | |||
<div class="image"> | |||
<img src="/img/i-pic-02.svg"> | |||
<img src="/img/i-pic-02.jpg"> | |||
</div> | |||
<div class="content"> | |||
<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}} | |||
</div> | |||
</div> | |||
</div> | |||
<div class="card"> | |||
<div class="image"> | |||
<img src="/img/i-pic-03.svg"> | |||
<img src="/img/i-pic-03.jpg"> | |||
</div> | |||
<div class="content"> | |||
<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}} | |||
</div> | |||
</div> | |||
</div> | |||
<div class="card"> | |||
<div class="image"> | |||
<img src="/img/i-pic-04.svg"> | |||
<img src="/img/i-pic-04.jpg"> | |||
</div> | |||
<div class="content"> | |||
<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}} | |||
</div> | |||
</div> | |||
@@ -172,8 +227,8 @@ | |||
</div> | |||
</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" .}} |
@@ -15,11 +15,11 @@ | |||
<label>{{.i18n.Tr "repo.visibility"}}</label> | |||
<div class="ui checkbox"> | |||
{{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}} | |||
<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}} | |||
</div> | |||
<span class="help">{{.i18n.Tr "repo.visibility_description"}}</span> | |||
@@ -42,33 +42,41 @@ | |||
<div class="inline field"> | |||
<label>{{.i18n.Tr "repo.template.items"}}</label> | |||
<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> | |||
</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> | |||
</div> | |||
</div> | |||
<div class="inline field"> | |||
<label></label> | |||
<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> | |||
</div> | |||
<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> | |||
</div> | |||
</div> | |||
<div class="inline field"> | |||
<label></label> | |||
<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> | |||
</div> | |||
<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> | |||
</div> | |||
</div> | |||
@@ -83,7 +91,8 @@ | |||
<div class="menu"> | |||
<div class="item" data-value="">{{.i18n.Tr "repo.issue_labels_helper"}}</div> | |||
{{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}} | |||
</div> | |||
</div> | |||
@@ -98,7 +107,7 @@ | |||
<div class="default text">{{.i18n.Tr "repo.repo_gitignore_helper"}}</div> | |||
<div class="menu"> | |||
{{range .Gitignores}} | |||
<div class="item" data-value="{{.}}">{{.}}</div> | |||
<div class="item" data-value="{{.}}">{{.}}</div> | |||
{{end}} | |||
</div> | |||
</div> | |||
@@ -111,7 +120,7 @@ | |||
<div class="menu"> | |||
<div class="item" data-value="">{{.i18n.Tr "repo.license_helper"}}</div> | |||
{{range .Licenses}} | |||
<div class="item" data-value="{{.}}">{{.}}</div> | |||
<div class="item" data-value="{{.}}">{{.}}</div> | |||
{{end}} | |||
</div> | |||
</div> | |||
@@ -124,24 +133,35 @@ | |||
<div class="default text">{{.i18n.Tr "repo.readme_helper"}}</div> | |||
<div class="menu"> | |||
{{range .Readmes}} | |||
<div class="item" data-value="{{.}}">{{.}}</div> | |||
<div class="item" data-value="{{.}}">{{.}}</div> | |||
{{end}} | |||
</div> | |||
</div> | |||
</div> | |||
<div class="inline field"> | |||
<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> | |||
</div> | |||
</div> | |||
<div class="inline field"> | |||
<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> | |||
<br/> | |||
<br /> | |||
<div class="inline field"> | |||
<label></label> | |||
<button class="ui green button" id="submit_reponame"> | |||
@@ -154,4 +174,4 @@ | |||
</div> | |||
</div> | |||
</div> | |||
{{template "base/footer" .}} | |||
{{template "base/footer" .}} |
@@ -11,7 +11,7 @@ | |||
.dataset_title { | |||
font-size: 14px; | |||
max-width: 80%; | |||
/* max-width: 80%; */ | |||
display: inline-block !important; | |||
margin-left: 6px !important; | |||
padding-right: 0 !important; | |||
@@ -279,7 +279,7 @@ | |||
<el-tooltip class="item" effect="dark" placement="top" popper-class="diy-popper"> | |||
<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}} | |||
{{end}}<i | |||
class="ri-download-line"></i>{{$.i18n.Tr "dataset.download"}}:{{.DownloadCount}} | |||
{{if .Description}} {{$.i18n.Tr "dataset.description"}}:{{.Description}}{{end}}</span> | |||
@@ -288,10 +288,10 @@ | |||
{{if eq .DecompressState 1}} | |||
<i class="ri-folder-open-line" style="color: #5bb973;" | |||
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;" | |||
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;" | |||
title='{{$.i18n.Tr "dataset.unzip_failed"}}'></i> | |||
{{else}} | |||
@@ -182,3 +182,15 @@ | |||
<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" /> |
@@ -177,6 +177,12 @@ | |||
border: 1px solid #dfe1e6; | |||
} | |||
.ti-download-file { | |||
display: flex; | |||
align-items: center; | |||
margin: 0.5rem 0; | |||
} | |||
.disabled { | |||
cursor: default; | |||
pointer-events: none; | |||
@@ -220,6 +226,7 @@ | |||
<div class="active section">{{.displayJobName}}</div> | |||
</div> | |||
</h4> | |||
{{range $k ,$v := .version_list_task}} | |||
<div class="ui accordion border-according" id="accordion{{.VersionName}}" | |||
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> | |||
<a class="item log_bottom" data-tab="second{{$k}}" | |||
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}}" | |||
onclick="loadModelFile({{.VersionName}},'','','init')">{{$.i18n.Tr "repo.model_download"}}</a> | |||
</div> | |||
@@ -478,7 +486,17 @@ | |||
</div> | |||
</div> | |||
<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> | |||
<a title="滚动到顶部" style="position: absolute; right: -32px;cursor: pointer;" | |||
class="log_top" data-version="{{.VersionName}}"><i class="icon-to-top"></i></a> | |||
@@ -501,6 +519,13 @@ | |||
</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}}"> | |||
<input type="hidden" name="model{{.VersionName}}" value="-1"> | |||
<input type="hidden" name="modelback{{.VersionName}}" value="-1"> | |||
@@ -709,6 +734,12 @@ | |||
// detail status and duration | |||
$('#' + version_name + '-duration').text(data.JobDuration) | |||
$('#' + 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) | |||
@@ -130,6 +130,19 @@ | |||
<label>模型版本</label> | |||
<input style="width: 45%;" id="version" name="Version" value="" readonly required maxlength="255"> | |||
</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"> | |||
<label>模型标签</label> | |||
<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}} | |||
const {_AppSubUrl, _StaticUrlPrefix, csrf} = window.config; | |||
$('input[name="_csrf"]').val(csrf) | |||
let modelData; | |||
function createModelName(){ | |||
let repoName = location.pathname.split('/')[2] | |||
let modelName = repoName + '_model_' + Math.random().toString(36).substr(2, 4) | |||
@@ -185,6 +198,7 @@ | |||
document.getElementById("formId").reset(); | |||
$('#choice_model').dropdown('clear') | |||
$('#choice_version').dropdown('clear') | |||
$('#choice_Engine').dropdown('clear') | |||
$('.ui.dimmer').css({"background-color":""}) | |||
$('.ui.error.message').text() | |||
$('.ui.error.message').css('display','none') | |||
@@ -197,10 +211,24 @@ | |||
$(function(){ | |||
$('#choice_model').dropdown({ | |||
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 | |||
$.get(`${repolink}/modelmanage/query_train_job_version?JobID=${JobID}`, (data) => { | |||
const n_length = data.length | |||
let train_html='' | |||
let train_html=''; | |||
modelData = data; | |||
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>' | |||
@@ -248,11 +277,59 @@ | |||
if(data.length){ | |||
$("#job-version").append(train_html) | |||
$(".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> | |||
@@ -108,6 +108,8 @@ | |||
<tr> | |||
{{if .IsFileTooLarge}} | |||
<td><strong>{{.i18n.Tr "repo.file_too_large"}}</strong></td> | |||
{{else if .IsNoteBook}} | |||
<td id="notebook"></td> | |||
{{else}} | |||
<td class="lines-num">{{.LineNums}}</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() | |||
} | |||
} | |||
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> |
@@ -10,9 +10,9 @@ | |||
{{.i18n.Tr "home.wecome_AI_plt"}} | |||
</div> | |||
<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"}} <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> <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 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> | |||
@@ -66,19 +66,12 @@ | |||
} | |||
.w_title{ | |||
padding-top: 25px; | |||
margin-bottom: 20px; | |||
color: rgba(16, 16, 16, 100); | |||
font-size: 20px; | |||
text-align: left; | |||
font-weight: 700; | |||
} | |||
.content{ | |||
color: rgba(80, 85, 89, 100); | |||
font-size: 14px; | |||
text-align: left; | |||
font-family: SourceHanSansSC-regular; | |||
margin-top: 20px; | |||
} | |||
.guide{ | |||
margin-top:30px; | |||
padding-bottom: 30px; | |||
@@ -6,7 +6,7 @@ | |||
<div class="ui grid"> | |||
<div class="ui fourteen wide column"> | |||
<div class="{{if or (eq .GetOpType 5) (eq .GetOpType 18)}}push news{{end}}"> | |||
<p> | |||
<p class="text truncate"> | |||
{{if gt .ActUser.ID 0}} | |||
<a href="{{AppSubUrl}}/{{.GetActUserName}}" title="{{.GetDisplayNameTitle}}">{{.GetDisplayName}}</a> | |||
{{else}} | |||
@@ -168,7 +168,7 @@ export default { | |||
tableData= res.data | |||
for(let i=0;i<tableData.length;i++){ | |||
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].cName=tableData[i].Name | |||
tableData[i].Name='' | |||
@@ -218,6 +218,7 @@ export default { | |||
$('input[name="Name"]').removeAttr('readonly') | |||
$('#choice_model').dropdown('clear') | |||
$('#choice_version').dropdown('clear') | |||
$('#choice_Engine').dropdown('clear') | |||
$('.ui.dimmer').css({"background-color":""}) | |||
$('.ui.error.message').text() | |||
$('.ui.error.message').css('display','none') | |||
@@ -347,6 +348,18 @@ export default { | |||
}) | |||
.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(){ | |||
try { | |||
this.$refs.table.store.states.lazyTreeNodeMap = {} | |||
@@ -360,7 +373,7 @@ export default { | |||
for(let i=0;i<this.tableData.length;i++){ | |||
TrainTaskInfo = JSON.parse(this.tableData[i].TrainTaskInfo) | |||
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].hasChildren = res.data.data[i].VersionCount===1 ? false : true | |||
} | |||
@@ -1214,7 +1214,7 @@ async function initRepository() { | |||
files: $attachments | |||
}, | |||
(data) => { | |||
if (data.length === 0) { | |||
if (data.length === 0 || data.content === '') { | |||
$renderContent.html($('#no-content').html()); | |||
} else { | |||
$renderContent.html(data.content); | |||
@@ -1222,10 +1222,18 @@ async function initRepository() { | |||
highlight(this); | |||
}); | |||
} | |||
let imageShow = '' | |||
const $content = $segment.parent(); | |||
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 === '') { | |||
$content | |||
@@ -5070,3 +5078,98 @@ function 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() |
@@ -82,6 +82,10 @@ | |||
line-height: 1.2; | |||
p { | |||
max-width: 100%; | |||
} | |||
> .ui.grid { | |||
margin-left: auto; | |||
margin-right: auto; | |||