Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
MindSpore
mindinsight
提交
4a11ba40
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看板
提交
4a11ba40
编写于
6月 19, 2020
作者:
M
mindspore-ci-bot
提交者:
Gitee
6月 19, 2020
浏览文件
操作
浏览文件
下载
差异文件
!300 UI add profiling minddata page(1st)
Merge pull request !300 from WeiFeng-mindinsight/myMaster
上级
ece0db72
90b1cc89
变更
3
隐藏空白更改
内联
并排
Showing
3 changed file
with
1439 addition
and
0 deletion
+1439
-0
mindinsight/ui/src/assets/images/queue.svg
mindinsight/ui/src/assets/images/queue.svg
+13
-0
mindinsight/ui/src/router.js
mindinsight/ui/src/router.js
+4
-0
mindinsight/ui/src/views/train-manage/minddata.vue
mindinsight/ui/src/views/train-manage/minddata.vue
+1422
-0
未找到文件。
mindinsight/ui/src/assets/images/queue.svg
0 → 100644
浏览文件 @
4a11ba40
<?xml version="1.0" encoding="UTF-8"?>
<svg
width=
"20px"
height=
"24px"
viewBox=
"0 0 20 24"
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>
<g
id=
"智能小助手"
stroke=
"none"
stroke-width=
"1"
fill=
"none"
fill-rule=
"evenodd"
>
<g
id=
"1备份-2"
transform=
"translate(-753.000000, -730.000000)"
fill=
"#8A8E99"
fill-rule=
"nonzero"
>
<g
id=
"队列服务"
transform=
"translate(753.000000, 730.000000)"
>
<path
d=
"M9.83303571,0 L9.13660714,0.6 L10.6446429,2.34642857 L0,2.34642857 L0,3.26785714 L12.6535714,3.26785714 L9.83303571,0 Z M6.76875,20.71875 L6.76875,21.6401786 L17.2232143,21.6401786 L15.7151786,23.3866071 L16.4116071,23.9866071 L19.2321429,20.71875 L6.76875,20.71875 Z M19.1973214,4.99553571 L13.5133929,4.99553571 L13.5133929,18.9910714 L19.1973214,18.9910714 L19.1973214,4.99553571 Z M18.2758929,18.0723214 L14.4348214,18.0723214 L14.4348214,5.91696429 L18.2758929,5.91696429 L18.2758929,18.0723214 L18.2758929,18.0723214 Z M16.8,7.28035714 L15.8785714,7.28035714 L15.8785714,8.65982143 L16.8,8.65982143 L16.8,7.28035714 Z M0.16875,18.99375 L5.85267857,18.99375 L5.85267857,4.99553571 L0.16875,4.99553571 L0.16875,18.99375 Z M1.09017857,5.91696429 L4.93125,5.91696429 L4.93125,18.0723214 L1.09017857,18.0723214 L1.09017857,5.91696429 L1.09017857,5.91696429 Z M9.14732143,8.65714286 L10.06875,8.65714286 L10.06875,7.27767857 L9.14732143,7.27767857 L9.14732143,8.65714286 Z M2.50446429,8.65714286 L3.42589286,8.65714286 L3.42589286,7.27767857 L2.50446429,7.27767857 L2.50446429,8.65714286 L2.50446429,8.65714286 Z M12.5544643,18.99375 L12.5544643,4.99553571 L6.87053571,4.99553571 L6.87053571,18.9910714 L12.5544643,18.9910714 L12.5544643,18.99375 Z M7.79196429,5.91696429 L11.6330357,5.91696429 L11.6330357,18.0723214 L7.79196429,18.0723214 L7.79196429,5.91696429 Z"
id=
"形状"
></path>
</g>
</g>
</g>
</svg>
\ No newline at end of file
mindinsight/ui/src/router.js
浏览文件 @
4a11ba40
...
@@ -87,6 +87,10 @@ export default new Router({
...
@@ -87,6 +87,10 @@ export default new Router({
path
:
'
operator
'
,
path
:
'
operator
'
,
component
:
()
=>
import
(
'
./views/train-manage/operator.vue
'
),
component
:
()
=>
import
(
'
./views/train-manage/operator.vue
'
),
},
},
{
path
:
'
minddata
'
,
component
:
()
=>
import
(
'
./views/train-manage/minddata.vue
'
),
},
],
],
},
},
],
],
...
...
mindinsight/ui/src/views/train-manage/minddata.vue
0 → 100644
浏览文件 @
4a11ba40
<!--
Copyright 2019 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=
"md-wrap"
>
<div
class=
"title"
>
{{
$t
(
'
profiling.minddataTitle
'
)
}}
</div>
<el-tabs
v-model=
"activeName"
@
tab-click=
"handleClick"
>
<el-tab-pane
:label=
"$t('profiling.queueInfo')"
name=
"queueInfo"
>
<div
class=
"md-top"
v-if=
"!(connectQueueChart.noData && dataQueueChart.noData &&
deviceQueueOpChart && getNextChart.getNextChart)"
>
<div
class=
"cell-container data-process"
v-show=
"!processSummary.noData"
>
<div
class=
"title"
>
{{
$t
(
'
profiling.pipeline
'
)
}}
</div>
</div>
<div
class=
"queue-container"
v-show=
"!processSummary.noData"
>
<div
class=
"img"
>
<div
class=
"edge"
>
<img
src=
"@/assets/images/data-flow.png"
alt=
""
/>
</div>
<div
class=
"icon"
>
<img
src=
"@/assets/images/queue.svg"
alt=
""
@
click=
"highlight('connector_queue')"
clickKey=
"connector_queue"
/>
</div>
<div
class=
"edge"
>
<img
src=
"@/assets/images/data-flow.png"
alt=
""
/>
</div>
</div>
<div
class=
"title"
>
{{
$t
(
'
profiling.connectorQuene
'
)
}}
</div>
<div
class=
"description"
>
<div
class=
"item"
v-if=
"processSummary.device.empty || processSummary.device.empty === 0"
>
{{
$t
(
'
profiling.queueTip2
'
)
}}
<span
class=
"num"
>
{{
processSummary
.
device
.
empty
}}
/
{{
processSummary
.
device
.
total
}}
</span>
</div>
<div
class=
"item"
v-if=
"processSummary.device.full || processSummary.device.full === 0"
>
{{
$t
(
'
profiling.queueTip1
'
)
}}
<span
class=
"num"
>
{{
processSummary
.
device
.
empty
}}
/
{{
processSummary
.
device
.
total
}}
</span>
</div>
</div>
</div>
<div
class=
"cell-container device_queue_op"
@
click=
"highlight('device_queue_op')"
clickKey=
"device_queue_op"
v-show=
"!processSummary.noData"
>
<div
class=
"title"
>
{{
$t
(
'
profiling.deviceQueueOp
'
)
}}
</div>
<div
class=
"content"
>
{{
$t
(
'
profiling.deviceQueueOpTip
'
)
}}
| TDT
</div>
</div>
<div
class=
"queue-container"
v-show=
"processSummary.count === 6 && !processSummary.noData"
>
<div
class=
"img"
>
<div
class=
"edge"
>
<img
src=
"@/assets/images/data-flow.png"
alt=
""
/>
</div>
<div
class=
"icon"
>
<img
src=
"@/assets/images/queue.svg"
@
click=
"highlight('data_queue')"
clickKey=
"data_queue"
alt=
""
/>
</div>
<div
class=
"edge"
>
<img
src=
"@/assets/images/data-flow.png"
alt=
""
/>
</div>
</div>
<div
class=
"title"
>
{{
$t
(
'
profiling.dataQueue
'
)
}}
</div>
<div
class=
"description"
>
<div
class=
"item"
v-if=
"processSummary.get_next.empty || processSummary.get_next.empty === 0"
>
{{
$t
(
'
profiling.queueTip2
'
)
}}
<span
class=
"num"
>
{{
processSummary
.
get_next
.
empty
}}
/
{{
processSummary
.
get_next
.
total
}}
</span>
</div>
<div
class=
"item"
v-if=
"processSummary.get_next.full || processSummary.get_next.full === 0"
>
{{
$t
(
'
profiling.queueTip1
'
)
}}
<span
class=
"num"
>
{{
processSummary
.
get_next
.
empty
}}
/
{{
processSummary
.
get_next
.
total
}}
</span>
</div>
</div>
</div>
<div
class=
"cell-container get-next"
@
click=
"highlight('get_next')"
clickKey=
"get_next"
v-if=
"processSummary.count === 6 && !processSummary.noData"
>
<div
class=
"title"
>
{{
$t
(
'
profiling.getData
'
)
}}
</div>
</div>
</div>
<div
class=
"md-bottom"
v-if=
"!(connectQueueChart.noData && dataQueueChart.noData && deviceQueueOpChart
&& getNextChart.getNextChart)"
>
<div
class=
"queue-step-wrap"
>
<div
class=
"title"
>
{{
$t
(
'
profiling.queueStep
'
)
}}
</div>
<div
class=
"chart-content"
>
<div
class=
"chart-wrap"
:class=
"
{highlight:selected==='connector_queue'}">
<div
class=
"title"
>
{{
$t
(
'
profiling.connectorQuene
'
)
}}
</div>
<template
v-if=
"!connectQueueChart.noData"
>
<div
class=
"data-tips"
>
<div
v-if=
"connectQueueChart.queueSummary.empty_queue!==undefined"
>
{{
$t
(
'
profiling.queueEmptyRatio
'
)
}}{{
connectQueueChart
.
queueSummary
.
empty_queue
}}
</div>
<div
v-if=
"connectQueueChart.queueSummary.full_queue!==undefined"
>
{{
$t
(
'
profiling.queueFullRatio
'
)
}}{{
connectQueueChart
.
queueSummary
.
full_queue
}}
</div>
</div>
<div
id=
"connect-queue"
class=
"chart"
></div>
</
template
>
<div
class=
"image-noData"
v-if=
"connectQueueChart.noData"
>
<div>
<img
:src=
"require('@/assets/images/nodata.png')"
alt=
""
/>
</div>
<p>
{{$t("public.noData")}}
</p>
</div>
</div>
<div
class=
"chart-wrap"
:class=
"{highlight:selected==='data_queue'}"
>
<div
class=
"title"
>
{{$t('profiling.dataQueue')}}
</div>
<
template
v-if=
"!dataQueueChart.noData"
>
<div
class=
"data-tips"
>
<div
v-if=
"dataQueueChart.queueSummary.empty_queue!==undefined"
>
{{
$t
(
'
profiling.queueEmptyRatio
'
)
}}{{
dataQueueChart
.
queueSummary
.
empty_queue
}}
</div>
<div
v-if=
"dataQueueChart.queueSummary.full_queue!==undefined"
>
{{
$t
(
'
profiling.queueFullRatio
'
)
}}{{
dataQueueChart
.
queueSummary
.
full_queue
}}
</div>
</div>
<div
id=
"data-queue"
class=
"chart"
></div>
</
template
>
<div
class=
"image-noData"
v-if=
"dataQueueChart.noData"
>
<div>
<img
:src=
"require('@/assets/images/nodata.png')"
alt=
""
/>
</div>
<p>
{{$t("public.noData")}}
</p>
</div>
</div>
</div>
</div>
<div
class=
"queue-step-wrap"
>
<div
class=
"title"
>
{{$t('profiling.operatorTimeConAnalysis')}}
</div>
<div
class=
"chart-content second"
>
<div
class=
"chart-wrap analysis"
:class=
"{highlight:selected==='device_queue_op'}"
>
<div
class=
"title"
>
{{$t('profiling.deviceQueueOp')}}
</div>
<
template
v-if=
"!deviceQueueOpChart.noData"
>
<div
class=
"data-tips"
>
<div
v-if=
"deviceQueueOpChart.timeSummary.avg_cost!==undefined"
>
{{
$t
(
'
profiling.avgCost
'
)
}}{{
deviceQueueOpChart
.
timeSummary
.
avg_cost
}}
ms
</div>
<div
v-if=
"deviceQueueOpChart.timeSummary.get_cost!==undefined"
>
{{
$t
(
'
profiling.getCost
'
)
}}{{
deviceQueueOpChart
.
timeSummary
.
get_cost
}}
ms
</div>
<div
v-if=
"deviceQueueOpChart.timeSummary.push_cost!==undefined"
>
{{
$t
(
'
profiling.pushCost
'
)
}}{{
deviceQueueOpChart
.
timeSummary
.
push_cost
}}
ms
</div>
</div>
<div
id=
"device_queue_op"
class=
"chart"
></div>
</
template
>
<div
class=
"image-noData"
v-if=
"deviceQueueOpChart.noData"
>
<div>
<img
:src=
"require('@/assets/images/nodata.png')"
alt=
""
/>
</div>
<p>
{{$t("public.noData")}}
</p>
</div>
</div>
<div
class=
"chart-wrap analysis"
:class=
"{highlight:selected==='get_next'}"
>
<div
class=
"title"
>
{{$t('profiling.getNext')}}
</div>
<
template
v-if=
"!getNextChart.noData"
>
<div
class=
"data-tips"
>
<div
v-if=
"getNextChart.timeSummary.avg_cost!==undefined"
>
{{
$t
(
'
profiling.avgCost
'
)
}}{{
getNextChart
.
timeSummary
.
avg_cost
}}
ms
</div>
<div
v-if=
"getNextChart.timeSummary.get_cost!==undefined"
>
{{
$t
(
'
profiling.getCost
'
)
}}{{
getNextChart
.
timeSummary
.
get_cost
}}
ms
</div>
<div
v-if=
"getNextChart.timeSummary.push_cost!==undefined"
>
{{
$t
(
'
profiling.pushCost
'
)
}}{{
getNextChart
.
timeSummary
.
push_cost
}}
ms
</div>
</div>
<div
id=
"get_next"
class=
"chart"
></div>
</
template
>
<div
class=
"image-noData"
v-if=
"getNextChart.noData"
>
<div>
<img
:src=
"require('@/assets/images/nodata.png')"
alt=
""
/>
</div>
<p>
{{$t("public.noData")}}
</p>
</div>
</div>
</div>
</div>
</div>
<div
class=
"image-noData"
v-if=
"(connectQueueChart.noData && dataQueueChart.noData &&
deviceQueueOpChart && getNextChart.getNextChart)"
>
<div>
<img
:src=
"require('@/assets/images/nodata.png')"
alt=
""
/>
</div>
<p>
{{$t("public.noData")}}
</p>
</div>
</el-tab-pane>
<el-tab-pane
:label=
"$t('profiling.pipeline')"
name=
"pipeLine"
>
<div
class=
"pipeline-wrap"
v-show=
"pipeData"
>
<div
class=
"pipeline-top"
>
<div
class=
"pipeline-top-title"
>
{{$t('profiling.pipelineTopTitle')}}
</div>
<div
class=
"average-rate-wrap"
>
<div
id=
"average-rate"
></div>
</div>
</div>
<div
class=
"pipeline-middle"
>
<div
class=
"pipeline-middle-title"
>
{{$t('profiling.pipelineMiddleTitle')}}
</div>
<div
class=
"operator-graph"
>
<div
id=
"graph"
></div>
</div>
</div>
<div
class=
"pipeline-bottom"
>
<div
class=
"queue-deep-wrap"
>
<div
class=
"left"
>
<div
id=
"queue-deep"
></div>
</div>
<div
class=
"right"
>
<div
class=
"title"
>
{{$t('profiling.operatorInfo',{msg1:current_op.name,msg2:parent_op.name})}}
</div>
<div
class=
"item-wrap"
>
<div
class=
"item"
><span>
{{current_op.name}} ID:
</span>
{{current_op.op_id}}
</div>
<div
class=
"item"
><span>
{{current_op.name}} type:
</span>
{{current_op.op_type}}
</div>
<div
class=
"item"
>
<span>
{{current_op.name}} {{$t('profiling.workersNum')}}:
</span>
{{current_op.num_workers}}
</div>
<div
class=
"item"
><span>
{{parent_op.name}} ID:
</span>
{{parent_op.op_id}}
</div>
<div
class=
"item"
><span>
{{parent_op.name}} type:
</span>
{{parent_op.op_type}}
</div>
<div
class=
"item"
>
<span>
{{parent_op.name}} {{$t('profiling.workersNum')}}:
</span>
{{parent_op.num_workers}}
</div>
</div>
</div>
</div>
</div>
</div>
<div
class=
"image-noData"
v-if=
"!pipeData"
>
<div>
<img
:src=
"require('@/assets/images/nodata.png')"
alt=
""
/>
</div>
<p>
{{$t("public.noData")}}
</p>
</div>
</el-tab-pane>
</el-tabs>
</div>
</template>
<
script
>
import
echarts
from
'
echarts
'
;
import
RequestService
from
'
../../services/request-service
'
;
import
{
select
,
selectAll
,
zoom
}
from
'
d3
'
;
import
'
d3-graphviz
'
;
const
d3
=
{
select
,
selectAll
,
zoom
};
export
default
{
props
:
{},
data
()
{
return
{
dir
:
''
,
currentCard
:
''
,
connectQueueChart
:
{
id
:
'
connect-queue
'
,
chartDom
:
null
,
data
:
[],
queueSummary
:
{},
advise
:
''
,
type
:
0
,
params
:
'
device_queue
'
,
noData
:
false
,
},
dataQueueChart
:
{
id
:
'
data-queue
'
,
chartDom
:
null
,
data
:
[],
queueSummary
:
{},
advise
:
''
,
type
:
0
,
params
:
'
get_next
'
,
noData
:
false
,
},
deviceQueueOpChart
:
{
id
:
'
device_queue_op
'
,
chartDom
:
null
,
data
:
[],
timeSummary
:
{},
type
:
1
,
params
:
'
device_queue
'
,
noData
:
false
,
},
getNextChart
:
{
id
:
'
get_next
'
,
chartDom
:
null
,
data
:
[],
timeSummary
:
{},
type
:
1
,
params
:
'
get_next
'
,
noData
:
false
,
},
processSummary
:
{
noData
:
true
,
count
:
6
,
device
:
{
empty
:
0
,
full
:
0
,
total
:
0
,
},
get_next
:
{
empty
:
0
,
full
:
0
,
total
:
0
,
},
},
activeName
:
'
queueInfo
'
,
averageRateChart
:
{
id
:
'
average-rate
'
,
chartDom
:
null
,
},
queueDeepChart
:
{
id
:
'
queue-deep
'
,
chartDom
:
null
,
},
current_op
:
{},
parent_op
:
{},
pipeData
:
true
,
allGraphData
:
{},
graphviz
:
null
,
totalMemory
:
16777216
*
2
,
// Memory size of the graph plug-in
scaleRange
:
[
1
,
10000
],
// graph zooms in and zooms out.
initQueue
:
''
,
trainId
:
''
,
selected
:
''
,
};
},
watch
:
{
'
$parent.curDashboardInfo
'
:
{
handler
(
newValue
,
oldValue
)
{
if
(
newValue
.
curCardNum
||
newValue
.
curCardNum
===
0
)
{
this
.
dir
=
newValue
.
query
.
dir
;
this
.
trainId
=
newValue
.
query
.
id
;
this
.
currentCard
=
newValue
.
curCardNum
;
if
(
this
.
trainingJobId
)
{
document
.
title
=
`
${
decodeURIComponent
(
this
.
trainingJobId
)}
`
+
`-
${
this
.
$t
(
'
profiling.profilingDashboard
'
)}
-MindInsight`
;
}
else
{
document
.
title
=
`
${
this
.
$t
(
'
profiling.profilingDashboard
'
,
)}
-MindInsight`
;
}
if
(
this
.
activeName
===
'
queueInfo
'
)
{
this
.
init
();
}
else
{
this
.
queryAverageRate
();
}
}
},
deep
:
true
,
immediate
:
true
,
},
},
computed
:
{},
mounted
()
{
window
.
addEventListener
(
'
resize
'
,
this
.
resizeCallback
,
false
);
setTimeout
(()
=>
{
this
.
$bus
.
$on
(
'
collapse
'
,
this
.
resizeCallback
);
},
500
);
},
methods
:
{
handleClick
()
{
if
(
this
.
activeName
===
'
pipeLine
'
)
{
if
(
!
Object
.
keys
(
this
.
allGraphData
).
length
)
{
this
.
$nextTick
(()
=>
{
this
.
queryAverageRate
();
});
}
}
},
init
()
{
this
.
queryQueueInfo
(
this
.
connectQueueChart
);
this
.
queryQueueInfo
(
this
.
dataQueueChart
);
this
.
queryMinddataOp
(
this
.
deviceQueueOpChart
);
this
.
queryMinddataOp
(
this
.
getNextChart
);
this
.
queryProcessSummary
();
},
resizeCallback
()
{
const
chartArr
=
[
'
connectQueueChart
'
,
'
dataQueueChart
'
,
'
deviceQueueOpChart
'
,
'
getNextChart
'
,
'
averageRateChart
'
,
'
queueDeepChart
'
,
];
chartArr
.
forEach
((
val
)
=>
{
if
(
this
[
val
].
chartDom
)
{
setTimeout
(()
=>
{
this
[
val
].
chartDom
.
resize
();
},
200
);
}
});
},
queryMinddataOp
(
chart
)
{
const
params
=
{
profile
:
this
.
dir
,
device_id
:
this
.
currentCard
,
type
:
chart
.
params
,
train_id
:
this
.
trainId
,
};
RequestService
.
minddataOp
(
params
).
then
(
(
res
)
=>
{
if
(
res
&&
res
.
data
)
{
const
result
=
res
.
data
;
chart
.
data
=
result
.
info
;
if
(
result
.
summary
)
{
chart
.
timeSummary
=
result
.
summary
.
time_summary
||
{};
Object
.
keys
(
chart
.
timeSummary
).
forEach
((
val
)
=>
{
chart
.
timeSummary
[
val
]
=
parseFloat
(
chart
.
timeSummary
[
val
],
).
toFixed
(
3
);
});
}
chart
.
advise
=
result
.
advise
;
if
(
result
.
size
>
0
)
{
this
.
setOption
(
chart
);
chart
.
noData
=
false
;
}
else
{
if
(
chart
.
chartDom
)
{
chart
.
chartDom
.
clear
();
}
chart
.
noData
=
true
;
}
}
},
(
err
)
=>
{
if
(
chart
.
chartDom
)
{
chart
.
chartDom
.
clear
();
}
chart
.
noData
=
true
;
},
);
},
queryQueueInfo
(
chart
)
{
const
params
=
{
profile
:
this
.
dir
,
device_id
:
this
.
currentCard
,
type
:
chart
.
params
,
train_id
:
this
.
trainId
,
};
RequestService
.
queueInfo
(
params
).
then
(
(
res
)
=>
{
if
(
res
&&
res
.
data
)
{
const
result
=
res
.
data
;
chart
.
data
=
result
.
info
;
if
(
result
.
summary
)
{
chart
.
queueSummary
=
result
.
summary
.
queue_summary
||
{};
}
chart
.
advise
=
result
.
advise
;
if
(
result
.
size
>
0
)
{
this
.
setOption
(
chart
,
result
.
size
);
chart
.
noData
=
false
;
}
else
{
if
(
chart
.
chartDom
)
{
chart
.
chartDom
.
clear
();
}
chart
.
noData
=
true
;
}
}
},
(
err
)
=>
{
chart
.
noData
=
true
;
if
(
chart
.
chartDom
)
{
chart
.
chartDom
.
clear
();
}
},
);
},
setOption
(
chart
,
size
)
{
const
myChart
=
echarts
.
init
(
document
.
getElementById
(
chart
.
id
));
const
option
=
{
title
:
{
text
:
''
,
},
tooltip
:
{
trigger
:
'
axis
'
,
},
toolbox
:
{
show
:
true
,
},
xAxis
:
{
name
:
'
step
'
,
data
:
[],
max
:
size
,
},
yAxis
:
{},
series
:
[],
grid
:
{
left
:
50
,
top
:
20
,
right
:
50
,
bottom
:
60
,
},
};
option
.
dataZoom
=
[
{
startValue
:
0
,
bottom
:
0
,
},
{
type
:
'
inside
'
,
bottom
:
0
,
},
];
const
arr
=
[];
Object
.
keys
(
chart
.
data
).
forEach
((
val
,
index
)
=>
{
const
item
=
{};
item
.
type
=
'
line
'
;
item
.
data
=
chart
.
data
[
val
];
item
.
name
=
val
;
if
(
chart
.
type
===
0
)
{
const
markPointArr
=
[];
item
.
data
.
forEach
((
val
,
key
)
=>
{
if
(
val
===
0
)
{
markPointArr
.
push
({
xAxis
:
key
,
yAxis
:
val
,
symbolSize
:
20
});
}
});
item
.
markPoint
=
{
data
:
markPointArr
};
}
arr
.
push
(
item
);
});
option
.
series
=
arr
;
option
.
xAxis
.
data
=
chart
.
data
[
Object
.
keys
(
chart
.
data
)[
0
]].
map
(
(
val
,
index
)
=>
index
+
1
,
);
myChart
.
setOption
(
option
);
chart
.
chartDom
=
myChart
;
if
(
this
.
connectQueueChart
.
chartDom
&&
this
.
deviceQueueOpChart
.
chartDom
)
{
echarts
.
connect
([
this
.
connectQueueChart
.
chartDom
,
this
.
deviceQueueOpChart
.
chartDom
,
]);
}
if
(
this
.
getNextChart
.
chartDom
&&
this
.
dataQueueChart
.
chartDom
)
{
echarts
.
connect
([
this
.
getNextChart
.
chartDom
,
this
.
dataQueueChart
.
chartDom
,
]);
}
},
queryProcessSummary
()
{
const
params
=
{
profile
:
this
.
dir
,
device_id
:
this
.
currentCard
,
train_id
:
this
.
trainId
,
};
RequestService
.
queryProcessSummary
(
params
).
then
(
(
res
)
=>
{
if
(
res
&&
res
.
data
)
{
const
data
=
JSON
.
parse
(
JSON
.
stringify
(
res
.
data
));
this
.
processSummary
.
count
=
Object
.
keys
(
data
).
length
;
this
.
dealProcess
(
data
);
}
else
{
this
.
dealProcess
(
null
);
}
},
(
error
)
=>
{
this
.
dealProcess
(
null
);
},
);
},
dealProcess
(
data
)
{
this
.
processSummary
.
device
=
{
empty
:
0
,
full
:
0
,
total
:
0
,
};
this
.
processSummary
.
get_next
=
{
empty
:
0
,
full
:
0
,
total
:
0
,
};
this
.
processSummary
.
noData
=
true
;
if
(
data
)
{
if
(
data
.
device_queue_info
&&
data
.
device_queue_info
.
summary
)
{
this
.
processSummary
.
device
=
{
empty
:
data
.
device_queue_info
.
summary
.
empty_batch_count
,
full
:
data
.
device_queue_info
.
summary
.
full_batch_count
,
total
:
data
.
device_queue_info
.
summary
.
total_batch
,
};
}
if
(
data
.
get_next_queue_info
&&
data
.
get_next_queue_info
.
summary
)
{
this
.
processSummary
.
get_next
=
{
empty
:
data
.
get_next_queue_info
.
summary
.
empty_batch_count
,
full
:
data
.
get_next_queue_info
.
summary
.
full_batch_count
,
total
:
data
.
get_next_queue_info
.
summary
.
total_batch
,
};
}
this
.
processSummary
.
noData
=
false
;
}
},
queryAverageRate
()
{
const
params
=
{
params
:
{
train_id
:
this
.
trainId
,
profile
:
this
.
dir
,
},
body
:
{
device_id
:
this
.
currentCard
,
},
};
RequestService
.
queryOpQueue
(
params
).
then
(
(
res
)
=>
{
if
(
res
&&
res
.
data
)
{
this
.
removeGraph
();
const
data
=
JSON
.
parse
(
JSON
.
stringify
(
res
.
data
));
this
.
dealPipeLineData
(
data
);
this
.
pipeData
=
!!
(
res
.
data
.
object
&&
res
.
data
.
object
.
length
);
if
(
res
.
data
.
object
&&
res
.
data
.
object
.
length
&&
res
.
data
.
col_name
)
{
const
result
=
res
.
data
.
object
.
map
((
val
)
=>
{
const
obj
=
{};
res
.
data
.
col_name
.
forEach
((
value
,
key
)
=>
{
obj
[
value
]
=
val
[
key
];
});
return
obj
;
});
const
data
=
result
.
sort
((
a
,
b
)
=>
{
return
a
.
output_queue_usage_rate
-
b
.
output_queue_usage_rate
;
})
.
filter
((
val
)
=>
{
return
val
.
parent_id
!==
null
;
});
const
dataY
=
data
.
map
((
val
)
=>
{
return
(
val
.
output_queue_usage_rate
*
100
).
toFixed
(
4
);
});
const
dataX
=
data
.
map
((
val
)
=>
{
return
`Queue_
${
val
.
op_id
}
`
;
});
const
profiling
=
this
.
$t
(
'
profiling
'
);
const
option
=
{
tooltip
:
{
trigger
:
'
axis
'
,
axisPointer
:
{
type
:
'
shadow
'
,
},
formatter
(
params
)
{
let
value
=
{};
data
.
forEach
((
val
)
=>
{
if
(
`
${
val
.
op_id
}
`
===
params
[
0
].
axisValue
.
split
(
''
)[
6
])
{
value
=
val
;
}
});
return
(
`
${
params
[
0
].
axisValue
}
<br>
${
params
[
0
].
marker
}
`
+
`
${
profiling
.
averageCapacity
}
:
${
value
.
output_queue_average_size
}
<br>`
+
`
${
params
[
0
].
marker
}${
profiling
.
totalCapacity
}
:`
+
`
${
value
.
output_queue_length
}
`
);
},
},
grid
:
{
left
:
70
,
top
:
20
,
right
:
100
,
bottom
:
50
,
},
xAxis
:
{
type
:
'
value
'
,
boundaryGap
:
[
0
,
0.01
],
max
:
100
,
axisLabel
:
{
formatter
(
params
)
{
return
`
${
params
}
%`
;
},
},
},
yAxis
:
{
type
:
'
category
'
,
data
:
dataX
,
},
series
:
[
{
type
:
'
bar
'
,
data
:
dataY
,
itemStyle
:
{
color
:
'
#00a5a7
'
,
},
label
:
{
show
:
true
,
position
:
'
right
'
,
color
:
'
#000
'
,
formatter
(
params
)
{
return
`
${
params
.
value
}
%`
;
},
},
},
],
dataZoom
:
[
{
orient
:
'
vertical
'
,
right
:
10
,
},
{
type
:
'
inside
'
,
orient
:
'
vertical
'
,
right
:
10
,
},
],
};
const
echart
=
echarts
.
init
(
document
.
getElementById
(
this
.
averageRateChart
.
id
),
);
echart
.
setOption
(
option
);
this
.
averageRateChart
.
chartDom
=
echart
;
}
}
},
()
=>
{
this
.
pipeData
=
false
;
this
.
removeGraph
();
},
);
},
queryQueue
(
id
)
{
const
params
=
{
profile
:
this
.
dir
,
train_id
:
this
.
trainId
,
device_id
:
this
.
currentCard
,
op_id
:
id
,
};
RequestService
.
queryQueue
(
params
).
then
((
res
)
=>
{
if
(
res
&&
res
.
data
)
{
const
data
=
res
.
data
.
queue_info
;
const
dataY
=
data
.
output_queue_size
;
this
.
current_op
=
res
.
data
.
current_op
||
{};
this
.
parent_op
=
res
.
data
.
parent_op
||
{};
this
.
current_op
.
name
=
`
${
this
.
current_op
.
op_type
}
_
${
this
.
current_op
.
op_id
}
`
;
this
.
parent_op
.
name
=
`
${
this
.
parent_op
.
op_type
}
_
${
this
.
parent_op
.
op_id
}
`
;
const
echart
=
echarts
.
init
(
document
.
getElementById
(
this
.
queueDeepChart
.
id
),
);
const
option
=
{
title
:
{
text
:
this
.
$t
(
'
profiling.queueDeepChartTitle
'
,
{
msg
:
`Queue
${
id
}
`
,
}),
textStyle
:
{
fontSize
:
13
,
},
left
:
20
,
top
:
10
,
},
tooltip
:
{
trigger
:
'
axis
'
,
},
xAxis
:
{
name
:
`
${
this
.
$t
(
'
profiling.sampleInterval
'
)}
/
${
data
.
sample_interval
}
ms`
,
data
:
dataY
.
map
((
val
,
index
)
=>
index
+
1
),
max
:
dataY
.
length
,
},
yAxis
:
{
name
:
''
,
},
series
:
[
{
type
:
'
line
'
,
data
:
dataY
,
itemStyle
:
{
color
:
'
#00a5a7
'
,
},
},
],
grid
:
{
left
:
50
,
top
:
40
,
right
:
100
,
bottom
:
60
,
},
dataZoom
:
[
{
startValue
:
0
,
bottom
:
10
,
},
{
type
:
'
inside
'
,
bottom
:
10
,
},
],
};
echart
.
setOption
(
option
);
this
.
queueDeepChart
.
chartDom
=
echart
;
}
});
},
highlight
(
key
)
{
const
domList
=
document
.
querySelectorAll
(
'
.md-top *[clickKey]
'
);
Array
.
prototype
.
forEach
.
call
(
domList
,
(
dom
)
=>
{
if
(
dom
.
getAttribute
(
'
clickKey
'
)
===
key
)
{
dom
.
classList
.
add
(
'
selected
'
);
}
else
{
dom
.
classList
.
remove
(
'
selected
'
);
}
});
this
.
selected
=
key
;
},
/** ************************ graph ****************************/
/**
* Processing Graph Data
* @param {Object} data Data of the graph
*/
dealPipeLineData
(
data
)
{
const
colName
=
data
.
col_name
;
const
colCount
=
colName
.
length
;
const
list
=
data
.
object
;
list
.
forEach
((
i
)
=>
{
if
(
i
&&
i
.
length
===
colCount
)
{
const
obj
=
{
output
:
''
,
};
colName
.
forEach
((
key
,
index
)
=>
{
obj
[
key
]
=
i
[
index
];
});
if
(
obj
.
op_id
||
obj
.
op_id
===
0
)
{
obj
.
key
=
`
${
obj
.
op_id
}
_operator`
;
if
(
obj
.
parent_id
||
obj
.
parent_id
===
0
)
{
const
queueKey
=
`
${
obj
.
op_id
}
_queue`
;
obj
.
output
=
queueKey
;
const
queueObj
=
JSON
.
parse
(
JSON
.
stringify
(
obj
));
queueObj
.
key
=
queueKey
;
queueObj
.
op_type
=
'
queue
'
;
queueObj
.
output
=
`
${
obj
.
parent_id
}
_operator`
;
this
.
allGraphData
[
queueKey
]
=
queueObj
;
if
(
!
(
this
.
initQueue
||
this
.
initQueue
===
0
))
{
this
.
initQueue
=
queueObj
.
op_id
;
}
}
this
.
allGraphData
[
obj
.
key
]
=
obj
;
}
}
});
if
(
Object
.
keys
(
this
.
allGraphData
).
length
)
{
const
dot
=
this
.
packageGraphData
();
this
.
initGraph
(
dot
);
}
else
{
this
.
removeGraph
();
}
},
/**
* Encapsulates graph data into dot data.
* @return {String} dot string for packing graph data
*/
packageGraphData
()
{
let
nodeStr
=
''
;
let
edgeStr
=
''
;
Object
.
keys
(
this
.
allGraphData
).
forEach
((
key
)
=>
{
const
node
=
this
.
allGraphData
[
key
];
nodeStr
+=
`<
${
key
}
>[id="
${
key
}
";`
+
`
${
node
.
op_type
===
'
queue
'
?
`shape=rect;class="queue";label="Queue_
${
node
.
op_id
}
(
${
parseFloat
(
((
node
.
output_queue_usage_rate
||
0
)
*
100
).
toFixed
(
4
),
)}
%)";`
:
`shape=Mrecord;class="operator";label="
${
node
.
op_type
}
_
${
node
.
op_id
}
";`
}
];`
;
if
(
node
.
output
)
{
edgeStr
+=
`<
${
node
.
key
}
>-><
${
node
.
output
}
>`
;
}
});
const
initSetting
=
'
node[style="filled";fontsize="10px"];edge[fontsize="6px";];
'
;
return
`digraph {compound=true;rankdir=LR;
${
initSetting
}${
nodeStr
}${
edgeStr
}
}`
;
},
/**
* Initializing the dataset graph
* @param {String} dot dot statement encapsulated in graph data
*/
initGraph
(
dot
)
{
this
.
graphviz
=
d3
.
select
(
'
#graph
'
)
.
graphviz
({
useWorker
:
false
,
totalMemory
:
this
.
totalMemory
})
.
zoomScaleExtent
(
this
.
scaleRange
)
.
dot
(
dot
)
.
attributer
(
this
.
attributer
)
.
render
(
this
.
startApp
);
},
/**
* Default method of the graph rendering adjustment. Set the node format.
* @param {Object} datum Object of the current rendering element.
* @param {Number} index Indicates the subscript of the current rendering element.
* @param {Array} nodes An array encapsulated with the current rendering element.
*/
attributer
(
datum
,
index
,
nodes
)
{
if
(
datum
.
tag
===
'
svg
'
)
{
const
width
=
'
100%
'
;
const
height
=
'
100%
'
;
datum
.
attributes
.
width
=
width
;
datum
.
attributes
.
height
=
height
;
}
},
/**
* Initialization method executed after the graph rendering is complete
*/
startApp
()
{
setTimeout
(()
=>
{
if
(
this
.
graphviz
)
{
this
.
graphviz
.
_data
=
null
;
this
.
graphviz
.
_dictionary
=
null
;
this
.
graphviz
=
null
;
}
},
500
);
d3
.
select
(
'
#graph
'
)
.
selectAll
(
'
.operator>title
'
)
.
remove
();
const
queueList
=
Array
.
from
(
document
.
querySelectorAll
(
'
#graph .queue
'
));
for
(
let
i
=
0
,
len
=
queueList
.
length
;
i
<
len
;
i
++
)
{
const
node
=
queueList
[
i
];
const
data
=
this
.
allGraphData
[
node
.
id
];
if
(
data
)
{
const
polygon
=
node
.
querySelector
(
'
polygon
'
);
const
color
=
`rgba(19, 171, 173,
${
data
.
output_queue_usage_rate
}
)`
;
polygon
.
setAttribute
(
'
fill
'
,
color
);
polygon
.
setAttribute
(
'
stroke
'
,
color
);
const
title
=
node
.
querySelector
(
'
title
'
);
title
.
textContent
=
`
${
this
.
$t
(
'
profiling.averageCapacity
'
,
)}
:
${
data
.
output_queue_average_size
||
0
}
\n`
+
`
${
this
.
$t
(
'
profiling.totalCapacity
'
)}
:
${
data
.
output_queue_length
||
0
}
`
;
}
}
this
.
initZooming
();
const
nodes
=
d3
.
selectAll
(
'
g.queue
'
);
nodes
.
on
(
'
click
'
,
(
target
,
index
,
nodesList
)
=>
{
const
selectedNode
=
nodesList
[
index
];
nodes
.
classed
(
'
selected
'
,
false
);
d3
.
select
(
`g[id="
${
selectedNode
.
id
}
"]`
).
classed
(
'
selected
'
,
true
);
const
nodeData
=
this
.
allGraphData
[
selectedNode
.
id
];
if
(
nodeData
)
{
this
.
queryQueue
(
nodeData
.
op_id
);
}
});
d3
.
select
(
`g[id="
${
this
.
initQueue
}
_queue"]`
).
classed
(
'
selected
'
,
true
);
this
.
queryQueue
(
this
.
initQueue
);
},
/**
* Initializing the Zoom Function of a Graph
*/
initZooming
()
{
const
graphDom
=
document
.
querySelector
(
'
#graph0
'
);
const
graphBox
=
graphDom
.
getBBox
();
const
padding
=
4
;
const
pointer
=
{
start
:
{
x
:
0
,
y
:
0
,
},
end
:
{
x
:
0
,
y
:
0
,
},
};
const
zoom
=
d3
.
zoom
()
.
on
(
'
start
'
,
(
target
)
=>
{
pointer
.
start
.
x
=
event
.
x
;
pointer
.
start
.
y
=
event
.
y
;
})
.
on
(
'
zoom
'
,
(
target
)
=>
{
const
transformData
=
this
.
getTransformData
(
graphDom
);
let
tempStr
=
''
;
let
change
=
{};
let
scale
=
transformData
.
scale
[
0
];
const
graphRect
=
graphDom
.
getBoundingClientRect
();
const
mapping
=
{
width
:
graphBox
.
width
/
graphRect
.
width
,
height
:
graphBox
.
height
/
graphRect
.
height
,
};
if
(
event
.
type
===
'
mousemove
'
)
{
pointer
.
end
.
x
=
event
.
x
;
pointer
.
end
.
y
=
event
.
y
;
change
=
{
x
:
(
pointer
.
end
.
x
-
pointer
.
start
.
x
)
*
mapping
.
width
*
scale
,
y
:
(
pointer
.
end
.
y
-
pointer
.
start
.
y
)
*
mapping
.
height
*
scale
,
};
pointer
.
start
.
x
=
pointer
.
end
.
x
;
pointer
.
start
.
y
=
pointer
.
end
.
y
;
}
else
if
(
event
.
type
===
'
wheel
'
)
{
const
wheelDelta
=
event
.
wheelDelta
;
const
rate
=
Math
.
abs
(
wheelDelta
/
100
);
scale
=
wheelDelta
>
0
?
transformData
.
scale
[
0
]
*
rate
:
transformData
.
scale
[
0
]
/
rate
;
scale
=
Math
.
max
(
this
.
scaleRange
[
0
],
scale
);
scale
=
Math
.
min
(
this
.
scaleRange
[
1
],
scale
);
change
=
{
x
:
(
graphRect
.
x
+
padding
/
mapping
.
width
-
event
.
x
)
*
mapping
.
width
*
(
scale
-
transformData
.
scale
[
0
]),
y
:
(
graphRect
.
bottom
-
padding
/
mapping
.
height
-
event
.
y
)
*
mapping
.
height
*
(
scale
-
transformData
.
scale
[
0
]),
};
}
tempStr
=
`translate(
${
transformData
.
translate
[
0
]
+
change
.
x
}
,
${
transformData
.
translate
[
1
]
+
change
.
y
}
) scale(
${
scale
}
)`
;
graphDom
.
setAttribute
(
'
transform
'
,
tempStr
);
});
const
svg
=
d3
.
select
(
'
svg
'
);
svg
.
on
(
'
.zoom
'
,
null
);
svg
.
call
(
zoom
);
svg
.
on
(
'
dblclick.zoom
'
,
null
);
},
/**
* Obtains the transform data of a node.
* @param {Object} node Node dom data
* @return {Object} transform data of a node
*/
getTransformData
(
node
)
{
if
(
!
node
)
{
return
[];
}
const
transformData
=
node
.
getAttribute
(
'
transform
'
);
const
attrObj
=
{};
if
(
transformData
)
{
const
lists
=
transformData
.
trim
().
split
(
'
'
);
lists
.
forEach
((
item
)
=>
{
const
index1
=
item
.
indexOf
(
'
(
'
);
const
index2
=
item
.
indexOf
(
'
)
'
);
const
name
=
item
.
substring
(
0
,
index1
);
const
params
=
item
.
substring
(
index1
+
1
,
index2
)
.
split
(
'
,
'
)
.
map
((
i
)
=>
{
return
parseFloat
(
i
)
||
0
;
});
attrObj
[
name
]
=
params
;
});
}
return
attrObj
;
},
removeGraph
()
{
const
svg
=
document
.
querySelector
(
'
#graph svg
'
);
if
(
svg
)
{
svg
.
remove
();
}
this
.
allGraphData
=
{};
},
},
destroyed
()
{
// Remove the listener of window size change
window
.
removeEventListener
(
'
resize
'
,
this
.
resizeCallback
);
this
.
$bus
.
$off
(
'
collapse
'
);
},
};
</
script
>
<
style
lang=
"scss"
>
.md-wrap
{
height
:
100%
;
background
:
#fff
;
padding
:
0
32px
;
.title
{
font-size
:
16px
;
font-weight
:
bold
;
text-align
:
left
;
}
.el-tabs.el-tabs--top
{
height
:
calc
(
100%
-
22px
);
}
.el-tabs__content
{
height
:
calc
(
100%
-
54px
);
&
>
.el-tab-pane
{
height
:
100%
;
}
}
.md-top
{
height
:
20%
;
font-size
:
0
;
display
:
flex
;
align-items
:
baseline
;
.cell-container
{
width
:
20%
;
cursor
:
pointer
;
padding
:
20px
0
;
border
:
2px
solid
transparent
;
.title
{
font-size
:
14px
;
line-height
:
20px
;
padding
:
0
0
0
20px
;
font-weight
:
bold
;
}
.content
{
padding
:
10px
20px
0px
20px
;
font-size
:
12px
;
}
}
.data-process
{
background-color
:
#e3f8eb
;
cursor
:
default
;
.title
{
border-left
:
2px
solid
#00a5a7
;
}
}
.device_queue_op
{
background-color
:
#e1f2ff
;
.title
{
border-left
:
2px
solid
#6cbfff
;
}
}
.get-next
{
background-color
:
#fef4dd
;
.title
{
border-left
:
2px
solid
#fdca5a
;
}
}
.queue-container
{
width
:
20%
;
position
:
relative
;
.img
{
width
:
100%
;
height
:
24px
;
margin-top
:
30px
;
.edge
{
width
:
calc
(
50%
-
40px
);
display
:
inline-block
;
vertical-align
:
middle
;
img
{
width
:
100%
;
}
}
.icon
{
padding
:
0
20px
;
display
:
inline-block
;
vertical-align
:
middle
;
img
{
padding
:
3px
;
border
:
2px
solid
transparent
;
cursor
:
pointer
;
}
}
}
.title
{
text-align
:
center
;
font-size
:
14px
;
margin-top
:
10px
;
font-weight
:
bold
;
}
.description
{
position
:
absolute
;
font-size
:
12px
;
line-height
:
12px
;
white-space
:
nowrap
;
overflow
:
hidden
;
width
:
100%
;
text-align
:
center
;
.item
{
font-size
:
12px
;
line-height
:
16px
;
white-space
:
normal
;
.num
{
color
:
#07a695
;
}
}
}
}
.selected
{
border
:
2px
solid
#3399ff
!
important
;
}
}
.md-bottom
{
height
:
80%
;
.queue-step-wrap
{
&
:first-child
{
height
:
50%
;
}
&
:last-child
{
height
:
50%
;
}
height
:
50%
;
&
>
.title
{
margin-bottom
:
15px
;
font-weight
:
bold
;
font-size
:
15px
;
}
.chart-content
{
height
:
calc
(
100%
-
30px
);
.chart-wrap
{
float
:
left
;
width
:
calc
(
50%
-
12px
);
height
:
100%
;
border-radius
:
4px
;
overflow-y
:
auto
;
border
:
1px
solid
#eee
;
&
:first-child
{
margin-right
:
20px
;
}
.title
{
font-size
:
13px
;
padding
:
10px
;
font-weight
:
bold
;
}
.data-tips
{
color
:
#999
;
padding
:
0
0
0
10px
;
&
>
div
{
display
:
inline-block
;
margin-right
:
10px
;
}
}
.chart
{
height
:
calc
(
100%
-
70px
);
min-height
:
150px
;
}
}
.chart-wrap.highlight
{
border-color
:
#3399ff
;
}
}
.chart-content.second
{
height
:
calc
(
100%
-
25px
);
}
}
}
.pipeline-wrap
{
height
:
100%
;
.pipeline-top
{
height
:
35%
;
.pipeline-top-title
{
font-size
:
15px
;
font-weight
:
bold
;
}
.average-rate-wrap
{
overflow-y
:
auto
;
height
:
calc
(
100%
-
20px
);
#average-rate
{
height
:
100%
;
min-height
:
180px
;
}
}
}
.pipeline-middle
{
height
:
30%
;
.pipeline-middle-title
{
font-size
:
15px
;
font-weight
:
bold
;
}
.operator-graph
{
height
:
calc
(
100%
-
20px
);
#graph
{
width
:
100%
;
height
:
100%
;
background-color
:
#f7faff
;
#graph0
>
polygon
{
fill
:
transparent
;
}
.node.queue
{
cursor
:
pointer
;
}
.operator
{
path
{
stroke
:
#e6ebf5
;
fill
:
#e6ebf5
;
}
}
.selected
{
path
,
polygon
{
stroke
:
red
;
}
}
.edge
{
path
,
polygon
{
stroke
:
#e6ebf5
;
fill
:
#e6ebf5
;
}
}
}
}
}
.pipeline-bottom
{
height
:
35%
;
.queue-deep-wrap
{
height
:
100%
;
background
:
#fafbfc
;
&
>
div
{
float
:
left
;
height
:
100%
;
}
.left
{
width
:
calc
(
60%
-
20px
);
overflow-y
:
auto
;
height
:
100%
;
border-right
:
1px
dashed
#ccc
;
padding-right
:
20px
;
margin-right
:
20px
;
#queue-deep
{
height
:
100%
;
width
:
100%
;
min-height
:
220px
;
}
}
.right
{
width
:
40%
;
.title
{
font-size
:
13px
;
margin-top
:
7px
;
}
.item-wrap
{
padding-top
:
10px
;
height
:
calc
(
100%
-
26px
);
overflow-y
:
auto
;
.item
{
margin-top
:
10px
;
&
>
span
{
color
:
#757b88
;
display
:
inline-block
;
width
:
50%
;
}
}
}
}
}
}
}
.image-noData
{
width
:
100%
;
height
:
calc
(
100%
-
37px
);
display
:
flex
;
justify-content
:
center
;
align-items
:
center
;
flex-direction
:
column
;
p
{
font-size
:
16px
;
padding-top
:
10px
;
}
}
}
</
style
>
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录