Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
MeterSphere
metersphere
提交
bc59848d
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,发现更多精彩内容 >>
提交
bc59848d
编写于
10月 13, 2020
作者:
C
chenjianxing
浏览文件
操作
浏览文件
下载
差异文件
Merge branch 'master' of
https://github.com/metersphere/server
上级
5d81523f
d11f0363
变更
20
展开全部
隐藏空白更改
内联
并排
Showing
20 changed file
with
1165 addition
and
854 deletion
+1165
-854
backend/src/main/java/io/metersphere/base/mapper/ext/ExtTestPlanTestCaseMapper.xml
...metersphere/base/mapper/ext/ExtTestPlanTestCaseMapper.xml
+6
-0
backend/src/main/java/io/metersphere/track/controller/TestCaseIssuesController.java
...etersphere/track/controller/TestCaseIssuesController.java
+2
-2
backend/src/main/java/io/metersphere/track/issue/AbstractIssuePlatform.java
...ava/io/metersphere/track/issue/AbstractIssuePlatform.java
+77
-0
backend/src/main/java/io/metersphere/track/issue/IssueFactory.java
...rc/main/java/io/metersphere/track/issue/IssueFactory.java
+32
-0
backend/src/main/java/io/metersphere/track/issue/IssuesPlatform.java
.../main/java/io/metersphere/track/issue/IssuesPlatform.java
+39
-0
backend/src/main/java/io/metersphere/track/issue/JiraIssue.java
...d/src/main/java/io/metersphere/track/issue/JiraIssue.java
+264
-0
backend/src/main/java/io/metersphere/track/issue/LocalIssue.java
.../src/main/java/io/metersphere/track/issue/LocalIssue.java
+72
-0
backend/src/main/java/io/metersphere/track/issue/PlatformUser.java
...rc/main/java/io/metersphere/track/issue/PlatformUser.java
+12
-0
backend/src/main/java/io/metersphere/track/issue/TapdIssue.java
...d/src/main/java/io/metersphere/track/issue/TapdIssue.java
+200
-0
backend/src/main/java/io/metersphere/track/service/IssuesService.java
...main/java/io/metersphere/track/service/IssuesService.java
+30
-437
frontend/src/business/components/api/test/ApiTestConfig.vue
frontend/src/business/components/api/test/ApiTestConfig.vue
+1
-1
frontend/src/business/components/api/test/components/ApiEnvironmentConfig.vue
...s/components/api/test/components/ApiEnvironmentConfig.vue
+1
-1
frontend/src/business/components/api/test/components/ApiVariableInput.vue
...iness/components/api/test/components/ApiVariableInput.vue
+4
-1
frontend/src/business/components/performance/test/EditPerformanceTestPlan.vue
...s/components/performance/test/EditPerformanceTestPlan.vue
+1
-1
frontend/src/business/components/settings/system/Organization.vue
.../src/business/components/settings/system/Organization.vue
+3
-3
frontend/src/business/components/settings/system/SystemWorkspace.vue
...c/business/components/settings/system/SystemWorkspace.vue
+5
-5
frontend/src/business/components/settings/system/User.vue
frontend/src/business/components/settings/system/User.vue
+10
-10
frontend/src/business/components/track/common/SelectMenu.vue
frontend/src/business/components/track/common/SelectMenu.vue
+39
-36
frontend/src/business/components/track/plan/view/comonents/TestPlanTestCaseEdit.vue
...onents/track/plan/view/comonents/TestPlanTestCaseEdit.vue
+2
-0
frontend/src/business/components/track/plan/view/comonents/TestPlanTestCaseList.vue
...onents/track/plan/view/comonents/TestPlanTestCaseList.vue
+365
-357
未找到文件。
backend/src/main/java/io/metersphere/base/mapper/ext/ExtTestPlanTestCaseMapper.xml
浏览文件 @
bc59848d
...
...
@@ -173,6 +173,12 @@
#{value}
</foreach>
</when>
<when
test=
"key=='executor'"
>
and test_plan_test_case.executor in
<foreach
collection=
"values"
item=
"value"
separator=
","
open=
"("
close=
")"
>
#{value}
</foreach>
</when>
<otherwise>
and test_plan_test_case.status in
<foreach
collection=
"values"
item=
"value"
separator=
","
open=
"("
close=
")"
>
...
...
backend/src/main/java/io/metersphere/track/controller/TestCaseIssuesController.java
浏览文件 @
bc59848d
package
io.metersphere.track.controller
;
import
io.metersphere.base.domain.Issues
;
import
io.metersphere.track.
domain.Tapd
User
;
import
io.metersphere.track.
issue.Platform
User
;
import
io.metersphere.track.service.IssuesService
;
import
io.metersphere.track.request.testcase.IssuesRequest
;
import
org.springframework.web.bind.annotation.*
;
...
...
@@ -42,7 +42,7 @@ public class TestCaseIssuesController {
}
@GetMapping
(
"/tapd/user/{caseId}"
)
public
List
<
TapdUser
>
getTapd
Users
(
@PathVariable
String
caseId
)
{
public
List
<
PlatformUser
>
getPlatform
Users
(
@PathVariable
String
caseId
)
{
return
issuesService
.
getTapdProjectUsers
(
caseId
);
}
...
...
backend/src/main/java/io/metersphere/track/issue/AbstractIssuePlatform.java
0 → 100644
浏览文件 @
bc59848d
package
io.metersphere.track.issue
;
import
io.metersphere.base.domain.ServiceIntegration
;
import
io.metersphere.base.mapper.IssuesMapper
;
import
io.metersphere.base.mapper.TestCaseIssuesMapper
;
import
io.metersphere.base.mapper.ext.ExtIssuesMapper
;
import
io.metersphere.commons.exception.MSException
;
import
io.metersphere.commons.user.SessionUser
;
import
io.metersphere.commons.utils.CommonBeanFactory
;
import
io.metersphere.commons.utils.EncryptUtils
;
import
io.metersphere.commons.utils.SessionUtils
;
import
io.metersphere.controller.request.IntegrationRequest
;
import
io.metersphere.service.IntegrationService
;
import
io.metersphere.service.ProjectService
;
import
io.metersphere.track.request.testcase.IssuesRequest
;
import
io.metersphere.track.service.TestCaseService
;
import
org.apache.commons.lang3.StringUtils
;
import
org.springframework.http.HttpHeaders
;
public
abstract
class
AbstractIssuePlatform
implements
IssuesPlatform
{
protected
IntegrationService
integrationService
;
protected
TestCaseIssuesMapper
testCaseIssuesMapper
;
protected
ProjectService
projectService
;
protected
TestCaseService
testCaseService
;
protected
IssuesMapper
issuesMapper
;
protected
ExtIssuesMapper
extIssuesMapper
;
protected
String
testCaseId
;
public
AbstractIssuePlatform
(
IssuesRequest
issuesRequest
)
{
this
.
integrationService
=
CommonBeanFactory
.
getBean
(
IntegrationService
.
class
);
this
.
testCaseIssuesMapper
=
CommonBeanFactory
.
getBean
(
TestCaseIssuesMapper
.
class
);
this
.
projectService
=
CommonBeanFactory
.
getBean
(
ProjectService
.
class
);
this
.
testCaseService
=
CommonBeanFactory
.
getBean
(
TestCaseService
.
class
);
this
.
issuesMapper
=
CommonBeanFactory
.
getBean
(
IssuesMapper
.
class
);
this
.
extIssuesMapper
=
CommonBeanFactory
.
getBean
(
ExtIssuesMapper
.
class
);
this
.
testCaseId
=
issuesRequest
.
getTestCaseId
();
}
protected
String
getPlatformConfig
(
String
platform
)
{
SessionUser
user
=
SessionUtils
.
getUser
();
String
orgId
=
user
.
getLastOrganizationId
();
IntegrationRequest
request
=
new
IntegrationRequest
();
if
(
StringUtils
.
isBlank
(
orgId
))
{
MSException
.
throwException
(
"organization id is null"
);
}
request
.
setOrgId
(
orgId
);
request
.
setPlatform
(
platform
);
ServiceIntegration
integration
=
integrationService
.
get
(
request
);
return
integration
.
getConfiguration
();
}
protected
HttpHeaders
auth
(
String
apiUser
,
String
password
)
{
String
authKey
=
EncryptUtils
.
base64Encoding
(
apiUser
+
":"
+
password
);
HttpHeaders
headers
=
new
HttpHeaders
();
headers
.
add
(
"Authorization"
,
"Basic "
+
authKey
);
return
headers
;
}
/**
* 获取平台与项目相关的属性
* @return
*/
abstract
String
getProjectId
();
protected
boolean
isIntegratedPlatform
(
String
orgId
,
String
platform
)
{
IntegrationRequest
request
=
new
IntegrationRequest
();
request
.
setPlatform
(
platform
);
request
.
setOrgId
(
orgId
);
ServiceIntegration
integration
=
integrationService
.
get
(
request
);
return
StringUtils
.
isNotBlank
(
integration
.
getId
());
}
}
backend/src/main/java/io/metersphere/track/issue/IssueFactory.java
0 → 100644
浏览文件 @
bc59848d
package
io.metersphere.track.issue
;
import
io.metersphere.commons.constants.IssuesManagePlatform
;
import
io.metersphere.track.request.testcase.IssuesRequest
;
import
org.apache.commons.lang3.StringUtils
;
import
java.util.ArrayList
;
import
java.util.List
;
public
class
IssueFactory
{
public
static
AbstractIssuePlatform
createPlatform
(
String
platform
,
IssuesRequest
addIssueRequest
)
{
if
(
StringUtils
.
equals
(
IssuesManagePlatform
.
Tapd
.
toString
(),
platform
))
{
return
new
TapdIssue
(
addIssueRequest
);
}
else
if
(
StringUtils
.
equals
(
IssuesManagePlatform
.
Jira
.
toString
(),
platform
))
{
return
new
JiraIssue
(
addIssueRequest
);
}
else
if
(
StringUtils
.
equals
(
"LOCAL"
,
platform
))
{
return
new
LocalIssue
(
addIssueRequest
);
}
return
null
;
}
public
static
List
<
AbstractIssuePlatform
>
createPlatforms
(
List
<
String
>
types
,
IssuesRequest
addIssueRequest
)
{
List
<
AbstractIssuePlatform
>
platforms
=
new
ArrayList
<>();
types
.
forEach
(
type
->
{
AbstractIssuePlatform
abstractIssuePlatform
=
createPlatform
(
type
,
addIssueRequest
);
if
(
abstractIssuePlatform
!=
null
)
{
platforms
.
add
(
abstractIssuePlatform
);
}
});
return
platforms
;
}
}
backend/src/main/java/io/metersphere/track/issue/IssuesPlatform.java
0 → 100644
浏览文件 @
bc59848d
package
io.metersphere.track.issue
;
import
io.metersphere.base.domain.Issues
;
import
io.metersphere.track.request.testcase.IssuesRequest
;
import
java.util.List
;
public
interface
IssuesPlatform
{
/**
* 获取平台相关联的缺陷
* @return
*/
List
<
Issues
>
getIssue
();
/**
* 添加缺陷到缺陷平台
* @param issuesRequest
*/
void
addIssue
(
IssuesRequest
issuesRequest
);
/**
* 删除缺陷平台缺陷
* @param id
*/
void
deleteIssue
(
String
id
);
/**
* 测试缺陷平台连通性
* @param
*/
void
testAuth
();
/**
* 获取缺陷平台项目下的相关人员
* @return
*/
List
<
PlatformUser
>
getPlatformUser
();
}
backend/src/main/java/io/metersphere/track/issue/JiraIssue.java
0 → 100644
浏览文件 @
bc59848d
package
io.metersphere.track.issue
;
import
com.alibaba.fastjson.JSON
;
import
com.alibaba.fastjson.JSONObject
;
import
io.metersphere.base.domain.*
;
import
io.metersphere.commons.constants.IssuesManagePlatform
;
import
io.metersphere.commons.exception.MSException
;
import
io.metersphere.commons.utils.EncryptUtils
;
import
io.metersphere.commons.utils.LogUtil
;
import
io.metersphere.track.request.testcase.IssuesRequest
;
import
org.apache.commons.lang3.StringUtils
;
import
org.commonmark.node.Node
;
import
org.commonmark.parser.Parser
;
import
org.commonmark.renderer.html.HtmlRenderer
;
import
org.jsoup.Jsoup
;
import
org.jsoup.nodes.Document
;
import
org.jsoup.safety.Whitelist
;
import
org.springframework.http.HttpEntity
;
import
org.springframework.http.HttpHeaders
;
import
org.springframework.http.HttpMethod
;
import
org.springframework.http.ResponseEntity
;
import
org.springframework.util.MultiValueMap
;
import
org.springframework.web.client.HttpClientErrorException
;
import
org.springframework.web.client.RestTemplate
;
import
java.util.ArrayList
;
import
java.util.List
;
import
java.util.UUID
;
import
java.util.stream.Collectors
;
public
class
JiraIssue
extends
AbstractIssuePlatform
{
public
JiraIssue
(
IssuesRequest
issuesRequest
)
{
super
(
issuesRequest
);
}
@Override
public
List
<
Issues
>
getIssue
()
{
List
<
Issues
>
list
=
new
ArrayList
<>();
String
config
=
getPlatformConfig
(
IssuesManagePlatform
.
Jira
.
toString
());
JSONObject
object
=
JSON
.
parseObject
(
config
);
if
(
object
==
null
)
{
MSException
.
throwException
(
"tapd config is null"
);
}
String
account
=
object
.
getString
(
"account"
);
String
password
=
object
.
getString
(
"password"
);
String
url
=
object
.
getString
(
"url"
);
HttpHeaders
headers
=
auth
(
account
,
password
);
TestCaseIssuesExample
example
=
new
TestCaseIssuesExample
();
example
.
createCriteria
().
andTestCaseIdEqualTo
(
testCaseId
);
List
<
Issues
>
issues
=
extIssuesMapper
.
getIssues
(
testCaseId
,
IssuesManagePlatform
.
Jira
.
toString
());
List
<
String
>
issuesIds
=
issues
.
stream
().
map
(
Issues:
:
getId
).
collect
(
Collectors
.
toList
());
issuesIds
.
forEach
(
issuesId
->
{
Issues
dto
=
getJiraIssues
(
headers
,
url
,
issuesId
);
if
(
StringUtils
.
isBlank
(
dto
.
getId
()))
{
// 缺陷不存在,解除用例和缺陷的关联
TestCaseIssuesExample
issuesExample
=
new
TestCaseIssuesExample
();
issuesExample
.
createCriteria
()
.
andTestCaseIdEqualTo
(
testCaseId
)
.
andIssuesIdEqualTo
(
issuesId
);
testCaseIssuesMapper
.
deleteByExample
(
issuesExample
);
issuesMapper
.
deleteByPrimaryKey
(
issuesId
);
}
else
{
// 缺陷状态为 完成,则不显示
if
(!
StringUtils
.
equals
(
"done"
,
dto
.
getStatus
()))
{
list
.
add
(
dto
);
}
}
});
return
list
;
}
@Override
public
void
addIssue
(
IssuesRequest
issuesRequest
)
{
String
config
=
getPlatformConfig
(
IssuesManagePlatform
.
Jira
.
toString
());
JSONObject
object
=
JSON
.
parseObject
(
config
);
if
(
object
==
null
)
{
MSException
.
throwException
(
"jira config is null"
);
}
String
account
=
object
.
getString
(
"account"
);
String
password
=
object
.
getString
(
"password"
);
String
url
=
object
.
getString
(
"url"
);
String
issuetype
=
object
.
getString
(
"issuetype"
);
if
(
StringUtils
.
isBlank
(
issuetype
))
{
MSException
.
throwException
(
"Jira 问题类型为空"
);
}
String
auth
=
EncryptUtils
.
base64Encoding
(
account
+
":"
+
password
);
String
testCaseId
=
issuesRequest
.
getTestCaseId
();
String
jiraKey
=
getProjectId
();
if
(
StringUtils
.
isBlank
(
jiraKey
))
{
MSException
.
throwException
(
"未关联Jira 项目Key"
);
}
String
content
=
issuesRequest
.
getContent
();
Document
document
=
Jsoup
.
parse
(
content
);
document
.
outputSettings
(
new
Document
.
OutputSettings
().
prettyPrint
(
false
));
document
.
select
(
"br"
).
append
(
"\\n"
);
document
.
select
(
"p"
).
prepend
(
"\\n\\n"
);
String
s
=
document
.
html
().
replaceAll
(
"\\\\n"
,
"\n"
);
String
desc
=
Jsoup
.
clean
(
s
,
""
,
Whitelist
.
none
(),
new
Document
.
OutputSettings
().
prettyPrint
(
false
));
desc
=
desc
.
replace
(
" "
,
""
);
String
json
=
"{\n"
+
" \"fields\":{\n"
+
" \"project\":{\n"
+
" \"key\":\""
+
jiraKey
+
"\"\n"
+
" },\n"
+
" \"summary\":\""
+
issuesRequest
.
getTitle
()
+
"\",\n"
+
" \"description\": "
+
JSON
.
toJSONString
(
desc
)
+
",\n"
+
" \"issuetype\":{\n"
+
" \"name\":\""
+
issuetype
+
"\"\n"
+
" }\n"
+
" }\n"
+
"}"
;
String
result
=
addJiraIssue
(
url
,
auth
,
json
);
JSONObject
jsonObject
=
JSON
.
parseObject
(
result
);
String
id
=
jsonObject
.
getString
(
"key"
);
// 用例与第三方缺陷平台中的缺陷关联
TestCaseIssues
testCaseIssues
=
new
TestCaseIssues
();
testCaseIssues
.
setId
(
UUID
.
randomUUID
().
toString
());
testCaseIssues
.
setIssuesId
(
id
);
testCaseIssues
.
setTestCaseId
(
testCaseId
);
testCaseIssuesMapper
.
insert
(
testCaseIssues
);
// 插入缺陷表
Issues
issues
=
new
Issues
();
issues
.
setId
(
id
);
issues
.
setPlatform
(
IssuesManagePlatform
.
Jira
.
toString
());
issuesMapper
.
insert
(
issues
);
}
private
String
addJiraIssue
(
String
url
,
String
auth
,
String
json
)
{
HttpHeaders
requestHeaders
=
new
HttpHeaders
();
requestHeaders
.
add
(
"Authorization"
,
"Basic "
+
auth
);
requestHeaders
.
setContentType
(
org
.
springframework
.
http
.
MediaType
.
APPLICATION_JSON
);
//HttpEntity
HttpEntity
<
String
>
requestEntity
=
new
HttpEntity
<>(
json
,
requestHeaders
);
RestTemplate
restTemplate
=
new
RestTemplate
();
//post
ResponseEntity
<
String
>
responseEntity
=
null
;
try
{
responseEntity
=
restTemplate
.
exchange
(
url
+
"/rest/api/2/issue"
,
HttpMethod
.
POST
,
requestEntity
,
String
.
class
);
}
catch
(
Exception
e
)
{
LogUtil
.
error
(
e
.
getMessage
(),
e
);
MSException
.
throwException
(
"调用Jira接口创建缺陷失败"
);
}
return
responseEntity
.
getBody
();
}
@Override
public
void
deleteIssue
(
String
id
)
{
}
@Override
public
void
testAuth
()
{
try
{
String
config
=
getPlatformConfig
(
IssuesManagePlatform
.
Jira
.
toString
());
JSONObject
object
=
JSON
.
parseObject
(
config
);
String
account
=
object
.
getString
(
"account"
);
String
password
=
object
.
getString
(
"password"
);
String
url
=
object
.
getString
(
"url"
);
HttpHeaders
headers
=
auth
(
account
,
password
);
HttpEntity
<
MultiValueMap
>
requestEntity
=
new
HttpEntity
<>(
headers
);
RestTemplate
restTemplate
=
new
RestTemplate
();
restTemplate
.
exchange
(
url
+
"rest/api/2/issue/createmeta"
,
HttpMethod
.
GET
,
requestEntity
,
String
.
class
);
}
catch
(
Exception
e
)
{
LogUtil
.
error
(
e
.
getMessage
(),
e
);
MSException
.
throwException
(
"验证失败!"
);
}
}
@Override
public
List
<
PlatformUser
>
getPlatformUser
()
{
return
null
;
}
@Override
String
getProjectId
()
{
TestCaseWithBLOBs
testCase
=
testCaseService
.
getTestCase
(
testCaseId
);
Project
project
=
projectService
.
getProjectById
(
testCase
.
getProjectId
());
return
project
.
getJiraKey
();
}
private
Issues
getJiraIssues
(
HttpHeaders
headers
,
String
url
,
String
issuesId
)
{
HttpEntity
<
MultiValueMap
>
requestEntity
=
new
HttpEntity
<>(
headers
);
RestTemplate
restTemplate
=
new
RestTemplate
();
//post
ResponseEntity
<
String
>
responseEntity
;
Issues
issues
=
new
Issues
();
try
{
responseEntity
=
restTemplate
.
exchange
(
url
+
"/rest/api/2/issue/"
+
issuesId
,
HttpMethod
.
GET
,
requestEntity
,
String
.
class
);
String
body
=
responseEntity
.
getBody
();
JSONObject
obj
=
JSONObject
.
parseObject
(
body
);
LogUtil
.
info
(
obj
);
String
lastmodify
=
""
;
String
status
=
""
;
JSONObject
fields
=
(
JSONObject
)
obj
.
get
(
"fields"
);
JSONObject
statusObj
=
(
JSONObject
)
fields
.
get
(
"status"
);
JSONObject
assignee
=
(
JSONObject
)
fields
.
get
(
"assignee"
);
if
(
statusObj
!=
null
)
{
JSONObject
statusCategory
=
(
JSONObject
)
statusObj
.
get
(
"statusCategory"
);
status
=
statusCategory
.
getString
(
"key"
);
}
String
id
=
obj
.
getString
(
"key"
);
String
title
=
fields
.
getString
(
"summary"
);
String
description
=
fields
.
getString
(
"description"
);
Parser
parser
=
Parser
.
builder
().
build
();
Node
document
=
parser
.
parse
(
description
);
HtmlRenderer
renderer
=
HtmlRenderer
.
builder
().
build
();
description
=
renderer
.
render
(
document
);
Long
createTime
=
fields
.
getLong
(
"created"
);
if
(
assignee
!=
null
)
{
lastmodify
=
assignee
.
getString
(
"displayName"
);
}
issues
.
setId
(
id
);
issues
.
setTitle
(
title
);
issues
.
setCreateTime
(
createTime
);
issues
.
setLastmodify
(
lastmodify
);
issues
.
setDescription
(
description
);
issues
.
setStatus
(
status
);
issues
.
setPlatform
(
IssuesManagePlatform
.
Jira
.
toString
());
}
catch
(
HttpClientErrorException
.
NotFound
e
)
{
LogUtil
.
error
(
e
.
getStackTrace
(),
e
);
return
new
Issues
();
}
catch
(
HttpClientErrorException
.
Unauthorized
e
)
{
LogUtil
.
error
(
e
.
getStackTrace
(),
e
);
MSException
.
throwException
(
"获取Jira缺陷失败,检查Jira配置信息"
);
}
catch
(
Exception
e
)
{
LogUtil
.
error
(
e
.
getMessage
(),
e
);
MSException
.
throwException
(
"调用Jira接口获取缺陷失败"
);
}
return
issues
;
}
}
backend/src/main/java/io/metersphere/track/issue/LocalIssue.java
0 → 100644
浏览文件 @
bc59848d
package
io.metersphere.track.issue
;
import
io.metersphere.base.domain.Issues
;
import
io.metersphere.base.domain.TestCaseIssues
;
import
io.metersphere.commons.constants.IssuesManagePlatform
;
import
io.metersphere.commons.user.SessionUser
;
import
io.metersphere.commons.utils.SessionUtils
;
import
io.metersphere.track.request.testcase.IssuesRequest
;
import
java.util.List
;
import
java.util.UUID
;
public
class
LocalIssue
extends
AbstractIssuePlatform
{
public
LocalIssue
(
IssuesRequest
issuesRequest
)
{
super
(
issuesRequest
);
}
@Override
public
List
<
Issues
>
getIssue
()
{
return
extIssuesMapper
.
getIssues
(
testCaseId
,
IssuesManagePlatform
.
Local
.
toString
());
}
@Override
public
void
addIssue
(
IssuesRequest
issuesRequest
)
{
SessionUser
user
=
SessionUtils
.
getUser
();
String
id
=
UUID
.
randomUUID
().
toString
();
Issues
issues
=
new
Issues
();
issues
.
setId
(
id
);
issues
.
setStatus
(
"new"
);
issues
.
setReporter
(
user
.
getId
());
issues
.
setTitle
(
issuesRequest
.
getTitle
());
issues
.
setDescription
(
issuesRequest
.
getContent
());
issues
.
setCreateTime
(
System
.
currentTimeMillis
());
issues
.
setUpdateTime
(
System
.
currentTimeMillis
());
issues
.
setPlatform
(
IssuesManagePlatform
.
Local
.
toString
());
issuesMapper
.
insert
(
issues
);
TestCaseIssues
testCaseIssues
=
new
TestCaseIssues
();
testCaseIssues
.
setId
(
UUID
.
randomUUID
().
toString
());
testCaseIssues
.
setIssuesId
(
id
);
testCaseIssues
.
setTestCaseId
(
issuesRequest
.
getTestCaseId
());
testCaseIssuesMapper
.
insert
(
testCaseIssues
);
}
@Override
public
void
deleteIssue
(
String
id
)
{
issuesMapper
.
deleteByPrimaryKey
(
id
);
}
@Override
public
void
testAuth
()
{
}
@Override
public
List
<
PlatformUser
>
getPlatformUser
()
{
return
null
;
}
@Override
String
getProjectId
()
{
return
null
;
}
public
void
closeIssue
(
String
issueId
)
{
Issues
issues
=
new
Issues
();
issues
.
setId
(
issueId
);
issues
.
setStatus
(
"closed"
);
issuesMapper
.
updateByPrimaryKeySelective
(
issues
);
}
}
backend/src/main/java/io/metersphere/track/issue/PlatformUser.java
0 → 100644
浏览文件 @
bc59848d
package
io.metersphere.track.issue
;
import
lombok.Data
;
import
java.util.List
;
@Data
public
class
PlatformUser
{
private
List
<
String
>
roleId
;
private
String
name
;
private
String
user
;
}
backend/src/main/java/io/metersphere/track/issue/TapdIssue.java
0 → 100644
浏览文件 @
bc59848d
package
io.metersphere.track.issue
;
import
com.alibaba.fastjson.JSON
;
import
com.alibaba.fastjson.JSONArray
;
import
com.alibaba.fastjson.JSONObject
;
import
io.metersphere.base.domain.*
;
import
io.metersphere.commons.constants.IssuesManagePlatform
;
import
io.metersphere.commons.exception.MSException
;
import
io.metersphere.commons.utils.LogUtil
;
import
io.metersphere.commons.utils.RestTemplateUtils
;
import
io.metersphere.commons.utils.SessionUtils
;
import
io.metersphere.controller.ResultHolder
;
import
io.metersphere.track.request.testcase.IssuesRequest
;
import
org.apache.commons.lang3.StringUtils
;
import
org.springframework.http.HttpEntity
;
import
org.springframework.http.HttpHeaders
;
import
org.springframework.http.HttpMethod
;
import
org.springframework.util.LinkedMultiValueMap
;
import
org.springframework.util.MultiValueMap
;
import
org.springframework.web.client.RestTemplate
;
import
java.util.ArrayList
;
import
java.util.List
;
import
java.util.UUID
;
import
java.util.stream.Collectors
;
public
class
TapdIssue
extends
AbstractIssuePlatform
{
public
TapdIssue
(
IssuesRequest
issueRequest
)
{
super
(
issueRequest
);
}
@Override
public
List
<
Issues
>
getIssue
()
{
List
<
Issues
>
list
=
new
ArrayList
<>();
String
tapdId
=
getProjectId
();
TestCaseIssuesExample
example
=
new
TestCaseIssuesExample
();
example
.
createCriteria
().
andTestCaseIdEqualTo
(
testCaseId
);
List
<
Issues
>
issues
=
extIssuesMapper
.
getIssues
(
testCaseId
,
IssuesManagePlatform
.
Tapd
.
toString
());
List
<
String
>
issuesIds
=
issues
.
stream
().
map
(
Issues:
:
getId
).
collect
(
Collectors
.
toList
());
issuesIds
.
forEach
(
issuesId
->
{
Issues
dto
=
getTapdIssues
(
tapdId
,
issuesId
);
if
(
StringUtils
.
isBlank
(
dto
.
getId
()))
{
// 缺陷不存在,解除用例和缺陷的关联
TestCaseIssuesExample
issuesExample
=
new
TestCaseIssuesExample
();
issuesExample
.
createCriteria
()
.
andTestCaseIdEqualTo
(
testCaseId
)
.
andIssuesIdEqualTo
(
issuesId
);
testCaseIssuesMapper
.
deleteByExample
(
issuesExample
);
issuesMapper
.
deleteByPrimaryKey
(
issuesId
);
}
else
{
dto
.
setPlatform
(
IssuesManagePlatform
.
Tapd
.
toString
());
// 缺陷状态为 关闭,则不显示
if
(!
StringUtils
.
equals
(
"closed"
,
dto
.
getStatus
()))
{
list
.
add
(
dto
);
}
}
});
return
list
;
}
private
Issues
getTapdIssues
(
String
projectId
,
String
issuesId
)
{
String
url
=
"https://api.tapd.cn/bugs?workspace_id="
+
projectId
+
"&id="
+
issuesId
;
ResultHolder
call
=
call
(
url
);
String
listJson
=
JSON
.
toJSONString
(
call
.
getData
());
if
(
StringUtils
.
equals
(
Boolean
.
FALSE
.
toString
(),
listJson
))
{
return
new
Issues
();
}
JSONObject
jsonObject
=
JSONObject
.
parseObject
(
listJson
);
JSONObject
bug
=
jsonObject
.
getJSONObject
(
"Bug"
);
Long
created
=
bug
.
getLong
(
"created"
);
Issues
issues
=
jsonObject
.
getObject
(
"Bug"
,
Issues
.
class
);
issues
.
setCreateTime
(
created
);
return
issues
;
}
@Override
public
void
addIssue
(
IssuesRequest
issuesRequest
)
{
String
url
=
"https://api.tapd.cn/bugs"
;
String
testCaseId
=
issuesRequest
.
getTestCaseId
();
String
tapdId
=
getProjectId
();
if
(
StringUtils
.
isBlank
(
tapdId
))
{
MSException
.
throwException
(
"未关联Tapd 项目ID"
);
}
List
<
String
>
PlatformUsers
=
issuesRequest
.
getTapdUsers
();
String
usersStr
=
String
.
join
(
";"
,
PlatformUsers
);
String
username
=
SessionUtils
.
getUser
().
getName
();
MultiValueMap
<
String
,
Object
>
paramMap
=
new
LinkedMultiValueMap
<>();
paramMap
.
add
(
"title"
,
issuesRequest
.
getTitle
());
paramMap
.
add
(
"workspace_id"
,
tapdId
);
paramMap
.
add
(
"description"
,
issuesRequest
.
getContent
());
paramMap
.
add
(
"reporter"
,
username
);
paramMap
.
add
(
"current_owner"
,
usersStr
);
ResultHolder
result
=
call
(
url
,
HttpMethod
.
POST
,
paramMap
);
String
listJson
=
JSON
.
toJSONString
(
result
.
getData
());
JSONObject
jsonObject
=
JSONObject
.
parseObject
(
listJson
);
String
issuesId
=
jsonObject
.
getObject
(
"Bug"
,
Issues
.
class
).
getId
();
// 用例与第三方缺陷平台中的缺陷关联
TestCaseIssues
testCaseIssues
=
new
TestCaseIssues
();
testCaseIssues
.
setId
(
UUID
.
randomUUID
().
toString
());
testCaseIssues
.
setIssuesId
(
issuesId
);
testCaseIssues
.
setTestCaseId
(
testCaseId
);
testCaseIssuesMapper
.
insert
(
testCaseIssues
);
// 插入缺陷表
Issues
issues
=
new
Issues
();
issues
.
setId
(
issuesId
);
issues
.
setPlatform
(
IssuesManagePlatform
.
Tapd
.
toString
());
issuesMapper
.
insert
(
issues
);
}
@Override
public
void
deleteIssue
(
String
id
)
{}
@Override
public
void
testAuth
()
{
try
{
String
tapdConfig
=
getPlatformConfig
(
IssuesManagePlatform
.
Tapd
.
toString
());
JSONObject
object
=
JSON
.
parseObject
(
tapdConfig
);
String
account
=
object
.
getString
(
"account"
);
String
password
=
object
.
getString
(
"password"
);
HttpHeaders
headers
=
auth
(
account
,
password
);
HttpEntity
<
MultiValueMap
>
requestEntity
=
new
HttpEntity
<>(
headers
);
RestTemplate
restTemplate
=
new
RestTemplate
();
restTemplate
.
exchange
(
"https://api.tapd.cn/quickstart/testauth"
,
HttpMethod
.
GET
,
requestEntity
,
String
.
class
);
}
catch
(
Exception
e
)
{
LogUtil
.
error
(
e
.
getMessage
(),
e
);
MSException
.
throwException
(
"验证失败!"
);
}
}
@Override
public
List
<
PlatformUser
>
getPlatformUser
()
{
List
<
PlatformUser
>
users
=
new
ArrayList
<>();
String
projectId
=
getProjectId
();
String
url
=
"https://api.tapd.cn/workspaces/users?workspace_id="
+
projectId
;
ResultHolder
call
=
call
(
url
);
String
listJson
=
JSON
.
toJSONString
(
call
.
getData
());
JSONArray
jsonArray
=
JSON
.
parseArray
(
listJson
);
for
(
int
i
=
0
;
i
<
jsonArray
.
size
();
i
++)
{
JSONObject
o
=
jsonArray
.
getJSONObject
(
i
);
PlatformUser
user
=
o
.
getObject
(
"UserWorkspace"
,
PlatformUser
.
class
);
users
.
add
(
user
);
}
return
users
;
}
@Override
String
getProjectId
()
{
TestCaseWithBLOBs
testCase
=
testCaseService
.
getTestCase
(
testCaseId
);
Project
project
=
projectService
.
getProjectById
(
testCase
.
getProjectId
());
return
project
.
getTapdId
();
}
private
ResultHolder
call
(
String
url
)
{
return
call
(
url
,
HttpMethod
.
GET
,
null
);
}
private
ResultHolder
call
(
String
url
,
HttpMethod
httpMethod
,
Object
params
)
{
String
responseJson
;
String
config
=
getPlatformConfig
(
IssuesManagePlatform
.
Tapd
.
toString
());
JSONObject
object
=
JSON
.
parseObject
(
config
);
if
(
object
==
null
)
{
MSException
.
throwException
(
"tapd config is null"
);
}
String
account
=
object
.
getString
(
"account"
);
String
password
=
object
.
getString
(
"password"
);
HttpHeaders
header
=
auth
(
account
,
password
);
if
(
httpMethod
.
equals
(
HttpMethod
.
GET
))
{
responseJson
=
RestTemplateUtils
.
get
(
url
,
header
);
}
else
{
responseJson
=
RestTemplateUtils
.
post
(
url
,
params
,
header
);
}
ResultHolder
result
=
JSON
.
parseObject
(
responseJson
,
ResultHolder
.
class
);
if
(!
result
.
isSuccess
())
{
MSException
.
throwException
(
result
.
getMessage
());
}
return
JSON
.
parseObject
(
responseJson
,
ResultHolder
.
class
);
}
}
backend/src/main/java/io/metersphere/track/service/IssuesService.java
浏览文件 @
bc59848d
此差异已折叠。
点击以展开。
frontend/src/business/components/api/test/ApiTestConfig.vue
浏览文件 @
bc59848d
...
...
@@ -8,7 +8,7 @@
<el-input
:disabled=
"isReadOnly"
class=
"test-name"
v-model=
"test.name"
maxlength=
"60"
:placeholder=
"$t('api_test.input_name')"
show-word-limit
>
<el-select
:disabled=
"isReadOnly"
class=
"test-project"
v-model=
"test.projectId"
slot=
"prepend"
<el-select
filterable
class=
"test-project"
v-model=
"test.projectId"
slot=
"prepend"
:placeholder=
"$t('api_test.select_project')"
>
<el-option
v-for=
"project in projects"
:key=
"project.id"
:label=
"project.name"
:value=
"project.id"
/>
</el-select>
...
...
frontend/src/business/components/api/test/components/ApiEnvironmentConfig.vue
浏览文件 @
bc59848d
<
template
>
<el-dialog
:close-on-click-modal=
"false"
:title=
"$t('api_test.environment.environment_config')"
:visible.sync=
"visible"
class=
"environment-dialog"
:visible.sync=
"visible"
class=
"environment-dialog"
width=
"60%"
@
close=
"close"
append-to-body
ref=
"environmentConfig"
>
<el-container
v-loading=
"result.loading"
>
<ms-aside-item
:enable-aside-hidden=
"false"
:title=
"$t('api_test.environment.environment_list')"
...
...
frontend/src/business/components/api/test/components/ApiVariableInput.vue
浏览文件 @
bc59848d
<
template
>
<div
class=
"variable-input"
>
<el-input
:disabled=
"isReadOnly"
:value=
"value"
v-bind=
"$attrs"
:size=
"size"
@
change=
"change"
@
input=
"input"
/>
<el-input
class=
"el-input__inner_pd"
:disabled=
"isReadOnly"
:value=
"value"
v-bind=
"$attrs"
:size=
"size"
@
change=
"change"
@
input=
"input"
/>
<div
:class=
"
{'hidden': !showVariable}" class="variable-combine" v-if="value">
<div
class=
"variable"
>
{{
variable
}}
</div>
<el-tooltip
:content=
"$t('api_test.copied')"
manual
v-model=
"visible"
placement=
"top"
:visible-arrow=
"false"
>
...
...
@@ -70,6 +70,9 @@
.variable-input
{
position
:
relative
;
}
.el-input__inner_pd
>>>
.el-input__inner
{
padding-right
:
135px
;
}
.variable-combine
{
color
:
#7F7F7F
;
...
...
frontend/src/business/components/performance/test/EditPerformanceTestPlan.vue
浏览文件 @
bc59848d
...
...
@@ -9,7 +9,7 @@
maxlength=
"30"
show-word-limit
>
<template
v-slot:prepend
>
<el-select
:disabled=
"isReadOnly"
v-model=
"testPlan.projectId"
<el-select
filterable
v-model=
"testPlan.projectId"
:placeholder=
"$t('load_test.select_project')"
>
<el-option
v-for=
"item in projects"
...
...
frontend/src/business/components/settings/system/Organization.vue
浏览文件 @
bc59848d
...
...
@@ -101,7 +101,7 @@
<el-form
:model=
"memberForm"
ref=
"form"
:rules=
"orgMemberRule"
label-position=
"right"
label-width=
"100px"
size=
"small"
>
<el-form-item
:label=
"$t('commons.member')"
prop=
"userIds"
>
<el-select
v-model=
"memberForm.userIds"
multiple
:placeholder=
"$t('member.please_choose_member')"
<el-select
filterable
v-model=
"memberForm.userIds"
multiple
:placeholder=
"$t('member.please_choose_member')"
class=
"select-width"
>
<el-option
v-for=
"item in memberForm.userList"
...
...
@@ -114,7 +114,7 @@
</el-select>
</el-form-item>
<el-form-item
:label=
"$t('commons.role')"
prop=
"roleIds"
>
<el-select
v-model=
"memberForm.roleIds"
multiple
:placeholder=
"$t('role.please_choose_role')"
<el-select
filterable
v-model=
"memberForm.roleIds"
multiple
:placeholder=
"$t('role.please_choose_role')"
class=
"select-width"
>
<el-option
v-for=
"item in memberForm.roles"
...
...
@@ -151,7 +151,7 @@
</el-form-item>
<el-form-item
:label=
"$t('commons.role')"
prop=
"roleIds"
:rules=
"{required: true, message: $t('role.please_choose_role'), trigger: 'change'}"
>
<el-select
v-model=
"memberForm.roleIds"
multiple
:placeholder=
"$t('role.please_choose_role')"
<el-select
filterable
v-model=
"memberForm.roleIds"
multiple
:placeholder=
"$t('role.please_choose_role')"
class=
"select-width"
>
<el-option
v-for=
"item in memberForm.allroles"
...
...
frontend/src/business/components/settings/system/SystemWorkspace.vue
浏览文件 @
bc59848d
...
...
@@ -37,7 +37,7 @@
<el-input
type=
"textarea"
v-model=
"form.description"
></el-input>
</el-form-item>
<el-form-item
:label=
"$t('workspace.organization_name')"
prop=
"organizationId"
>
<el-select
v-model=
"form.organizationId"
:placeholder=
"$t('organization.select_organization')"
<el-select
filterable
v-model=
"form.organizationId"
:placeholder=
"$t('organization.select_organization')"
class=
"select-width"
>
<el-option
v-for=
"item in form.orgList"
...
...
@@ -65,7 +65,7 @@
<el-input
type=
"textarea"
v-model=
"form.description"
></el-input>
</el-form-item>
<el-form-item
:label=
"$t('workspace.organization_name')"
prop=
"organizationId"
>
<el-select
v-model=
"form.organizationId"
:placeholder=
"$t('organization.select_organization')"
<el-select
filterable
v-model=
"form.organizationId"
:placeholder=
"$t('organization.select_organization')"
class=
"select-width"
>
<el-option
v-for=
"item in form.orgList1"
...
...
@@ -117,7 +117,7 @@
<el-form
:model=
"memberForm"
ref=
"form"
:rules=
"wsMemberRule"
label-position=
"right"
label-width=
"100px"
size=
"small"
>
<el-form-item
:label=
"$t('commons.member')"
prop=
"userIds"
>
<el-select
v-model=
"memberForm.userIds"
multiple
:placeholder=
"$t('member.please_choose_member')"
<el-select
filterable
v-model=
"memberForm.userIds"
multiple
:placeholder=
"$t('member.please_choose_member')"
class=
"select-width"
>
<el-option
v-for=
"item in memberForm.userList"
...
...
@@ -130,7 +130,7 @@
</el-select>
</el-form-item>
<el-form-item
:label=
"$t('commons.role')"
prop=
"roleIds"
>
<el-select
v-model=
"memberForm.roleIds"
multiple
:placeholder=
"$t('role.please_choose_role')"
<el-select
filterable
v-model=
"memberForm.roleIds"
multiple
:placeholder=
"$t('role.please_choose_role')"
class=
"select-width"
>
<el-option
v-for=
"item in memberForm.roles"
...
...
@@ -166,7 +166,7 @@
<el-input
v-model=
"memberForm.phone"
autocomplete=
"off"
:disabled=
"true"
/>
</el-form-item>
<el-form-item
:label=
"$t('commons.role')"
prop=
"roleIds"
:rules=
"{required: true, message: $t('role.please_choose_role'), trigger: 'change'}"
>
<el-select
v-model=
"memberForm.roleIds"
multiple
:placeholder=
"$t('role.please_choose_role')"
<el-select
filterable
v-model=
"memberForm.roleIds"
multiple
:placeholder=
"$t('role.please_choose_role')"
class=
"select-width"
>
<el-option
v-for=
"item in memberForm.allroles"
...
...
frontend/src/business/components/settings/system/User.vue
浏览文件 @
bc59848d
...
...
@@ -74,7 +74,7 @@
:prop=
"'roles.' + index + '.id'"
:rules=
"{required: true, message: $t('role.please_choose_role'), trigger: 'change'}"
>
<el-select
v-model=
"role.id"
:placeholder=
"$t('role.please_choose_role')"
>
<el-select
filterable
v-model=
"role.id"
:placeholder=
"$t('role.please_choose_role')"
>
<el-option
v-for=
"item in activeRole(role)"
:key=
"item.id"
...
...
@@ -93,7 +93,7 @@
:prop=
"'roles.' + index + '.ids'"
:rules=
"{required: true, message: $t('organization.select_organization'), trigger: 'change'}"
>
<el-select
v-model=
"role.ids"
:placeholder=
"$t('organization.select_organization')"
multiple
>
<el-select
filterable
v-model=
"role.ids"
:placeholder=
"$t('organization.select_organization')"
multiple
>
<el-option
v-for=
"item in form.orgList"
:key=
"item.id"
...
...
@@ -108,7 +108,7 @@
:prop=
"'roles.' + index + '.ids'"
:rules=
"{required: true, message: $t('workspace.select'), trigger: 'change'}"
>
<el-select
v-model=
"role.ids"
:placeholder=
"$t('workspace.select')"
multiple
>
<el-select
filterable
v-model=
"role.ids"
:placeholder=
"$t('workspace.select')"
multiple
>
<el-option
v-for=
"item in form.wsList"
:key=
"item.id"
...
...
@@ -123,7 +123,7 @@
:prop=
"'roles.' + index + '.ids'"
:rules=
"{required: true, message: $t('workspace.select'), trigger: 'change'}"
>
<el-select
v-model=
"role.ids"
:placeholder=
"$t('workspace.select')"
multiple
>
<el-select
filterable
v-model=
"role.ids"
:placeholder=
"$t('workspace.select')"
multiple
>
<el-option
v-for=
"item in form.wsList"
:key=
"item.id"
...
...
@@ -138,7 +138,7 @@
:prop=
"'roles.' + index + '.ids'"
:rules=
"{required: true, message: $t('workspace.select'), trigger: 'change'}"
>
<el-select
v-model=
"role.ids"
:placeholder=
"$t('workspace.select')"
multiple
>
<el-select
filterable
v-model=
"role.ids"
:placeholder=
"$t('workspace.select')"
multiple
>
<el-option
v-for=
"item in form.wsList"
:key=
"item.id"
...
...
@@ -187,7 +187,7 @@
:prop=
"'roles.' + index + '.id'"
:rules=
"{required: true, message: $t('role.please_choose_role'), trigger: 'change'}"
>
<el-select
v-model=
"role.id"
:placeholder=
"$t('role.please_choose_role')"
:disabled=
"!!role.id"
>
<el-select
filterable
v-model=
"role.id"
:placeholder=
"$t('role.please_choose_role')"
:disabled=
"!!role.id"
>
<el-option
v-for=
"item in activeRole(role)"
:key=
"item.id"
...
...
@@ -204,7 +204,7 @@
:prop=
"'roles.' + index + '.ids'"
:rules=
"{required: true, message: $t('organization.select_organization'), trigger: 'change'}"
>
<el-select
v-model=
"role.ids"
:placeholder=
"$t('organization.select_organization')"
multiple
>
<el-select
filterable
v-model=
"role.ids"
:placeholder=
"$t('organization.select_organization')"
multiple
>
<el-option
v-for=
"item in form.orgList"
:key=
"item.id"
...
...
@@ -219,7 +219,7 @@
:prop=
"'roles.' + index + '.ids'"
:rules=
"{required: true, message: $t('workspace.select'), trigger: 'change'}"
>
<el-select
v-model=
"role.ids"
:placeholder=
"$t('workspace.select')"
multiple
>
<el-select
filterable
v-model=
"role.ids"
:placeholder=
"$t('workspace.select')"
multiple
>
<el-option
v-for=
"item in form.wsList"
:key=
"item.id"
...
...
@@ -234,7 +234,7 @@
:prop=
"'roles.' + index + '.ids'"
:rules=
"{required: true, message: $t('workspace.select'), trigger: 'change'}"
>
<el-select
v-model=
"role.ids"
:placeholder=
"$t('workspace.select')"
multiple
>
<el-select
filterable
v-model=
"role.ids"
:placeholder=
"$t('workspace.select')"
multiple
>
<el-option
v-for=
"item in form.wsList"
:key=
"item.id"
...
...
@@ -249,7 +249,7 @@
:prop=
"'roles.' + index + '.ids'"
:rules=
"{required: true, message: $t('workspace.select'), trigger: 'change'}"
>
<el-select
v-model=
"role.ids"
:placeholder=
"$t('workspace.select')"
multiple
>
<el-select
filterable
v-model=
"role.ids"
:placeholder=
"$t('workspace.select')"
multiple
>
<el-option
v-for=
"item in form.wsList"
:key=
"item.id"
...
...
frontend/src/business/components/track/common/SelectMenu.vue
浏览文件 @
bc59848d
<
template
>
<el-menu
:unique-opened=
"true"
mode=
"horizontal"
active-text-color=
"write"
class=
"project_menu"
>
<el-submenu
index=
"1"
popper-class=
"submenu"
>
<template
v-slot:title
>
<span
class=
"menu-title"
>
{{
'
[
'
+
title
+
'
]
'
}}
</span>
<span>
{{
currentData
==
null
?
''
:
currentData
.
name
}}
</span>
</
template
>
<
template
v-slot:default
>
<div
style=
"height:400px;"
>
<el-scrollbar
style=
"height:100%"
>
<label
v-for=
"(item,index) in data"
:key=
"index"
>
<el-menu-item
@
click=
"changeData(item)"
>
{{
item
.
name
}}
<i
class=
"el-icon-check"
v-if=
"currentData && item.id === currentData.id"
></i>
</el-menu-item>
</label>
</el-scrollbar>
</div>
</
template
>
</el-submenu>
</el-menu>
<div>
<span
class=
"menu-title"
>
{{
'
[
'
+
title
+
'
]
'
}}
</span>
<el-select
filterable
slot=
"prepend"
v-model=
"value"
@
change=
"changeData"
class=
"project_menu"
size=
"small"
>
<el-option
v-for=
"(item,index) in data"
:key=
"index"
:label=
"item.name"
:value=
"index"
/>
</el-select>
</div>
</
template
>
<
script
>
export
default
{
name
:
"
SelectMenu
"
,
props
:
{
data
:
{
type
:
Array
},
currentData
:
{
type
:
Object
},
title
:
{
type
:
String
}
export
default
{
name
:
"
SelectMenu
"
,
props
:
{
data
:
{
type
:
Array
},
currentData
:
{
type
:
Object
},
methods
:
{
changeData
(
data
)
{
this
.
$emit
(
"
dataChange
"
,
data
);
title
:
{
type
:
String
}
},
data
()
{
return
{
value
:
''
}
},
watch
:
{
currentData
(
data
)
{
if
(
data
!=
undefined
&&
data
!=
null
)
{
this
.
value
=
data
.
name
;
}
}
},
methods
:
{
changeData
(
index
)
{
this
.
$emit
(
"
dataChange
"
,
this
.
data
[
index
]);
}
}
}
</
script
>
<
style
scoped
>
.project_menu
{
width
:
214px
;
}
.menu-title
{
color
:
darkgrey
;
margin-left
:
10px
;
margin-right
:
10px
;
}
</
style
>
frontend/src/business/components/track/plan/view/comonents/TestPlanTestCaseEdit.vue
浏览文件 @
bc59848d
...
...
@@ -180,6 +180,7 @@
:disabled=
"isReadOnly"
v-model=
"scope.row.executeResult"
@
change=
"stepResultChange()"
filterable
size=
"mini"
>
<el-option
:label=
"$t('test_track.plan_view.pass')"
value=
"Pass"
style=
"color: #7ebf50;"
></el-option>
...
...
@@ -227,6 +228,7 @@
{{ $t('test_track.issue.please_choose_current_owner') }}
<el-select
v-model=
"testCase.tapdUsers"
multiple
filterable
style=
"width: 20%"
:placeholder=
"$t('test_track.issue.please_choose_current_owner')"
collapse-tags
>
...
...
frontend/src/business/components/track/plan/view/comonents/TestPlanTestCaseList.vue
浏览文件 @
bc59848d
此差异已折叠。
点击以展开。
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录