Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
MeterSphere
metersphere
提交
f9447a3a
M
metersphere
项目概览
MeterSphere
/
metersphere
上一次同步 3 年多
通知
25
Star
1
Fork
1
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
DevOps
流水线
流水线任务
计划
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
M
metersphere
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
DevOps
DevOps
流水线
流水线任务
计划
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
流水线任务
提交
Issue看板
体验新版 GitCode,发现更多精彩内容 >>
提交
f9447a3a
编写于
3月 17, 2021
作者:
C
chenjianxing
浏览文件
操作
浏览文件
下载
差异文件
Merge branch 'master' of github.com:metersphere/metersphere
上级
492dbb42
816cb478
变更
20
隐藏空白更改
内联
并排
Showing
20 changed file
with
1148 addition
and
326 deletion
+1148
-326
frontend/src/business/components/api/automation/ApiAutomation.vue
.../src/business/components/api/automation/ApiAutomation.vue
+12
-3
frontend/src/business/components/api/automation/scenario/EditApiScenario.vue
...ss/components/api/automation/scenario/EditApiScenario.vue
+22
-11
frontend/src/business/components/api/automation/scenario/api/AddBasisApi.vue
...ss/components/api/automation/scenario/api/AddBasisApi.vue
+284
-0
frontend/src/business/components/api/automation/scenario/api/ScenarioRelevance.vue
...ponents/api/automation/scenario/api/ScenarioRelevance.vue
+2
-1
frontend/src/business/components/api/automation/scenario/common/ApiBaseComponent.vue
...nents/api/automation/scenario/common/ApiBaseComponent.vue
+21
-10
frontend/src/business/components/api/automation/scenario/component/ApiComponent.vue
...onents/api/automation/scenario/component/ApiComponent.vue
+57
-75
frontend/src/business/components/api/automation/scenario/component/ApiScenarioComponent.vue
...pi/automation/scenario/component/ApiScenarioComponent.vue
+10
-2
frontend/src/business/components/api/automation/scenario/component/ComponentConfig.vue
...nts/api/automation/scenario/component/ComponentConfig.vue
+9
-2
frontend/src/business/components/api/automation/scenario/component/ConstantTimer.vue
...nents/api/automation/scenario/component/ConstantTimer.vue
+2
-2
frontend/src/business/components/api/automation/scenario/component/IfController.vue
...onents/api/automation/scenario/component/IfController.vue
+4
-4
frontend/src/business/components/api/automation/scenario/component/LoopController.vue
...ents/api/automation/scenario/component/LoopController.vue
+32
-31
frontend/src/business/components/api/automation/scenario/component/StepExtendBtns.vue
...ents/api/automation/scenario/component/StepExtendBtns.vue
+27
-48
frontend/src/business/components/api/automation/scenario/maximize/MaximizeScenario.vue
...nts/api/automation/scenario/maximize/MaximizeScenario.vue
+51
-9
frontend/src/business/components/api/automation/scenario/maximize/MsLeftContainer.vue
...ents/api/automation/scenario/maximize/MsLeftContainer.vue
+55
-0
frontend/src/business/components/api/automation/scenario/maximize/ScenarioHeader.vue
...nents/api/automation/scenario/maximize/ScenarioHeader.vue
+66
-44
frontend/src/business/components/api/automation/scenario/variable/VariableList.vue
...ponents/api/automation/scenario/variable/VariableList.vue
+96
-82
frontend/src/business/components/common/head/HeaderTopMenus.vue
...nd/src/business/components/common/head/HeaderTopMenus.vue
+6
-0
frontend/src/business/components/common/select-tree/SelectTree.vue
...src/business/components/common/select-tree/SelectTree.vue
+390
-0
frontend/src/business/components/track/plan/view/comonents/base/RelevanceDialog.vue
...onents/track/plan/view/comonents/base/RelevanceDialog.vue
+1
-1
frontend/src/business/components/xpack
frontend/src/business/components/xpack
+1
-1
未找到文件。
frontend/src/business/components/api/automation/ApiAutomation.vue
浏览文件 @
f9447a3a
...
...
@@ -39,7 +39,7 @@
:name=
"item.name"
closable
>
<div
class=
"ms-api-scenario-div"
>
<ms-edit-api-scenario
@
refresh=
"refresh"
:currentScenario=
"item.currentScenario"
<ms-edit-api-scenario
@
refresh=
"refresh"
@
openScenario=
"editScenario"
@
closePage=
"closePage"
:currentScenario=
"item.currentScenario"
:moduleOptions=
"moduleOptions"
ref=
"autoScenarioConfig"
/>
</div>
</el-tab-pane>
...
...
@@ -94,7 +94,7 @@
this
.
checkRedirectEditPage
(
redirectParam
);
return
redirectParam
;
},
isReadOnly
(){
isReadOnly
()
{
return
!
checkoutTestManagerOrTestUser
();
}
},
...
...
@@ -137,7 +137,7 @@
exportAPI
()
{
this
.
$refs
.
apiScenarioList
.
exportApi
();
},
exportJmx
(){
exportJmx
()
{
this
.
$refs
.
apiScenarioList
.
exportJmx
();
},
checkRedirectEditPage
(
redirectParam
)
{
...
...
@@ -226,6 +226,15 @@
break
;
}
},
closePage
(
targetName
)
{
this
.
tabs
=
this
.
tabs
.
filter
(
tab
=>
tab
.
label
!==
targetName
);
if
(
this
.
tabs
.
length
>
0
)
{
this
.
activeName
=
this
.
tabs
[
this
.
tabs
.
length
-
1
].
name
;
this
.
addListener
();
// 自动切换当前标签时,也添加监听
}
else
{
this
.
activeName
=
"
default
"
}
},
removeTab
(
targetName
)
{
this
.
tabs
=
this
.
tabs
.
filter
(
tab
=>
tab
.
name
!==
targetName
);
if
(
this
.
tabs
.
length
>
0
)
{
...
...
frontend/src/business/components/api/automation/scenario/EditApiScenario.vue
浏览文件 @
f9447a3a
...
...
@@ -119,7 +119,7 @@
:project-list=
"projectList"
ref=
"envPopover"
/>
</el-col>
<el-col
:span=
"3"
>
<el-button
:disabled=
"scenarioDefinition.length
<
1"
size=
"
small
"
type=
"primary"
v-prevent-re-click
@
click=
"runDebug"
>
{{
$t
(
'
api_test.request.debug
'
)
}}
</el-button>
<el-button
:disabled=
"scenarioDefinition.length
<
1"
size=
"
mini
"
type=
"primary"
v-prevent-re-click
@
click=
"runDebug"
>
{{
$t
(
'
api_test.request.debug
'
)
}}
</el-button>
<font-awesome-icon
class=
"alt-ico"
:icon=
"['fa', 'expand-alt']"
size=
"lg"
@
click=
"fullScreen"
/>
</el-col>
</el-row>
...
...
@@ -137,7 +137,7 @@
<!-- 步骤组件-->
<ms-component-config
:type=
"data.type"
:scenario=
"data"
:response=
"response"
:currentScenario=
"currentScenario"
:currentEnvironmentId=
"currentEnvironmentId"
:node=
"node"
:project-list=
"projectList"
:env-map=
"projectEnvMap"
@
remove=
"remove"
@
copyRow=
"copyRow"
@
suggestClick=
"suggestClick"
@
refReload=
"refReload"
/>
@
remove=
"remove"
@
copyRow=
"copyRow"
@
suggestClick=
"suggestClick"
@
refReload=
"refReload"
@
openScenario=
"openScenario"
/>
</span>
</el-tree>
</div>
...
...
@@ -198,10 +198,10 @@
<ms-drawer
:visible=
"drawer"
:size=
"100"
@
close=
"close"
direction=
"right"
:show-full-screen=
"false"
:is-show-close=
"false"
style=
"overflow: hidden"
>
<template
v-slot:header
>
<scenario-header
:currentScenario=
"currentScenario"
:projectEnvMap=
"projectEnvMap"
:projectIds=
"projectIds"
:projectList=
"projectList"
:scenarioDefinition=
"scenarioDefinition"
:enableCookieShare=
"enableCookieShare"
@
closePage=
"close"
@
showAllBtn=
"showAllBtn"
@
runDebug=
"runDebug"
@
showScenarioParameters=
"showScenarioParameters
"
ref=
"maximizeHeader"
/>
@
closePage=
"close"
@
unFullScreen=
"unFullScreen"
@
showAllBtn=
"showAllBtn"
@
runDebug=
"runDebug"
@
setProjectEnvMap=
"setProjectEnvMap"
@
showScenarioParameters=
"showScenarioParameters"
@
setCookieShare=
"setCookieShare
"
ref=
"maximizeHeader"
/>
</
template
>
<maximize-scenario
:scenario-definition=
"scenarioDefinition"
:
moduleOptions=
"moduleOptions"
:currentScenario=
"currentScenario"
:type=
"type"
ref=
"maximize
Scenario"
/>
<maximize-scenario
:scenario-definition=
"scenarioDefinition"
:
envMap=
"projectEnvMap"
:moduleOptions=
"moduleOptions"
:currentScenario=
"currentScenario"
:type=
"type"
ref=
"maximizeScenario"
@
openScenario=
"open
Scenario"
/>
</ms-drawer>
</div>
...
...
@@ -222,7 +222,7 @@
import
{
parseEnvironment
}
from
"
../../definition/model/EnvironmentModel
"
;
import
{
ELEMENT_TYPE
,
ELEMENTS
}
from
"
./Setting
"
;
import
MsApiCustomize
from
"
./ApiCustomize
"
;
import
{
getCurrentProjectID
,
getUUID
,
objToStrMap
,
strMapToObj
}
from
"
@/common/js/utils
"
;
import
{
getCurrentProjectID
,
getUUID
,
objToStrMap
,
strMapToObj
,
handleCtrlSEvent
}
from
"
@/common/js/utils
"
;
import
ApiEnvironmentConfig
from
"
../../definition/components/environment/ApiEnvironmentConfig
"
;
import
MsInputTag
from
"
./MsInputTag
"
;
import
MsRun
from
"
./DebugRun
"
;
...
...
@@ -234,7 +234,6 @@
import
ScenarioApiRelevance
from
"
./api/ApiRelevance
"
;
import
ScenarioRelevance
from
"
./api/ScenarioRelevance
"
;
import
MsComponentConfig
from
"
./component/ComponentConfig
"
;
import
{
handleCtrlSEvent
}
from
"
../../../../../common/js/utils
"
;
import
EnvPopover
from
"
@/business/components/api/automation/scenario/EnvPopover
"
;
import
MaximizeScenario
from
"
./maximize/MaximizeScenario
"
;
import
ScenarioHeader
from
"
./maximize/ScenarioHeader
"
;
...
...
@@ -442,6 +441,13 @@
}
},
methods
:
{
// 打开引用的场景
openScenario
(
data
)
{
this
.
$emit
(
'
openScenario
'
,
data
);
},
setCookieShare
(
cookie
)
{
this
.
enableCookieShare
=
cookie
;
},
showAllBtn
()
{
this
.
$refs
.
maximizeScenario
.
showAll
();
},
...
...
@@ -465,7 +471,9 @@
// 直接更新场景防止编辑内容丢失
this
.
editScenario
();
}
this
.
$refs
.
maximizeHeader
.
getVariableSize
();
if
(
this
.
$refs
.
maximizeHeader
)
{
this
.
$refs
.
maximizeHeader
.
getVariableSize
();
}
this
.
reload
();
},
showButton
(...
names
)
{
...
...
@@ -555,7 +563,6 @@
this
.
operatingElements
=
ELEMENTS
.
get
(
"
ALL
"
);
this
.
selectedTreeNode
=
undefined
;
}
//this.reload();
},
apiListImport
()
{
this
.
$refs
.
scenarioApiRelevance
.
open
();
...
...
@@ -1072,10 +1079,13 @@
fullScreen
()
{
this
.
drawer
=
true
;
},
close
()
{
unFullScreen
()
{
this
.
drawer
=
false
;
},
close
(
name
)
{
this
.
drawer
=
false
;
this
.
$emit
(
'
closePage
'
,
name
);
}
}
}
</
script
>
...
...
@@ -1214,7 +1224,8 @@
.alt-ico
{
font-size
:
15px
;
margin
:
0px
10px
0px
;
margin
:
5px
10px
0px
;
float
:
right
;
color
:
#8c939d
;
}
...
...
frontend/src/business/components/api/automation/scenario/api/AddBasisApi.vue
0 → 100644
浏览文件 @
f9447a3a
<
template
>
<el-dialog
:close-on-click-modal=
"false"
:title=
"$t('api_test.definition.request.title')"
:visible.sync=
"httpVisible"
width=
"45%"
:destroy-on-close=
"true"
append-to-body
>
<el-form
:model=
"httpForm"
label-position=
"right"
label-width=
"80px"
size=
"small"
:rules=
"rule"
ref=
"httpForm"
v-if=
"!loading"
>
<el-form-item
:label=
"$t('commons.name')"
prop=
"name"
>
<el-input
v-model=
"httpForm.name"
autocomplete=
"off"
:placeholder=
"$t('commons.name')"
/>
</el-form-item>
<!--HTTP 协议特有参数-->
<el-form-item
:label=
"$t('api_report.request')"
prop=
"path"
v-if=
"currentProtocol==='HTTP'"
>
<el-input
:placeholder=
"$t('api_test.definition.request.path_info')"
v-model=
"httpForm.path"
class=
"ms-http-input"
size=
"small"
>
<el-select
v-model=
"httpForm.method"
slot=
"prepend"
style=
"width: 100px"
size=
"small"
>
<el-option
v-for=
"item in options"
:key=
"item.id"
:label=
"item.label"
:value=
"item.id"
/>
</el-select>
</el-input>
</el-form-item>
<el-form-item
:label=
"$t('api_test.definition.request.responsible')"
prop=
"userId"
>
<el-select
v-model=
"httpForm.userId"
:placeholder=
"$t('api_test.definition.request.responsible')"
filterable
size=
"small"
style=
"width: 100%"
>
<el-option
v-for=
"item in maintainerOptions"
:key=
"item.id"
:label=
"item.id + ' (' + item.name + ')'"
:value=
"item.id"
>
</el-option>
</el-select>
</el-form-item>
<el-form-item
:label=
"$t('test_track.module.module')"
prop=
"moduleId"
>
<ms-select-tree
size=
"small"
:data=
"moduleOptions"
@
getValue=
"setModule"
:obj=
"moduleObj"
clearable
checkStrictly
/>
</el-form-item>
<el-form-item
:label=
"$t('commons.description')"
prop=
"description"
style=
"margin-bottom: 29px"
>
<el-input
class=
"ms-http-textarea"
v-model=
"httpForm.description"
type=
"textarea"
:autosize=
"
{ minRows: 2, maxRows: 10}"
:rows="2" size="small"/>
</el-form-item>
<el-form-item
class=
"create-tip"
>
{{
$t
(
'
api_test.definition.create_tip
'
)
}}
</el-form-item>
</el-form>
<template
v-slot:footer
>
<ms-dialog-footer
@
cancel=
"httpVisible = false"
@
confirm=
"saveApi"
v-prevent-re-click
>
</ms-dialog-footer>
</
template
>
</el-dialog>
</template>
<
script
>
import
MsDialogFooter
from
"
../../../../common/components/MsDialogFooter
"
;
import
{
WORKSPACE_ID
}
from
'
../../../../../../common/js/constants
'
;
import
{
REQ_METHOD
}
from
"
../../../definition/model/JsonData
"
;
import
{
getCurrentProjectID
,
getCurrentUser
}
from
"
@/common/js/utils
"
;
import
{
createComponent
,
Request
}
from
"
../../../definition/components/jmeter/components
"
;
import
{
getUUID
}
from
"
@/common/js/utils
"
;
import
MsSelectTree
from
"
@/business/components/common/select-tree/SelectTree
"
;
export
default
{
name
:
"
MsAddBasisApi
"
,
components
:
{
MsDialogFooter
,
MsSelectTree
},
props
:
{
currentProtocol
:
{
type
:
String
,
default
:
"
HTTP
"
},
},
data
()
{
let
validateURL
=
(
rule
,
value
,
callback
)
=>
{
if
(
!
this
.
httpForm
.
path
.
startsWith
(
"
/
"
)
||
this
.
httpForm
.
path
.
match
(
/
\s
/
)
!=
null
)
{
callback
(
this
.
$t
(
'
api_test.definition.request.path_valid_info
'
));
}
callback
();
};
return
{
httpForm
:
{
environmentId
:
""
},
moduleOptions
:
[],
httpVisible
:
false
,
currentModule
:
{},
maintainerOptions
:
[],
loading
:
false
,
moduleObj
:
{
id
:
'
id
'
,
label
:
'
name
'
,
},
rule
:
{
name
:
[
{
required
:
true
,
message
:
this
.
$t
(
'
test_track.case.input_name
'
),
trigger
:
'
blur
'
},
{
max
:
100
,
message
:
this
.
$t
(
'
test_track.length_less_than
'
)
+
'
100
'
,
trigger
:
'
blur
'
}
],
path
:
[{
required
:
true
,
message
:
this
.
$t
(
'
api_test.definition.request.path_info
'
),
trigger
:
'
blur
'
},
{
validator
:
validateURL
,
trigger
:
'
blur
'
}],
userId
:
[{
required
:
true
,
message
:
this
.
$t
(
'
test_track.case.input_maintainer
'
),
trigger
:
'
change
'
}],
// moduleId: [{required: true, message: this.$t('test_track.module.module'), trigger: 'change'}],
},
value
:
REQ_METHOD
[
0
].
id
,
options
:
REQ_METHOD
,
}
}
,
methods
:
{
saveApi
()
{
this
.
$refs
[
'
httpForm
'
].
validate
((
valid
)
=>
{
if
(
valid
)
{
if
(
this
.
httpForm
.
path
&&
this
.
httpForm
.
path
.
match
(
/
\s
/
)
!=
null
)
{
this
.
$error
(
this
.
$t
(
"
api_test.definition.request.path_valid_info
"
));
return
false
;
}
this
.
save
(
this
.
httpForm
);
}
else
{
return
false
;
}
})
},
save
(
data
)
{
this
.
setParameters
(
data
);
let
bodyFiles
=
this
.
getBodyUploadFiles
(
data
);
this
.
$fileUpload
(
"
/api/definition/create
"
,
null
,
bodyFiles
,
data
,
()
=>
{
this
.
saveCase
(
data
);
});
},
saveCase
(
api
)
{
let
obj
=
{
apiDefinitionId
:
api
.
id
,
name
:
api
.
name
,
priority
:
'
P0
'
,
active
:
true
,
uuid
:
getUUID
(),
request
:
api
.
request
};
obj
.
projectId
=
getCurrentProjectID
();
obj
.
id
=
obj
.
uuid
;
let
url
=
"
/api/testcase/create
"
;
let
bodyFiles
=
this
.
getBodyUploadFiles
(
obj
);
this
.
$fileUpload
(
url
,
null
,
bodyFiles
,
obj
,
(
response
)
=>
{
this
.
$success
(
this
.
$t
(
'
commons.save_success
'
));
this
.
httpVisible
=
false
;
});
},
setParameters
(
data
)
{
data
.
projectId
=
getCurrentProjectID
();
data
.
request
.
name
=
data
.
name
;
if
(
data
.
protocol
===
"
DUBBO
"
||
data
.
protocol
===
"
dubbo://
"
)
{
data
.
request
.
protocol
=
"
dubbo://
"
;
}
data
.
id
=
data
.
request
.
id
;
if
(
!
data
.
method
)
{
data
.
method
=
data
.
protocol
;
}
},
getBodyUploadFiles
(
data
)
{
let
bodyUploadFiles
=
[];
data
.
bodyUploadIds
=
[];
let
request
=
data
.
request
;
if
(
request
.
body
)
{
if
(
request
.
body
.
kvs
)
{
request
.
body
.
kvs
.
forEach
(
param
=>
{
if
(
param
.
files
)
{
param
.
files
.
forEach
(
item
=>
{
if
(
item
.
file
)
{
let
fileId
=
getUUID
().
substring
(
0
,
8
);
item
.
name
=
item
.
file
.
name
;
item
.
id
=
fileId
;
data
.
bodyUploadIds
.
push
(
fileId
);
bodyUploadFiles
.
push
(
item
.
file
);
}
});
}
});
}
if
(
request
.
body
.
binary
)
{
request
.
body
.
binary
.
forEach
(
param
=>
{
if
(
param
.
files
)
{
param
.
files
.
forEach
(
item
=>
{
if
(
item
.
file
)
{
let
fileId
=
getUUID
().
substring
(
0
,
8
);
item
.
name
=
item
.
file
.
name
;
item
.
id
=
fileId
;
data
.
bodyUploadIds
.
push
(
fileId
);
bodyUploadFiles
.
push
(
item
.
file
);
}
});
}
});
}
}
return
bodyUploadFiles
;
},
setParameter
()
{
switch
(
this
.
currentProtocol
)
{
case
Request
.
TYPES
.
SQL
:
this
.
initSQL
();
break
;
case
Request
.
TYPES
.
DUBBO
:
this
.
initDUBBO
();
break
;
case
Request
.
TYPES
.
TCP
:
this
.
initTCP
();
break
;
default
:
this
.
initHTTP
();
break
;
}
this
.
httpForm
.
bodyUploadIds
=
[];
this
.
httpForm
.
projectId
=
getCurrentProjectID
();
this
.
httpForm
.
id
=
this
.
httpForm
.
request
.
id
;
this
.
httpForm
.
protocol
=
this
.
currentProtocol
;
this
.
httpForm
.
request
.
name
=
this
.
httpForm
.
name
;
this
.
httpForm
.
request
.
protocol
=
this
.
currentProtocol
;
if
(
this
.
currentProtocol
===
'
HTTP
'
)
{
this
.
httpForm
.
request
.
method
=
this
.
httpForm
.
method
;
this
.
httpForm
.
request
.
path
=
this
.
httpForm
.
path
;
}
if
(
this
.
currentModule
!=
null
)
{
this
.
httpForm
.
modulePath
=
this
.
currentModule
.
method
!=
undefined
?
this
.
currentModule
.
method
:
null
;
this
.
httpForm
.
moduleId
=
this
.
currentModule
.
id
;
}
},
initHTTP
()
{
let
request
=
createComponent
(
"
HTTPSamplerProxy
"
);
request
.
path
=
this
.
httpForm
.
path
;
this
.
httpForm
.
request
=
request
;
},
initSQL
()
{
this
.
httpForm
.
method
=
Request
.
TYPES
.
SQL
;
this
.
httpForm
.
request
=
createComponent
(
"
JDBCSampler
"
);
},
initTCP
()
{
this
.
httpForm
.
method
=
Request
.
TYPES
.
TCP
;
this
.
httpForm
.
request
=
createComponent
(
"
TCPSampler
"
);
},
initDUBBO
()
{
this
.
httpForm
.
method
=
"
dubbo://
"
;
this
.
httpForm
.
request
=
createComponent
(
"
DubboSampler
"
);
},
getMaintainerOptions
()
{
let
workspaceId
=
localStorage
.
getItem
(
WORKSPACE_ID
);
this
.
$post
(
'
/user/ws/member/tester/list
'
,
{
workspaceId
:
workspaceId
},
response
=>
{
this
.
maintainerOptions
=
response
.
data
;
});
},
list
(
data
)
{
let
url
=
"
/api/module/list/
"
+
getCurrentProjectID
()
+
"
/
"
+
data
.
protocol
;
this
.
result
=
this
.
$get
(
url
,
response
=>
{
if
(
response
.
data
!=
undefined
&&
response
.
data
!=
null
)
{
this
.
moduleOptions
=
response
.
data
;
}
});
},
setModule
(
id
)
{
this
.
httpForm
.
moduleId
=
id
;
//this.reload();
},
reload
()
{
this
.
loading
=
true
this
.
$nextTick
(()
=>
{
this
.
loading
=
false
})
},
open
(
api
)
{
if
(
api
)
{
let
data
=
JSON
.
parse
(
JSON
.
stringify
(
api
));
data
.
id
=
getUUID
();
this
.
httpForm
=
{
id
:
data
.
id
,
name
:
data
.
name
,
protocol
:
data
.
protocol
,
path
:
data
.
path
,
method
:
REQ_METHOD
[
0
].
id
,
userId
:
getCurrentUser
().
id
,
request
:
data
};
this
.
getMaintainerOptions
();
this
.
list
(
data
);
this
.
httpVisible
=
true
;
}
},
}
}
</
script
>
<
style
scoped
>
.create-tip
{
color
:
#8c939d
;
}
</
style
>
frontend/src/business/components/api/automation/scenario/api/ScenarioRelevance.vue
浏览文件 @
f9447a3a
...
...
@@ -90,7 +90,8 @@
response
.
data
.
forEach
(
item
=>
{
let
scenarioDefinition
=
JSON
.
parse
(
item
.
scenarioDefinition
);
if
(
scenarioDefinition
&&
scenarioDefinition
.
hashTree
)
{
let
obj
=
{
id
:
item
.
id
,
name
:
item
.
name
,
type
:
"
scenario
"
,
referenced
:
'
Copy
'
,
resourceId
:
getUUID
(),
hashTree
:
scenarioDefinition
.
hashTree
,
projectId
:
item
.
projectId
};
let
obj
=
{
id
:
item
.
id
,
name
:
item
.
name
,
type
:
"
scenario
"
,
headers
:
scenarioDefinition
.
headers
,
variables
:
scenarioDefinition
.
variables
,
environmentMap
:
scenarioDefinition
.
environmentMap
,
referenced
:
'
Copy
'
,
resourceId
:
getUUID
(),
hashTree
:
scenarioDefinition
.
hashTree
,
projectId
:
item
.
projectId
};
scenarios
.
push
(
obj
);
}
});
...
...
frontend/src/business/components/api/automation/scenario/common/ApiBaseComponent.vue
浏览文件 @
f9447a3a
...
...
@@ -5,7 +5,7 @@
<div
v-if=
"data.index"
class=
"el-step__icon is-text"
style=
"margin-right: 10px;"
:style=
"
{'color': color, 'background-color': backgroundColor}">
<div
class=
"el-step__icon-inner"
>
{{
data
.
index
}}
</div>
</div>
<el-
button
class=
"ms-left-buttion"
size=
"mini"
:style=
"
{'color': color, 'background-color': backgroundColor}">
{{
title
}}
</el-button
>
<el-
tag
class=
"ms-left-buttion"
size=
"small"
:style=
"
{'color': color, 'background-color': backgroundColor}">
{{
title
}}
</el-tag
>
<el-tag
size=
"mini"
v-if=
"data.method"
>
{{
data
.
method
}}
</el-tag>
</slot>
...
...
@@ -15,11 +15,6 @@
@click="active(data)" v-if="data.type!='scenario'
&&
!isMax "/>
<el-input
:draggable=
"draggable"
v-if=
"isShowInput && isShowNameInput"
size=
"mini"
v-model=
"data.name"
class=
"name-input"
@
blur=
"isShowInput = false"
:placeholder=
"$t('commons.input_name')"
ref=
"nameEdit"
:disabled=
"data.disabled"
/>
<span
v-else-if=
"isMax"
>
<el-tooltip
:content=
"data.name"
placement=
"top"
>
<span>
{{
data
.
name
}}
</span>
</el-tooltip>
</span>
<span
v-else
>
{{
data
.
name
}}
<i
class=
"el-icon-edit"
style=
"cursor:pointer"
@
click=
"editName"
v-tester
v-if=
"data.referenced!='REF' && !data.disabled"
/>
...
...
@@ -31,16 +26,17 @@
<div
class=
"header-right"
@
click.stop
>
<slot
name=
"message"
></slot>
<el-tooltip
:content=
"$t('test_resource_pool.enable_disable')"
placement=
"top"
v-if=
"showBtn"
>
<el-switch
v-model=
"data.enable"
class=
"enable-switch"
/>
<el-switch
v-model=
"data.enable"
class=
"enable-switch"
size=
"mini"
/>
</el-tooltip>
<slot
name=
"button"
></slot>
<step-extend-btns
style=
"display: contents"
@
copy=
"copyRow"
@
remove=
"remove
"
v-if=
"showBtn"
/>
<step-extend-btns
style=
"display: contents"
:data=
"data"
@
copy=
"copyRow"
@
remove=
"remove"
@
openScenario=
"openScenario
"
v-if=
"showBtn"
/>
</div>
</div>
<!--最大化不显示具体内容-->
<div
class=
"header"
v-if=
"!isMax"
>
<fieldset
:disabled=
"data.disabled"
class=
"ms-fieldset"
>
<el-collapse-transition>
6.
<el-collapse-transition>
<div
v-if=
"data.active && showCollapse"
:draggable=
"draggable"
>
<el-divider></el-divider>
<slot></slot>
...
...
@@ -54,6 +50,7 @@
<
script
>
import
StepExtendBtns
from
"
../component/StepExtendBtns
"
;
import
{
ELEMENTS
}
from
"
../Setting
"
;
export
default
{
name
:
"
ApiBaseComponent
"
,
...
...
@@ -117,6 +114,11 @@
if
(
this
.
data
&&
this
.
data
.
type
===
"
JmeterElement
"
)
{
this
.
data
.
active
=
false
;
}
if
(
this
.
data
&&
ELEMENTS
.
get
(
"
AllSamplerProxy
"
).
indexOf
(
this
.
data
.
type
)
!=
-
1
)
{
if
(
!
this
.
data
.
method
)
{
this
.
data
.
method
=
this
.
data
.
protocol
;
}
}
},
methods
:
{
active
()
{
...
...
@@ -130,6 +132,9 @@
remove
()
{
this
.
$emit
(
'
remove
'
);
},
openScenario
(
data
)
{
this
.
$emit
(
'
openScenario
'
,
data
);
},
editName
()
{
this
.
isShowInput
=
true
;
this
.
$nextTick
(()
=>
{
...
...
@@ -159,7 +164,7 @@
}
.header-right
{
margin-top
:
5
px
;
margin-top
:
0
px
;
float
:
right
;
z-index
:
1
;
}
...
...
@@ -179,6 +184,12 @@
width
:
100px
;
}
/
deep
/
.el-step__icon
{
width
:
20px
;
height
:
20px
;
font-size
:
12px
;
}
fieldset
{
padding
:
0px
;
margin
:
0px
;
...
...
frontend/src/business/components/api/automation/scenario/component/ApiComponent.vue
浏览文件 @
f9447a3a
<
template
>
<api-base-component
v-loading=
"loading"
@
copy=
"copyRow"
@
remove=
"remove"
@
active=
"active"
:is-show-name-input=
"!isDeletedOrRef"
:data=
"request"
:draggable=
"true"
:color=
"displayColor.color"
:background-color=
"displayColor.backgroundColor"
:is-max=
"isMax"
:show-btn=
"showBtn"
:title=
"displayTitle"
>
<div>
<api-base-component
v-loading=
"loading"
@
copy=
"copyRow"
@
remove=
"remove"
@
active=
"active"
:is-show-name-input=
"!isDeletedOrRef"
:data=
"request"
:draggable=
"draggable"
:color=
"displayColor.color"
:background-color=
"displayColor.backgroundColor"
:is-max=
"isMax"
:show-btn=
"showBtn"
:title=
"displayTitle"
>
<template
v-slot:behindHeaderLeft
>
<el-tag
size=
"mini"
class=
"ms-tag"
v-if=
"request.referenced==='Deleted'"
type=
"danger"
>
{{
$t
(
'
api_test.automation.reference_deleted
'
)
}}
</el-tag>
<el-tag
size=
"mini"
class=
"ms-tag"
v-if=
"request.referenced==='Copy'"
>
{{
$t
(
'
commons.copy
'
)
}}
</el-tag>
<el-tag
size=
"mini"
class=
"ms-tag"
v-if=
"request.referenced ==='REF'"
>
{{
$t
(
'
api_test.scenario.reference
'
)
}}
</el-tag>
<span
class=
"ms-tag"
>
{{
getProjectName
(
request
.
projectId
)
}}
</span>
<ms-run
:debug=
"true"
:reportId=
"reportId"
:run-data=
"runData"
:env-map=
"envMap"
@
runRefresh=
"runRefresh"
ref=
"runTest"
/>
<template
v-slot:behindHeaderLeft
>
<el-tag
size=
"mini"
class=
"ms-tag"
v-if=
"request.referenced==='Deleted'"
type=
"danger"
>
{{
$t
(
'
api_test.automation.reference_deleted
'
)
}}
</el-tag>
<el-tag
size=
"mini"
class=
"ms-tag"
v-if=
"request.referenced==='Copy'"
>
{{
$t
(
'
commons.copy
'
)
}}
</el-tag>
<el-tag
size=
"mini"
class=
"ms-tag"
v-if=
"request.referenced ==='REF'"
>
{{
$t
(
'
api_test.scenario.reference
'
)
}}
</el-tag>
<span
class=
"ms-tag"
>
{{
getProjectName
(
request
.
projectId
)
}}
</span>
</
template
>
</
template
>
<
template
v-slot:button
>
<el-tooltip
:content=
"$t('api_test.run')"
placement=
"top"
>
<el-button
@
click=
"run"
icon=
"el-icon-video-play"
class=
"ms-btn"
size=
"mini"
circle
/>
</el-tooltip>
</
template
>
<
template
v-slot:button
>
<el-tooltip
:content=
"$t('api_test.run')"
placement=
"top"
>
<el-button
@
click=
"run"
icon=
"el-icon-video-play"
class=
"ms-btn"
size=
"mini"
circle
/>
</el-tooltip>
</
template
>
<customize-req-info
:is-customize-req=
"isCustomizeReq"
:request=
"request"
/>
<customize-req-info
:is-customize-req=
"isCustomizeReq"
:request=
"request"
/>
<p
class=
"tip"
>
{{ $t('api_test.definition.request.req_param') }}
</p>
<ms-api-request-form
:isShowEnable=
"true"
:referenced=
"true"
:headers=
"request.headers "
:request=
"request"
v-if=
"request.protocol==='HTTP' || request.type==='HTTPSamplerProxy'"
/>
<ms-tcp-basis-parameters
:request=
"request"
v-if=
"request.protocol==='TCP'|| request.type==='TCPSampler'"
:showScript=
"false"
/>
<ms-sql-basis-parameters
:request=
"request"
v-if=
"request.protocol==='SQL'|| request.type==='JDBCSampler'"
:showScript=
"false"
/>
<ms-dubbo-basis-parameters
:request=
"request"
v-if=
"request.protocol==='DUBBO' || request.protocol==='dubbo://'|| request.type==='DubboSampler'"
<p
class=
"tip"
>
{{ $t('api_test.definition.request.req_param') }}
</p>
<ms-api-request-form
:isShowEnable=
"true"
:referenced=
"true"
:headers=
"request.headers "
:request=
"request"
v-if=
"request.protocol==='HTTP' || request.type==='HTTPSamplerProxy'"
/>
<ms-tcp-basis-parameters
:request=
"request"
v-if=
"request.protocol==='TCP'|| request.type==='TCPSampler'"
:showScript=
"false"
/>
<ms-sql-basis-parameters
:request=
"request"
v-if=
"request.protocol==='SQL'|| request.type==='JDBCSampler'"
:showScript=
"false"
/>
<ms-dubbo-basis-parameters
:request=
"request"
v-if=
"request.protocol==='DUBBO' || request.protocol==='dubbo://'|| request.type==='DubboSampler'"
:showScript=
"false"
/>
<p
class=
"tip"
>
{{ $t('api_test.definition.request.res_param') }}
</p>
<div
v-if=
"request.result"
>
<el-tabs
v-model=
"request.activeName"
closable
class=
"ms-tabs"
>
<el-tab-pane
:label=
"item.name"
:name=
"item.name"
v-for=
"(item,index) in request.result.scenarios"
:key=
"index"
>
<div
v-for=
"(result,i) in item.requestResults"
:key=
"i"
style=
"margin-bottom: 5px"
>
<api-response-component
v-if=
"result.name===request.name"
:result=
"result"
/>
</div>
</el-tab-pane>
</el-tabs>
</div>
<api-response-component
:currentProtocol=
"request.protocol"
:result=
"request.requestResult"
v-else
/>
<p
class=
"tip"
>
{{ $t('api_test.definition.request.res_param') }}
</p>
<div
v-if=
"request.result"
>
<el-tabs
v-model=
"request.activeName"
closable
class=
"ms-tabs"
>
<el-tab-pane
:label=
"item.name"
:name=
"item.name"
v-for=
"(item,index) in request.result.scenarios"
:key=
"index"
>
<div
v-for=
"(result,i) in item.requestResults"
:key=
"i"
style=
"margin-bottom: 5px"
>
<api-response-component
v-if=
"result.name===request.name"
:result=
"result"
/>
</div>
</el-tab-pane>
</el-tabs>
</div>
<api-response-component
:currentProtocol=
"request.protocol"
:result=
"request.requestResult"
v-else
/>
<!-- 保存操作 -->
<el-button
type=
"primary"
size=
"small"
class=
"ms-btn-flot"
@
click=
"saveTestCase(item)"
v-if=
"!request.referenced"
>
{{ $t('commons.save') }}
</el-button>
</api-base-component>
<ms-run
:debug=
"true"
:reportId=
"reportId"
:run-data=
"runData"
:env-map=
"envMap"
@
runRefresh=
"runRefresh"
ref=
"runTest"
/>
<!-- 保存操作 -->
<el-button
type=
"primary"
size=
"small"
class=
"ms-btn-flot"
@
click=
"saveTestCase(item)"
v-if=
"!request.referenced"
>
{{ $t('commons.save') }}
</el-button>
</
api-base-component
>
</
div
>
</template>
<
script
>
...
...
@@ -73,7 +75,6 @@
import
ApiBaseComponent
from
"
../common/ApiBaseComponent
"
;
import
ApiResponseComponent
from
"
./ApiResponseComponent
"
;
import
CustomizeReqInfo
from
"
@/business/components/api/automation/scenario/common/CustomizeReqInfo
"
;
import
{
ELEMENTS
}
from
"
../Setting
"
;
export
default
{
name
:
"
MsApiComponent
"
,
...
...
@@ -133,11 +134,6 @@
}
}
}
// if (this.isMax && this.request && ELEMENTS.get("AllSamplerProxy").indexOf(this.request.type) != -1
// && this.request.hashTree && this.request.hashTree != null && this.request.hashTree.length > 0) {
// this.request.hashTrees = JSON.parse(JSON.stringify(this.request.hashTree));
// this.request.hashTree = undefined;
// }
},
computed
:
{
displayColor
()
{
...
...
@@ -236,12 +232,6 @@
if
(
!
this
.
request
.
projectId
)
{
this
.
request
.
projectId
=
response
.
data
.
projectId
;
}
// if (this.isMax && this.request && ELEMENTS.get("AllSamplerProxy").indexOf(this.request.type) != -1) {
// this.request.hashTrees = [];
// Object.assign(this.request.hashTrees, this.request.hashTree);
// this.request.hashTree = [];
// }
this
.
reload
();
this
.
sort
();
}
else
{
...
...
@@ -299,7 +289,7 @@
};
this
.
runData
.
push
(
debugData
);
/*触发执行操作*/
this
.
reportId
=
getUUID
()
.
substring
(
0
,
8
)
;
this
.
reportId
=
getUUID
();
},
runRefresh
(
data
)
{
this
.
request
.
requestResult
=
data
;
...
...
@@ -328,7 +318,7 @@
}
/
deep
/
.el-card__body
{
padding
:
1
5
px
;
padding
:
1
0
px
;
}
.tip
{
...
...
@@ -339,14 +329,6 @@
margin
:
20px
0
;
}
.name-input
{
width
:
30%
;
}
.el-icon-arrow-right
{
margin-right
:
5px
;
}
.icon.is-active
{
transform
:
rotate
(
90deg
);
}
...
...
frontend/src/business/components/api/automation/scenario/component/ApiScenarioComponent.vue
浏览文件 @
f9447a3a
...
...
@@ -4,6 +4,7 @@
@
copy=
"copyRow"
@
remove=
"remove"
@
active=
"active"
@
openScenario=
"openScenario"
:data=
"scenario"
:show-collapse=
"false"
:is-show-name-input=
"!isDeletedOrRef"
...
...
@@ -62,8 +63,10 @@
this
.
result
=
this
.
$get
(
"
/api/automation/getApiScenario/
"
+
this
.
scenario
.
id
,
response
=>
{
if
(
response
.
data
)
{
this
.
scenario
.
loaded
=
true
;
let
obj
=
{};
if
(
response
.
data
.
scenarioDefinition
)
{
this
.
scenario
.
hashTree
=
JSON
.
parse
(
response
.
data
.
scenarioDefinition
).
hashTree
;
obj
=
JSON
.
parse
(
response
.
data
.
scenarioDefinition
);
this
.
scenario
.
hashTree
=
obj
.
hashTree
;
}
if
(
this
.
scenario
.
hashTree
)
{
this
.
setDisabled
(
this
.
scenario
.
hashTree
);
...
...
@@ -73,7 +76,9 @@
if
(
!
this
.
scenario
.
projectId
)
{
this
.
scenario
.
projectId
=
response
.
data
.
projectId
;
}
this
.
scenario
.
headers
=
obj
.
headers
;
this
.
scenario
.
variables
=
obj
.
variables
;
this
.
scenario
.
environmentMap
=
obj
.
environmentMap
;
this
.
$emit
(
'
refReload
'
);
}
else
{
this
.
scenario
.
referenced
=
"
Deleted
"
;
...
...
@@ -109,6 +114,9 @@
copyRow
()
{
this
.
$emit
(
'
copyRow
'
,
this
.
scenario
,
this
.
node
);
},
openScenario
(
data
){
this
.
$emit
(
'
openScenario
'
,
data
);
},
reload
()
{
this
.
loading
=
true
this
.
$nextTick
(()
=>
{
...
...
frontend/src/business/components/api/automation/scenario/component/ComponentConfig.vue
浏览文件 @
f9447a3a
...
...
@@ -2,8 +2,8 @@
<div
class=
"request-form"
>
<component
:is=
"component"
:isMax=
"isMax"
:show-btn=
"showBtn"
:scenario=
"scenario"
:controller=
"scenario"
:timer=
"scenario"
:assertions=
"scenario"
:extract=
"scenario"
:jsr223-processor=
"scenario"
:request=
"scenario"
:currentScenario=
"currentScenario"
:currentEnvironmentId=
"currentEnvironmentId"
:node=
"node"
:draggable=
"
tru
e"
:title=
"title"
:color=
"titleColor"
:background-color=
"backgroundColor"
@
suggestClick=
"suggestClick(node)"
:response=
"response"
@
remove=
"remove"
@
copyRow=
"copyRow"
@
refReload=
"refReload"
:project-list=
"projectList"
:env-map=
"envMap"
/>
:draggable=
"
draggabl
e"
:title=
"title"
:color=
"titleColor"
:background-color=
"backgroundColor"
@
suggestClick=
"suggestClick(node)"
:response=
"response"
@
remove=
"remove"
@
copyRow=
"copyRow"
@
refReload=
"refReload"
@
openScenario=
"openScenario"
:project-list=
"projectList"
:env-map=
"envMap"
/>
</div>
</
template
>
...
...
@@ -25,6 +25,10 @@
props
:
{
type
:
String
,
scenario
:
{},
draggable
:
{
type
:
Boolean
,
default
:
true
,
},
isMax
:
{
type
:
Boolean
,
default
:
false
,
...
...
@@ -120,6 +124,9 @@
this
.
$emit
(
'
copyRow
'
,
row
,
node
);
},
openScenario
(
data
){
this
.
$emit
(
'
openScenario
'
,
data
);
},
suggestClick
(
node
)
{
this
.
$emit
(
'
suggestClick
'
,
node
);
},
...
...
frontend/src/business/components/api/automation/scenario/component/ConstantTimer.vue
浏览文件 @
f9447a3a
...
...
@@ -3,7 +3,7 @@
@
copy=
"copyRow"
@
remove=
"remove"
:data=
"timer"
:draggable=
"
tru
e"
:draggable=
"
draggabl
e"
:show-collapse=
"false"
:is-max=
"isMax"
color=
"#67C23A"
...
...
@@ -11,7 +11,7 @@
:title=
"$t('api_test.automation.wait_controller')"
>
<template
v-slot:headerLeft
>
<el-input-number
class=
"time-input"
size=
"
small
"
v-model=
"timer.delay"
:min=
"0"
:step=
"1000"
ref=
"nameInput"
/>
<el-input-number
class=
"time-input"
size=
"
mini
"
v-model=
"timer.delay"
:min=
"0"
:step=
"1000"
ref=
"nameInput"
/>
ms
</
template
>
...
...
frontend/src/business/components/api/automation/scenario/component/IfController.vue
浏览文件 @
f9447a3a
...
...
@@ -4,7 +4,7 @@
@
remove=
"remove"
:data=
"controller"
:show-collapse=
"false"
:draggable=
"
tru
e"
:draggable=
"
draggabl
e"
:is-max=
"isMax"
:show-btn=
"showBtn"
color=
"#E6A23C"
...
...
@@ -13,14 +13,14 @@
<template
v-slot:headerLeft
>
<el-input
draggable
size=
"
small
"
v-model=
"controller.variable"
style=
"width: 20%"
:placeholder=
"$t('api_test.request.condition_variable')"
/>
<el-input
draggable
size=
"
mini
"
v-model=
"controller.variable"
style=
"width: 20%"
:placeholder=
"$t('api_test.request.condition_variable')"
/>
<el-select
v-model=
"controller.operator"
:placeholder=
"$t('commons.please_select')"
size=
"
small
"
<el-select
v-model=
"controller.operator"
:placeholder=
"$t('commons.please_select')"
size=
"
mini
"
@
change=
"change"
class=
"ms-select"
>
<el-option
v-for=
"o in operators"
:key=
"o.value"
:label=
"$t(o.label)"
:value=
"o.value"
/>
</el-select>
<el-input
draggable
size=
"
small
"
v-model=
"controller.value"
:placeholder=
"$t('api_test.value')"
v-if=
"!hasEmptyOperator"
class=
"ms-btn"
/>
<el-input
draggable
size=
"
mini
"
v-model=
"controller.value"
:placeholder=
"$t('api_test.value')"
v-if=
"!hasEmptyOperator"
class=
"ms-btn"
/>
</
template
>
</api-base-component>
...
...
frontend/src/business/components/api/automation/scenario/component/LoopController.vue
浏览文件 @
f9447a3a
...
...
@@ -6,7 +6,7 @@
@
copy=
"copyRow"
@
remove=
"remove"
:data=
"controller"
:draggable=
"
tru
e"
:draggable=
"
draggabl
e"
:is-max=
"isMax"
:show-btn=
"showBtn"
color=
"#02A7F0"
...
...
@@ -15,9 +15,9 @@
<template
v-slot:headerLeft
>
<i
class=
"icon el-icon-arrow-right"
:class=
"
{'is-active': controller.active}" @click="active(controller)" style="margin-right: 10px" v-if="!isMax"/>
<el-radio
@
change=
"changeRadio"
class=
"ms-radio"
v-model=
"controller.loopType"
label=
"LOOP_COUNT"
>
{{
$t
(
'
loop.loops_title
'
)
}}
</el-radio>
<el-radio
@
change=
"changeRadio"
class=
"ms-radio"
v-model=
"controller.loopType"
label=
"FOREACH"
>
{{
$t
(
'
loop.foreach
'
)
}}
</el-radio>
<el-radio
@
change=
"changeRadio"
class=
"ms-radio"
v-model=
"controller.loopType"
label=
"WHILE"
>
{{
$t
(
'
loop.while
'
)
}}
</el-radio>
<el-radio
@
change=
"changeRadio"
class=
"ms-radio
ms-radio-margin
"
v-model=
"controller.loopType"
label=
"LOOP_COUNT"
>
{{
$t
(
'
loop.loops_title
'
)
}}
</el-radio>
<el-radio
@
change=
"changeRadio"
class=
"ms-radio
ms-radio-margin
"
v-model=
"controller.loopType"
label=
"FOREACH"
>
{{
$t
(
'
loop.foreach
'
)
}}
</el-radio>
<el-radio
@
change=
"changeRadio"
class=
"ms-radio
ms-radio-margin
"
v-model=
"controller.loopType"
label=
"WHILE"
>
{{
$t
(
'
loop.while
'
)
}}
</el-radio>
</
template
>
<
template
v-slot:message
>
...
...
@@ -86,36 +86,33 @@
</template>
<
script
>
import
ApiBaseComponent
from
"
../common/ApiBaseComponent
"
;
import
ApiResponseComponent
from
"
./ApiResponseComponent
"
;
import
MsRun
from
"
../DebugRun
"
;
import
{
getUUID
}
from
"
@/common/js/utils
"
;
import
ApiBaseComponent
from
"
../common/ApiBaseComponent
"
;
import
ApiResponseComponent
from
"
./ApiResponseComponent
"
;
import
MsRun
from
"
../DebugRun
"
;
import
{
getUUID
}
from
"
@/common/js/utils
"
;
export
default
{
name
:
"
MsLoopController
"
,
components
:
{
ApiBaseComponent
,
ApiResponseComponent
,
MsRun
},
props
:
{
controller
:
{},
currentEnvironmentId
:
String
,
currentScenario
:
{},
node
:
{},
isMax
:
{
type
:
Boolean
,
default
:
false
,
},
showBtn
:
{
type
:
Boolean
,
default
:
true
,
},
index
:
Object
,
draggable
:
{
type
:
Boolean
,
export
default
{
name
:
"
MsLoopController
"
,
components
:
{
ApiBaseComponent
,
ApiResponseComponent
,
MsRun
},
props
:
{
controller
:
{},
currentEnvironmentId
:
String
,
currentScenario
:
{},
node
:
{},
isMax
:
{
type
:
Boolean
,
default
:
false
,
},
envMap
:
Map
},
created
()
{
// this.initResult();
showBtn
:
{
type
:
Boolean
,
default
:
true
,
},
index
:
Object
,
draggable
:
{
type
:
Boolean
,
default
:
false
,
},
envMap
:
Map
},
data
()
{
return
{
...
...
@@ -344,4 +341,8 @@ export default {
.icon.is-active
{
transform
:
rotate
(
90deg
);
}
/
deep
/
.el-radio
{
margin-right
:
5px
;
}
</
style
>
frontend/src/business/components/api/automation/scenario/component/StepExtendBtns.vue
浏览文件 @
f9447a3a
...
...
@@ -7,34 +7,32 @@
<el-dropdown-menu
slot=
"dropdown"
>
<el-dropdown-item
command=
"copy"
>
复制步骤
</el-dropdown-item>
<el-dropdown-item
command=
"remove"
v-tester
>
删除步骤
</el-dropdown-item>
<el-dropdown-item
command=
"scenarioVar"
v-tester
>
查看场景变量
</el-dropdown-item>
<el-dropdown-item
command=
"openScenario"
v-tester
>
打开场景
</el-dropdown-item>
<el-dropdown-item
command=
"saveAs"
v-tester
>
另存为接口定义
</el-dropdown-item>
<!--
<el-tooltip
content=
"Copy"
placement=
"top"
>
-->
<!--
<el-button
size=
"mini"
icon=
"el-icon-copy-document"
circle
@
click=
"copyRow"
:disabled=
"data && data.disabled"
/>
-->
<!--
</el-tooltip>
-->
<!--
<el-tooltip
:content=
"$t('commons.remove')"
placement=
"top"
>
-->
<!--
<el-button
size=
"mini"
icon=
"el-icon-delete"
type=
"danger"
circle
@
click=
"remove"
:disabled=
"data && data.disabled"
/>
-->
<!--
</el-tooltip>
-->
<el-dropdown-item
command=
"scenarioVar"
v-tester
v-if=
"data.type==='scenario'"
>
查看场景变量
</el-dropdown-item>
<el-dropdown-item
command=
"openScenario"
v-tester
v-if=
"data.type==='scenario' && data.referenced==='REF'"
>
打开场景
</el-dropdown-item>
<el-dropdown-item
command=
"saveAs"
v-tester
v-if=
"allSamplers.indexOf(data.type)!=-1"
>
另存为接口定义
</el-dropdown-item>
</el-dropdown-menu>
</el-dropdown>
<ms-reference-view
@
openScenario=
"openScenario"
ref=
"viewRef"
/>
<ms-schedule-maintain
ref=
"scheduleMaintain"
@
refreshTable=
"refreshTable"
/>
<ms-variable-list
ref=
"scenarioParameters"
/>
<ms-add-basis-api
ref=
"api"
/>
</div>
</
template
>
<
script
>
import
MsReferenceView
from
"
@/business/components/api/automation/scenario/ReferenceView
"
;
import
MsScheduleMaintain
from
"
@/business/components/api/automation/schedule/ScheduleMaintain
"
import
{
getCurrentProjectID
,
getUUID
}
from
"
@/common/js/utils
"
;
import
{
ELEMENTS
}
from
"
../Setting
"
;
import
MsVariableList
from
"
../variable/VariableList
"
;
import
MsAddBasisApi
from
"
../api/AddBasisApi
"
;
export
default
{
name
:
"
StepExtendBtns
"
,
components
:
{
MsReferenceView
,
MsScheduleMaintain
},
components
:
{
ELEMENTS
,
MsVariableList
,
MsAddBasisApi
},
props
:
{
row
:
Object
data
:
Object
,
},
data
()
{
return
{
allSamplers
:
ELEMENTS
.
get
(
'
AllSamplerProxy
'
),
}
},
methods
:
{
handleCommand
(
cmd
)
{
...
...
@@ -46,46 +44,27 @@
this
.
$emit
(
'
remove
'
);
break
;
case
"
scenarioVar
"
:
this
.
$
emit
(
'
copy
'
);
this
.
$
refs
.
scenarioParameters
.
open
(
this
.
data
.
variables
,
this
.
data
.
headers
,
true
);
break
;
case
"
openScenario
"
:
this
.
$emit
(
'
copy
'
);
this
.
getScenario
(
);
break
;
case
"
saveAs
"
:
this
.
$emit
(
'
copy
'
);
this
.
saveAsApi
(
);
break
;
}
},
createPerformance
(
row
)
{
this
.
infoDb
=
false
;
let
url
=
"
/api/automation/genPerformanceTestJmx
"
;
let
run
=
{};
let
scenarioIds
=
[];
scenarioIds
.
push
(
row
.
id
);
run
.
projectId
=
getCurrentProjectID
();
run
.
ids
=
scenarioIds
;
run
.
id
=
getUUID
();
run
.
name
=
row
.
name
;
this
.
$post
(
url
,
run
,
response
=>
{
let
jmxObj
=
{};
jmxObj
.
name
=
response
.
data
.
name
;
jmxObj
.
xml
=
response
.
data
.
xml
;
jmxObj
.
attachFiles
=
response
.
data
.
attachFiles
;
jmxObj
.
attachByteFiles
=
response
.
data
.
attachByteFiles
;
this
.
$store
.
commit
(
'
setTest
'
,
{
name
:
row
.
name
,
jmx
:
jmxObj
})
this
.
$router
.
push
({
path
:
"
/performance/test/create
"
})
getScenario
()
{
this
.
result
=
this
.
$get
(
"
/api/automation/getApiScenario/
"
+
this
.
data
.
id
,
response
=>
{
if
(
response
.
data
)
{
this
.
$emit
(
'
openScenario
'
,
response
.
data
);
}
else
{
this
.
$error
(
"
引用场景已经被删除
"
);
}
});
},
openScenario
(
item
)
{
this
.
$emit
(
'
openScenario
'
,
item
)
},
refreshTable
()
{
saveAsApi
(){
this
.
$refs
.
api
.
open
(
this
.
data
);
}
}
}
...
...
frontend/src/business/components/api/automation/scenario/maximize/MaximizeScenario.vue
浏览文件 @
f9447a3a
...
...
@@ -2,7 +2,7 @@
<div>
<!-- 场景步骤-->
<ms-container>
<ms-aside-container
width=
"600px"
class=
"scenario-aside"
>
<ms-aside-container>
<!-- 场景步骤内容 -->
<div
v-loading=
"loading"
>
<el-tree
node-key=
"resourceId"
:props=
"props"
:data=
"scenarioDefinition"
...
...
@@ -16,7 +16,7 @@
<!-- 步骤组件-->
<ms-component-config
:isMax=
"true"
:type=
"data.type"
:scenario=
"data"
:response=
"response"
:currentScenario=
"currentScenario"
:currentEnvironmentId=
"currentEnvironmentId"
:node=
"node"
:project-list=
"projectList"
:env-map=
"projectEnvMap"
@
remove=
"remove"
@
copyRow=
"copyRow"
@
suggestClick=
"suggestClick"
@
refReload=
"refReload"
/>
@
remove=
"remove"
@
copyRow=
"copyRow"
@
suggestClick=
"suggestClick"
@
refReload=
"refReload"
@
openScenario=
"openScenario"
/>
</span>
</el-tree>
...
...
@@ -41,15 +41,35 @@
<ms-main-container>
<!-- 第一层当前节点内容-->
<ms-component-config
:isMax=
"false"
:showBtn=
"false"
:type=
"selectedTreeNode.type"
:scenario=
"selectedTreeNode"
:response=
"response"
:currentScenario=
"currentScenario"
:currentEnvironmentId=
"currentEnvironmentId"
:node=
"selectedNode"
:project-list=
"projectList"
:env-map=
"projectEnvMap"
@
remove=
"remove"
@
copyRow=
"copyRow"
@
suggestClick=
"suggestClick"
@
refReload=
"refReload"
v-if=
"selectedTreeNode && selectedNode"
/>
<ms-component-config
:isMax=
"false"
:showBtn=
"false"
:type=
"selectedTreeNode.type"
:scenario=
"selectedTreeNode"
:response=
"response"
:currentScenario=
"currentScenario"
:currentEnvironmentId=
"currentEnvironmentId"
:node=
"selectedNode"
:project-list=
"projectList"
:env-map=
"projectEnvMap"
:draggable=
"false"
@
remove=
"remove"
@
copyRow=
"copyRow"
@
suggestClick=
"suggestClick"
@
refReload=
"refReload"
@
openScenario=
"openScenario"
v-if=
"selectedTreeNode && selectedNode"
/>
<!-- 请求下还有的子步骤-->
<div
v-if=
"selectedTreeNode && selectedTreeNode.hashTree && showNode(selectedTreeNode)"
>
<div
v-for=
"item in selectedTreeNode.hashTree"
:key=
"item.id"
class=
"ms-col-one"
>
<ms-component-config
:showBtn=
"false"
:isMax=
"false"
:type=
"item.type"
:scenario=
"item"
:response=
"response"
:currentScenario=
"currentScenario"
:currentEnvironmentId=
"currentEnvironmentId"
:project-list=
"projectList"
:env-map=
"projectEnvMap"
@
remove=
"remove"
@
copyRow=
"copyRow"
@
suggestClick=
"suggestClick"
@
refReload=
"refReload"
v-if=
"selectedTreeNode && selectedNode"
/>
<ms-component-config
:showBtn=
"false"
:isMax=
"false"
:type=
"item.type"
:scenario=
"item"
:response=
"response"
:currentScenario=
"currentScenario"
:currentEnvironmentId=
"currentEnvironmentId"
:project-list=
"projectList"
:env-map=
"projectEnvMap"
:draggable=
"false"
@
remove=
"remove"
@
copyRow=
"copyRow"
@
suggestClick=
"suggestClick"
@
refReload=
"refReload"
@
openScenario=
"openScenario"
v-if=
"selectedTreeNode && selectedNode"
/>
</div>
</div>
...
...
@@ -120,7 +140,7 @@
import
EnvPopover
from
"
@/business/components/api/automation/scenario/EnvPopover
"
;
import
MsContainer
from
"
../../../../common/components/MsContainer
"
;
import
MsMainContainer
from
"
../../../../common/components/MsMainContainer
"
;
import
MsAsideContainer
from
"
.
./../../../common/components/MsAside
Container
"
;
import
MsAsideContainer
from
"
.
/MsLeft
Container
"
;
let
jsonPath
=
require
(
'
jsonpath
'
);
export
default
{
...
...
@@ -130,6 +150,7 @@
currentScenario
:
{},
type
:
String
,
scenarioDefinition
:
Array
,
envMap
:
Map
,
},
components
:
{
MsVariableList
,
...
...
@@ -201,6 +222,7 @@
}
this
.
projectId
=
getCurrentProjectID
();
this
.
operatingElements
=
ELEMENTS
.
get
(
"
ALL
"
);
this
.
projectEnvMap
=
this
.
envMap
;
},
directives
:
{
OutsideClick
},
computed
:
{
...
...
@@ -319,6 +341,10 @@
}
},
methods
:
{
// 打开引用的场景
openScenario
(
data
)
{
this
.
$emit
(
'
openScenario
'
,
data
);
},
removeListener
()
{
document
.
removeEventListener
(
"
keydown
"
,
this
.
createCtrlSHandle
);
},
...
...
@@ -1038,12 +1064,28 @@
}
.scenario-aside
{
min-width
:
400px
;
position
:
relative
;
border-radius
:
4px
;
border
:
1px
solid
#EBEEF5
;
box-sizing
:
border-box
;
}
.scenario-main
{
position
:
relative
;
margin-left
:
20px
;
border
:
1px
solid
#EBEEF5
;
}
.scenario-list
{
overflow-y
:
auto
;
position
:
absolute
;
top
:
0
;
left
:
0
;
right
:
0
;
bottom
:
28px
;
}
.father
:hover
.child
{
display
:
block
;
}
...
...
frontend/src/business/components/api/automation/scenario/maximize/MsLeftContainer.vue
0 → 100644
浏览文件 @
f9447a3a
<
template
>
<el-aside
class=
"ms-aside-container"
>
<slot></slot>
<ms-horizontal-drag-bar/>
</el-aside>
</
template
>
<
script
>
import
MsHorizontalDragBar
from
"
../../../../../components/common/components/dragbar/MsLeft2RightDragBar
"
;
export
default
{
name
:
"
MsLeftContainer
"
,
components
:
{
MsHorizontalDragBar
},
props
:
{
width
:
{
type
:
String
,
default
:
'
500px
'
},
enableAsideHidden
:
{
type
:
Boolean
,
default
:
true
},
},
data
()
{
return
{
asideHidden
:
false
}
}
}
</
script
>
<
style
scoped
>
.ms-aside-container
{
border
:
1px
solid
#E6E6E6
;
padding
:
10px
;
min-width
:
600px
;
border-radius
:
2px
;
box-sizing
:
border-box
;
background-color
:
#FFF
;
height
:
calc
(
100vh
-
60px
);
border-right
:
0px
;
position
:
relative
;
}
.hiddenBottom
i
{
margin-left
:
-2px
;
}
.hiddenBottom
:hover
i
{
margin-left
:
0
;
color
:
white
;
}
</
style
>
frontend/src/business/components/api/automation/scenario/maximize/ScenarioHeader.vue
浏览文件 @
f9447a3a
<
template
>
<div
class=
"ms-header"
@
click=
"showAll"
>
<el-row>
<div
class=
"ms-div"
v-loading=
"loading"
>
<!-- 调试部分 -->
<el-row
style=
"margin: 5px"
>
<el-col
:span=
"6"
class=
"ms-col-one ms-font"
>
{{
$t
(
'
api_test.automation.step_total
'
)
}}
:
{{
scenarioDefinition
.
length
}}
</el-col>
<el-col
:span=
"6"
class=
"ms-col-one ms-font"
>
<el-link
class=
"head"
@
click=
"showScenarioParameters"
>
{{
$t
(
'
api_test.automation.scenario_total
'
)
}}
</el-link>
:
{{
varSize
}}
</el-col>
<el-col
:span=
"5"
class=
"ms-col-one ms-font"
>
<el-checkbox
v-model=
"enableCookieShare"
>
共享cookie
</el-checkbox>
</el-col>
<el-col
:span=
"7"
>
<env-popover
:env-map=
"envMap"
:project-ids=
"projectIds"
@
setProjectEnvMap=
"setProjectEnvMap"
:project-list=
"projectList"
ref=
"envPopover"
style=
"margin-top: 0px"
/>
</el-col>
</el-row>
</div>
<div
class=
"ms-header-right"
>
<el-button
:disabled=
"scenarioDefinition.length
<
1"
size=
"small"
type=
"primary"
v-prevent-re-click
@
click=
"runDebug"
>
{{
$t
(
'
api_test.request.debug
'
)
}}
</el-button>
|
<i
class=
"el-icon-close alt-ico"
@
click=
"close"
/>
</div>
</el-row>
<div
class=
"ms-header"
>
<div
class=
"ms-div"
v-loading=
"loading"
@
click=
"showAll"
>
<!-- 调试部分 -->
<el-row
class=
"ms-header-margin"
>
<el-col
:span=
"8"
>
{{
currentScenario
.
name
}}
</el-col>
<el-col
:span=
"8"
>
{{
$t
(
'
api_test.automation.step_total
'
)
}}
:
{{
scenarioDefinition
.
length
}}
</el-col>
<el-col
:span=
"8"
>
<el-link
class=
"head"
@
click=
"showScenarioParameters"
>
{{
$t
(
'
api_test.automation.scenario_total
'
)
}}
</el-link>
:
{{
varSize
}}
</el-col>
</el-row>
</div>
<div
class=
"ms-header-right"
>
<el-checkbox
v-model=
"cookieShare"
@
change=
"setCookieShare"
style=
"margin-right: 20px"
>
共享cookie
</el-checkbox>
<env-popover
:env-map=
"envMap"
:project-ids=
"projectIds"
@
setProjectEnvMap=
"setProjectEnvMap"
:project-list=
"projectList"
ref=
"envPopover"
class=
"ms-right"
/>
<el-button
:disabled=
"scenarioDefinition.length
<
1"
size=
"mini"
type=
"primary"
v-prevent-re-click
@
click=
"runDebug"
>
{{
$t
(
'
api_test.request.debug
'
)
}}
</el-button>
<font-awesome-icon
class=
"alt-ico"
:icon=
"['fa', 'compress-alt']"
size=
"lg"
@
click=
"unFullScreen"
/>
|
<i
class=
"el-icon-close alt-ico-close"
@
click=
"close"
/>
</div>
</div>
</
template
>
...
...
@@ -43,11 +44,13 @@
envMap
:
new
Map
,
loading
:
false
,
varSize
:
0
,
cookieShare
:
false
,
}
},
mounted
()
{
this
.
envMap
=
this
.
projectEnvMap
;
this
.
getVariableSize
();
this
.
cookieShare
=
this
.
enableCookieShare
;
},
methods
:
{
handleExport
()
{
...
...
@@ -66,11 +69,17 @@
this
.
$emit
(
'
showAllBtn
'
);
},
close
()
{
this
.
$emit
(
'
closePage
'
);
this
.
$emit
(
'
closePage
'
,
this
.
currentScenario
.
name
);
},
unFullScreen
()
{
this
.
$emit
(
'
unFullScreen
'
);
},
runDebug
()
{
this
.
$emit
(
'
runDebug
'
);
},
setCookieShare
()
{
this
.
$emit
(
'
setCookieShare
'
,
this
.
cookieShare
);
},
showScenarioParameters
()
{
this
.
$emit
(
'
showScenarioParameters
'
);
},
...
...
@@ -92,6 +101,7 @@
})
},
setProjectEnvMap
(
projectEnvMap
)
{
this
.
$emit
(
'
setProjectEnvMap
'
,
projectEnvMap
);
this
.
envMap
=
projectEnvMap
;
}
},
...
...
@@ -101,46 +111,58 @@
<
style
scoped
>
.ms-header
{
border-bottom
:
1px
solid
#E6E6E6
;
height
:
65
px
;
height
:
50
px
;
background-color
:
#FFF
;
}
.ms-div
{
float
:
left
;
width
:
8
0%
;
width
:
6
0%
;
margin-left
:
20px
;
margin-top
:
12px
;
}
.ms-span
{
margin
:
0px
10px
10px
;
}
.ms-header-right
{
float
:
right
;
margin-bottom
:
10px
;
margin-top
:
10px
;
margin-right
:
20px
;
margin-top
:
2px
;
position
:
fixed
;
right
:
20px
;
z-index
:
1
;
}
.alt-ico
{
font-size
:
16px
;
margin
:
10px
10px
0px
;
}
.alt-ico-close
{
font-size
:
18px
;
margin
:
10px
0px
0px
;
margin
:
10px
10px
10px
;
}
.alt-ico-close
:hover
{
color
:
black
;
cursor
:
pointer
;
}
.alt-ico
:hover
{
color
:
black
;
cursor
:
pointer
;
font-size
:
18px
;
}
.ms-font
{
.ms-header-margin
{
margin-top
:
3px
;
}
.ms-right
{
margin-right
:
40px
;
}
.head
{
border-bottom
:
1px
solid
#303133
;
color
:
#303133
;
font-family
:
"Helvetica Neue"
,
Helvetica
,
"PingFang SC"
,
"Hiragino Sans GB"
,
Arial
,
sans-serif
;
font-size
:
13px
;
}
.ms-col-one
{
margin-top
:
5px
;
}
</
style
>
frontend/src/business/components/api/automation/scenario/variable/VariableList.vue
浏览文件 @
f9447a3a
<
template
>
<el-dialog
title=
"场景变量"
:close-on-click-modal=
"false"
:visible.sync=
"visible"
class=
"visible-dialog"
width=
"60%"
@
close=
"close"
v-loading=
"loading"
>
<el-tabs
v-model=
"activeName"
>
<el-tab-pane
:label=
"$t('api_test.scenario.variables')"
name=
"variable"
>
<div
style=
"margin-top: 10px"
>
<el-row
style=
"margin-bottom: 10px"
>
<el-col
:span=
"8"
>
<el-input
placeholder=
"变量名称搜索"
v-model=
"selectVariable"
size=
"small"
@
change=
"filter"
@
keyup.enter=
"filter"
>
<el-select
v-model=
"searchType"
slot=
"prepend"
placeholder=
"类型"
style=
"width: 90px"
@
change=
"filter"
>
<el-option
value=
"CONSTANT"
label=
"常量"
></el-option>
<el-option
value=
"LIST"
label=
"列表"
></el-option>
<el-option
value=
"CSV"
label=
"CSV"
></el-option>
<el-option
value=
"COUNTER"
label=
"计数器"
></el-option>
<el-option
value=
"RANDOM"
label=
"随机数"
></el-option>
</el-select>
</el-input>
</el-col>
@
close=
"close"
v-loading=
"loading"
append-to-body
>
<fieldset
:disabled=
"disabled"
class=
"ms-fieldset"
>
<el-collapse-transition>
<el-col
:span=
"6"
>
<el-dropdown
split-button
type=
"primary"
@
command=
"handleClick"
@
click=
"handleClick('CONSTANT')"
size=
"small"
style=
"margin-left: 10px"
>
{{
$t
(
'
commons.add
'
)
}}
<el-dropdown-menu
slot=
"dropdown"
>
<el-dropdown-item
command=
"CONSTANT"
>
常量
</el-dropdown-item>
<el-dropdown-item
command=
"LIST"
>
列表
</el-dropdown-item>
<el-dropdown-item
command=
"CSV"
>
CSV
</el-dropdown-item>
<el-dropdown-item
command=
"COUNTER"
>
计数器
</el-dropdown-item>
<el-dropdown-item
command=
"RANDOM"
>
随机数
</el-dropdown-item>
</el-dropdown-menu>
</el-dropdown>
<el-button
size=
"small"
style=
"margin-left: 10px"
@
click=
"deleteVariable"
>
{{
$t
(
'
commons.delete
'
)
}}
</el-button>
<el-tabs
v-model=
"activeName"
>
<el-tab-pane
:label=
"$t('api_test.scenario.variables')"
name=
"variable"
>
<div
style=
"margin-top: 10px"
>
<el-row
style=
"margin-bottom: 10px"
>
<el-col
:span=
"8"
>
<el-input
placeholder=
"变量名称搜索"
v-model=
"selectVariable"
size=
"small"
@
change=
"filter"
@
keyup.enter=
"filter"
>
<el-select
v-model=
"searchType"
slot=
"prepend"
placeholder=
"类型"
style=
"width: 90px"
@
change=
"filter"
>
<el-option
value=
"CONSTANT"
label=
"常量"
></el-option>
<el-option
value=
"LIST"
label=
"列表"
></el-option>
<el-option
value=
"CSV"
label=
"CSV"
></el-option>
<el-option
value=
"COUNTER"
label=
"计数器"
></el-option>
<el-option
value=
"RANDOM"
label=
"随机数"
></el-option>
</el-select>
</el-input>
</el-col>
</el-col>
</el-row>
<el-row>
<el-col
:span=
"12"
>
<div
style=
"border:1px #DCDFE6 solid; min-height: 400px;border-radius: 4px ;width: 100% ;"
>
<el-table
ref=
"table"
border
:data=
"variables"
class=
"adjust-table"
@
select-all=
"select"
@
select=
"select"
v-loading=
"loading"
@
row-click=
"edit"
height=
"400px"
:row-class-name=
"tableRowClassName"
>
<el-table-column
type=
"selection"
width=
"38"
/>
<el-table-column
prop=
"num"
label=
"ID"
sortable
/>
<el-table-column
prop=
"name"
:label=
"$t('api_test.variable_name')"
sortable
show-overflow-tooltip
/>
<el-table-column
prop=
"type"
:label=
"$t('test_track.case.type')"
>
<template
v-slot:default=
"scope"
>
<span>
{{
types
.
get
(
scope
.
row
.
type
)
}}
</span>
</
template
>
</el-table-column>
<el-table-column
prop=
"value"
:label=
"$t('api_test.value')"
show-overflow-tooltip
/>
</el-table>
</div>
</el-col>
<el-col
:span=
"12"
>
<ms-edit-constant
v-if=
"editData.type=='CONSTANT'"
ref=
"parameters"
:editData.sync=
"editData"
/>
<ms-edit-counter
v-if=
"editData.type=='COUNTER'"
ref=
"counter"
:editData.sync=
"editData"
/>
<ms-edit-random
v-if=
"editData.type=='RANDOM'"
ref=
"random"
:editData.sync=
"editData"
/>
<ms-edit-list-value
v-if=
"editData.type=='LIST'"
ref=
"listValue"
:editData=
"editData"
/>
<ms-edit-csv
v-if=
"editData.type=='CSV'"
ref=
"csv"
:editData.sync=
"editData"
/>
</el-col>
</el-row>
</div>
<el-col
:span=
"6"
>
<el-dropdown
split-button
type=
"primary"
@
command=
"handleClick"
@
click=
"handleClick('CONSTANT')"
size=
"small"
style=
"margin-left: 10px"
>
{{
$t
(
'
commons.add
'
)
}}
<el-dropdown-menu
slot=
"dropdown"
>
<el-dropdown-item
command=
"CONSTANT"
>
常量
</el-dropdown-item>
<el-dropdown-item
command=
"LIST"
>
列表
</el-dropdown-item>
<el-dropdown-item
command=
"CSV"
>
CSV
</el-dropdown-item>
<el-dropdown-item
command=
"COUNTER"
>
计数器
</el-dropdown-item>
<el-dropdown-item
command=
"RANDOM"
>
随机数
</el-dropdown-item>
</el-dropdown-menu>
</el-dropdown>
<el-button
size=
"small"
style=
"margin-left: 10px"
@
click=
"deleteVariable"
>
{{
$t
(
'
commons.delete
'
)
}}
</el-button>
</el-col>
</el-row>
<el-row>
<el-col
:span=
"12"
>
<div
style=
"border:1px #DCDFE6 solid; min-height: 400px;border-radius: 4px ;width: 100% ;"
>
<el-table
ref=
"table"
border
:data=
"variables"
class=
"adjust-table"
@
select-all=
"select"
@
select=
"select"
v-loading=
"loading"
@
row-click=
"edit"
height=
"400px"
:row-class-name=
"tableRowClassName"
>
<el-table-column
type=
"selection"
width=
"38"
/>
<el-table-column
prop=
"num"
label=
"ID"
sortable
/>
<el-table-column
prop=
"name"
:label=
"$t('api_test.variable_name')"
sortable
show-overflow-tooltip
/>
<el-table-column
prop=
"type"
:label=
"$t('test_track.case.type')"
>
<template
v-slot:default=
"scope"
>
<span>
{{
types
.
get
(
scope
.
row
.
type
)
}}
</span>
</
template
>
</el-table-column>
<el-table-column
prop=
"value"
:label=
"$t('api_test.value')"
show-overflow-tooltip
/>
</el-table>
</div>
</el-col>
<el-col
:span=
"12"
>
<ms-edit-constant
v-if=
"editData.type=='CONSTANT'"
ref=
"parameters"
:editData.sync=
"editData"
/>
<ms-edit-counter
v-if=
"editData.type=='COUNTER'"
ref=
"counter"
:editData.sync=
"editData"
/>
<ms-edit-random
v-if=
"editData.type=='RANDOM'"
ref=
"random"
:editData.sync=
"editData"
/>
<ms-edit-list-value
v-if=
"editData.type=='LIST'"
ref=
"listValue"
:editData=
"editData"
/>
<ms-edit-csv
v-if=
"editData.type=='CSV'"
ref=
"csv"
:editData.sync=
"editData"
/>
</el-col>
</el-row>
</div>
</el-tab-pane>
<el-tab-pane
:label=
"$t('api_test.scenario.headers')"
name=
"headers"
>
<!-- 请求头-->
<el-tooltip
class=
"item-tabs"
effect=
"dark"
:content=
"$t('api_test.request.headers')"
placement=
"top-start"
slot=
"label"
>
</el-tab-pane>
<el-tab-pane
:label=
"$t('api_test.scenario.headers')"
name=
"headers"
>
<!-- 请求头-->
<el-tooltip
class=
"item-tabs"
effect=
"dark"
:content=
"$t('api_test.request.headers')"
placement=
"top-start"
slot=
"label"
>
<span>
{{ $t('api_test.request.headers') }}
<div
class=
"el-step__icon is-text ms-api-col ms-variable-header"
v-if=
"headers.length>1"
>
<div
class=
"el-step__icon-inner"
>
{{ headers.length - 1 }}
</div>
</div>
</span>
</el-tooltip>
<el-row>
<el-link
class=
"ms-variable-link"
@
click=
"batchAdd"
style=
"color: #783887"
>
{{ $t("commons.batch_add") }}
</el-link>
</el-row>
<div
style=
"min-height: 400px"
>
<ms-api-key-value
:items=
"headers"
:suggestions=
"headerSuggestions"
/>
<batch-add-parameter
@
batchSave=
"batchSave"
ref=
"batchAddParameter"
/>
</div>
</el-tab-pane>
</el-tabs>
<
template
v-slot:footer
>
<div>
<el-button
type=
"primary"
@
click=
"save"
>
{{
$t
(
'
commons.confirm
'
)
}}
</el-button>
</div>
</
template
>
</el-tooltip>
<el-row>
<el-link
class=
"ms-variable-link"
@
click=
"batchAdd"
style=
"color: #783887"
>
{{ $t("commons.batch_add") }}
</el-link>
</el-row>
<div
style=
"min-height: 400px"
>
<ms-api-key-value
:items=
"headers"
:suggestions=
"headerSuggestions"
/>
<batch-add-parameter
@
batchSave=
"batchSave"
ref=
"batchAddParameter"
/>
</div>
</el-tab-pane>
</el-tabs>
<
template
v-slot:footer
>
<div>
<el-button
type=
"primary"
@
click=
"save"
>
{{
$t
(
'
commons.confirm
'
)
}}
</el-button>
</div>
</
template
>
</el-collapse-transition>
</fieldset>
</el-dialog>
</template>
...
...
@@ -146,6 +151,7 @@
pageSize
:
10
,
total
:
0
,
headerSuggestions
:
REQUEST_HEADERS
,
disabled
:
false
,
}
},
methods
:
{
...
...
@@ -212,12 +218,13 @@
isSelect
(
row
)
{
return
this
.
selection
.
includes
(
row
.
id
)
},
open
:
function
(
variables
,
headers
)
{
open
:
function
(
variables
,
headers
,
disabled
)
{
this
.
variables
=
variables
;
this
.
headers
=
headers
;
this
.
visible
=
true
;
this
.
editData
=
{
type
:
"
CONSTANT
"
};
this
.
addParameters
(
this
.
editData
);
this
.
disabled
=
disabled
;
},
save
()
{
this
.
visible
=
false
;
...
...
@@ -302,4 +309,11 @@
float
:
right
;
margin-right
:
45px
;
}
fieldset
{
padding
:
0px
;
margin
:
0px
;
min-width
:
100%
;
min-inline-size
:
0px
;
border
:
0px
;
}
</
style
>
frontend/src/business/components/common/head/HeaderTopMenus.vue
浏览文件 @
f9447a3a
...
...
@@ -29,6 +29,8 @@
</
template
>
<
script
>
import
{
LicenseKey
}
from
'
@/common/js/constants
'
;
const
requireContext
=
require
.
context
(
'
@/business/components/xpack/
'
,
true
,
/router
\.
js$/
)
const
report
=
requireContext
.
keys
().
map
(
key
=>
requireContext
(
key
).
report
);
const
isReport
=
report
&&
report
!=
null
&&
report
.
length
>
0
&&
report
[
0
]
!=
undefined
?
true
:
false
;
...
...
@@ -55,6 +57,10 @@
if
(
this
.
$route
.
matched
.
length
>
0
)
{
this
.
activeIndex
=
this
.
$route
.
matched
[
0
].
path
;
}
let
license
=
localStorage
.
getItem
(
LicenseKey
);
if
(
license
!=
"
valid
"
)
{
this
.
isReport
=
false
;
}
},
methods
:
{
handleSelect
(
index
)
{
...
...
frontend/src/business/components/common/select-tree/SelectTree.vue
0 → 100644
浏览文件 @
f9447a3a
<
template
>
<div>
<div
class=
"mask"
v-show=
"isShowSelect"
></div>
<el-popover
placement=
"bottom-start"
:width=
"popoverWidth"
trigger=
"manual"
v-model=
"isShowSelect"
@
hide=
"popoverHide"
v-outside-click=
"outsideClick"
>
<el-input
size=
"mini"
prefix-icon=
"el-icon-search"
v-model=
"filterText"
>
</el-input>
<el-tree
class=
"common-tree"
:width=
"width"
ref=
"tree"
:data=
"treeData"
:props=
"obj"
:show-checkbox=
"multiple"
:node-key=
"obj.id"
:check-strictly=
"checkStrictly"
:expand-on-click-node=
"multiple&&expandClickNode"
:check-on-click-node=
"checkClickNode"
:highlight-current=
"true"
@
check-change=
"nodeClick"
:filter-node-method=
"filterNode"
@
node-click=
"nodeClick"
/>
<el-select
slot=
"reference"
ref=
"select"
:size=
"size"
v-model=
"returnDataKeys"
:multiple=
"multiple"
:clearable=
"clearable"
:collapse-tags=
"collapseTags"
:disabled=
"disabled"
@
click.native=
"selectClick"
@
remove-tag=
"removeTag"
@
clear=
"clean"
class=
"ms-tree-select"
>
<el-option
v-for=
"item in options"
:key=
"item.value"
:label=
"item.label"
:value=
"item.value"
></el-option>
</el-select>
<el-row>
<el-button
v-if=
"multiple"
class=
"ok"
@
click=
"isShowSelect=false"
size=
"mini"
type=
"text"
>
{{
$t
(
'
commons.confirm
'
)
}}
</el-button>
</el-row>
</el-popover>
</div>
</
template
>
<
script
>
import
OutsideClick
from
"
@/common/js/outside-click
"
;
export
default
{
name
:
'
test-code
'
,
directives
:
{
OutsideClick
},
props
:
{
// 树结构数据
data
:
{
type
:
Array
,
default
()
{
return
[];
}
},
obj
:
{
type
:
Object
,
required
:
false
,
default
:
()
=>
{
return
{
id
:
'
id
'
,
// ID
label
:
'
name
'
,
// 显示名称
children
:
'
children
'
,
//子级字段名
path
:
'
path
'
,
//路径
content
:
'
content
'
,
//描述
pid
:
'
pid
'
,
//父id
}
}
},
disabled
:
{
type
:
Boolean
,
default
:
false
,
},
// 配置是否可多选
multiple
:
{
type
:
Boolean
,
default
()
{
return
false
;
}
},
// 配置是否可清空选择
clearable
:
{
type
:
Boolean
,
default
()
{
return
false
;
}
},
// 配置多选时是否将选中值按文字的形式展示
collapseTags
:
{
type
:
Boolean
,
default
()
{
return
false
;
}
},
// 显示复选框情况下,是否严格遵循父子不互相关联
checkStrictly
:
{
type
:
Boolean
,
default
()
{
return
false
;
}
},
//多选是设置点击节点是否可以选中
checkClickNode
:
{
type
:
Boolean
,
default
()
{
return
false
;
}
},
//多选时:点击节点展开还是点三角标
expandClickNode
:
{
type
:
Boolean
,
default
()
{
return
false
;
}
},
// 默认选中的节点key
defaultKey
:
{
type
:
[
Number
,
String
,
Array
,
Object
],
default
()
{
return
[];
}
},
size
:
{
type
:
String
,
default
()
{
return
'
small
'
;
}
},
width
:
{
type
:
String
,
default
()
{
return
'
100%
'
;
}
},
height
:
{
type
:
String
,
default
()
{
return
'
300px
'
;
}
}
},
//上面是父组件可传入参数
data
()
{
return
{
popoverWidth
:
"
0px
"
,
//下拉框大小
isShowSelect
:
false
,
// 是否显示树状选择器
options
:
[],
//select option选项
returnDatas
:
[],
//返回给父组件数组对象
returnDataKeys
:
[],
//返回父组件数组主键值
filterText
:
""
,
};
},
computed
:
{
treeData
()
{
// 若非树状结构,则转化为树状结构数据
return
JSON
.
stringify
(
this
.
data
).
indexOf
(
this
.
obj
.
children
)
!==
-
1
?
this
.
data
:
this
.
switchTree
();
},
},
methods
:
{
outsideClick
(
e
)
{
e
.
stopPropagation
();
this
.
isShowSelect
=
false
;
},
init
()
{
if
(
this
.
defaultKey
!=
undefined
&&
this
.
defaultKey
.
length
>
0
)
{
if
(
this
.
multiple
)
{
// 多选
if
(
Object
.
prototype
.
toString
.
call
(
this
.
defaultKey
).
indexOf
(
"
Array
"
)
!=
-
1
)
{
if
(
Object
.
prototype
.
toString
.
call
(
this
.
defaultKey
[
0
]).
indexOf
(
"
Object
"
)
!=
-
1
)
{
//对象
this
.
setDatas
(
this
.
defaultKey
);
}
else
if
(
Object
.
prototype
.
toString
.
call
(
this
.
defaultKey
[
0
]).
indexOf
(
"
Number
"
)
!=
-
1
||
Object
.
prototype
.
toString
.
call
(
this
.
defaultKey
[
0
]).
indexOf
(
"
String
"
)
!=
-
1
)
{
this
.
setKeys
(
this
.
defaultKey
);
}
else
{
console
.
log
(
"
多选:传入参数类型不匹配
"
);
return
;
}
}
else
{
console
.
log
(
"
多选:传入参数类型不匹配
"
);
return
;
}
}
else
{
// 单选
if
(
Object
.
prototype
.
toString
.
call
(
this
.
defaultKey
).
indexOf
(
"
Number
"
)
!=
-
1
||
Object
.
prototype
.
toString
.
call
(
this
.
defaultKey
).
indexOf
(
"
String
"
)
!=
-
1
||
Object
.
prototype
.
toString
.
call
(
this
.
defaultKey
).
indexOf
(
"
Object
"
)
!=
-
1
)
{
this
.
setKey
(
this
.
defaultKey
);
}
else
{
console
.
log
(
"
单选:传入参数类型不匹配
"
);
return
;
}
}
}
},
//下拉框select点击[入口]
selectClick
()
{
if
(
this
.
disabled
)
{
return
;
}
this
.
$nextTick
(
function
()
{
//设置下拉框自适应宽度
this
.
popoverWidth
=
this
.
$refs
.
select
.
$el
.
clientWidth
-
26
;
})
//显示下拉框
return
this
.
isShowSelect
=
!
this
.
isShowSelect
},
//单选: 树点击方法
nodeClick
(
data
,
node
)
{
if
(
!
this
.
multiple
)
{
//单选
this
.
isShowSelect
=
false
;
this
.
setKey
(
node
.
key
);
}
else
{
//多选
let
checkedKeys
=
this
.
$refs
.
tree
.
getCheckedKeys
();
// 所有被选中的节点的 key 所组成的数组数据
let
t
=
[];
this
.
options
=
checkedKeys
.
map
((
item
)
=>
{
//设置option选项
let
node
=
this
.
$refs
.
tree
.
getNode
(
item
);
// 所有被选中的节点对应的node
t
.
push
(
node
.
data
);
return
{
label
:
node
.
label
,
value
:
node
.
key
};
});
this
.
returnDataKeys
=
this
.
options
.
map
((
item
)
=>
{
return
item
.
value
;
});
this
.
returnDatas
=
t
;
}
},
//单选:清空选中
clean
()
{
this
.
$refs
.
tree
.
setCurrentKey
(
null
);
//清除树选中key
this
.
returnDatas
=
null
;
this
.
returnDataKeys
=
''
;
this
.
popoverHide
();
},
//单选:设置、初始化值 key
setKey
(
thisKey
)
{
this
.
$refs
.
tree
.
setCurrentKey
(
thisKey
);
let
node
=
this
.
$refs
.
tree
.
getNode
(
thisKey
);
this
.
setData
(
node
.
data
);
},
//单选:设置、初始化对象
setData
(
data
)
{
this
.
options
=
[];
this
.
options
.
push
({
label
:
data
[
this
.
obj
.
label
],
value
:
data
[
this
.
obj
.
id
]});
this
.
returnDatas
=
data
;
this
.
returnDataKeys
=
data
[
this
.
obj
.
id
]
},
//多选:设置、初始化值 keys
setKeys
(
thisKeys
)
{
this
.
$refs
.
tree
.
setCheckedKeys
(
thisKeys
);
this
.
returnDataKeys
=
thisKeys
;
let
t
=
[];
thisKeys
.
map
((
item
)
=>
{
//设置option选项
let
node
=
this
.
$refs
.
tree
.
getNode
(
item
);
// 所有被选中的节点对应的node
t
.
push
(
node
.
data
);
return
{
label
:
node
.
label
,
value
:
node
.
key
};
});
this
.
returnDatas
=
t
;
this
.
popoverHide
()
},
//多选:设置、初始化对象
setDatas
(
data
)
{
this
.
$refs
.
tree
.
setCheckedNodes
(
data
);
this
.
returnDatas
=
data
;
let
t
=
[];
data
.
map
((
item
)
=>
{
//设置option选项
t
.
push
(
item
[
this
.
obj
.
id
]);
});
this
.
returnDataKeys
=
t
;
this
.
popoverHide
()
},
// 多选,删除任一select选项的回调
removeTag
(
val
)
{
this
.
$refs
.
tree
.
setChecked
(
val
,
false
);
//设置为未选中
let
node
=
this
.
$refs
.
tree
.
getNode
(
val
);
//获取节点
if
(
!
this
.
checkStrictly
&&
node
.
childNodes
.
length
>
0
)
{
this
.
treeToList
(
node
).
map
(
item
=>
{
if
(
item
.
childNodes
.
length
<=
0
)
{
this
.
$refs
.
tree
.
setChecked
(
item
,
false
);
}
});
}
this
.
nodeClick
();
this
.
popoverHide
();
},
//下拉框关闭执行
popoverHide
()
{
this
.
$emit
(
'
getValue
'
,
this
.
returnDataKeys
,
this
.
returnDatas
);
},
// 多选,清空所有勾选
clearSelectedNodes
()
{
let
checkedKeys
=
this
.
$refs
.
tree
.
getCheckedKeys
();
// 所有被选中的节点的 key 所组成的数组数据
for
(
let
i
=
0
;
i
<
checkedKeys
.
length
;
i
++
)
{
this
.
$refs
.
tree
.
setChecked
(
checkedKeys
[
i
],
false
);
}
},
//树形转为集合
treeToList
(
tree
)
{
let
queen
=
[];
let
out
=
[];
queen
=
queen
.
concat
(
tree
);
while
(
queen
.
length
)
{
let
first
=
queen
.
shift
();
if
(
first
.
childNodes
)
{
queen
=
queen
.
concat
(
first
.
childNodes
);
}
out
.
push
(
first
);
}
return
out
;
},
switchTree
()
{
return
this
.
buildTree
(
this
.
data
,
this
.
defaultValue
);
},
// 将一维的扁平数组转换为多层级对象
buildTree
(
data
,
id
)
{
const
fa
=
(
id
)
=>
{
const
temp
=
[];
for
(
let
i
=
0
;
i
<
data
.
length
;
i
++
)
{
const
n
=
data
[
i
];
if
(
n
[
this
.
obj
.
pid
]
===
id
)
{
n
[
this
.
obj
.
children
]
=
fa
(
n
[
this
.
obj
.
id
]);
temp
.
push
(
n
);
}
}
return
temp
;
};
return
fa
(
id
);
},
filterNode
(
value
,
data
)
{
if
(
!
value
)
return
true
;
if
(
data
.
label
)
{
return
data
.
label
.
indexOf
(
value
.
toLowerCase
())
!==
-
1
;
}
return
false
;
},
},
watch
:
{
// eslint-disable-next-line no-unused-vars
isShowSelect
(
val
)
{
// 隐藏select自带的下拉框
this
.
$refs
.
select
.
blur
();
},
treeData
()
{
//监听tree数据
this
.
$nextTick
(()
=>
{
this
.
init
();
})
},
filterText
(
val
)
{
this
.
$nextTick
(()
=>
{
this
.
$refs
.
tree
.
filter
(
val
);
});
},
filter
(
val
)
{
this
.
$nextTick
(()
=>
{
this
.
$refs
.
tree
.
filter
(
val
);
});
},
}
};
</
script
>
<
style
scoped
>
.mask
{
height
:
100%
;
position
:
fixed
;
top
:
0
;
left
:
0
;
opacity
:
0
;
z-index
:
11
;
}
.common-tree
{
overflow
:
auto
;
height
:
200px
;
}
.ms-tree-select
{
width
:
100%
;
z-index
:
111
;
}
.ok
{
float
:
right
;
}
.el-row
{
padding-top
:
0px
!important
;
}
</
style
>
frontend/src/business/components/track/plan/view/comonents/base/RelevanceDialog.vue
浏览文件 @
f9447a3a
...
...
@@ -4,7 +4,7 @@
@
close=
"close"
width=
"60%"
v-loading=
"result.loading"
:close-on-click-modal=
"false"
top=
"50px"
>
top=
"50px"
append-to-body
>
<el-container
class=
"main-content"
>
...
...
xpack
@
f2781219
比较
b2571e06
...
f2781219
Subproject commit
b2571e06e8b211821409115cc2c4a7c52cbac1db
Subproject commit
f2781219889c2f993436bcc3ea90038f588fa73e
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录