Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
MindSpore
mindinsight
提交
b3ef9496
M
mindinsight
项目概览
MindSpore
/
mindinsight
通知
8
Star
4
Fork
2
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
M
mindinsight
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
提交
Issue看板
提交
b3ef9496
编写于
7月 16, 2020
作者:
F
fengxuefeng
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
Add hardware resource visualization
上级
6c82ec3e
变更
7
隐藏空白更改
内联
并排
Showing
7 changed file
with
1086 addition
and
36 deletion
+1086
-36
mindinsight/ui/src/assets/images/cpu-bg.svg
mindinsight/ui/src/assets/images/cpu-bg.svg
+22
-0
mindinsight/ui/src/components/header.vue
mindinsight/ui/src/components/header.vue
+116
-32
mindinsight/ui/src/locales/zh-cn.json
mindinsight/ui/src/locales/zh-cn.json
+33
-4
mindinsight/ui/src/router.js
mindinsight/ui/src/router.js
+4
-0
mindinsight/ui/src/services/request-service.js
mindinsight/ui/src/services/request-service.js
+9
-0
mindinsight/ui/src/store.js
mindinsight/ui/src/store.js
+13
-0
mindinsight/ui/src/views/train-manage/hardware-visual.vue
mindinsight/ui/src/views/train-manage/hardware-visual.vue
+889
-0
未找到文件。
mindinsight/ui/src/assets/images/cpu-bg.svg
0 → 100644
浏览文件 @
b3ef9496
<?xml version="1.0" encoding="UTF-8"?>
<svg
width=
"1920px"
height=
"1080px"
viewBox=
"0 0 1920 1080"
version=
"1.1"
xmlns=
"http://www.w3.org/2000/svg"
xmlns:xlink=
"http://www.w3.org/1999/xlink"
>
<!-- Generator: Sketch 63.1 (92452) - https://sketch.com -->
<title>
矩形
</title>
<desc>
Created with Sketch.
</desc>
<defs>
<polygon
id=
"path-1"
points=
"0 0 1920 0 1920 1080 0 1080"
></polygon>
<pattern
id=
"pattern-3"
width=
"16.4850993"
height=
"16.4850993"
x=
"-16.4850993"
y=
"-16.4850993"
patternUnits=
"userSpaceOnUse"
>
<use
xlink:href=
"#image-4"
transform=
"scale(0.34343957,0.34343957)"
></use>
</pattern>
<image
id=
"image-4"
width=
"48"
height=
"48"
xlink:href=
"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADAAAAAwCAYAAABXAvmHAAAEGWlDQ1BrQ0dDb2xvclNwYWNlR2VuZXJpY1JHQgAAOI2NVV1oHFUUPrtzZyMkzlNsNIV0qD8NJQ2TVjShtLp/3d02bpZJNtoi6GT27s6Yyc44M7v9oU9FUHwx6psUxL+3gCAo9Q/bPrQvlQol2tQgKD60+INQ6Ium65k7M5lpurHeZe58853vnnvuuWfvBei5qliWkRQBFpquLRcy4nOHj4g9K5CEh6AXBqFXUR0rXalMAjZPC3e1W99Dwntf2dXd/p+tt0YdFSBxH2Kz5qgLiI8B8KdVy3YBevqRHz/qWh72Yui3MUDEL3q44WPXw3M+fo1pZuQs4tOIBVVTaoiXEI/MxfhGDPsxsNZfoE1q66ro5aJim3XdoLFw72H+n23BaIXzbcOnz5mfPoTvYVz7KzUl5+FRxEuqkp9G/Ajia219thzg25abkRE/BpDc3pqvphHvRFys2weqvp+krbWKIX7nhDbzLOItiM8358pTwdirqpPFnMF2xLc1WvLyOwTAibpbmvHHcvttU57y5+XqNZrLe3lE/Pq8eUj2fXKfOe3pfOjzhJYtB/yll5SDFcSDiH+hRkH25+L+sdxKEAMZahrlSX8ukqMOWy/jXW2m6M9LDBc31B9LFuv6gVKg/0Szi3KAr1kGq1GMjU/aLbnq6/lRxc4XfJ98hTargX++DbMJBSiYMIe9Ck1YAxFkKEAG3xbYaKmDDgYyFK0UGYpfoWYXG+fAPPI6tJnNwb7ClP7IyF+D+bjOtCpkhz6CFrIa/I6sFtNl8auFXGMTP34sNwI/JhkgEtmDz14ySfaRcTIBInmKPE32kxyyE2Tv+thKbEVePDfW/byMM1Kmm0XdObS7oGD/MypMXFPXrCwOtoYjyyn7BV29/MZfsVzpLDdRtuIZnbpXzvlf+ev8MvYr/Gqk4H/kV/G3csdazLuyTMPsbFhzd1UabQbjFvDRmcWJxR3zcfHkVw9GfpbJmeev9F08WW8uDkaslwX6avlWGU6NRKz0g/SHtCy9J30o/ca9zX3Kfc19zn3BXQKRO8ud477hLnAfc1/G9mrzGlrfexZ5GLdn6ZZrrEohI2wVHhZywjbhUWEy8icMCGNCUdiBlq3r+xafL549HQ5jH+an+1y+LlYBifuxAvRN/lVVVOlwlCkdVm9NOL5BE4wkQ2SMlDZU97hX86EilU/lUmkQUztTE6mx1EEPh7OmdqBtAvv8HdWpbrJS6tJj3n0CWdM6busNzRV3S9KTYhqvNiqWmuroiKgYhshMjmhTh9ptWhsF7970j/SbMrsPE1suR5z7DMC+P/Hs+y7ijrQAlhyAgccjbhjPygfeBTjzhNqy28EdkUh8C+DU9+z2v/oyeH791OncxHOs5y2AtTc7nb/f73TWPkD/qwBnjX8BoJ98VQNcC+8AAAFFSURBVGgF7djbDYMwDAXQBjEMYqyqY1WMxTppLiJIQIA8ariWkp8IPuweO60am67r7MstY8wwjuPH7dMz3uUua63p+/7r9rePIRW/9QmQzCV9ub0YgSIgzhxvQkjFb1EZBAdEKolkfJTqtnb7bv/zOJm58moRE0AzYgFoRawAGhE7gDZEEKAJcQjQgjgFaEBcAtgRUQBmRDSAFZEEYEQkA9gQWQAmRDaABVEEYEAUAx5H4EaGOyw+SMl66mbXzNOD4k6gCPNUY/CFwF1YOn5zRxJJRINqaUbUuZA/79sd3wm3xIdbdS60rXzo2XVCbO60/HxKJgFKKv4CkEziuyKBWAE0InYAbYggQBPiEKAFcQrQgLgEsCOiAMyIaAArIgnAiEgGsCGyAEyIbAALogjAgCgGPI7AX9w6F3JtqHMhnMWLFSrSD9jOnakVHpZYAAAAAElFTkSuQmCC"
></image>
</defs>
<g
id=
"硬件资源可视-特性文档"
stroke=
"none"
stroke-width=
"1"
fill=
"none"
fill-rule=
"evenodd"
>
<mask
id=
"mask-2"
fill=
"white"
>
<use
xlink:href=
"#path-1"
></use>
</mask>
<g
id=
"矩形"
>
<use
fill=
"#F2F5FC"
xlink:href=
"#path-1"
></use>
<use
fill-opacity=
"0.2"
fill=
"url(#pattern-3)"
style=
"mix-blend-mode: multiply;"
xlink:href=
"#path-1"
></use>
</g>
</g>
</svg>
\ No newline at end of file
mindinsight/ui/src/components/header.vue
浏览文件 @
b3ef9496
...
@@ -32,6 +32,7 @@ limitations under the License.
...
@@ -32,6 +32,7 @@ limitations under the License.
<el-menu-item
index=
"/model-traceback"
>
{{
$t
(
"
summaryManage.modelTraceback
"
)
}}
</el-menu-item>
<el-menu-item
index=
"/model-traceback"
>
{{
$t
(
"
summaryManage.modelTraceback
"
)
}}
</el-menu-item>
<el-menu-item
index=
"/data-traceback"
>
{{
$t
(
"
summaryManage.dataTraceback
"
)
}}
</el-menu-item>
<el-menu-item
index=
"/data-traceback"
>
{{
$t
(
"
summaryManage.dataTraceback
"
)
}}
</el-menu-item>
<el-menu-item
index=
"/compare-plate"
>
{{
$t
(
"
summaryManage.comparePlate
"
)
}}
</el-menu-item>
<el-menu-item
index=
"/compare-plate"
>
{{
$t
(
"
summaryManage.comparePlate
"
)
}}
</el-menu-item>
<el-menu-item
index=
"/hardware-visual"
>
{{
$t
(
"
summaryManage.hardwareVisual
"
)
}}
</el-menu-item>
</el-menu>
</el-menu>
</div>
</div>
</div>
</div>
...
@@ -42,28 +43,61 @@ limitations under the License.
...
@@ -42,28 +43,61 @@ limitations under the License.
|| this.$route.path.indexOf('/histogram') > 0
|| this.$route.path.indexOf('/histogram') > 0
|| this.$route.path.indexOf('/tensor') > 0
|| this.$route.path.indexOf('/tensor') > 0
|| this.$route.path.indexOf('/training-dashboard') > 0
|| this.$route.path.indexOf('/training-dashboard') > 0
|| !this.$route.path.indexOf('/compare-plate')"
>
|| !this.$route.path.indexOf('/compare-plate')
<!-- automatic refresh switch -->
|| !this.$route.path.indexOf('/hardware-visual')"
>
<el-switch
v-model=
"isTimeReload"
<div
class=
"reload-training"
:active-text=
"$t('header.timeReload')+$t('symbols.leftbracket')+
v-if=
"this.$route.path.indexOf('/scalar') > 0
timeReloadValue+$t('header.timeSecond')+$t('symbols.rightbracket')"
|| this.$route.path.indexOf('/image') > 0
@
change=
"timeReload"
></el-switch>
|| this.$route.path.indexOf('/histogram') > 0
<i
class=
"el-icon-edit"
|| this.$route.path.indexOf('/training-dashboard') > 0
:title=
"$t('header.timeReloadScope')"
|| !this.$route.path.indexOf('/compare-plate')"
>
v-if=
"isTimeReload && !isShowInp"
<!-- automatic refresh switch -->
@
click=
"editTime"
></i>
<el-switch
v-model=
"isTimeReload"
:active-text=
"$t('header.timeReload')+$t('symbols.leftbracket')+
timeReloadValue+$t('header.timeSecond')+$t('symbols.rightbracket')"
@
change=
"timeReload"
></el-switch>
<i
class=
"el-icon-edit"
:title=
"$t('header.timeReloadScope')"
v-if=
"isTimeReload && !isShowInp"
@
click=
"editTime"
></i>
<el-input
v-if=
"isTimeReload && isShowInp"
<el-input
v-if=
"isTimeReload && isShowInp"
v-model=
"newReloadValue"
v-model=
"newReloadValue"
type=
"text"
type=
"text"
@
input=
"timeValueChange"
></el-input>
@
input=
"timeValueChange"
></el-input>
<i
class=
"el-icon-check"
v-if=
"isTimeReload && isShowInp"
@
click=
"saveTimeValue"
></i>
<i
class=
"el-icon-close"
v-if=
"isTimeReload && isShowInp"
@
click=
"cancelTimeValue"
></i>
</div>
<div
class=
"reload-hardware"
v-if=
"!this.$route.path.indexOf('/hardware-visual')"
>
<!-- automatic refresh switch -->
<el-switch
v-model=
"isHardwareTimeReload"
:active-text=
"$t('header.timeReload')+$t('symbols.leftbracket')+
hardwareTimeReloadValue+$t('header.timeSecond')+$t('symbols.rightbracket')"
@
change=
"hardwareTimeReload"
></el-switch>
<i
class=
"el-icon-edit"
:title=
"$t('header.timeReloadScope')"
v-if=
"isHardwareTimeReload && !isShowHardwareInp"
@
click=
"editHardwareTime"
></i>
<el-input
v-if=
"isHardwareTimeReload && isShowHardwareInp"
v-model=
"newHardwareReloadValue"
type=
"text"
@
input=
"hardwareTimeValueChange"
></el-input>
<i
class=
"el-icon-check"
v-if=
"isHardwareTimeReload && isShowHardwareInp"
@
click=
"saveHardwareTimeValue"
></i>
<i
class=
"el-icon-close"
v-if=
"isHardwareTimeReload && isShowHardwareInp"
@
click=
"cancelHardwareTimeValue"
></i>
</div>
<i
class=
"el-icon-check"
v-if=
"isTimeReload && isShowInp"
@
click=
"saveTimeValue"
></i>
<i
class=
"el-icon-close"
v-if=
"isTimeReload && isShowInp"
@
click=
"cancleTimeValue"
></i>
<!-- manual refresh switch -->
<!-- manual refresh switch -->
<img
src=
"../assets/images/reload.png"
<img
src=
"../assets/images/reload.png"
...
@@ -90,6 +124,9 @@ export default {
...
@@ -90,6 +124,9 @@ export default {
isShowInp
:
false
,
isShowInp
:
false
,
timeReloadValue
:
this
.
$store
.
state
.
timeReloadValue
,
timeReloadValue
:
this
.
$store
.
state
.
timeReloadValue
,
newReloadValue
:
this
.
$store
.
state
.
timeReloadValue
,
newReloadValue
:
this
.
$store
.
state
.
timeReloadValue
,
isShowHardwareInp
:
false
,
hardwareTimeReloadValue
:
this
.
$store
.
state
.
hardwareTimeReloadValue
,
newHardwareReloadValue
:
this
.
$store
.
state
.
hardwareTimeReloadValue
,
};
};
},
},
computed
:
{
computed
:
{
...
@@ -104,6 +141,13 @@ export default {
...
@@ -104,6 +141,13 @@ export default {
},
},
set
(
val
)
{},
set
(
val
)
{},
},
},
// set and get isHardwareTimeReload status
isHardwareTimeReload
:
{
get
()
{
return
this
.
$store
.
state
.
isHardwareTimeReload
;
},
set
(
val
)
{},
},
},
},
watch
:
{},
watch
:
{},
mounted
()
{},
mounted
()
{},
...
@@ -117,7 +161,7 @@ export default {
...
@@ -117,7 +161,7 @@ export default {
relPath
(
path
)
{
relPath
(
path
)
{
this
.
$router
.
push
(
path
);
this
.
$router
.
push
(
path
);
},
},
//
save isTimeReload status
//
training reload setting
timeReload
(
val
)
{
timeReload
(
val
)
{
localStorage
.
isTimeReload
=
val
;
localStorage
.
isTimeReload
=
val
;
this
.
$store
.
commit
(
'
setIsTimeReload
'
,
val
);
this
.
$store
.
commit
(
'
setIsTimeReload
'
,
val
);
...
@@ -128,7 +172,7 @@ export default {
...
@@ -128,7 +172,7 @@ export default {
},
},
saveTimeValue
()
{
saveTimeValue
()
{
if
(
this
.
newReloadValue
)
{
if
(
this
.
newReloadValue
>=
0
)
{
this
.
newReloadValue
=
this
.
newReloadValue
=
this
.
newReloadValue
<
3
this
.
newReloadValue
<
3
?
3
?
3
...
@@ -141,10 +185,10 @@ export default {
...
@@ -141,10 +185,10 @@ export default {
this
.
$store
.
commit
(
'
setTimeReloadValue
'
,
timeValue
);
this
.
$store
.
commit
(
'
setTimeReloadValue
'
,
timeValue
);
this
.
isShowInp
=
false
;
this
.
isShowInp
=
false
;
}
else
{
}
else
{
this
.
canc
le
TimeValue
();
this
.
canc
el
TimeValue
();
}
}
},
},
canc
le
TimeValue
()
{
canc
el
TimeValue
()
{
this
.
isShowInp
=
false
;
this
.
isShowInp
=
false
;
this
.
newReloadValue
=
this
.
timeReloadValue
;
this
.
newReloadValue
=
this
.
timeReloadValue
;
},
},
...
@@ -155,6 +199,45 @@ export default {
...
@@ -155,6 +199,45 @@ export default {
.
replace
(
/
\.
/g
,
''
);
.
replace
(
/
\.
/g
,
''
);
this
.
newReloadValue
=
Number
(
this
.
newReloadValue
);
this
.
newReloadValue
=
Number
(
this
.
newReloadValue
);
},
},
// hardware reload setting
hardwareTimeReload
(
val
)
{
localStorage
.
isHardwareTimeReload
=
val
;
this
.
$store
.
commit
(
'
setIsHardwareTimeReload
'
,
val
);
},
editHardwareTime
()
{
this
.
isShowHardwareInp
=
true
;
},
saveHardwareTimeValue
()
{
if
(
this
.
newHardwareReloadValue
>=
0
)
{
this
.
newHardwareReloadValue
=
this
.
newHardwareReloadValue
<
3
?
3
:
this
.
newHardwareReloadValue
>
300
?
300
:
this
.
newHardwareReloadValue
;
const
timeValue
=
this
.
newHardwareReloadValue
;
this
.
hardwareTimeReloadValue
=
timeValue
;
localStorage
.
hardwareTimeReloadValue
=
timeValue
;
this
.
$store
.
commit
(
'
setHardwareTimeReloadValue
'
,
timeValue
);
this
.
isShowHardwareInp
=
false
;
}
else
{
this
.
cancelHardwareTimeValue
();
}
},
cancelHardwareTimeValue
()
{
this
.
isShowHardwareInp
=
false
;
this
.
newHardwareReloadValue
=
this
.
timeReloadValue
;
},
hardwareTimeValueChange
()
{
this
.
newHardwareReloadValue
=
this
.
newHardwareReloadValue
.
toString
()
.
replace
(
/
[^\.\d]
/g
,
''
)
.
replace
(
/
\.
/g
,
''
);
this
.
newHardwareReloadValue
=
Number
(
this
.
newHardwareReloadValue
);
},
// get active menu item
// get active menu item
getActive
()
{
getActive
()
{
const
str
=
this
.
$route
.
path
.
split
(
'
/
'
);
const
str
=
this
.
$route
.
path
.
split
(
'
/
'
);
...
@@ -217,6 +300,13 @@ export default {
...
@@ -217,6 +300,13 @@ export default {
.el-icon-close
{
.el-icon-close
{
color
:
#f56c6c
;
color
:
#f56c6c
;
}
}
.el-input
{
width
:
45px
;
input
{
padding
:
0
;
text-align
:
center
;
}
}
}
}
// reload style
// reload style
...
@@ -232,16 +322,10 @@ export default {
...
@@ -232,16 +322,10 @@ export default {
transform
:
rotate
(
1turn
);
transform
:
rotate
(
1turn
);
}
}
}
}
.cl-header-right
.el-input
{
width
:
45px
;
input
{
padding
:
0
;
text-align
:
center
;
}
}
.cl-header-nav
{
.cl-header-nav
{
margin-left
:
50px
;
margin-left
:
50px
;
flex
:
1
;
flex
:
1
.5
;
.el-menu
{
.el-menu
{
border-bottom
:
none
;
border-bottom
:
none
;
...
...
mindinsight/ui/src/locales/zh-cn.json
浏览文件 @
b3ef9496
...
@@ -45,7 +45,8 @@
...
@@ -45,7 +45,8 @@
"modelTraceback"
:
"模型溯源"
,
"modelTraceback"
:
"模型溯源"
,
"dataTraceback"
:
"数据溯源"
,
"dataTraceback"
:
"数据溯源"
,
"comparePlate"
:
"对比看板"
,
"comparePlate"
:
"对比看板"
,
"disableProfilerTip"
:
"无profiler日志,无法查看性能分析"
"disableProfilerTip"
:
"无profiler日志,无法查看性能分析"
,
"hardwareVisual"
:
"硬件资源"
},
},
"modelTraceback"
:
{
"modelTraceback"
:
{
"summaryPath"
:
"训练日志路径"
,
"summaryPath"
:
"训练日志路径"
,
...
@@ -367,7 +368,7 @@
...
@@ -367,7 +368,7 @@
"FPMessage"
:
"前向起始算子:"
,
"FPMessage"
:
"前向起始算子:"
,
"BPMessage"
:
"反向终止算子:"
,
"BPMessage"
:
"反向终止算子:"
,
"approximateTime"
:
"总时长 ≈ "
,
"approximateTime"
:
"总时长 ≈ "
,
"stepInputTip"
:
"请输入step值(1~{max}的正整数)"
,
"stepInputTip"
:
"请输入step值(1~{max}的正整数
,值为空时展示平均值
)"
,
"inputError"
:
"输入参数异常,请输入一个1~{max}的正整数"
,
"inputError"
:
"输入参数异常,请输入一个1~{max}的正整数"
,
"defaultTip"
:
"默认展示平均值"
,
"defaultTip"
:
"默认展示平均值"
,
"downloadTimeline"
:
"下载"
,
"downloadTimeline"
:
"下载"
,
...
@@ -383,7 +384,35 @@
...
@@ -383,7 +384,35 @@
"title3"
:
"如何使用时间线:"
,
"title3"
:
"如何使用时间线:"
,
"content31"
:
"您可以通过时间线信息分析流切分方法是否合理、迭代间隙和拖尾时间是否过长等;"
,
"content31"
:
"您可以通过时间线信息分析流切分方法是否合理、迭代间隙和拖尾时间是否过长等;"
,
"content32"
:
"也可以具体定位到某个算子,查看分析它的执行时间。"
"content32"
:
"也可以具体定位到某个算子,查看分析它的执行时间。"
}
},
"unit"
:
"ms/次"
},
"hardwareVisual"
:
{
"processor"
:
"昇腾AI处理器"
,
"ram"
:
"内存"
,
"selectedCpu"
:
"CPU-选中:"
,
"allCpu"
:
"CPU-总计:"
,
"chipNameTip"
:
"芯片名称"
,
"deviceIdTip"
:
"芯片号"
,
"availableTip"
:
"芯片是否空闲"
,
"healthTip"
:
"芯片健康指数(正常、一般警告、重要警告、紧急警告)"
,
"ipTip"
:
"芯片IP地址"
,
"aicoreTip"
:
"芯片利用率"
,
"hbmTip"
:
"芯片已用HBM内存"
,
"powerTip"
:
"芯片功耗"
,
"temperatureTip"
:
"芯片温度"
,
"cpuUserTip"
:
"运行于用户态的时间百分比"
,
"cpuSystemTip"
:
"运行于内核态的时间百分比"
,
"cpuIdleTip"
:
"处于空闲状态的时间百分比"
,
"cpuNiceTip"
:
"运行低优先级进程的时间百分比"
,
"cpuIowaitTip"
:
"等待IO的时间百分比"
,
"cpuIrqTip"
:
"处理硬中断的时间百分比"
,
"cpuSoftirqTip"
:
"处理软中断的时间百分比"
,
"cpuStealTip"
:
"被其他虚拟机抢夺的时间百分比"
,
"cpuGuestTip"
:
"运行虚拟机的时间百分比"
,
"cpuGuestniceTip"
:
"运行低优先级虚拟机的时间百分比"
,
"cpuInterruptTip"
:
"处理硬中断的时间百分比"
,
"cpuDpcTip"
:
"远程调用的时间百分比"
},
},
"components"
:
{
"components"
:
{
"summaryTitle"
:
"训练选择"
,
"summaryTitle"
:
"训练选择"
,
...
@@ -423,4 +452,4 @@
...
@@ -423,4 +452,4 @@
"50545013"
:
"请求的数据过大,无法返回,请使用其他维度重试。"
,
"50545013"
:
"请求的数据过大,无法返回,请使用其他维度重试。"
,
"50545014"
:
"查询的张量数据已被新数据替换,请刷新。"
"50545014"
:
"查询的张量数据已被新数据替换,请刷新。"
}
}
}
}
\ No newline at end of file
mindinsight/ui/src/router.js
浏览文件 @
b3ef9496
...
@@ -102,5 +102,9 @@ export default new Router({
...
@@ -102,5 +102,9 @@ export default new Router({
},
},
],
],
},
},
{
path
:
'
/hardware-visual
'
,
component
:
()
=>
import
(
'
./views/train-manage/hardware-visual.vue
'
),
},
],
],
});
});
mindinsight/ui/src/services/request-service.js
浏览文件 @
b3ef9496
...
@@ -288,4 +288,13 @@ export default {
...
@@ -288,4 +288,13 @@ export default {
},
},
});
});
},
},
getMetricsData
()
{
return
axios
({
method
:
'
get
'
,
url
:
'
v1/mindinsight/resource_monitor/current/metrics
'
,
headers
:
{
ignoreError
:
true
,
},
});
},
};
};
mindinsight/ui/src/store.js
浏览文件 @
b3ef9496
...
@@ -30,6 +30,12 @@ export default new Vuex.Store({
...
@@ -30,6 +30,12 @@ export default new Vuex.Store({
timeReloadValue
:
localStorage
.
timeReloadValue
timeReloadValue
:
localStorage
.
timeReloadValue
?
localStorage
.
timeReloadValue
?
localStorage
.
timeReloadValue
:
3
,
:
3
,
// Scheduled hardware reload flag
isHardwareTimeReload
:
localStorage
.
isHardwareTimeReload
===
'
false
'
?
false
:
true
,
// hardware reload time
hardwareTimeReloadValue
:
localStorage
.
hardwareTimeReloadValue
?
localStorage
.
hardwareTimeReloadValue
:
3
,
// multiSelevtGroup component count
// multiSelevtGroup component count
multiSelectedGroupCount
:
0
,
multiSelectedGroupCount
:
0
,
tableId
:
0
,
tableId
:
0
,
...
@@ -75,6 +81,13 @@ export default new Vuex.Store({
...
@@ -75,6 +81,13 @@ export default new Vuex.Store({
setTimeReloadValue
:
(
state
,
val
)
=>
{
setTimeReloadValue
:
(
state
,
val
)
=>
{
state
.
timeReloadValue
=
val
;
state
.
timeReloadValue
=
val
;
},
},
// set isHardwareTimeReload
setIsHardwareTimeReload
:
(
state
,
val
)
=>
{
state
.
isHardwareTimeReload
=
val
;
},
setHardwareTimeReloadValue
:
(
state
,
val
)
=>
{
state
.
hardwareTimeReloadValue
=
val
;
},
multiSelectedGroupComponentNum
(
state
)
{
multiSelectedGroupComponentNum
(
state
)
{
state
.
multiSelectedGroupCount
++
;
state
.
multiSelectedGroupCount
++
;
},
},
...
...
mindinsight/ui/src/views/train-manage/hardware-visual.vue
0 → 100644
浏览文件 @
b3ef9496
<!--
Copyright 2020 Huawei Technologies Co., Ltd.All Rights Reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<
template
>
<div
class=
"cl-hardware-visual"
>
<div
class=
"cl-hardware-content"
v-if=
"!(chipTableData.length === 0 && cpuList.length===0)"
>
<div
class=
"cl-hardware-top"
>
<div
class=
"cl-hardware-left"
>
<div
class=
"cl-sub-title"
>
{{
$t
(
'
hardwareVisual.processor
'
)
}}
</div>
<div
class=
"cl-chip-wrap"
>
<el-table
v-if=
"!(chipTableData.length === 0)"
:data=
"chipTableData"
width=
"100%"
height=
"100%"
>
<el-table-column
prop=
"chip_name"
width=
"120"
>
<template
slot=
"header"
>
Name
<el-tooltip
class=
"item"
effect=
"light"
:content=
"$t('hardwareVisual.chipNameTip')"
placement=
"top-start"
>
<i
class=
"el-icon-info"
></i>
</el-tooltip>
</
template
>
</el-table-column>
<el-table-column
prop=
"device_id"
width=
"80"
>
<
template
slot=
"header"
>
NPU
<el-tooltip
class=
"item"
effect=
"light"
:content=
"$t('hardwareVisual.deviceIdTip')"
placement=
"top-start"
>
<i
class=
"el-icon-info"
></i>
</el-tooltip>
</
template
>
</el-table-column>
<el-table-column
prop=
"available"
width=
"110"
>
<
template
slot=
"header"
>
Available
<el-tooltip
class=
"item"
effect=
"light"
:content=
"$t('hardwareVisual.availableTip')"
placement=
"top-start"
>
<i
class=
"el-icon-info"
></i>
</el-tooltip>
</
template
>
<
template
slot-scope=
"scope"
>
<i
class=
"el-icon-success"
v-if=
"scope.row.available"
></i>
<i
class=
"el-icon-error"
v-else
></i>
</
template
>
</el-table-column>
<el-table-column
prop=
"health"
width=
"80"
>
<
template
slot=
"header"
>
Health
<el-tooltip
class=
"item"
effect=
"light"
:content=
"$t('hardwareVisual.healthTip')"
placement=
"top-start"
>
<i
class=
"el-icon-info"
></i>
</el-tooltip>
</
template
>
<
template
slot-scope=
"scope"
>
<i
class=
"el-icon-success"
v-if=
"scope.row.health===0"
></i>
<i
class=
"el-icon-warning normal"
v-if=
"scope.row.health===1"
></i>
<i
class=
"el-icon-warning important"
v-if=
"scope.row.health===2"
></i>
<i
class=
"el-icon-warning emergency"
v-if=
"scope.row.health===3"
></i>
<i
class=
"el-icon-remove"
v-if=
"scope.row.health=== 0xffffffff"
></i>
</
template
>
</el-table-column>
<el-table-column
prop=
"ip_address"
width=
"130"
>
<
template
slot=
"header"
>
IP Address
<el-tooltip
class=
"item"
effect=
"light"
:content=
"$t('hardwareVisual.ipTip')"
placement=
"top-start"
>
<i
class=
"el-icon-info"
></i>
</el-tooltip>
</
template
>
</el-table-column>
<el-table-column
prop=
"aicore"
>
<
template
slot=
"header"
>
AI Core(%)
<el-tooltip
class=
"item"
effect=
"light"
:content=
"$t('hardwareVisual.aicoreTip')"
placement=
"top-start"
>
<i
class=
"el-icon-info"
></i>
</el-tooltip>
</
template
>
<
template
slot-scope=
"scope"
>
<el-progress
:percentage=
"scope.row.aicore_rate"
:format=
"format"
></el-progress>
</
template
>
</el-table-column>
<el-table-column
prop=
"hbm_usage"
min-width=
"100"
>
<
template
slot=
"header"
>
HBM-Usage(MB)
<el-tooltip
class=
"item"
effect=
"light"
:content=
"$t('hardwareVisual.hbmTip')"
placement=
"top-start"
>
<i
class=
"el-icon-info"
></i>
</el-tooltip>
</
template
>
<
template
slot-scope=
"scope"
>
<div
class=
"hbs-wrap"
>
<el-progress
:percentage=
"
parseInt(scope.row.hbm_info.memory_usage/scope.row.hbm_info.memory_size*100)"
:format=
"formatHbm(scope.row.hbm_info)"
></el-progress>
</div>
</
template
>
</el-table-column>
<el-table-column
prop=
"power"
>
<
template
slot=
"header"
>
Power(W)
<el-tooltip
class=
"item"
effect=
"light"
:content=
"$t('hardwareVisual.powerTip')"
placement=
"top-start"
>
<i
class=
"el-icon-info"
></i>
</el-tooltip>
</
template
>
<
template
slot-scope=
"scope"
>
<div
class=
"power-wrap"
>
<div
class=
"power"
:style=
"
{width:`${scope.row.power/powerMax*100}%`}">
{{
scope
.
row
.
power
}}
</div>
</div>
</
template
>
</el-table-column>
<el-table-column
prop=
"temp"
width=
"150"
>
<
template
slot=
"header"
>
Temp(℃)
<el-tooltip
class=
"item"
effect=
"light"
:content=
"$t('hardwareVisual.temperatureTip')"
placement=
"top-start"
>
<i
class=
"el-icon-info"
></i>
</el-tooltip>
</
template
>
<
template
slot-scope=
"scope"
>
<div
class=
"temp-wrap"
>
<div
class=
"circle"
:class=
"
{zero:!scope.row.temperature}">
</div>
<div
class=
"process-wrap"
>
<div
class=
"process-cover"
:style=
"
{width:scope.row.temperature/temperatureMax*100+'%'}">
</div>
</div>
<span>
{{
scope
.
row
.
temperature
}}
</span>
</div>
</
template
>
</el-table-column>
</el-table>
<div
class=
"image-noData"
v-if=
"chipTableData.length === 0"
>
<div>
<img
:src=
"require('@/assets/images/nodata.png')"
alt=
""
/>
</div>
<p>
{{$t("public.noData")}}
</p>
</div>
</div>
</div>
</div>
<div
class=
"cl-hardware-bottom"
>
<div
class=
"cl-hardware-left"
>
<div
class=
"cl-sub-title"
>
CPU
</div>
<div
class=
"cl-cpu-wrap"
>
<div
class=
"cpu-items"
>
<div
class=
"cpu-item"
v-for=
"(item,key) in cpuList"
:key=
"key"
>
<div
class=
"cpu"
:class=
"{selected:item.selected}"
:style=
"{backgroundColor:item.idle!==undefined?
`rgba(250,152,65,${(100-item.idle).toFixed(2)/100}`:'#ccc'}"
:title=
"item.idle!==undefined?`Core ${key}`:''"
@
click=
"viewPerCpuInfo(key)"
>
{{ item.idle!==undefined?(100-item.idle).toFixed(2):'' }}
</div>
</div>
</div>
<div
class=
"cpu-detail"
>
<div
class=
"all-cpu-info"
>
<span>
{{$t('hardwareVisual.allCpu')}}
</span>
<div
class=
"info-item"
v-for=
"(item,index) in overallCpuInfo"
:key=
"index"
>
<el-tooltip
class=
"item"
effect=
"light"
:content=
"item.tips"
placement=
"top-start"
>
<span>
<span
class=
"label"
>
{{item.label}}
</span>
<span
class=
"value"
>
{{`${item.value}%`}}
</span>
</span>
</el-tooltip>
</div>
</div>
<div
class=
"selected-cpu-info"
v-if=
"selectedCpuIndex!==null"
>
<span>
{{$t('hardwareVisual.selectedCpu')}}
</span>
<div
class=
"info-item"
v-for=
"(item,index) in selectedCpuInfo"
:key=
"index"
>
<el-tooltip
class=
"item"
effect=
"light"
:content=
"item.tips"
placement=
"top-start"
>
<span>
<span
class=
"label"
>
{{item.label}}
</span>
<span
class=
"value"
>
{{`${item.value}%`}}
</span>
</span>
</el-tooltip>
</div>
</div>
</div>
</div>
</div>
<div
class=
"cl-hardware-right"
>
<div
class=
"cl-sub-title ram"
>
{{$t('hardwareVisual.ram')}}
</div>
<div
class=
"cl-ram-wrap"
>
<div
class=
"virtual-wrap"
>
<div
id=
"virtual"
></div>
</div>
</div>
</div>
</div>
</div>
<div
class=
"image-noData"
v-if=
"chipTableData.length === 0 && cpuList.length===0"
>
<div>
<img
:src=
"require('@/assets/images/nodata.png')"
alt=
""
/>
</div>
<p>
{{$t("public.noData")}}
</p>
</div>
</div>
</template>
<
script
>
import
echarts
from
'
echarts
'
;
import
RequestService
from
'
../../services/request-service
'
;
export
default
{
data
()
{
return
{
chipTableData
:
[],
powerMax
:
null
,
temperatureMax
:
null
,
virtualChart
:
{
id
:
'
virtual
'
,
chartDom
:
null
,
data
:
[],
legend
:
[],
totalValue
:
null
,
},
defaultCpuNum
:
96
,
cpuList
:
[],
overallCpuInfo
:
[],
selectedCpuInfo
:
[],
selectedCpuIndex
:
null
,
pieColorArr
:
[
'
#5e7ce0
'
,
'
#a6dd82
'
],
autoUpdateTimer
:
null
,
// Automatic refresh timer
isReloading
:
false
,
// Manually refresh
};
},
computed
:
{
/**
* Global refresh switch
* @return {Boolean}
*/
isReload
()
{
return
this
.
$store
.
state
.
isReload
;
},
/**
* Automatic hardware refresh switch
* @return {Boolean}
*/
isHardwareTimeReload
()
{
return
this
.
$store
.
state
.
isHardwareTimeReload
;
},
/**
* Automatic hardware refresh value
* @return {Boolean}
*/
hardwareTimeReloadValue
()
{
return
this
.
$store
.
state
.
hardwareTimeReloadValue
;
},
},
watch
:
{
/**
* Global refresh switch Listener
* @param {Boolean} newVal Value After Change
* @param {Boolean} oldVal Value Before Change
*/
isReload
(
newVal
,
oldVal
)
{
if
(
newVal
)
{
this
.
isReloading
=
true
;
if
(
this
.
isHardwareTimeReload
)
{
this
.
autoUpdateSamples
();
}
this
.
init
();
}
},
/**
* Automatic refresh switch Listener
* @param {Boolean} newVal Value After Change
* @param {Boolean} oldVal Value Before Change
*/
isHardwareTimeReload
(
newVal
,
oldVal
)
{
if
(
newVal
)
{
this
.
autoUpdateSamples
();
}
else
{
this
.
stopUpdateSamples
();
}
},
/**
* The refresh time is changed.
*/
hardwareTimeReloadValue
()
{
this
.
autoUpdateSamples
();
},
},
destroyed
()
{
// Disable the automatic refresh function
if
(
this
.
autoUpdateTimer
)
{
clearInterval
(
this
.
autoUpdateTimer
);
this
.
autoUpdateTimer
=
null
;
}
// Stop Refreshing
if
(
this
.
isReloading
)
{
this
.
$store
.
commit
(
'
setIsReload
'
,
false
);
this
.
isReloading
=
false
;
}
},
mounted
()
{
document
.
title
=
this
.
$t
(
'
summaryManage.hardwareVisual
'
)
+
'
-MindInsight
'
;
// Automatic refresh
if
(
this
.
isHardwareTimeReload
)
{
this
.
autoUpdateSamples
();
}
this
.
init
();
},
methods
:
{
/**
* Initialization data
*/
init
()
{
RequestService
.
getMetricsData
().
then
(
(
res
)
=>
{
if
(
this
.
isReloading
)
{
this
.
$store
.
commit
(
'
setIsReload
'
,
false
);
this
.
isReloading
=
false
;
}
if
(
res
&&
res
.
data
)
{
this
.
chipTableData
=
res
.
data
.
npu
||
[];
this
.
powerMax
=
Math
.
max
(...
this
.
chipTableData
.
map
((
val
)
=>
val
.
power
))
*
1.2
;
this
.
temperatureMax
=
Math
.
max
(...
this
.
chipTableData
.
map
((
val
)
=>
val
.
temperature
))
*
1.2
;
// 1.2 In order to Demonstrated effect
if
(
res
.
data
.
momory
&&
res
.
data
.
momory
.
virtual
)
{
this
.
dealChartData
(
this
.
virtualChart
,
res
.
data
.
momory
.
virtual
);
this
.
setOption
(
this
.
virtualChart
);
}
if
(
res
.
data
.
cpu
)
{
const
overall
=
res
.
data
.
cpu
.
overall
||
{};
this
.
overallCpuInfo
=
Object
.
keys
(
overall
).
map
((
val
)
=>
{
return
{
label
:
val
,
value
:
overall
[
val
],
};
});
this
.
addtips
(
this
.
overallCpuInfo
);
this
.
cpuList
=
(
res
.
data
.
cpu
.
percpu
||
[]).
map
((
val
)
=>
{
return
{...
val
,
selected
:
false
};
});
while
(
this
.
cpuList
.
length
<
this
.
defaultCpuNum
)
{
this
.
cpuList
.
push
({});
}
if
(
this
.
selectedCpuIndex
!==
null
)
{
this
.
viewPerCpuInfo
(
this
.
selectedCpuIndex
);
}
else
{
this
.
selectedCpuInfo
=
[];
}
}
}
},
(
err
)
=>
{
this
.
chipTableData
=
[];
this
.
cpuList
=
[];
if
(
this
.
isReloading
)
{
this
.
$store
.
commit
(
'
setIsReload
'
,
false
);
this
.
isReloading
=
false
;
}
},
);
},
/**
* add tips
* @param {Array} arr cpu Info
*/
addtips
(
arr
)
{
arr
.
forEach
((
val
)
=>
{
switch
(
val
.
label
)
{
case
'
user
'
:
val
.
tips
=
this
.
$t
(
'
hardwareVisual.cpuUserTip
'
);
break
;
case
'
nice
'
:
val
.
tips
=
this
.
$t
(
'
hardwareVisual.cpuNiceTip
'
);
break
;
case
'
system
'
:
val
.
tips
=
this
.
$t
(
'
hardwareVisual.cpuSystemTip
'
);
break
;
case
'
idle
'
:
val
.
tips
=
this
.
$t
(
'
hardwareVisual.cpuIdleTip
'
);
break
;
case
'
iowait
'
:
val
.
tips
=
this
.
$t
(
'
hardwareVisual.cpuIowaitTip
'
);
break
;
case
'
irq
'
:
val
.
tips
=
this
.
$t
(
'
hardwareVisual.cpuIrqTip
'
);
break
;
case
'
softirq
'
:
val
.
tips
=
this
.
$t
(
'
hardwareVisual.cpuSoftirqTip
'
);
break
;
case
'
steal
'
:
val
.
tips
=
this
.
$t
(
'
hardwareVisual.cpuStealTip
'
);
break
;
case
'
guest
'
:
val
.
tips
=
this
.
$t
(
'
hardwareVisual.cpuGuestTip
'
);
break
;
case
'
guest_nice
'
:
val
.
tips
=
this
.
$t
(
'
hardwareVisual.cpuGuestniceTip
'
);
break
;
case
'
interrupt
'
:
val
.
tips
=
this
.
$t
(
'
hardwareVisual.cpuInterruptTip
'
);
break
;
case
'
dpc
'
:
val
.
tips
=
this
.
$t
(
'
hardwareVisual.cpuDpcTip
'
);
break
;
}
});
},
/**
* View the information of each cpu
* @param {Number} index index
*/
viewPerCpuInfo
(
index
)
{
this
.
cpuList
.
forEach
((
val
,
key
)
=>
{
if
(
val
.
idle
!==
undefined
)
{
if
(
index
===
key
)
{
this
.
selectedCpuIndex
=
key
;
val
.
selected
=
true
;
this
.
selectedCpuInfo
=
Object
.
keys
(
this
.
cpuList
[
index
]).
map
((
val
)
=>
{
return
{
label
:
val
,
value
:
this
.
cpuList
[
index
][
val
],
};
});
this
.
selectedCpuInfo
.
pop
();
}
else
{
if
(
this
.
cpuList
[
index
].
idle
!==
undefined
)
{
val
.
selected
=
false
;
}
}
}
});
this
.
addtips
(
this
.
selectedCpuInfo
);
},
/**
* Handling pie chart data
* @param {Object} chart chart obejct
* @param {Object} data chart data
*/
dealChartData
(
chart
,
data
)
{
const
virtual
=
Object
.
keys
(
data
);
chart
.
legend
=
virtual
.
reverse
();
chart
.
data
=
virtual
.
map
((
val
)
=>
{
return
{
value
:
data
[
val
],
name
:
val
,
};
});
chart
.
totalValue
=
0
;
chart
.
data
.
forEach
((
val
)
=>
{
chart
.
totalValue
+=
val
.
value
;
});
},
/**
* Data unit conversion
* @param {Number} n chart obejct
* @param {Boolean} type format type
* @return {String}
*/
bytesHuman
(
n
,
type
)
{
const
symbols
=
'
KMG
'
.
split
(
''
)
.
map
((
symbol
,
index
)
=>
[
symbol
,
1
<<
((
index
+
1
)
*
10
)]);
for
(
const
[
symbol
,
prefix
]
of
symbols
.
reverse
())
{
if
(
n
>=
prefix
)
{
if
(
type
)
{
return
`
${
n
}
(
${(
n
/
prefix
).
toFixed
(
1
)}${
symbol
}
)`
;
}
else
{
return
`
${(
n
/
prefix
).
toFixed
(
1
)}${
symbol
}
`
;
}
}
}
return
`
${
n
}
`
;
},
format
(
percentage
,
item
)
{
return
`
${
percentage
}
`
;
},
formatHbm
(
hbmInfo
)
{
return
function
()
{
return
`
${
hbmInfo
.
memory_usage
}
/
${
hbmInfo
.
memory_size
}
`
;
};
},
/**
* Enable automatic hardware refresh
*/
autoUpdateSamples
()
{
if
(
this
.
autoUpdateTimer
)
{
clearInterval
(
this
.
autoUpdateTimer
);
this
.
autoUpdateTimer
=
null
;
}
this
.
autoUpdateTimer
=
setInterval
(()
=>
{
this
.
$store
.
commit
(
'
clearToken
'
);
this
.
init
();
},
this
.
hardwareTimeReloadValue
*
1000
);
},
/**
* Disable automatic refresh
*/
stopUpdateSamples
()
{
if
(
this
.
autoUpdateTimer
)
{
clearInterval
(
this
.
autoUpdateTimer
);
this
.
autoUpdateTimer
=
null
;
}
},
setOption
(
chart
)
{
const
option
=
{
tooltip
:
{
trigger
:
'
item
'
,
formatter
:
(
params
)
=>
{
return
`
${
params
.
name
}
<br>
${
params
.
marker
}${
this
.
bytesHuman
(
params
.
value
,
true
)}
`
;
},
confine
:
true
,
},
legend
:
{
orient
:
'
vertical
'
,
left
:
'
50%
'
,
top
:
'
35%
'
,
icon
:
'
circle
'
,
data
:
chart
.
legend
,
formatter
:
(
params
)
=>
{
let
legendStr
=
''
;
for
(
let
i
=
0
;
i
<
chart
.
data
.
length
;
i
++
)
{
if
(
chart
.
data
[
i
].
name
===
params
)
{
const
name
=
chart
.
data
[
i
].
name
;
legendStr
=
`{a|
${
this
.
bytesHuman
(
chart
.
data
[
i
].
value
,
true
,
)}
}\n{b|
${
name
}
}`
;
}
}
return
legendStr
;
},
textStyle
:
{
rich
:
{
a
:
{
fontSize
:
14
,
},
b
:
{
color
:
'
#aeb2bf
'
,
},
},
},
},
series
:
[
{
name
:
''
,
center
:
[
'
25%
'
,
'
50%
'
],
type
:
'
pie
'
,
radius
:
[
'
40%
'
,
'
60%
'
],
avoidLabelOverlap
:
false
,
label
:
{
show
:
true
,
formatter
:
()
=>
{
return
`{a|
${
this
.
bytesHuman
(
chart
.
totalValue
)}
}{b|All}`
;
},
position
:
'
center
'
,
textStyle
:
{
rich
:
{
a
:
{
fontSize
:
20
,
color
:
'
#000
'
,
},
b
:
{
color
:
'
#aeb2bf
'
,
},
},
},
},
labelLine
:
{
show
:
false
,
},
data
:
chart
.
data
,
itemStyle
:
{
normal
:
{
color
:
(
params
)
=>
{
return
this
.
pieColorArr
[
params
.
dataIndex
];
},
},
},
},
],
};
this
.
$nextTick
(()
=>
{
const
cpuDom
=
document
.
getElementById
(
chart
.
id
);
if
(
cpuDom
)
{
chart
.
chartDom
=
echarts
.
init
(
cpuDom
,
null
);
chart
.
chartDom
.
setOption
(
option
,
true
);
chart
.
chartDom
.
resize
();
}
});
},
},
};
</
script
>
<
style
lang=
"scss"
>
.cl-hardware-visual
{
height
:
100%
;
background-color
:
#fff
;
.cl-hardware-content
{
height
:
100%
;
padding
:
0
24px
24px
24px
;
.cl-hardware-top
{
height
:
calc
(
100%
-
372px
);
padding-top
:
16px
;
&
>
div
{
width
:
100%
;
.el-table_1_column_1
,
.el-table_1_column_2
,
.el-table_1_column_3
,
.el-table_1_column_4
,
.el-table_1_column_5
{
text-align
:
center
;
}
.
el-table
:
:
before
{
height
:
0px
;
}
}
}
.cl-hardware-bottom
{
height
:
360px
;
.cl-hardware-left
{
width
:
calc
(
100%
-
466px
);
margin-right
:
16px
;
}
.cl-hardware-right
{
width
:
450px
;
}
}
&
>
div
{
height
:
calc
(
50%
-
8px
);
margin-bottom
:
16px
;
&
>
div
{
float
:
left
;
height
:
100%
;
border
:
1px
solid
#eee
;
border-radius
:
4px
;
padding
:
16px
;
.cl-sub-title
{
font-weight
:
bold
;
font-size
:
16px
;
margin-bottom
:
15px
;
}
.cl-sub-title.ram
{
margin-bottom
:
10px
;
}
.cl-chip-wrap
{
height
:
calc
(
100%
-
36px
);
overflow
:
auto
;
.el-icon-success
:before
{
color
:
#57d7ac
;
}
.el-icon-error
:before
{
color
:
#e37783
;
}
.el-icon-warning.normal
:before
{
color
:
#6f81e4
;
}
.el-icon-warning.important
:before
{
color
:
#faa048
;
}
.el-icon-warning.emergency
:before
{
color
:
#f06281
;
}
.el-icon-remove
:before
{
color
:
#8b8e95
;
}
.temp-wrap
{
.circle
{
width
:
10px
;
height
:
10px
;
border-radius
:
5px
;
background
:
#ffaa00
;
display
:
inline-block
;
position
:
absolute
;
left
:
1px
;
top
:
50%
;
margin-top
:
-4px
;
}
.circle.zero
{
background
:
#e6ebf5
;
}
.process-wrap
{
background
:
#e6ebf5
;
width
:
calc
(
100%
-
50px
);
height
:
6px
;
display
:
inline-block
;
border-top-right-radius
:
50px
;
border-bottom-right-radius
:
50px
;
margin-right
:
5px
;
.process-cover
{
height
:
6px
;
border-top-right-radius
:
50px
;
border-bottom-right-radius
:
50px
;
background
:
#ff5100
;
background-image
:
linear-gradient
(
to
right
,
#ffaa00
,
#ff5100
);
}
}
}
.hbs-wrap
{
.el-progress-bar
{
padding-right
:
140px
;
margin-right
:
-145px
;
}
}
.power
{
background
:
#e5f6f6
;
padding-left
:
10px
;
}
}
.cl-ram-wrap
{
height
:
calc
(
100%
-
36px
);
.virtual-wrap
{
height
:
100%
;
overflow
:
auto
;
#virtual
{
height
:
100%
;
overflow
:
hidden
;
}
}
}
.cl-disk-wrap
{
height
:
calc
(
100%
-
36px
);
overflow
:
auto
;
}
.cl-cpu-wrap
{
height
:
201px
;
.cpu-items
{
height
:
100%
;
overflow
:
auto
;
background
:
url('../../assets/images/cpu-bg.svg')
repeat
;
padding
:
3px
0
0
3px
;
.cpu-item
{
float
:
left
;
width
:
calc
(
6
.25%
-
3px
);
height
:
30px
;
text-align
:
center
;
background
:
#fff
;
margin-right
:
3px
;
margin-bottom
:
3px
;
cursor
:
pointer
;
.cpu
{
height
:
100%
;
line-height
:
30px
;
}
.cpu.selected
{
line-height
:
30px
;
outline
:
3px
solid
#00a5a7
;
}
}
}
.cpu-detail
{
&
>
div
{
margin-top
:
10px
;
&
>
span
{
margin-right
:
5px
;
color
:
#b2b4bb
;
}
&
>
div
{
display
:
inline-block
;
padding
:
0
7px
;
border-right
:
1px
solid
#ccc
;
&
:last-child
{
border-right
:
none
;
}
.label
{
margin-right
:
5px
;
cursor
:
pointer
;
}
.value
{
display
:
inline-block
;
width
:
40px
;
text-align
:
right
;
cursor
:
pointer
;
}
}
}
}
}
}
}
.el-table
thead
tr
{
background
:
#f0f3fa
;
}
.el-table
th
.is-leaf
.cell
{
border-left
:
1px
solid
#d4d9e6
;
}
.el-table
th
.is-leaf
:first-child
.cell
{
border-left
:
none
;
}
.el-pagination
{
margin
:
7px
0
;
float
:
right
;
}
}
.el-table
th
{
height
:
32px
;
}
.image-noData
{
width
:
100%
;
height
:
100%
;
display
:
flex
;
justify-content
:
center
;
align-items
:
center
;
flex-direction
:
column
;
p
{
font-size
:
16px
;
padding-top
:
10px
;
}
}
.el-icon-info
:before
{
color
:
#6c7280
;
}
}
</
style
>
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录