Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
MindSpore
mindinsight
提交
3780de85
M
mindinsight
项目概览
MindSpore
/
mindinsight
通知
7
Star
3
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看板
提交
3780de85
编写于
4月 21, 2020
作者:
M
mindspore-ci-bot
提交者:
Gitee
4月 21, 2020
浏览文件
操作
浏览文件
下载
差异文件
!54 UI Linkage of lineages: model and dataset(2nd commit)
Merge pull request !54 from 潘慧/master_ph
上级
4598422c
04934ab5
变更
3
隐藏空白更改
内联
并排
Showing
3 changed file
with
386 addition
and
328 deletion
+386
-328
mindinsight/ui/src/assets/css/reset.scss
mindinsight/ui/src/assets/css/reset.scss
+2
-2
mindinsight/ui/src/views/train-manage/data-traceback.vue
mindinsight/ui/src/views/train-manage/data-traceback.vue
+206
-167
mindinsight/ui/src/views/train-manage/model-traceback.vue
mindinsight/ui/src/views/train-manage/model-traceback.vue
+178
-159
未找到文件。
mindinsight/ui/src/assets/css/reset.scss
浏览文件 @
3780de85
...
...
@@ -156,8 +156,8 @@ body {
* Defines the width of the scroll bar and the width of the background, respectively corresponding to the dimensions of the horizontal and vertical scroll bars.
*/
::-webkit-scrollbar
{
width
:
6
px
;
height
:
6
px
;
width
:
10
px
;
height
:
10
px
;
}
/*
...
...
mindinsight/ui/src/views/train-manage/data-traceback.vue
浏览文件 @
3780de85
...
...
@@ -28,37 +28,37 @@ limitations under the License.
{{
$t
(
'
modelTraceback.showAllData
'
)
}}
</el-button>
<div
v-show=
"totalSeries&&totalSeries.length&&(!summaryDirList||(summaryDirList&&summaryDirList.length))"
>
<div
class=
"fixed-checkbox-group"
>
<el-checkbox
v-for=
"item in fixedSeries"
:key=
"item.id"
:checked=
"item.checked"
:disabled=
"true"
>
{{
item
.
name
}}
</el-checkbox>
<br
/>
</div>
<div
class=
"data-checkbox"
>
<!-- check box -->
<div
class=
"check-box-div"
>
<el-checkbox
v-model=
"checkAll"
:indeterminate=
"isIndeterminate"
class=
"select-all"
@
change=
"handleCheckAllChange"
>
{{
$t
(
'
scalar.selectAll
'
)
}}
<div
class=
"fixed-checkbox-group"
>
<el-checkbox
v-for=
"item in fixedSeries"
:key=
"item.id"
:checked=
"item.checked"
:disabled=
"true"
>
{{
item
.
name
}}
</el-checkbox>
<br
/>
</div>
<div
class=
"checkbox-scroll"
>
<div
class=
"checkbox-group-div"
>
<el-checkbox
v-for=
"item in noFixedSeries"
@
change=
"handleCheckedSeriesChange()"
v-model=
"item.checked"
:key=
"item.id"
>
{{
item
.
name
}}
<div
class=
"data-checkbox"
>
<!-- check box -->
<div
class=
"check-box-div"
>
<el-checkbox
v-model=
"checkAll"
:indeterminate=
"isIndeterminate"
class=
"select-all"
@
change=
"handleCheckAllChange"
>
{{
$t
(
'
scalar.selectAll
'
)
}}
</el-checkbox>
</div>
<div
class=
"checkbox-scroll"
>
<div
class=
"checkbox-group-div"
>
<el-checkbox
v-for=
"item in noFixedSeries"
@
change=
"handleCheckedSeriesChange()"
v-model=
"item.checked"
:key=
"item.id"
>
{{
item
.
name
}}
</el-checkbox>
</div>
</div>
</div>
</div>
</div>
</div>
<!-- echart drawing area -->
<div
id=
"data-echart"
></div>
...
...
@@ -80,13 +80,16 @@ limitations under the License.
:key=
"key"
:prop=
"key"
:label=
"table.columnOptions[key].label"
:sortable=
'sortArray.includes(table.columnOptions[key].label)?"custom":false'
:sortable=
"sortArray.includes(table.columnOptions[key].label)?'custom':false"
:fixed=
"table.columnOptions[key].label===text?true:false"
min-width=
"200"
show-overflow-tooltip
>
<template
slot=
"header"
slot-scope=
"scope"
>
<div
class=
"custom-label"
:title=
"scope.column.label"
>
<template
slot=
"header"
slot-scope=
"scope"
>
<div
class=
"custom-label"
:title=
"scope.column.label"
>
{{
scope
.
column
.
label
}}
</div>
</div>
</
template
>
<
template
slot-scope=
"scope"
>
<span
class=
"icon-container"
...
...
@@ -125,15 +128,15 @@ limitations under the License.
<img
:src=
"require('@/assets/images/nodata.png')"
alt=
""
/>
<p
class=
"no-data-text"
v-show=
"!summaryDirList||(summaryDirList&&summaryDirList.length)&&!lineagedata.serData"
>
v-show=
"!summaryDirList||(summaryDirList&&summaryDirList.length)&&!lineagedata.serData"
>
{{ $t('public.noData') }}
</p>
<div
v-show=
"echartNoData&&(lineagedata.serData&&!!lineagedata.serData.length)"
>
<p
class=
"no-data-text"
>
{{ $t('dataTraceback.noDataFound') }}
</p>
<div
v-show=
"echartNoData&&(lineagedata.serData&&!!lineagedata.serData.length)"
>
<p
class=
"no-data-text"
>
{{ $t('dataTraceback.noDataFound') }}
</p>
</div>
<div
v-show=
"summaryDirList&&!summaryDirList.length"
>
<p
class=
"no-data-text"
>
{{ $t('dataTraceback.noDataFound') }}
</p>
<p
class=
"no-data-text"
>
{{ $t('dataTraceback.noDataTips') }}
</p>
<p
class=
"no-data-text"
>
{{ $t('dataTraceback.noDataFound') }}
</p>
<p
class=
"no-data-text"
>
{{ $t('dataTraceback.noDataTips') }}
</p>
</div>
</div>
</div>
...
...
@@ -315,6 +318,10 @@ export default {
detailsDataTitle
:
''
,
detailsDataList
:
[],
rowName
:
this
.
$t
(
'
dataTraceback.details
'
),
replaceStr
:
{
metric
:
'
metric/
'
,
userDefined
:
'
user_defined/
'
,
},
};
},
computed
:
{},
...
...
@@ -328,23 +335,27 @@ export default {
* init
*/
init
()
{
this
.
customizedColumnOptions
=
this
.
$store
.
state
.
customizedColumnOptions
||
[];
this
.
table
.
columnOptions
=
Object
.
assign
(
this
.
table
.
columnOptions
,
this
.
customizedColumnOptions
);
this
.
customizedColumnOptions
=
this
.
$store
.
state
.
customizedColumnOptions
||
[];
this
.
table
.
columnOptions
=
Object
.
assign
(
this
.
table
.
columnOptions
,
this
.
customizedColumnOptions
,
);
// Obtain the value of summary_dir from the store,
this
.
summaryDirList
=
this
.
$store
.
state
.
summaryDirList
;
this
.
selectedBarList
=
this
.
$store
.
state
.
selectedBarList
;
if
(
this
.
selectedBarList
&&
this
.
selectedBarList
.
length
)
{
this
.
tableFilter
=
{};
this
.
summaryDirList
=
this
.
$store
.
state
.
summaryDirList
;
this
.
selectedBarList
=
this
.
$store
.
state
.
selectedBarList
;
if
(
this
.
selectedBarList
&&
this
.
selectedBarList
.
length
)
{
this
.
tableFilter
=
{};
}
else
{
this
.
tableFilter
.
lineage_type
=
{
in
:
[
'
dataset
'
]};
this
.
tableFilter
.
lineage_type
=
{
in
:
[
'
dataset
'
]};
}
const
params
=
{};
const
params
=
{};
if
(
this
.
summaryDirList
)
{
this
.
tableFilter
.
summary_dir
=
{
in
:
this
.
summaryDirList
};
this
.
tableFilter
.
summary_dir
=
{
in
:
this
.
summaryDirList
};
}
else
{
this
.
tableFilter
.
summary_dir
=
undefined
;
this
.
tableFilter
.
summary_dir
=
undefined
;
}
params
.
body
=
Object
.
assign
({},
this
.
tableFilter
);
params
.
body
=
Object
.
assign
({},
this
.
tableFilter
);
this
.
queryLineagesData
(
params
);
},
...
...
@@ -353,29 +364,24 @@ export default {
*/
initChart
()
{
const
parallelAxis
=
[];
const
selectedBarList
=
this
.
$store
.
state
.
selectedBarList
;
const
selectedBarList
=
this
.
$store
.
state
.
selectedBarList
;
const
data
=
[];
const
arrayTemp
=
[];
if
(
selectedBarList
&&
selectedBarList
.
length
)
{
selectedBarList
.
forEach
((
item
)
=>
{
const
value
=
this
.
customizedTypeObject
[
item
];
if
(
value
&&
value
.
type
==
'
float
'
)
{
arrayTemp
.
push
({
name
:
item
,
id
:
item
,
type
:
'
float
'
,
checked
:
true
,
});
}
else
{
arrayTemp
.
push
({
name
:
this
.
table
.
columnOptions
[
item
].
label
,
id
:
item
,
checked
:
true
,
});
const
arrayTemp
=
[];
if
(
selectedBarList
&&
selectedBarList
.
length
)
{
selectedBarList
.
forEach
((
item
)
=>
{
const
value
=
this
.
customizedTypeObject
[
item
];
const
obj
=
{
name
:
this
.
table
.
columnOptions
[
item
].
label
,
id
:
item
,
checked
:
true
,
};
if
(
value
&&
value
.
type
==
'
float
'
)
{
obj
.
type
=
'
float
'
;
}
arrayTemp
.
push
(
obj
);
});
}
const
totalBarArray
=
arrayTemp
.
concat
(
this
.
checkedSeries
);
const
totalBarArray
=
arrayTemp
.
concat
(
this
.
checkedSeries
);
this
.
echart
.
showData
.
forEach
((
val
,
i
)
=>
{
const
item
=
{
lineStyle
:
{
...
...
@@ -398,13 +404,13 @@ export default {
content
.
name
===
this
.
shuffleTitle
)
{
obj
.
scale
=
true
;
obj
.
minInterval
=
1
;
obj
.
minInterval
=
1
;
this
.
setColorOfSelectedBar
(
selectedBarList
,
obj
);
}
else
if
(
this
.
numberTypeIdList
.
includes
(
content
.
id
)
||
(
content
.
type
&&
content
.
type
==
'
float
'
)
this
.
numberTypeIdList
.
includes
(
content
.
id
)
||
(
content
.
type
&&
content
.
type
==
'
float
'
)
)
{
obj
.
scale
=
true
;
obj
.
scale
=
true
;
this
.
setColorOfSelectedBar
(
selectedBarList
,
obj
);
}
else
{
// String type
...
...
@@ -413,12 +419,11 @@ export default {
show
:
false
,
};
this
.
setColorOfSelectedBar
(
selectedBarList
,
obj
);
if
(
content
.
id
===
'
dataset_mark
'
)
{
obj
.
axisLabel
=
{
if
(
content
.
id
===
'
dataset_mark
'
)
{
obj
.
axisLabel
=
{
show
:
false
,
};
}
const
values
=
{};
this
.
echart
.
showData
.
forEach
((
i
)
=>
{
if
(
i
[
content
.
id
]
||
i
[
content
.
id
]
===
0
)
{
...
...
@@ -438,8 +443,8 @@ export default {
},
parallel
:
{
top
:
30
,
left
:
8
0
,
right
:
8
0
,
left
:
5
0
,
right
:
10
0
,
bottom
:
12
,
parallelAxisDefault
:
{
areaSelectStyle
:
{
...
...
@@ -454,7 +459,8 @@ export default {
series
:
{
type
:
'
parallel
'
,
lineStyle
:
{
width
:
2
,
width
:
1
,
opacity
:
1
,
},
data
:
data
,
},
...
...
@@ -490,17 +496,17 @@ export default {
});
}
const
tempList
=
this
.
echart
.
brushData
;
const
summaryList
=
[];
tempList
.
forEach
((
item
)
=>
{
const
summaryList
=
[];
tempList
.
forEach
((
item
)
=>
{
summaryList
.
push
(
item
.
summary_dir
);
});
// The summaryList value could not be saved in the destroy state.
this
.
dataCheckedSummary
=
[];
this
.
dataCheckedSummary
=
[];
this
.
$store
.
commit
(
'
setSummaryDirList
'
,
summaryList
);
if
(
!
tempList
.
length
)
{
this
.
summaryDirList
=
[];
this
.
lineagedata
.
serData
=
undefined
;
document
.
querySelector
(
'
#data-echart
'
).
style
.
display
=
'
none
'
;
this
.
summaryDirList
=
[];
this
.
lineagedata
.
serData
=
undefined
;
document
.
querySelector
(
'
#data-echart
'
).
style
.
display
=
'
none
'
;
}
else
{
this
.
echart
.
showData
=
this
.
echart
.
brushData
;
this
.
initChart
();
...
...
@@ -516,21 +522,39 @@ export default {
},
/**
* Set the color of the model tracing axis.
* @param {Array} selectedBarList
* @param {Object} obj
* @param {Array} selectedBarList
* @param {Object} obj
*/
setColorOfSelectedBar
(
selectedBarList
,
obj
)
{
if
(
selectedBarList
&&
obj
.
dim
<
selectedBarList
.
length
)
{
obj
.
nameTextStyle
=
{
if
(
selectedBarList
&&
obj
.
dim
<
selectedBarList
.
length
)
{
obj
.
nameTextStyle
=
{
color
:
'
#00a5a7
'
,
};
obj
.
axisLabel
=
{
obj
.
axisLabel
=
{
show
:
true
,
textStyle
:
{
color
:
'
#00a5a7
'
,
},
formatter
:
function
(
val
)
{
if
(
typeof
val
!==
'
string
'
)
{
return
val
;
}
const
strs
=
val
.
split
(
''
);
let
str
=
''
;
if
(
val
.
length
>
100
)
{
return
val
.
substring
(
0
,
12
)
+
'
...
'
;
}
else
{
for
(
let
i
=
0
,
s
=
''
;
(
s
=
strs
[
i
++
]);
)
{
str
+=
s
;
if
(
!
(
i
%
12
))
{
str
+=
'
\n
'
;
}
}
return
str
;
}
},
};
obj
.
axisLine
=
{
obj
.
axisLine
=
{
show
:
true
,
lineStyle
:
{
color
:
'
#00a5a7
'
,
...
...
@@ -538,7 +562,7 @@ export default {
};
}
else
{
// Text color
obj
.
nameTextStyle
=
{
obj
.
nameTextStyle
=
{
color
:
'
black
'
,
};
}
...
...
@@ -567,22 +591,20 @@ export default {
if
(
isNaN
(
value
)
||
!
value
)
{
return
value
;
}
else
{
if
(
key
===
'
accuracy
'
)
{
return
this
.
toFixedFun
(
value
*
100
,
2
)
+
'
%
'
;
}
else
if
(
key
===
'
learning_rate
'
)
{
let
temp
=
value
.
toPrecision
(
3
);
if
(
key
===
'
learning_rate
'
)
{
let
temp
=
value
.
toPrecision
(
4
);
let
row
=
0
;
while
(
temp
<
1
)
{
temp
=
temp
*
10
;
row
+=
1
;
}
temp
=
this
.
toFixedFun
(
temp
,
2
);
temp
=
this
.
toFixedFun
(
temp
,
4
);
return
`
${
temp
}${
row
?
`e-
${
row
}
`
:
''
}
`
;
}
else
if
(
key
===
'
model_size
'
)
{
return
value
+
'
MB
'
;
}
else
{
if
(
value
<
1000
)
{
return
Math
.
round
(
value
*
Math
.
pow
(
10
,
2
))
/
Math
.
pow
(
10
,
2
);
return
Math
.
round
(
value
*
Math
.
pow
(
10
,
4
))
/
Math
.
pow
(
10
,
4
);
}
else
{
const
reg
=
/
(?=(\B)(\d{3})
+$
)
/g
;
return
(
value
+
''
).
replace
(
reg
,
'
,
'
);
...
...
@@ -610,17 +632,15 @@ export default {
* @param {Object} scope
*/
showDialogData
(
val
,
scope
)
{
if
(
typeof
val
!==
'
string
'
||
val
==
'
{}
'
)
{
if
(
typeof
val
!==
'
string
'
||
val
==
'
{}
'
)
{
return
;
}
else
{
const
isJson
=
this
.
isJSON
(
val
);
const
isJson
=
this
.
isJSON
(
val
);
if
(
!
isJson
)
{
return
;
}
}
this
.
rowName
=
`
${
scope
.
column
.
property
}${
this
.
$t
(
'
dataTraceback.details
'
,
)}
`
;
this
.
rowName
=
`
${
scope
.
column
.
label
}${
this
.
$t
(
'
dataTraceback.details
'
)}
`
;
this
.
detailsDialogVisible
=
true
;
this
.
detailsDataTitle
=
scope
.
row
.
summary_dir
;
this
.
detailsDataList
=
this
.
formateJsonString
(
val
);
...
...
@@ -666,52 +686,69 @@ export default {
if
(
!
res
||
!
res
.
data
)
{
return
;
}
this
.
customizedTypeObject
=
res
.
data
.
customized
;
const
key
=
Object
.
keys
(
this
.
customizedTypeObject
);
if
(
key
.
length
)
{
this
.
sortArray
=
this
.
sortArray
.
concat
(
key
);
this
.
customizedTypeObject
=
res
.
data
.
customized
;
let
keys
=
Object
.
keys
(
this
.
customizedTypeObject
);
if
(
keys
.
length
)
{
keys
=
keys
.
map
((
i
)
=>
{
if
(
i
.
startsWith
(
this
.
replaceStr
.
userDefined
))
{
return
i
.
replace
(
this
.
replaceStr
.
userDefined
,
'
[U]
'
);
}
else
if
(
i
.
startsWith
(
this
.
replaceStr
.
metric
))
{
return
i
.
replace
(
this
.
replaceStr
.
metric
,
'
[M]
'
);
}
});
this
.
sortArray
=
this
.
sortArray
.
concat
(
keys
);
}
// Model source tracing filtering parameters
this
.
selectedBarList
=
this
.
$store
.
state
.
selectedBarList
;
if
(
this
.
selectedBarList
&&
this
.
selectedBarList
.
length
)
{
this
.
selectedBarList
=
this
.
$store
.
state
.
selectedBarList
;
if
(
this
.
selectedBarList
&&
this
.
selectedBarList
.
length
)
{
const
tempList
=
JSON
.
parse
(
JSON
.
stringify
(
res
.
data
.
object
));
const
list
=
[];
const
metricKeys
=
{};
tempList
.
forEach
((
item
)
=>
{
const
list
=
[];
const
metricKeys
=
{};
tempList
.
forEach
((
item
)
=>
{
if
(
item
.
model_lineage
)
{
const
i
=
JSON
.
parse
(
JSON
.
stringify
(
item
.
model_lineage
));
i
.
model_size
=
parseFloat
(((
i
.
model_size
||
0
)
/
1024
/
1024
).
toFixed
(
2
));
const
keys
=
Object
.
keys
(
i
.
metric
||
{});
const
modelData
=
JSON
.
parse
(
JSON
.
stringify
(
item
.
model_lineage
),
);
modelData
.
model_size
=
parseFloat
(
((
modelData
.
model_size
||
0
)
/
1024
/
1024
).
toFixed
(
2
),
);
const
keys
=
Object
.
keys
(
modelData
.
metric
||
{});
if
(
keys
.
length
)
{
keys
.
forEach
((
key
)
=>
{
if
(
i
.
metric
[
key
]
||
i
.
metric
[
key
]
===
0
)
{
const
temp
=
'
metric/
'
+
key
;
metricKeys
[
temp
]
=
key
;
i
[
temp
]
=
i
.
metric
[
key
];
keys
.
forEach
((
key
)
=>
{
if
(
modelData
.
metric
[
key
]
||
modelData
.
metric
[
key
]
===
0
)
{
const
temp
=
this
.
replaceStr
.
metric
+
key
;
metricKeys
[
temp
]
=
key
;
modelData
[
temp
]
=
modelData
.
metric
[
key
];
}
});
delete
i
.
metric
;
delete
modelData
.
metric
;
}
const
udkeys
=
Object
.
keys
(
i
.
user_defined
||
{});
const
udkeys
=
Object
.
keys
(
modelData
.
user_defined
||
{});
if
(
udkeys
.
length
)
{
udkeys
.
forEach
((
key
)
=>
{
if
(
i
.
user_defined
[
key
]
||
i
.
user_defined
[
key
]
===
0
)
{
const
temp
=
'
user_defined/
'
+
key
;
i
[
temp
]
=
i
.
user_defined
[
key
];
udkeys
.
forEach
((
key
)
=>
{
if
(
modelData
.
user_defined
[
key
]
||
modelData
.
user_defined
[
key
]
===
0
)
{
const
temp
=
this
.
replaceStr
.
userDefined
+
key
;
modelData
[
temp
]
=
modelData
.
user_defined
[
key
];
}
});
delete
i
.
user_defined
;
delete
modelData
.
user_defined
;
}
list
.
push
(
i
);
list
.
push
(
modelData
);
}
});
this
.
modelObjectArray
=
[];
for
(
let
i
=
0
;
i
<
list
.
length
;
i
++
)
{
const
modelObject
=
{};
for
(
let
j
=
0
;
j
<
this
.
selectedBarList
.
length
;
j
++
)
{
const
tempObject
=
list
[
i
];
const
key
=
this
.
selectedBarList
[
j
];
modelObject
[
key
]
=
tempObject
[
key
];
this
.
modelObjectArray
=
[];
for
(
let
i
=
0
;
i
<
list
.
length
;
i
++
)
{
const
modelObject
=
{};
for
(
let
j
=
0
;
j
<
this
.
selectedBarList
.
length
;
j
++
)
{
const
tempObject
=
list
[
i
];
const
key
=
this
.
selectedBarList
[
j
];
modelObject
[
key
]
=
tempObject
[
key
];
}
this
.
modelObjectArray
.
push
(
modelObject
);
}
...
...
@@ -723,7 +760,7 @@ export default {
this
.
lineagedata
=
this
.
formateOriginData
(
res
.
data
);
this
.
totalSeries
=
this
.
lineagedata
.
fullNodeList
;
if
(
!
this
.
totalSeries
.
length
)
{
this
.
echartNoData
=
true
;
this
.
echartNoData
=
true
;
}
this
.
totalSeries
.
forEach
((
nodeItem
)
=>
{
if
(
this
.
createType
[
nodeItem
.
name
])
{
...
...
@@ -752,14 +789,14 @@ export default {
this
.
setEchartValue
();
this
.
initChart
();
// Total number of pages in the table
this
.
pagination
.
total
=
res
.
data
.
count
;
this
.
pagination
.
total
=
res
.
data
.
count
;
// Data encapsulation of the table
this
.
setTableData
();
if
(
this
.
selectedBarList
)
{
const
resultArray
=
this
.
hideDataMarkTableData
();
this
.
table
.
column
=
this
.
dirPathList
.
concat
(
const
resultArray
=
this
.
hideDataMarkTableData
();
this
.
table
.
column
=
this
.
dirPathList
.
concat
(
resultArray
,
this
.
checkedSeries
.
map
((
i
)
=>
i
.
id
),
this
.
checkedSeries
.
map
((
i
)
=>
i
.
id
),
);
}
else
{
this
.
table
.
column
=
this
.
dirPathList
.
concat
(
...
...
@@ -806,15 +843,15 @@ export default {
*/
echartShowAllData
()
{
// The first page is displayed.
this
.
initOver
=
false
;
this
.
echartNoData
=
false
;
this
.
initOver
=
false
;
this
.
echartNoData
=
false
;
this
.
pagination
.
currentPage
=
1
;
this
.
$store
.
commit
(
'
setSummaryDirList
'
,
undefined
);
this
.
$store
.
commit
(
'
setSelectedBarList
'
,
[]);
if
(
this
.
parallelEchart
)
{
this
.
parallelEchart
.
clear
();
}
document
.
querySelector
(
'
#data-echart
'
).
style
.
display
=
'
block
'
;
document
.
querySelector
(
'
#data-echart
'
).
style
.
display
=
'
block
'
;
this
.
$refs
.
table
.
clearSelection
();
this
.
init
();
this
.
parallelEchart
.
resize
();
...
...
@@ -832,10 +869,10 @@ export default {
this
.
getCheckedSerList
();
// Value assignment in the table column
if
(
this
.
selectedBarList
)
{
const
resultArray
=
this
.
hideDataMarkTableData
();
this
.
table
.
column
=
this
.
dirPathList
.
concat
(
const
resultArray
=
this
.
hideDataMarkTableData
();
this
.
table
.
column
=
this
.
dirPathList
.
concat
(
resultArray
,
this
.
checkedSeries
.
map
((
i
)
=>
i
.
id
),
this
.
checkedSeries
.
map
((
i
)
=>
i
.
id
),
);
}
else
{
this
.
table
.
column
=
this
.
dirPathList
.
concat
(
...
...
@@ -852,9 +889,9 @@ export default {
* @return {Array}
*/
hideDataMarkTableData
()
{
const
result
=
[];
this
.
selectedBarList
.
forEach
((
item
)
=>
{
if
(
item
!==
'
dataset_mark
'
)
{
const
result
=
[];
this
.
selectedBarList
.
forEach
((
item
)
=>
{
if
(
item
!==
'
dataset_mark
'
)
{
result
.
push
(
item
);
}
});
...
...
@@ -868,12 +905,11 @@ export default {
this
.
$forceUpdate
();
this
.
getCheckedSerList
();
// Value assignment in the table column
// Value assignment in the table column
if
(
this
.
selectedBarList
)
{
const
resultArray
=
this
.
hideDataMarkTableData
();
this
.
table
.
column
=
this
.
dirPathList
.
concat
(
const
resultArray
=
this
.
hideDataMarkTableData
();
this
.
table
.
column
=
this
.
dirPathList
.
concat
(
resultArray
,
this
.
checkedSeries
.
map
((
i
)
=>
i
.
id
),
this
.
checkedSeries
.
map
((
i
)
=>
i
.
id
),
);
}
else
{
this
.
table
.
column
=
this
.
dirPathList
.
concat
(
...
...
@@ -892,7 +928,7 @@ export default {
*/
handleSelectionChange
(
val
)
{
// summary_dir cannot be stored here.If it is not selected ,it cannot be stroed correctly.
this
.
dataCheckedSummary
=
val
;
this
.
dataCheckedSummary
=
val
;
if
(
val
.
length
)
{
this
.
echart
.
showData
=
val
;
}
else
{
...
...
@@ -903,10 +939,13 @@ export default {
setEchartValue
()
{
if
(
this
.
modelObjectArray
.
length
)
{
const
list
=
this
.
echart
.
showData
;
for
(
let
i
=
0
;
i
<
list
.
length
;
i
++
)
{
const
temp
=
this
.
modelObjectArray
[
i
];
this
.
echart
.
showData
[
i
]
=
Object
.
assign
(
this
.
echart
.
showData
[
i
],
temp
);
const
list
=
this
.
echart
.
showData
;
for
(
let
i
=
0
;
i
<
list
.
length
;
i
++
)
{
const
temp
=
this
.
modelObjectArray
[
i
];
this
.
echart
.
showData
[
i
]
=
Object
.
assign
(
this
.
echart
.
showData
[
i
],
temp
,
);
}
}
},
...
...
@@ -916,12 +955,12 @@ export default {
* @param {Object} data
*/
tableSortChange
(
data
)
{
const
params
=
{};
const
tempParam
=
{
const
params
=
{};
const
tempParam
=
{
sorted_name
:
data
.
prop
,
sorted_type
:
data
.
order
,
};
params
.
body
=
Object
.
assign
({},
tempParam
,
this
.
tableFilter
);
params
.
body
=
Object
.
assign
({},
tempParam
,
this
.
tableFilter
);
this
.
queryLineagesData
(
params
);
},
...
...
@@ -1130,9 +1169,9 @@ export default {
* Destroy the page
*/
destroyed
()
{
if
(
this
.
dataCheckedSummary
&&
this
.
dataCheckedSummary
.
length
)
{
const
summaryDirList
=
[];
this
.
dataCheckedSummary
.
forEach
((
item
)
=>
{
if
(
this
.
dataCheckedSummary
&&
this
.
dataCheckedSummary
.
length
)
{
const
summaryDirList
=
[];
this
.
dataCheckedSummary
.
forEach
((
item
)
=>
{
summaryDirList
.
push
(
item
.
summary_dir
);
});
this
.
$store
.
commit
(
'
setSummaryDirList
'
,
summaryDirList
);
...
...
@@ -1165,9 +1204,9 @@ export default {
img
{
max-width
:
100%
;
}
p
{
font-size
:
16px
;
padding-top
:
10px
p
{
font-size
:
16px
;
padding-top
:
10px
;
}
}
.no-data-text
{
...
...
@@ -1185,7 +1224,7 @@ export default {
.data-checkbox-area
{
position
:
relative
;
margin
:
24px
32px
12px
;
height
:
62px
;
height
:
62px
;
.reset-btn
{
position
:
absolute
;
right
:
0px
;
...
...
@@ -1239,10 +1278,10 @@ export default {
height
:
calc
(
60%
-
90px
);
margin
:
2px
32px
0
;
position
:
relative
;
.custom-label
{
max-width
:calc
(
100
%
-
25px
)
;
padding
:
0
;
vertical-align
:middle
;
.custom-label
{
max-width
:
calc
(
100%
-
25px
);
padding
:
0
;
vertical-align
:
middle
;
}
.el-icon-warning
{
font-size
:
16px
;
...
...
mindinsight/ui/src/views/train-manage/model-traceback.vue
浏览文件 @
3780de85
...
...
@@ -16,18 +16,17 @@ limitations under the License.
<
template
>
<div
id=
"cl-model-traceback"
>
<div
class=
"cl-model-right"
>
<div
class=
"checkbox-area"
>
<el-button
class=
"reset-btn custom-btn"
@
click=
"resetChart"
type=
"primary"
size=
"mini"
plain
v-if=
"(!noData && echart.allData.length) ||
(noData && summaryDirList && !summaryDirList.length)"
>
{{
$t
(
'
modelTraceback.showAllData
'
)
}}
</el-button>
<div
class=
"top-area"
>
<div
class=
"checkbox"
:style=
"
{'max-height': haveCustomizedParams ? '88px' : '66px',
'min-height': haveCustomizedParams ? '63px' : '42px'}"
v-if="!noData
&&
echart.allData.length
&&
(!summaryDirList ||(summaryDirList && summaryDirList.length))"
>
(!summaryDirList || (summaryDirList
&&
summaryDirList.length))">
<div
class=
"label-legend"
v-if=
"haveCustomizedParams"
>
<div>
[U]:
{{
$t
(
'
modelTraceback.userDefined
'
)
}}
</div>
<div>
[M]:
{{
$t
(
'
modelTraceback.metric
'
)
}}
</div>
</div>
<el-checkbox
v-for=
"item in table.mandatoryColumn"
:key=
"item"
:label=
"item"
...
...
@@ -45,11 +44,21 @@ limitations under the License.
<el-checkbox
v-for=
"item in table.optionalColumn"
:key=
"item"
:label=
"item"
:class=
"
table.optionsNotInCheckbox.includes(item) ? 'notShow' : 'option'
"
>
{{
table
.
columnOptions
[
item
].
label
}}
</el-checkbox>
:class=
"table.optionsNotInCheckbox.includes(item) ? 'notShow' : 'option'"
>
{{
table
.
columnOptions
[
item
].
label
}}
</el-checkbox>
</el-checkbox-group>
</div>
<div
class=
"btns"
>
<el-button
class=
"custom-btn"
@
click=
"resetChart"
type=
"primary"
size=
"mini"
plain
v-if=
"(!noData && echart.allData.length) ||
(noData && summaryDirList && !summaryDirList.length)"
>
{{
$t
(
'
modelTraceback.showAllData
'
)
}}
</el-button>
</div>
</div>
<div
id=
"echart"
v-show=
"!noData"
></div>
...
...
@@ -71,6 +80,7 @@ limitations under the License.
:key=
"key"
:prop=
"key"
:label=
"table.columnOptions[key].label"
:fixed=
"table.columnOptions[key].label===text?true:false"
show-overflow-tooltip
min-width=
"180"
sortable=
"custom"
>
...
...
@@ -123,6 +133,7 @@ export default {
return
{
table
:
{},
summaryDirList
:
undefined
,
text
:
this
.
$t
(
'
modelTraceback.summaryPath
'
),
checkedSummary
:
[],
keysOfStringValue
:
[
'
summary_dir
'
,
...
...
@@ -160,6 +171,11 @@ export default {
},
showTable
:
false
,
noData
:
false
,
haveCustomizedParams
:
false
,
replaceStr
:
{
metric
:
'
metric/
'
,
userDefined
:
'
user_defined/
'
,
},
};
},
computed
:
{},
...
...
@@ -311,51 +327,32 @@ export default {
.
then
(
(
res
)
=>
{
if
(
res
&&
res
.
data
&&
res
.
data
.
object
)
{
const
tempList
=
JSON
.
parse
(
JSON
.
stringify
(
res
.
data
.
object
));
const
list
=
[];
tempList
.
forEach
((
item
)
=>
{
if
(
item
.
model_lineage
)
{
item
.
model_lineage
.
summary_dir
=
item
.
summary_dir
;
const
i
=
JSON
.
parse
(
JSON
.
stringify
(
item
.
model_lineage
));
i
.
model_size
=
parseFloat
(
((
i
.
model_size
||
0
)
/
1024
/
1024
).
toFixed
(
2
),
);
const
keys
=
Object
.
keys
(
i
.
metric
||
{});
if
(
keys
.
length
)
{
keys
.
forEach
((
key
)
=>
{
if
(
i
.
metric
[
key
]
||
i
.
metric
[
key
]
===
0
)
{
const
temp
=
'
metric/
'
+
key
;
i
[
temp
]
=
i
.
metric
[
key
];
}
});
delete
i
.
metric
;
}
const
udkeys
=
Object
.
keys
(
i
.
user_defined
||
{});
if
(
udkeys
.
length
)
{
udkeys
.
forEach
((
key
)
=>
{
if
(
i
.
user_defined
[
key
]
||
i
.
user_defined
[
key
]
===
0
)
{
const
temp
=
'
user_defined/
'
+
key
;
i
[
temp
]
=
i
.
user_defined
[
key
];
}
});
delete
i
.
user_defined
;
}
list
.
push
(
i
);
}
});
const
list
=
this
.
setDataOfModel
(
res
.
data
.
object
);
if
(
allData
)
{
let
customized
=
{};
if
(
res
.
data
.
customized
)
{
customized
=
JSON
.
parse
(
JSON
.
stringify
(
res
.
data
.
customized
));
const
customizedKeys
=
Object
.
keys
(
customized
);
if
(
customizedKeys
.
length
>
0
)
{
if
(
customizedKeys
.
length
)
{
customizedKeys
.
forEach
((
i
)
=>
{
if
(
customized
[
i
].
type
===
'
int
'
)
{
this
.
keysOfIntValue
.
push
(
i
);
}
else
if
(
customized
[
i
].
type
===
'
str
'
)
{
this
.
keysOfStringValue
.
push
(
i
);
}
if
(
i
.
startsWith
(
this
.
replaceStr
.
userDefined
))
{
customized
[
i
].
label
=
customized
[
i
].
label
.
replace
(
this
.
replaceStr
.
userDefined
,
'
[U]
'
,
);
}
else
if
(
i
.
startsWith
(
this
.
replaceStr
.
metric
))
{
customized
[
i
].
label
=
customized
[
i
].
label
.
replace
(
this
.
replaceStr
.
metric
,
'
[M]
'
,
);
}
});
this
.
haveCustomizedParams
=
true
;
}
}
this
.
table
.
columnOptions
=
Object
.
assign
(
...
...
@@ -377,6 +374,7 @@ export default {
this
.
noData
=
!
res
.
data
.
object
.
length
;
this
.
echart
.
showData
=
this
.
echart
.
brushData
=
this
.
echart
.
allData
=
list
;
Object
.
keys
(
this
.
table
.
columnOptions
).
forEach
((
i
)
=>
{
this
.
table
.
columnOptions
[
i
].
selected
=
true
;
const
flag
=
list
.
some
((
val
)
=>
{
return
val
[
i
]
||
val
[
i
]
===
0
;
});
...
...
@@ -415,19 +413,71 @@ export default {
)
.
catch
(()
=>
{});
},
/**
* Selected data in the table
* @param {Array} data
* @return {Array}
*/
setDataOfModel
(
data
=
[])
{
const
modelLineageList
=
[];
data
.
forEach
((
item
)
=>
{
if
(
item
.
model_lineage
)
{
item
.
model_lineage
.
summary_dir
=
item
.
summary_dir
;
const
modelData
=
JSON
.
parse
(
JSON
.
stringify
(
item
.
model_lineage
));
modelData
.
model_size
=
parseFloat
(
((
modelData
.
model_size
||
0
)
/
1024
/
1024
).
toFixed
(
2
),
);
const
keys
=
Object
.
keys
(
modelData
.
metric
||
{});
if
(
keys
.
length
)
{
keys
.
forEach
((
key
)
=>
{
if
(
modelData
.
metric
[
key
]
||
modelData
.
metric
[
key
]
===
0
)
{
const
temp
=
this
.
replaceStr
.
metric
+
key
;
modelData
[
temp
]
=
modelData
.
metric
[
key
];
}
});
delete
modelData
.
metric
;
}
const
udkeys
=
Object
.
keys
(
modelData
.
user_defined
||
{});
if
(
udkeys
.
length
)
{
udkeys
.
forEach
((
key
)
=>
{
if
(
modelData
.
user_defined
[
key
]
||
modelData
.
user_defined
[
key
]
===
0
)
{
const
temp
=
this
.
replaceStr
.
userDefined
+
key
;
modelData
[
temp
]
=
modelData
.
user_defined
[
key
];
}
});
delete
modelData
.
user_defined
;
}
modelLineageList
.
push
(
modelData
);
}
});
return
modelLineageList
;
},
/**
* The column options in the table are changed.
*/
columnSelectionChange
()
{
this
.
table
.
optionalColumn
.
forEach
((
key
)
=>
{
this
.
table
.
columnOptions
[
key
].
selected
=
false
;
});
this
.
table
.
selectedColumn
.
forEach
((
key
)
=>
{
this
.
table
.
columnOptions
[
key
].
selected
=
true
;
});
const
columnCount
=
Object
.
keys
(
this
.
table
.
columnOptions
).
length
-
this
.
table
.
optionsNotInCheckbox
.
length
;
this
.
table
.
column
=
this
.
table
.
mandatoryColumn
.
concat
(
this
.
table
.
selectedColumn
)
.
filter
((
i
)
=>
{
return
!
this
.
table
.
optionsNotInTable
.
includes
(
i
);
});
this
.
table
.
column
=
Object
.
keys
(
this
.
table
.
columnOptions
).
filter
((
i
)
=>
{
return
(
this
.
table
.
columnOptions
[
i
].
selected
&&
!
this
.
table
.
optionsNotInTable
.
includes
(
i
)
);
});
this
.
table
.
selectAll
=
this
.
table
.
selectedColumn
...
...
@@ -481,39 +531,7 @@ export default {
.
then
(
(
res
)
=>
{
if
(
res
&&
res
.
data
&&
res
.
data
.
object
)
{
const
tempList
=
JSON
.
parse
(
JSON
.
stringify
(
res
.
data
.
object
));
const
list
=
[];
tempList
.
forEach
((
item
)
=>
{
if
(
item
.
model_lineage
)
{
item
.
model_lineage
.
summary_dir
=
item
.
summary_dir
;
const
i
=
JSON
.
parse
(
JSON
.
stringify
(
item
.
model_lineage
));
i
.
model_size
=
parseFloat
(
((
i
.
model_size
||
0
)
/
1024
/
1024
).
toFixed
(
2
),
);
const
keys
=
Object
.
keys
(
i
.
metric
||
{});
if
(
keys
.
length
)
{
keys
.
forEach
((
key
)
=>
{
if
(
i
.
metric
[
key
]
||
i
.
metric
[
key
]
===
0
)
{
const
temp
=
'
metric/
'
+
key
;
i
[
temp
]
=
i
.
metric
[
key
];
}
});
delete
i
.
metric
;
}
const
udkeys
=
Object
.
keys
(
i
.
user_defined
||
{});
if
(
udkeys
.
length
)
{
udkeys
.
forEach
((
key
)
=>
{
if
(
i
.
user_defined
[
key
]
||
i
.
user_defined
[
key
]
===
0
)
{
const
temp
=
'
user_defined/
'
+
key
;
i
[
temp
]
=
i
.
user_defined
[
key
];
}
});
delete
i
.
user_defined
;
}
list
.
push
(
i
);
}
});
const
list
=
this
.
setDataOfModel
(
res
.
data
.
object
);
this
.
table
.
data
=
list
;
this
.
pagination
.
total
=
res
.
data
.
count
||
0
;
this
.
pagination
.
currentPage
=
0
;
...
...
@@ -527,11 +545,12 @@ export default {
* Initializing the Eechart
*/
initChart
()
{
const
chartAxis
=
this
.
table
.
mandatoryColumn
.
concat
(
this
.
table
.
selectedColumn
)
.
filter
((
i
)
=>
{
return
!
this
.
table
.
optionsNotInEchart
.
includes
(
i
);
});
const
chartAxis
=
Object
.
keys
(
this
.
table
.
columnOptions
).
filter
((
i
)
=>
{
return
(
this
.
table
.
columnOptions
[
i
].
selected
&&
!
this
.
table
.
optionsNotInEchart
.
includes
(
i
)
);
});
const
data
=
[];
this
.
echart
.
showData
.
forEach
((
i
,
index
)
=>
{
const
item
=
{
...
...
@@ -566,6 +585,33 @@ export default {
obj
.
axisLabel
=
{
show
:
false
,
};
}
else
{
obj
.
axisLabel
=
{
formatter
:
function
(
val
)
{
const
strs
=
val
.
split
(
''
);
let
str
=
''
;
if
(
val
.
length
>
100
)
{
return
val
.
substring
(
0
,
12
)
+
'
...
'
;
}
else
{
if
(
chartAxis
.
length
<
10
)
{
for
(
let
i
=
0
,
s
=
''
;
(
s
=
strs
[
i
++
]);
)
{
str
+=
s
;
if
(
!
(
i
%
16
))
{
str
+=
'
\n
'
;
}
}
}
else
{
for
(
let
i
=
0
,
s
=
''
;
(
s
=
strs
[
i
++
]);
)
{
str
+=
s
;
if
(
!
(
i
%
12
))
{
str
+=
'
\n
'
;
}
}
}
return
str
;
}
},
};
}
}
if
(
this
.
keysOfIntValue
.
includes
(
key
))
{
...
...
@@ -583,7 +629,7 @@ export default {
parallel
:
{
top
:
25
,
left
:
50
,
right
:
8
0
,
right
:
10
0
,
bottom
:
10
,
parallelAxisDefault
:
{
type
:
'
value
'
,
...
...
@@ -695,45 +741,14 @@ export default {
RequestService
.
queryLineagesData
(
filterParams
)
.
then
(
(
res
)
=>
{
if
(
res
&&
res
.
data
&&
res
.
data
.
object
)
{
const
tempList
=
JSON
.
parse
(
JSON
.
stringify
(
res
.
data
.
object
));
const
list
=
[];
const
summaryDirList
=
[];
tempList
.
forEach
((
item
)
=>
{
if
(
item
.
model_lineage
)
{
item
.
model_lineage
.
summary_dir
=
item
.
summary_dir
;
const
i
=
JSON
.
parse
(
JSON
.
stringify
(
item
.
model_lineage
));
i
.
model_size
=
parseFloat
(
((
i
.
model_size
||
0
)
/
1024
/
1024
).
toFixed
(
2
),
);
const
keys
=
Object
.
keys
(
i
.
metric
||
{});
if
(
keys
.
length
)
{
keys
.
forEach
((
key
)
=>
{
if
(
i
.
metric
[
key
]
||
i
.
metric
[
key
]
===
0
)
{
const
temp
=
'
metric/
'
+
key
;
i
[
temp
]
=
i
.
metric
[
key
];
}
});
delete
i
.
metric
;
}
summaryDirList
.
push
(
i
.
summary_dir
);
const
udkeys
=
Object
.
keys
(
i
.
user_defined
||
{});
if
(
udkeys
.
length
)
{
udkeys
.
forEach
((
key
)
=>
{
if
(
i
.
user_defined
[
key
]
||
i
.
user_defined
[
key
]
===
0
)
{
const
temp
=
'
user_defined/
'
+
key
;
i
[
temp
]
=
i
.
user_defined
[
key
];
}
});
delete
i
.
user_defined
;
}
list
.
push
(
i
);
}
});
if
(
res
&&
res
.
data
&&
res
.
data
.
object
&&
res
.
data
.
object
.
length
)
{
const
list
=
this
.
setDataOfModel
(
res
.
data
.
object
);
const
summaryDirList
=
list
.
map
((
i
)
=>
i
.
summary_dir
);
this
.
$store
.
commit
(
'
setSummaryDirList
'
,
summaryDirList
);
this
.
echart
.
showData
=
this
.
echart
.
brushData
=
list
;
...
...
@@ -749,8 +764,8 @@ export default {
}
else
{
this
.
summaryDirList
=
[];
this
.
$store
.
commit
(
'
setSummaryDirList
'
,
[]);
this
.
checkedSummary
=
[];
this
.
noData
=
true
;
this
.
checkedSummary
=
summaryDirList
;
}
},
(
error
)
=>
{},
...
...
@@ -783,6 +798,9 @@ export default {
* @param {Boolean} value Select All
*/
checkboxSelectAll
(
value
)
{
this
.
table
.
optionalColumn
.
forEach
((
key
)
=>
{
this
.
table
.
columnOptions
[
key
].
selected
=
value
;
});
this
.
table
.
selectedColumn
=
value
?
this
.
table
.
optionalColumn
:
[];
this
.
table
.
column
=
this
.
table
.
mandatoryColumn
.
concat
(
value
?
this
.
table
.
optionalColumn
:
[])
...
...
@@ -826,22 +844,20 @@ export default {
if
(
isNaN
(
value
)
||
!
value
)
{
return
value
;
}
else
{
if
(
key
===
'
accuracy
'
)
{
return
this
.
toFixedFun
(
value
*
100
,
2
)
+
'
%
'
;
}
else
if
(
key
===
'
learning_rate
'
)
{
let
temp
=
value
.
toPrecision
(
3
);
if
(
key
===
'
learning_rate
'
)
{
let
temp
=
value
.
toPrecision
(
4
);
let
row
=
0
;
while
(
temp
<
1
)
{
temp
=
temp
*
10
;
row
+=
1
;
}
temp
=
this
.
toFixedFun
(
temp
,
2
);
temp
=
this
.
toFixedFun
(
temp
,
4
);
return
`
${
temp
}${
row
?
`e-
${
row
}
`
:
''
}
`
;
}
else
if
(
key
===
'
model_size
'
)
{
return
value
+
'
MB
'
;
}
else
{
if
(
value
<
1000
)
{
return
Math
.
round
(
value
*
Math
.
pow
(
10
,
2
))
/
Math
.
pow
(
10
,
2
);
return
Math
.
round
(
value
*
Math
.
pow
(
10
,
4
))
/
Math
.
pow
(
10
,
4
);
}
else
{
const
reg
=
/
(?=(\B)(\d{3})
+$
)
/g
;
return
(
value
+
''
).
replace
(
reg
,
'
,
'
);
...
...
@@ -885,28 +901,24 @@ export default {
-webkit-box-shadow
:
0
1px
0
0
rgba
(
200
,
200
,
200
,
0
.5
);
box-shadow
:
0
1px
0
0
rgba
(
200
,
200
,
200
,
0
.5
);
overflow
:
hidden
;
.custom-btn
{
border
:
1px
solid
#00a5a7
;
border-radius
:
2px
;
background-color
:
white
;
color
:
#00a5a7
;
}
.custom-btn
:hover
{
color
:
#00a5a7
;
background
:
#e9f7f7
;
}
.
checkbox
-area
{
.
top
-area
{
margin
:
24px
32px
16px
;
position
:
relative
;
min-height
:
42px
;
max-height
:
66px
;
display
:
flex
;
justify-content
:
flex-end
;
.checkbox
{
width
:
calc
(
100%
-
264px
);
max-height
:
66px
;
overflow
:
auto
;
.mgr30
{
margin-right
:
30px
;
flex-grow
:
1
;
.label-legend
{
height
:
19px
;
margin-bottom
:
4px
;
div
{
display
:
inline-block
;
font-size
:
12px
;
}
div
+
div
{
margin-left
:
30px
;
}
}
.notShow
{
display
:
none
;
...
...
@@ -921,11 +933,18 @@ export default {
margin-right
:
30px
;
}
}
.reset-btn
{
position
:
absolute
;
right
:
0
;
bottom
:
0
;
.btns
{
margin-left
:
20px
;
.custom-btn
{
border
:
1px
solid
#00a5a7
;
border-radius
:
2px
;
background-color
:
white
;
color
:
#00a5a7
;
}
.custom-btn
:hover
{
color
:
#00a5a7
;
background
:
#e9f7f7
;
}
}
}
#echart
{
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录