提交 bc59848d 编写于 作者: C chenjianxing

Merge branch 'master' of https://github.com/metersphere/server

......@@ -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=")">
......
package io.metersphere.track.controller;
import io.metersphere.base.domain.Issues;
import io.metersphere.track.domain.TapdUser;
import io.metersphere.track.issue.PlatformUser;
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> getTapdUsers(@PathVariable String caseId) {
public List<PlatformUser> getPlatformUsers(@PathVariable String caseId) {
return issuesService.getTapdProjectUsers(caseId);
}
......
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());
}
}
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;
}
}
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();
}
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("&nbsp;", "");
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;
}
}
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);
}
}
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;
}
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);
}
}
......@@ -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>
......
<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')"
......
<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;
......
......@@ -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"
......
......@@ -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"
......
......@@ -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"
......
......@@ -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"
......
<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>
......@@ -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>
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册