refactor: merge v1.2

This commit is contained in:
chenjianxing 2020-09-02 19:32:31 +08:00
commit 86098dee8a
57 changed files with 872 additions and 611 deletions

1
.gitignore vendored
View File

@ -30,3 +30,4 @@ target
.settings .settings
.project .project
.classpath .classpath
.jython_cache

View File

@ -153,6 +153,12 @@
</exclusions> </exclusions>
</dependency> </dependency>
<dependency>
<groupId>org.python</groupId>
<artifactId>jython</artifactId>
<version>2.7.2</version>
</dependency>
<dependency> <dependency>
<groupId>org.apache.jmeter</groupId> <groupId>org.apache.jmeter</groupId>
<artifactId>ApacheJMeter_functions</artifactId> <artifactId>ApacheJMeter_functions</artifactId>

View File

@ -66,7 +66,7 @@ public class APITestController {
@PostMapping(value = "/update", consumes = {"multipart/form-data"}) @PostMapping(value = "/update", consumes = {"multipart/form-data"})
public void update(@RequestPart("request") SaveAPITestRequest request, @RequestPart(value = "file") MultipartFile file, @RequestPart(value = "files") List<MultipartFile> bodyFiles) { public void update(@RequestPart("request") SaveAPITestRequest request, @RequestPart(value = "file") MultipartFile file, @RequestPart(value = "files") List<MultipartFile> bodyFiles) {
apiTestService.update(request, file, bodyFiles); apiTestService.update(request, file, bodyFiles);
} }
@PostMapping(value = "/copy") @PostMapping(value = "/copy")

View File

@ -0,0 +1,10 @@
package io.metersphere.api.dto.scenario.processor;
import lombok.Data;
import lombok.EqualsAndHashCode;
@EqualsAndHashCode(callSuper = true)
@Data
public class JSR223PostProcessor extends JSR223Processor {
}

View File

@ -0,0 +1,10 @@
package io.metersphere.api.dto.scenario.processor;
import lombok.Data;
import lombok.EqualsAndHashCode;
@EqualsAndHashCode(callSuper = true)
@Data
public class JSR223PreProcessor extends JSR223Processor {
}

View File

@ -0,0 +1,9 @@
package io.metersphere.api.dto.scenario.processor;
import lombok.Data;
@Data
public class JSR223Processor {
private String script;
private String language;
}

View File

@ -8,6 +8,8 @@ import io.metersphere.api.dto.scenario.assertions.Assertions;
import io.metersphere.api.dto.scenario.extract.Extract; import io.metersphere.api.dto.scenario.extract.Extract;
import io.metersphere.api.dto.scenario.processor.BeanShellPostProcessor; import io.metersphere.api.dto.scenario.processor.BeanShellPostProcessor;
import io.metersphere.api.dto.scenario.processor.BeanShellPreProcessor; import io.metersphere.api.dto.scenario.processor.BeanShellPreProcessor;
import io.metersphere.api.dto.scenario.processor.JSR223PostProcessor;
import io.metersphere.api.dto.scenario.processor.JSR223PreProcessor;
import io.metersphere.api.dto.scenario.request.dubbo.ConfigCenter; import io.metersphere.api.dto.scenario.request.dubbo.ConfigCenter;
import io.metersphere.api.dto.scenario.request.dubbo.ConsumerAndService; import io.metersphere.api.dto.scenario.request.dubbo.ConsumerAndService;
import io.metersphere.api.dto.scenario.request.dubbo.RegistryCenter; import io.metersphere.api.dto.scenario.request.dubbo.RegistryCenter;
@ -51,4 +53,8 @@ public class DubboRequest implements Request {
private BeanShellPostProcessor beanShellPostProcessor; private BeanShellPostProcessor beanShellPostProcessor;
@JSONField(ordinal = 14) @JSONField(ordinal = 14)
private Boolean enable; private Boolean enable;
@JSONField(ordinal = 15)
private JSR223PreProcessor jsr223PreProcessor;
@JSONField(ordinal = 16)
private JSR223PostProcessor jsr223PostProcessor;
} }

View File

@ -8,6 +8,8 @@ import io.metersphere.api.dto.scenario.assertions.Assertions;
import io.metersphere.api.dto.scenario.extract.Extract; import io.metersphere.api.dto.scenario.extract.Extract;
import io.metersphere.api.dto.scenario.processor.BeanShellPostProcessor; import io.metersphere.api.dto.scenario.processor.BeanShellPostProcessor;
import io.metersphere.api.dto.scenario.processor.BeanShellPreProcessor; import io.metersphere.api.dto.scenario.processor.BeanShellPreProcessor;
import io.metersphere.api.dto.scenario.processor.JSR223PostProcessor;
import io.metersphere.api.dto.scenario.processor.JSR223PreProcessor;
import lombok.Data; import lombok.Data;
import java.util.List; import java.util.List;
@ -47,4 +49,10 @@ public class HttpRequest implements Request {
private Long connectTimeout; private Long connectTimeout;
@JSONField(ordinal = 15) @JSONField(ordinal = 15)
private Long responseTimeout; private Long responseTimeout;
@JSONField(ordinal = 16)
private Boolean followRedirects;
@JSONField(ordinal = 17)
private JSR223PreProcessor jsr223PreProcessor;
@JSONField(ordinal = 18)
private JSR223PostProcessor jsr223PostProcessor;
} }

View File

@ -11,6 +11,8 @@ import org.apache.jmeter.save.SaveService;
import org.apache.jmeter.util.JMeterUtils; import org.apache.jmeter.util.JMeterUtils;
import org.apache.jmeter.visualizers.backend.BackendListener; import org.apache.jmeter.visualizers.backend.BackendListener;
import org.apache.jorphan.collections.HashTree; import org.apache.jorphan.collections.HashTree;
import org.python.core.Options;
import org.springframework.context.i18n.LocaleContextHolder;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import javax.annotation.Resource; import javax.annotation.Resource;
@ -30,6 +32,12 @@ public class JMeterService {
String JMETER_PROPERTIES = JMETER_HOME + "/bin/jmeter.properties"; String JMETER_PROPERTIES = JMETER_HOME + "/bin/jmeter.properties";
JMeterUtils.loadJMeterProperties(JMETER_PROPERTIES); JMeterUtils.loadJMeterProperties(JMETER_PROPERTIES);
JMeterUtils.setJMeterHome(JMETER_HOME); JMeterUtils.setJMeterHome(JMETER_HOME);
JMeterUtils.setLocale(LocaleContextHolder.getLocale());
//解决无法加载 PyScriptEngineFactory
Options.importSite = false;
try { try {
Object scriptWrapper = SaveService.loadElement(is); Object scriptWrapper = SaveService.loadElement(is);
HashTree testPlan = getHashTree(scriptWrapper); HashTree testPlan = getHashTree(scriptWrapper);

View File

@ -157,7 +157,7 @@ public class JmeterDocumentParser {
u += k + "=" + ScriptEngineUtils.calculate(v); u += k + "=" + ScriptEngineUtils.calculate(v);
return u; return u;
}); });
ele.setTextContent(url + params); ele.setTextContent(url + ((params != null && !params.equals("?")) ? params : ""));
break; break;
case "Argument.value": case "Argument.value":
String textContent = ele.getTextContent(); String textContent = ele.getTextContent();

View File

@ -1,8 +1,11 @@
package io.metersphere.excel.utils; package io.metersphere.excel.utils;
import com.alibaba.excel.EasyExcel; import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.write.metadata.style.WriteCellStyle;
import com.alibaba.excel.write.style.HorizontalCellStyleStrategy;
import io.metersphere.commons.utils.LogUtil; import io.metersphere.commons.utils.LogUtil;
import io.metersphere.exception.ExcelException; import io.metersphere.exception.ExcelException;
import org.apache.poi.ss.usermodel.IndexedColors;
import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpServletResponse;
import java.io.IOException; import java.io.IOException;
@ -29,9 +32,12 @@ public class EasyExcelExporter {
public void export(HttpServletResponse response, List data, String fileName, String sheetName) { public void export(HttpServletResponse response, List data, String fileName, String sheetName) {
response.setContentType("application/vnd.ms-excel"); response.setContentType("application/vnd.ms-excel");
response.setCharacterEncoding("utf-8"); response.setCharacterEncoding("utf-8");
WriteCellStyle contentWriteCellStyle = new WriteCellStyle();
contentWriteCellStyle.setWrapped(true);
try { try {
HorizontalCellStyleStrategy horizontalCellStyleStrategy = new HorizontalCellStyleStrategy(null, contentWriteCellStyle);
response.setHeader("Content-disposition", "attachment;filename=" + URLEncoder.encode(fileName, "UTF-8") + ".xlsx"); response.setHeader("Content-disposition", "attachment;filename=" + URLEncoder.encode(fileName, "UTF-8") + ".xlsx");
EasyExcel.write(response.getOutputStream(), this.clazz).sheet(sheetName).doWrite(data); EasyExcel.write(response.getOutputStream(), this.clazz).registerWriteHandler(horizontalCellStyleStrategy).sheet(sheetName).doWrite(data);
} catch (UnsupportedEncodingException e) { } catch (UnsupportedEncodingException e) {
LogUtil.error(e.getMessage(), e); LogUtil.error(e.getMessage(), e);
throw new ExcelException("Utf-8 encoding is not supported"); throw new ExcelException("Utf-8 encoding is not supported");

View File

@ -34,6 +34,7 @@ import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils; import org.springframework.util.CollectionUtils;
import org.springframework.web.multipart.MultipartFile; import org.springframework.web.multipart.MultipartFile;
import javax.annotation.Resource;
import java.io.OutputStream; import java.io.OutputStream;
import java.net.InetSocketAddress; import java.net.InetSocketAddress;
import java.net.Socket; import java.net.Socket;
@ -42,8 +43,6 @@ import java.time.temporal.ChronoUnit;
import java.util.*; import java.util.*;
import java.util.stream.Collectors; import java.util.stream.Collectors;
import javax.annotation.Resource;
@Service @Service
@Transactional(rollbackFor = Exception.class) @Transactional(rollbackFor = Exception.class)
public class PerformanceTestService { public class PerformanceTestService {
@ -381,6 +380,10 @@ public class PerformanceTestService {
if (!CollectionUtils.isEmpty(loadTestFiles)) { if (!CollectionUtils.isEmpty(loadTestFiles)) {
loadTestFiles.forEach(loadTestFile -> { loadTestFiles.forEach(loadTestFile -> {
FileMetadata fileMetadata = fileService.copyFile(loadTestFile.getFileId()); FileMetadata fileMetadata = fileService.copyFile(loadTestFile.getFileId());
if (fileMetadata == null) {
// 如果性能测试出现文件变更这里会有 null
return;
}
loadTestFile.setTestId(copy.getId()); loadTestFile.setTestId(copy.getId());
loadTestFile.setFileId(fileMetadata.getId()); loadTestFile.setFileId(fileMetadata.getId());
loadTestFileMapper.insert(loadTestFile); loadTestFileMapper.insert(loadTestFile);

View File

@ -60,6 +60,10 @@ public class FileService {
FileContentExample example2 = new FileContentExample(); FileContentExample example2 = new FileContentExample();
example2.createCriteria().andFileIdIn(ids); example2.createCriteria().andFileIdIn(ids);
fileContentMapper.deleteByExample(example2); fileContentMapper.deleteByExample(example2);
LoadTestFileExample example3 = new LoadTestFileExample();
example3.createCriteria().andFileIdIn(ids);
loadTestFileMapper.deleteByExample(example3);
} }
public FileMetadata saveFile(MultipartFile file) { public FileMetadata saveFile(MultipartFile file) {

View File

@ -224,6 +224,10 @@ public class IssuesService {
String account = object.getString("account"); String account = object.getString("account");
String password = object.getString("password"); String password = object.getString("password");
String url = object.getString("url"); String url = object.getString("url");
String issuetype = object.getString("issuetype");
if (StringUtils.isBlank(issuetype)) {
MSException.throwException("Jira 问题类型为空");
}
String auth = EncryptUtils.base64Encoding(account + ":" + password); String auth = EncryptUtils.base64Encoding(account + ":" + password);
String testCaseId = issuesRequest.getTestCaseId(); String testCaseId = issuesRequest.getTestCaseId();
@ -252,8 +256,7 @@ public class IssuesService {
" \"summary\":\"" + issuesRequest.getTitle() + "\",\n" + " \"summary\":\"" + issuesRequest.getTitle() + "\",\n" +
" \"description\": " + JSON.toJSONString(desc) + ",\n" + " \"description\": " + JSON.toJSONString(desc) + ",\n" +
" \"issuetype\":{\n" + " \"issuetype\":{\n" +
" \"id\":\"10009\",\n" + " \"name\":\"" + issuetype + "\"\n" +
" \"name\":\"Defect\"\n" +
" }\n" + " }\n" +
" }\n" + " }\n" +
"}"; "}";

View File

@ -0,0 +1,100 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
package org.apache.jmeter.util;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.ListResourceBundle;
import java.util.Locale;
import java.util.Map;
import java.util.Map.Entry;
import java.util.ResourceBundle;
import javax.script.ScriptEngineFactory;
import javax.script.ScriptEngineManager;
import org.apache.jmeter.testbeans.TestBean;
/**
* 解决JSR233加载 ScriptEngineFactory 空指针问题
*/
public abstract class JSR223BeanInfoSupport extends ScriptingBeanInfoSupport {
private static final String[] LANGUAGE_TAGS;
/**
* Will be removed in next version following 3.2
* @deprecated use {@link JSR223BeanInfoSupport#getLanguageNames()}
*/
@Deprecated
public static final String[][] LANGUAGE_NAMES; // NOSONAR Kept for backward compatibility
private static final String[][] CONSTANT_LANGUAGE_NAMES;
static {
Map<String, ScriptEngineFactory> nameMap = new HashMap<>();
ScriptEngineManager sem = new ScriptEngineManager();
final List<ScriptEngineFactory> engineFactories = sem.getEngineFactories();
for(ScriptEngineFactory fact : engineFactories){
List<String> names = fact.getNames();
for(String shortName : names) {
if (shortName != null) {
nameMap.put(shortName.toLowerCase(Locale.ENGLISH), fact);
}
}
}
LANGUAGE_TAGS = nameMap.keySet().toArray(new String[nameMap.size()]);
Arrays.sort(LANGUAGE_TAGS);
CONSTANT_LANGUAGE_NAMES = new String[nameMap.size()][2];
int i = 0;
for(Entry<String, ScriptEngineFactory> me : nameMap.entrySet()) {
final String key = me.getKey();
CONSTANT_LANGUAGE_NAMES[i][0] = key;
final ScriptEngineFactory fact = me.getValue();
CONSTANT_LANGUAGE_NAMES[i++][1] = key +
" (" // $NON-NLS-1$
+ fact.getLanguageName() + " " + fact.getLanguageVersion() // $NON-NLS-1$
+ " / " // $NON-NLS-1$
+ fact.getEngineName() + " " + fact.getEngineVersion() // $NON-NLS-1$
+ ")"; // $NON-NLS-1$
}
LANGUAGE_NAMES = getLanguageNames(); // NOSONAR Kept for backward compatibility
}
private static final ResourceBundle NAME_BUNDLE = new ListResourceBundle() {
@Override
protected Object[][] getContents() {
return CONSTANT_LANGUAGE_NAMES;
}
};
protected JSR223BeanInfoSupport(Class<? extends TestBean> beanClass) {
super(beanClass, LANGUAGE_TAGS, NAME_BUNDLE);
}
/**
* @return String array of 2 columns array containing Script engine short name / Script Language details
*/
public static final String[][] getLanguageNames() {
return CONSTANT_LANGUAGE_NAMES.clone();
}
}

View File

@ -1,4 +1,3 @@
export HEAP=$(cat /proc/meminfo | grep MemTotal | awk '{ mem=int($2/1024/1024 * 3/4 + 0.5); metasize=int(mem/4+0.5)"g"; if(mem<1) mem=1; if (metasize == "0g") metasize="256m"; HEAP="-Xms"mem"g -Xmx"mem"g -XX:MaxMetaspaceSize="metasize; print HEAP }')
for file in ${TESTS_DIR}/*.jmx; do for file in ${TESTS_DIR}/*.jmx; do
jmeter -n -t ${file} -Jserver.rmi.ssl.disable=${SSL_DISABLED} jmeter -n -t ${file} -Jserver.rmi.ssl.disable=${SSL_DISABLED}
done done

View File

@ -1,85 +1,85 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 19.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) --> <!-- Generator: Adobe Illustrator 19.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<svg version="1.1" id="图层_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" <svg version="1.1" id="图层_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
viewBox="947.2 183.1 174 35" style="enable-background:new 947.2 183.1 174 35;" xml:space="preserve"> viewBox="947.2 183.1 174 35" style="enable-background:new 947.2 183.1 174 35;" xml:space="preserve">
<style type="text/css"> <style type="text/css">
.st0{fill:#783887;} .st0{fill:#783887;}
.st1{fill:#622870;} .st1{fill:#622870;}
.st2{fill:#8B489B;} .st2{fill:#8B489B;}
.st3{fill:#FFFFFF;} .st3{fill:#FFFFFF;}
</style> </style>
<g> <g>
<g id="XMLID_803_"> <g id="XMLID_803_">
<path id="XMLID_829_" class="st0" d="M998.3,209.6l-1.1-11.2l-3.1,11.2h-3.6l-3-11.2l-1.1,11.2l-5,0l2.4-16.5h6.3l2.2,7.8l2.2-7.8 <path id="XMLID_829_" class="st0" d="M998.3,209.6l-1.1-11.2l-3.1,11.2h-3.6l-3-11.2l-1.1,11.2l-5,0l2.4-16.5h6.3l2.2,7.8l2.2-7.8
h6.2l2.5,16.5H998.3z"/> h6.2l2.5,16.5H998.3z"/>
<path id="XMLID_826_" class="st0" d="M1015.2,202.7v2.1h-6.5l0,0.4c0,0.8,0.3,1.3,0.8,1.4c0.4,0.1,0.8,0.2,1.3,0.2h0.3 <path id="XMLID_826_" class="st0" d="M1015.2,202.7v2.1h-6.5l0,0.4c0,0.8,0.3,1.3,0.8,1.4c0.4,0.1,0.8,0.2,1.3,0.2h0.3
c1.3,0,3.1-0.3,4.5-0.6h0l-0.5,2.9c0,0-0.6,0.3-1.8,0.5c-0.8,0.1-1.6,0.1-2.6,0.1c-2.6,0-4.2-0.9-4.9-2.6 c1.3,0,3.1-0.3,4.5-0.6h0l-0.5,2.9c0,0-0.6,0.3-1.8,0.5c-0.8,0.1-1.6,0.1-2.6,0.1c-2.6,0-4.2-0.9-4.9-2.6
c-0.3-0.7-0.5-1.4-0.5-2.2v-2.8c0-2.1,1-3.4,2.7-4.1c0.8-0.3,1.6-0.4,2.4-0.4c2.4,0,4,0.8,4.7,2.4 c-0.3-0.7-0.5-1.4-0.5-2.2v-2.8c0-2.1,1-3.4,2.7-4.1c0.8-0.3,1.6-0.4,2.4-0.4c2.4,0,4,0.8,4.7,2.4
C1015.1,200.7,1015.2,201.6,1015.2,202.7z M1011.8,202.1c0-0.8-0.2-1.4-0.6-1.5c-0.3-0.2-0.7-0.2-1-0.2c-1,0-1.4,0.5-1.4,1.4 C1015.1,200.7,1015.2,201.6,1015.2,202.7z M1011.8,202.1c0-0.8-0.2-1.4-0.6-1.5c-0.3-0.2-0.7-0.2-1-0.2c-1,0-1.4,0.5-1.4,1.4
l-0.1,0.6h3.1V202.1z"/> l-0.1,0.6h3.1V202.1z"/>
<path id="XMLID_823_" class="st0" d="M1037.3,202.7v2.1h-6.5l0,0.4c0,0.8,0.3,1.3,0.8,1.4c0.4,0.1,0.8,0.2,1.3,0.2h0.3 <path id="XMLID_823_" class="st0" d="M1037.3,202.7v2.1h-6.5l0,0.4c0,0.8,0.3,1.3,0.8,1.4c0.4,0.1,0.8,0.2,1.3,0.2h0.3
c1.3,0,3.1-0.3,4.5-0.6h0l-0.5,2.9c0,0-0.6,0.3-1.8,0.5c-0.8,0.1-1.6,0.1-2.6,0.1c-2.6,0-4.2-0.9-4.9-2.6 c1.3,0,3.1-0.3,4.5-0.6h0l-0.5,2.9c0,0-0.6,0.3-1.8,0.5c-0.8,0.1-1.6,0.1-2.6,0.1c-2.6,0-4.2-0.9-4.9-2.6
c-0.3-0.7-0.5-1.4-0.5-2.2v-2.8c0-2.1,1-3.4,2.7-4.1c0.8-0.3,1.6-0.4,2.4-0.4c2.4,0,4,0.8,4.7,2.4 c-0.3-0.7-0.5-1.4-0.5-2.2v-2.8c0-2.1,1-3.4,2.7-4.1c0.8-0.3,1.6-0.4,2.4-0.4c2.4,0,4,0.8,4.7,2.4
C1037.2,200.7,1037.3,201.6,1037.3,202.7z M1033.9,202.1c0-0.8-0.2-1.4-0.6-1.5c-0.3-0.2-0.7-0.2-1-0.2c-1,0-1.4,0.5-1.4,1.4 C1037.2,200.7,1037.3,201.6,1037.3,202.7z M1033.9,202.1c0-0.8-0.2-1.4-0.6-1.5c-0.3-0.2-0.7-0.2-1-0.2c-1,0-1.4,0.5-1.4,1.4
l-0.1,0.6h3.1V202.1L1033.9,202.1z"/> l-0.1,0.6h3.1V202.1L1033.9,202.1z"/>
<path id="XMLID_820_" class="st0" d="M1098.2,202.7v2.1h-6.5l0,0.4c0,0.8,0.3,1.3,0.8,1.4c0.4,0.1,0.8,0.2,1.3,0.2h0.3 <path id="XMLID_820_" class="st0" d="M1098.2,202.7v2.1h-6.5l0,0.4c0,0.8,0.3,1.3,0.8,1.4c0.4,0.1,0.8,0.2,1.3,0.2h0.3
c1.3,0,3.1-0.3,4.5-0.6h0l-0.5,2.9c0,0-0.6,0.3-1.8,0.5c-0.8,0.1-1.6,0.1-2.6,0.1c-2.6,0-4.2-0.9-4.9-2.6 c1.3,0,3.1-0.3,4.5-0.6h0l-0.5,2.9c0,0-0.6,0.3-1.8,0.5c-0.8,0.1-1.6,0.1-2.6,0.1c-2.6,0-4.2-0.9-4.9-2.6
c-0.3-0.7-0.5-1.4-0.5-2.2v-2.8c0-2.1,1-3.4,2.7-4.1c0.8-0.3,1.6-0.4,2.4-0.4c2.4,0,4,0.8,4.7,2.4 c-0.3-0.7-0.5-1.4-0.5-2.2v-2.8c0-2.1,1-3.4,2.7-4.1c0.8-0.3,1.6-0.4,2.4-0.4c2.4,0,4,0.8,4.7,2.4
C1098.1,200.7,1098.2,201.6,1098.2,202.7z M1094.8,202.1c0-0.8-0.2-1.4-0.6-1.5c-0.3-0.2-0.7-0.2-1-0.2c-1,0-1.4,0.5-1.4,1.4 C1098.1,200.7,1098.2,201.6,1098.2,202.7z M1094.8,202.1c0-0.8-0.2-1.4-0.6-1.5c-0.3-0.2-0.7-0.2-1-0.2c-1,0-1.4,0.5-1.4,1.4
l-0.1,0.6h3.1V202.1z"/> l-0.1,0.6h3.1V202.1z"/>
<path id="XMLID_817_" class="st0" d="M1120.3,202.7v2.1h-6.5l0,0.4c0,0.8,0.3,1.3,0.8,1.4c0.4,0.1,0.8,0.2,1.3,0.2h0.3 <path id="XMLID_817_" class="st0" d="M1120.3,202.7v2.1h-6.5l0,0.4c0,0.8,0.3,1.3,0.8,1.4c0.4,0.1,0.8,0.2,1.3,0.2h0.3
c1.3,0,3.1-0.3,4.5-0.6h0l-0.5,2.9c0,0-0.6,0.3-1.8,0.5c-0.8,0.1-1.6,0.1-2.6,0.1c-2.6,0-4.2-0.9-4.9-2.6 c1.3,0,3.1-0.3,4.5-0.6h0l-0.5,2.9c0,0-0.6,0.3-1.8,0.5c-0.8,0.1-1.6,0.1-2.6,0.1c-2.6,0-4.2-0.9-4.9-2.6
c-0.3-0.7-0.5-1.4-0.5-2.2v-2.8c0-2.1,1-3.4,2.7-4.1c0.8-0.3,1.6-0.4,2.4-0.4c2.4,0,4,0.8,4.7,2.4 c-0.3-0.7-0.5-1.4-0.5-2.2v-2.8c0-2.1,1-3.4,2.7-4.1c0.8-0.3,1.6-0.4,2.4-0.4c2.4,0,4,0.8,4.7,2.4
C1120.2,200.7,1120.3,201.6,1120.3,202.7z M1116.9,202.1c0-0.8-0.2-1.4-0.6-1.5c-0.3-0.2-0.7-0.2-1-0.2c-1,0-1.4,0.5-1.4,1.4 C1120.2,200.7,1120.3,201.6,1120.3,202.7z M1116.9,202.1c0-0.8-0.2-1.4-0.6-1.5c-0.3-0.2-0.7-0.2-1-0.2c-1,0-1.4,0.5-1.4,1.4
l-0.1,0.6h3.1V202.1z"/> l-0.1,0.6h3.1V202.1z"/>
<path id="XMLID_815_" class="st0" d="M1025.7,209.6h-2.1c-0.4,0-0.7,0-0.9,0c-0.7-0.1-1.3-0.2-1.7-0.4c-0.5-0.3-1-0.7-1.2-1.2 <path id="XMLID_815_" class="st0" d="M1025.7,209.6h-2.1c-0.4,0-0.7,0-0.9,0c-0.7-0.1-1.3-0.2-1.7-0.4c-0.5-0.3-1-0.7-1.2-1.2
c-0.3-0.6-0.5-1.4-0.5-2.5l0-4.6h-1.7v-3h1.7v-2.3l1.7,0l1.8-0.2v2.6h2.7l-0.4,3h-2.3v4.4c0,0.1,0,0.2,0,0.3c0,0.2,0,0.3,0.1,0.5 c-0.3-0.6-0.5-1.4-0.5-2.5l0-4.6h-1.7v-3h1.7v-2.3l1.7,0l1.8-0.2v2.6h2.7l-0.4,3h-2.3v4.4c0,0.1,0,0.2,0,0.3c0,0.2,0,0.3,0.1,0.5
c0.1,0.3,0.3,0.5,0.7,0.6c0.3,0.1,1.9,0.1,1.9,0.1L1025.7,209.6z"/> c0.1,0.3,0.3,0.5,0.7,0.6c0.3,0.1,1.9,0.1,1.9,0.1L1025.7,209.6z"/>
<path id="XMLID_813_" class="st0" d="M1047.7,197.9l-0.1,2.8c-0.3,0-1.2,0-2.1,0.2c-0.8,0.2-1.7,0.6-2.1,0.8v8h-3.5v-11.8h3.3 <path id="XMLID_813_" class="st0" d="M1047.7,197.9l-0.1,2.8c-0.3,0-1.2,0-2.1,0.2c-0.8,0.2-1.7,0.6-2.1,0.8v8h-3.5v-11.8h3.3
c0,0-0.1,0.6,0,0.9l0.8-0.3c0.5-0.2,1-0.3,1.7-0.4C1046.7,197.8,1047.3,197.9,1047.7,197.9z"/> c0,0-0.1,0.6,0,0.9l0.8-0.3c0.5-0.2,1-0.3,1.7-0.4C1046.7,197.8,1047.3,197.9,1047.7,197.9z"/>
<path id="XMLID_811_" class="st0" d="M1108.9,197.9l-0.1,2.8c-0.3,0-1.2,0-2.1,0.2c-0.8,0.2-1.7,0.6-2.1,0.8v8h-3.5v-11.8h3.3 <path id="XMLID_811_" class="st0" d="M1108.9,197.9l-0.1,2.8c-0.3,0-1.2,0-2.1,0.2c-0.8,0.2-1.7,0.6-2.1,0.8v8h-3.5v-11.8h3.3
c0,0-0.1,0.6,0,0.9l0.8-0.3c0.5-0.2,1-0.3,1.7-0.4C1107.9,197.8,1108.5,197.9,1108.9,197.9z"/> c0,0-0.1,0.6,0,0.9l0.8-0.3c0.5-0.2,1-0.3,1.7-0.4C1107.9,197.8,1108.5,197.9,1108.9,197.9z"/>
<path id="XMLID_809_" class="st0" d="M1054.6,210.1c-0.8,0-1.8-0.1-2.7-0.2c-0.4,0-0.8-0.1-1.2-0.2l-1.6-0.2l0-4.1l2.4,0.4 <path id="XMLID_809_" class="st0" d="M1054.6,210.1c-0.8,0-1.8-0.1-2.7-0.2c-0.4,0-0.8-0.1-1.2-0.2l-1.6-0.2l0-4.1l2.4,0.4
c0,0,1,0.1,1.4,0.2c0.5,0.1,1,0.1,1.4,0.1c1.5,0,2.4-0.4,2.7-1.1c0.1-0.3,0.1-0.6,0-0.9c-0.2-0.3-0.5-0.6-0.9-0.8 c0,0,1,0.1,1.4,0.2c0.5,0.1,1,0.1,1.4,0.1c1.5,0,2.4-0.4,2.7-1.1c0.1-0.3,0.1-0.6,0-0.9c-0.2-0.3-0.5-0.6-0.9-0.8
c-0.2-0.1-0.5-0.2-0.8-0.3l-0.9-0.3c-0.4-0.1-0.8-0.2-1.1-0.3c-0.4-0.1-0.8-0.3-1.1-0.4c-0.8-0.4-1.5-0.8-2-1.3 c-0.2-0.1-0.5-0.2-0.8-0.3l-0.9-0.3c-0.4-0.1-0.8-0.2-1.1-0.3c-0.4-0.1-0.8-0.3-1.1-0.4c-0.8-0.4-1.5-0.8-2-1.3
c-0.4-0.5-0.7-1.1-0.9-1.8c-0.1-0.5-0.1-1.1,0-1.7c0.2-1.8,1-3.1,2.3-3.8c0.5-0.3,1.1-0.5,1.8-0.6c0.3,0,0.6-0.1,0.9-0.1l0.9-0.1 c-0.4-0.5-0.7-1.1-0.9-1.8c-0.1-0.5-0.1-1.1,0-1.7c0.2-1.8,1-3.1,2.3-3.8c0.5-0.3,1.1-0.5,1.8-0.6c0.3,0,0.6-0.1,0.9-0.1l0.9-0.1
h0.6c0.7,0,1.5,0,2.3,0.1l1,0.1l1.2,0.2l0,3.6c-0.5-0.1-1-0.2-1.7-0.3c-0.9-0.1-1.7-0.2-2.4-0.2c-1.6,0-2.2,0.3-2.5,1.1 h0.6c0.7,0,1.5,0,2.3,0.1l1,0.1l1.2,0.2l0,3.6c-0.5-0.1-1-0.2-1.7-0.3c-0.9-0.1-1.7-0.2-2.4-0.2c-1.6,0-2.2,0.3-2.5,1.1
c-0.1,0.3-0.1,0.6-0.1,0.9c0,0.4,0,0.5,0.7,0.8c0.2,0.1,0.5,0.2,0.8,0.3l2.1,0.6c0.4,0.1,0.8,0.3,1.1,0.4c0.8,0.3,1.4,0.7,1.8,1.1 c-0.1,0.3-0.1,0.6-0.1,0.9c0,0.4,0,0.5,0.7,0.8c0.2,0.1,0.5,0.2,0.8,0.3l2.1,0.6c0.4,0.1,0.8,0.3,1.1,0.4c0.8,0.3,1.4,0.7,1.8,1.1
c0.5,0.5,0.8,1.1,0.9,1.8c0.1,0.5,0.1,1.1,0,1.7c-0.2,1.8-1.1,3.4-2.4,4.1c-0.5,0.3-1.1,0.5-1.8,0.6c-0.3,0-0.6,0.1-0.9,0.1 c0.5,0.5,0.8,1.1,0.9,1.8c0.1,0.5,0.1,1.1,0,1.7c-0.2,1.8-1.1,3.4-2.4,4.1c-0.5,0.3-1.1,0.5-1.8,0.6c-0.3,0-0.6,0.1-0.9,0.1
l-0.8,0.1L1054.6,210.1L1054.6,210.1z"/> l-0.8,0.1L1054.6,210.1L1054.6,210.1z"/>
<path id="XMLID_806_" class="st0" d="M1063.6,197.8h3.2l-0.1,0.8c0.3-0.2,0.6-0.3,1-0.4c0.4-0.2,0.8-0.3,1.1-0.3 <path id="XMLID_806_" class="st0" d="M1063.6,197.8h3.2l-0.1,0.8c0.3-0.2,0.6-0.3,1-0.4c0.4-0.2,0.8-0.3,1.1-0.3
c0.9-0.2,1.8-0.2,2.7,0.1c0.5,0.2,1,0.5,1.4,1c0.2,0.2,0.3,0.4,0.4,0.6l0.1,0.2c0,0.1,0.1,0.1,0.1,0.2c0.2,0.4,0.3,0.9,0.4,1.4 c0.9-0.2,1.8-0.2,2.7,0.1c0.5,0.2,1,0.5,1.4,1c0.2,0.2,0.3,0.4,0.4,0.6l0.1,0.2c0,0.1,0.1,0.1,0.1,0.2c0.2,0.4,0.3,0.9,0.4,1.4
c0.1,0.6,0.2,1.3,0.2,2.2v0.7c0,1.8-0.1,2.7-0.4,3.4c-0.5,1.1-1.6,1.6-3.7,1.7c-0.3,0-0.7,0-1.2,0l-0.8,0c-0.3,0-0.5,0-0.7,0v5.1 c0.1,0.6,0.2,1.3,0.2,2.2v0.7c0,1.8-0.1,2.7-0.4,3.4c-0.5,1.1-1.6,1.6-3.7,1.7c-0.3,0-0.7,0-1.2,0l-0.8,0c-0.3,0-0.5,0-0.7,0v5.1
l-3.6,0.2V197.8L1063.6,197.8z M1067.2,206.1c0.7,0.1,1.1,0.1,1.7,0.1l0.6-0.1c0.7-0.2,1-0.6,1-1.3v-2.3c0-0.3,0-0.6-0.1-0.7 l-3.6,0.2V197.8L1063.6,197.8z M1067.2,206.1c0.7,0.1,1.1,0.1,1.7,0.1l0.6-0.1c0.7-0.2,1-0.6,1-1.3v-2.3c0-0.3,0-0.6-0.1-0.7
c-0.2-0.7-0.8-1-1.8-0.9l-0.4,0.1l-0.7,0.2l-0.3,0.1L1067.2,206.1L1067.2,206.1z"/> c-0.2-0.7-0.8-1-1.8-0.9l-0.4,0.1l-0.7,0.2l-0.3,0.1L1067.2,206.1L1067.2,206.1z"/>
<path id="XMLID_804_" class="st0" d="M1086.5,203.2v6.4h-3.6v-7c0-0.4-0.3-1.1-0.8-1.4c-0.4-0.2-1-0.2-1.2-0.1 <path id="XMLID_804_" class="st0" d="M1086.5,203.2v6.4h-3.6v-7c0-0.4-0.3-1.1-0.8-1.4c-0.4-0.2-1-0.2-1.2-0.1
c-0.5,0.1-1,0.4-1.3,0.6v7.9h-3.6v-17l3.6,0v6c0.4-0.2,0.9-0.3,1.4-0.4c0.4-0.1,0.8-0.1,1.2-0.1c2.1,0,3.2,0.6,3.7,1.7 c-0.5,0.1-1,0.4-1.3,0.6v7.9h-3.6v-17l3.6,0v6c0.4-0.2,0.9-0.3,1.4-0.4c0.4-0.1,0.8-0.1,1.2-0.1c2.1,0,3.2,0.6,3.7,1.7
C1086.2,200.2,1086.5,201.4,1086.5,203.2z"/> C1086.2,200.2,1086.5,201.4,1086.5,203.2z"/>
</g> </g>
<g id="XMLID_799_"> <g id="XMLID_799_">
<path id="XMLID_800_" class="st0" d="M961.7,184.4l13.7,8v16.1l-13.7,8l-13.7-8v-16.1L961.7,184.4 M961.7,183.9l-14.1,8.3v16.5 <path id="XMLID_800_" class="st0" d="M961.7,184.4l13.7,8v16.1l-13.7,8l-13.7-8v-16.1L961.7,184.4 M961.7,183.9l-14.1,8.3v16.5
l14.1,8.3l14.1-8.3v-16.5L961.7,183.9L961.7,183.9z"/> l14.1,8.3l14.1-8.3v-16.5L961.7,183.9L961.7,183.9z"/>
</g> </g>
<g id="XMLID_796_"> <g id="XMLID_796_">
<polygon id="XMLID_64_" class="st1" points="961.9,200.6 973.8,193.6 973.8,207.5 961.9,214.5 "/> <polygon id="XMLID_64_" class="st1" points="961.9,200.6 973.8,193.6 973.8,207.5 961.9,214.5 "/>
</g> </g>
<polygon id="XMLID_795_" class="st2" points="949.8,193.2 961.7,186.3 973.6,193.2 961.7,200.2 "/> <polygon id="XMLID_795_" class="st2" points="949.8,193.2 961.7,186.3 973.6,193.2 961.7,200.2 "/>
<g id="XMLID_792_"> <g id="XMLID_792_">
<polygon id="XMLID_65_" class="st0" points="949.6,207.5 949.6,193.6 961.5,200.6 961.5,214.5 "/> <polygon id="XMLID_65_" class="st0" points="949.6,207.5 949.6,193.6 961.5,200.6 961.5,214.5 "/>
</g> </g>
<g id="XMLID_789_"> <g id="XMLID_789_">
<path id="XMLID_790_" class="st3" d="M957.8,209.4v-4.9l-1.8,3.9l-1.5-0.9l-0.8-5.4l-0.9,4.3l-2.1-1.3l1.7-6.2l2.6,1.6l0.6,3.8 <path id="XMLID_790_" class="st3" d="M957.8,209.4v-4.9l-1.8,3.9l-1.5-0.9l-0.8-5.4l-0.9,4.3l-2.1-1.3l1.7-6.2l2.6,1.6l0.6,3.8
l1.2-2.7l2.6,1.5l0.4,7.5L957.8,209.4z"/> l1.2-2.7l2.6,1.5l0.4,7.5L957.8,209.4z"/>
</g> </g>
<g id="XMLID_786_"> <g id="XMLID_786_">
<path id="XMLID_787_" class="st3" d="M968,209.1c-0.4,0.2-0.9,0.3-1.4,0.5c-0.2,0.1-0.4,0.1-0.6,0.2l-0.8,0.2l0-2l1.2-0.3 <path id="XMLID_787_" class="st3" d="M968,209.1c-0.4,0.2-0.9,0.3-1.4,0.5c-0.2,0.1-0.4,0.1-0.6,0.2l-0.8,0.2l0-2l1.2-0.3
c0,0,0.5-0.1,0.7-0.2c0.3-0.1,0.5-0.2,0.7-0.3c0.8-0.3,1.2-0.7,1.3-1.1c0.1-0.2,0.1-0.3,0-0.4c-0.1-0.1-0.2-0.2-0.5-0.2 c0,0,0.5-0.1,0.7-0.2c0.3-0.1,0.5-0.2,0.7-0.3c0.8-0.3,1.2-0.7,1.3-1.1c0.1-0.2,0.1-0.3,0-0.4c-0.1-0.1-0.2-0.2-0.5-0.2
c-0.1,0-0.2,0-0.4,0l-0.5,0c-0.2,0-0.4,0.1-0.5,0.1c-0.2,0-0.4,0-0.6,0c-0.4,0-0.8-0.1-1-0.2c-0.2-0.1-0.4-0.4-0.5-0.7 c-0.1,0-0.2,0-0.4,0l-0.5,0c-0.2,0-0.4,0.1-0.5,0.1c-0.2,0-0.4,0-0.6,0c-0.4,0-0.8-0.1-1-0.2c-0.2-0.1-0.4-0.4-0.5-0.7
c-0.1-0.2-0.1-0.5,0-0.8c0.1-0.9,0.4-1.7,1.1-2.3c0.3-0.2,0.5-0.5,0.9-0.7c0.1-0.1,0.3-0.2,0.5-0.2l0.5-0.2l0.3-0.1 c-0.1-0.2-0.1-0.5,0-0.8c0.1-0.9,0.4-1.7,1.1-2.3c0.3-0.2,0.5-0.5,0.9-0.7c0.1-0.1,0.3-0.2,0.5-0.2l0.5-0.2l0.3-0.1
c0.4-0.1,0.7-0.3,1.2-0.4l0.5-0.2l0.6-0.2l0.1,1.8c-0.2,0-0.5,0.1-0.9,0.2c-0.4,0.1-0.9,0.3-1.2,0.4c-0.8,0.3-1.1,0.6-1.2,1 c0.4-0.1,0.7-0.3,1.2-0.4l0.5-0.2l0.6-0.2l0.1,1.8c-0.2,0-0.5,0.1-0.9,0.2c-0.4,0.1-0.9,0.3-1.2,0.4c-0.8,0.3-1.1,0.6-1.2,1
c0,0.2,0,0.3,0,0.5c0,0.2,0,0.2,0.4,0.3c0.1,0,0.3,0,0.4,0l1.1-0.1c0.2,0,0.4,0,0.5,0c0.4,0,0.7,0.1,0.9,0.2 c0,0.2,0,0.3,0,0.5c0,0.2,0,0.2,0.4,0.3c0.1,0,0.3,0,0.4,0l1.1-0.1c0.2,0,0.4,0,0.5,0c0.4,0,0.7,0.1,0.9,0.2
c0.2,0.1,0.4,0.4,0.5,0.7c0.1,0.2,0.1,0.5,0,0.8c-0.1,0.9-0.5,1.9-1.1,2.5c-0.2,0.2-0.5,0.5-0.9,0.7c-0.1,0.1-0.3,0.2-0.5,0.2 c0.2,0.1,0.4,0.4,0.5,0.7c0.1,0.2,0.1,0.5,0,0.8c-0.1,0.9-0.5,1.9-1.1,2.5c-0.2,0.2-0.5,0.5-0.9,0.7c-0.1,0.1-0.3,0.2-0.5,0.2
l-0.4,0.2L968,209.1z"/> l-0.4,0.2L968,209.1z"/>
</g> </g>
</g> </g>
</svg> </svg>

Before

Width:  |  Height:  |  Size: 6.6 KiB

After

Width:  |  Height:  |  Size: 6.6 KiB

View File

@ -1,80 +1,80 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 19.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) --> <!-- Generator: Adobe Illustrator 19.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<svg version="1.1" id="图层_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" <svg version="1.1" id="图层_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
viewBox="947.2 183.1 174 35" style="enable-background:new 947.2 183.1 174 35;" xml:space="preserve"> viewBox="947.2 183.1 174 35" style="enable-background:new 947.2 183.1 174 35;" xml:space="preserve">
<style type="text/css"> <style type="text/css">
.st0{fill:#FFFFFF;} .st0{fill:#FFFFFF;}
</style> </style>
<g> <g>
<g id="XMLID_140_"> <g id="XMLID_140_">
<path id="XMLID_166_" class="st0" d="M998.3,209.6l-1.1-11.2l-3.1,11.2h-3.6l-3-11.2l-1.1,11.2l-5,0l2.4-16.5h6.3l2.2,7.8l2.2-7.8 <path id="XMLID_166_" class="st0" d="M998.3,209.6l-1.1-11.2l-3.1,11.2h-3.6l-3-11.2l-1.1,11.2l-5,0l2.4-16.5h6.3l2.2,7.8l2.2-7.8
h6.2l2.5,16.5H998.3z"/> h6.2l2.5,16.5H998.3z"/>
<path id="XMLID_163_" class="st0" d="M1015.2,202.7v2.1h-6.5l0,0.4c0,0.8,0.3,1.3,0.8,1.4c0.4,0.1,0.8,0.2,1.3,0.2h0.3 <path id="XMLID_163_" class="st0" d="M1015.2,202.7v2.1h-6.5l0,0.4c0,0.8,0.3,1.3,0.8,1.4c0.4,0.1,0.8,0.2,1.3,0.2h0.3
c1.3,0,3.1-0.3,4.5-0.6h0l-0.5,2.9c0,0-0.6,0.3-1.8,0.5c-0.8,0.1-1.6,0.1-2.6,0.1c-2.6,0-4.2-0.9-4.9-2.6 c1.3,0,3.1-0.3,4.5-0.6h0l-0.5,2.9c0,0-0.6,0.3-1.8,0.5c-0.8,0.1-1.6,0.1-2.6,0.1c-2.6,0-4.2-0.9-4.9-2.6
c-0.3-0.7-0.5-1.4-0.5-2.2v-2.8c0-2.1,1-3.4,2.7-4.1c0.8-0.3,1.6-0.4,2.4-0.4c2.4,0,4,0.8,4.7,2.4 c-0.3-0.7-0.5-1.4-0.5-2.2v-2.8c0-2.1,1-3.4,2.7-4.1c0.8-0.3,1.6-0.4,2.4-0.4c2.4,0,4,0.8,4.7,2.4
C1015.1,200.7,1015.2,201.6,1015.2,202.7z M1011.8,202.1c0-0.8-0.2-1.4-0.6-1.5c-0.3-0.2-0.7-0.2-1-0.2c-1,0-1.4,0.5-1.4,1.4 C1015.1,200.7,1015.2,201.6,1015.2,202.7z M1011.8,202.1c0-0.8-0.2-1.4-0.6-1.5c-0.3-0.2-0.7-0.2-1-0.2c-1,0-1.4,0.5-1.4,1.4
l-0.1,0.6h3.1V202.1z"/> l-0.1,0.6h3.1V202.1z"/>
<path id="XMLID_160_" class="st0" d="M1037.3,202.7v2.1h-6.5l0,0.4c0,0.8,0.3,1.3,0.8,1.4c0.4,0.1,0.8,0.2,1.3,0.2h0.3 <path id="XMLID_160_" class="st0" d="M1037.3,202.7v2.1h-6.5l0,0.4c0,0.8,0.3,1.3,0.8,1.4c0.4,0.1,0.8,0.2,1.3,0.2h0.3
c1.3,0,3.1-0.3,4.5-0.6h0l-0.5,2.9c0,0-0.6,0.3-1.8,0.5c-0.8,0.1-1.6,0.1-2.6,0.1c-2.6,0-4.2-0.9-4.9-2.6 c1.3,0,3.1-0.3,4.5-0.6h0l-0.5,2.9c0,0-0.6,0.3-1.8,0.5c-0.8,0.1-1.6,0.1-2.6,0.1c-2.6,0-4.2-0.9-4.9-2.6
c-0.3-0.7-0.5-1.4-0.5-2.2v-2.8c0-2.1,1-3.4,2.7-4.1c0.8-0.3,1.6-0.4,2.4-0.4c2.4,0,4,0.8,4.7,2.4 c-0.3-0.7-0.5-1.4-0.5-2.2v-2.8c0-2.1,1-3.4,2.7-4.1c0.8-0.3,1.6-0.4,2.4-0.4c2.4,0,4,0.8,4.7,2.4
C1037.2,200.7,1037.3,201.6,1037.3,202.7z M1033.9,202.1c0-0.8-0.2-1.4-0.6-1.5c-0.3-0.2-0.7-0.2-1-0.2c-1,0-1.4,0.5-1.4,1.4 C1037.2,200.7,1037.3,201.6,1037.3,202.7z M1033.9,202.1c0-0.8-0.2-1.4-0.6-1.5c-0.3-0.2-0.7-0.2-1-0.2c-1,0-1.4,0.5-1.4,1.4
l-0.1,0.6h3.1V202.1L1033.9,202.1z"/> l-0.1,0.6h3.1V202.1L1033.9,202.1z"/>
<path id="XMLID_157_" class="st0" d="M1098.2,202.7v2.1h-6.5l0,0.4c0,0.8,0.3,1.3,0.8,1.4c0.4,0.1,0.8,0.2,1.3,0.2h0.3 <path id="XMLID_157_" class="st0" d="M1098.2,202.7v2.1h-6.5l0,0.4c0,0.8,0.3,1.3,0.8,1.4c0.4,0.1,0.8,0.2,1.3,0.2h0.3
c1.3,0,3.1-0.3,4.5-0.6h0l-0.5,2.9c0,0-0.6,0.3-1.8,0.5c-0.8,0.1-1.6,0.1-2.6,0.1c-2.6,0-4.2-0.9-4.9-2.6 c1.3,0,3.1-0.3,4.5-0.6h0l-0.5,2.9c0,0-0.6,0.3-1.8,0.5c-0.8,0.1-1.6,0.1-2.6,0.1c-2.6,0-4.2-0.9-4.9-2.6
c-0.3-0.7-0.5-1.4-0.5-2.2v-2.8c0-2.1,1-3.4,2.7-4.1c0.8-0.3,1.6-0.4,2.4-0.4c2.4,0,4,0.8,4.7,2.4 c-0.3-0.7-0.5-1.4-0.5-2.2v-2.8c0-2.1,1-3.4,2.7-4.1c0.8-0.3,1.6-0.4,2.4-0.4c2.4,0,4,0.8,4.7,2.4
C1098.1,200.7,1098.2,201.6,1098.2,202.7z M1094.8,202.1c0-0.8-0.2-1.4-0.6-1.5c-0.3-0.2-0.7-0.2-1-0.2c-1,0-1.4,0.5-1.4,1.4 C1098.1,200.7,1098.2,201.6,1098.2,202.7z M1094.8,202.1c0-0.8-0.2-1.4-0.6-1.5c-0.3-0.2-0.7-0.2-1-0.2c-1,0-1.4,0.5-1.4,1.4
l-0.1,0.6h3.1V202.1z"/> l-0.1,0.6h3.1V202.1z"/>
<path id="XMLID_154_" class="st0" d="M1120.3,202.7v2.1h-6.5l0,0.4c0,0.8,0.3,1.3,0.8,1.4c0.4,0.1,0.8,0.2,1.3,0.2h0.3 <path id="XMLID_154_" class="st0" d="M1120.3,202.7v2.1h-6.5l0,0.4c0,0.8,0.3,1.3,0.8,1.4c0.4,0.1,0.8,0.2,1.3,0.2h0.3
c1.3,0,3.1-0.3,4.5-0.6h0l-0.5,2.9c0,0-0.6,0.3-1.8,0.5c-0.8,0.1-1.6,0.1-2.6,0.1c-2.6,0-4.2-0.9-4.9-2.6 c1.3,0,3.1-0.3,4.5-0.6h0l-0.5,2.9c0,0-0.6,0.3-1.8,0.5c-0.8,0.1-1.6,0.1-2.6,0.1c-2.6,0-4.2-0.9-4.9-2.6
c-0.3-0.7-0.5-1.4-0.5-2.2v-2.8c0-2.1,1-3.4,2.7-4.1c0.8-0.3,1.6-0.4,2.4-0.4c2.4,0,4,0.8,4.7,2.4 c-0.3-0.7-0.5-1.4-0.5-2.2v-2.8c0-2.1,1-3.4,2.7-4.1c0.8-0.3,1.6-0.4,2.4-0.4c2.4,0,4,0.8,4.7,2.4
C1120.2,200.7,1120.3,201.6,1120.3,202.7z M1116.9,202.1c0-0.8-0.2-1.4-0.6-1.5c-0.3-0.2-0.7-0.2-1-0.2c-1,0-1.4,0.5-1.4,1.4 C1120.2,200.7,1120.3,201.6,1120.3,202.7z M1116.9,202.1c0-0.8-0.2-1.4-0.6-1.5c-0.3-0.2-0.7-0.2-1-0.2c-1,0-1.4,0.5-1.4,1.4
l-0.1,0.6h3.1V202.1z"/> l-0.1,0.6h3.1V202.1z"/>
<path id="XMLID_152_" class="st0" d="M1025.7,209.6h-2.1c-0.4,0-0.7,0-0.9,0c-0.7-0.1-1.3-0.2-1.7-0.4c-0.5-0.3-1-0.7-1.2-1.2 <path id="XMLID_152_" class="st0" d="M1025.7,209.6h-2.1c-0.4,0-0.7,0-0.9,0c-0.7-0.1-1.3-0.2-1.7-0.4c-0.5-0.3-1-0.7-1.2-1.2
c-0.3-0.6-0.5-1.4-0.5-2.5l0-4.6h-1.7v-3h1.7v-2.3l1.7,0l1.8-0.2v2.6h2.7l-0.4,3h-2.3v4.4c0,0.1,0,0.2,0,0.3c0,0.2,0,0.3,0.1,0.5 c-0.3-0.6-0.5-1.4-0.5-2.5l0-4.6h-1.7v-3h1.7v-2.3l1.7,0l1.8-0.2v2.6h2.7l-0.4,3h-2.3v4.4c0,0.1,0,0.2,0,0.3c0,0.2,0,0.3,0.1,0.5
c0.1,0.3,0.3,0.5,0.7,0.6c0.3,0.1,1.9,0.1,1.9,0.1L1025.7,209.6z"/> c0.1,0.3,0.3,0.5,0.7,0.6c0.3,0.1,1.9,0.1,1.9,0.1L1025.7,209.6z"/>
<path id="XMLID_150_" class="st0" d="M1047.7,197.9l-0.1,2.8c-0.3,0-1.2,0-2.1,0.2c-0.8,0.2-1.7,0.6-2.1,0.8v8h-3.5v-11.8h3.3 <path id="XMLID_150_" class="st0" d="M1047.7,197.9l-0.1,2.8c-0.3,0-1.2,0-2.1,0.2c-0.8,0.2-1.7,0.6-2.1,0.8v8h-3.5v-11.8h3.3
c0,0-0.1,0.6,0,0.9l0.8-0.3c0.5-0.2,1-0.3,1.7-0.4C1046.7,197.8,1047.3,197.9,1047.7,197.9z"/> c0,0-0.1,0.6,0,0.9l0.8-0.3c0.5-0.2,1-0.3,1.7-0.4C1046.7,197.8,1047.3,197.9,1047.7,197.9z"/>
<path id="XMLID_148_" class="st0" d="M1108.9,197.9l-0.1,2.8c-0.3,0-1.2,0-2.1,0.2c-0.8,0.2-1.7,0.6-2.1,0.8v8h-3.5v-11.8h3.3 <path id="XMLID_148_" class="st0" d="M1108.9,197.9l-0.1,2.8c-0.3,0-1.2,0-2.1,0.2c-0.8,0.2-1.7,0.6-2.1,0.8v8h-3.5v-11.8h3.3
c0,0-0.1,0.6,0,0.9l0.8-0.3c0.5-0.2,1-0.3,1.7-0.4C1107.9,197.8,1108.5,197.9,1108.9,197.9z"/> c0,0-0.1,0.6,0,0.9l0.8-0.3c0.5-0.2,1-0.3,1.7-0.4C1107.9,197.8,1108.5,197.9,1108.9,197.9z"/>
<path id="XMLID_146_" class="st0" d="M1054.6,210.1c-0.8,0-1.8-0.1-2.7-0.2c-0.4,0-0.8-0.1-1.2-0.2l-1.6-0.2l0-4.1l2.4,0.4 <path id="XMLID_146_" class="st0" d="M1054.6,210.1c-0.8,0-1.8-0.1-2.7-0.2c-0.4,0-0.8-0.1-1.2-0.2l-1.6-0.2l0-4.1l2.4,0.4
c0,0,1,0.1,1.4,0.2c0.5,0.1,1,0.1,1.4,0.1c1.5,0,2.4-0.4,2.7-1.1c0.1-0.3,0.1-0.6,0-0.9c-0.2-0.3-0.5-0.6-0.9-0.8 c0,0,1,0.1,1.4,0.2c0.5,0.1,1,0.1,1.4,0.1c1.5,0,2.4-0.4,2.7-1.1c0.1-0.3,0.1-0.6,0-0.9c-0.2-0.3-0.5-0.6-0.9-0.8
c-0.2-0.1-0.5-0.2-0.8-0.3l-0.9-0.3c-0.4-0.1-0.8-0.2-1.1-0.3c-0.4-0.1-0.8-0.3-1.1-0.4c-0.8-0.4-1.5-0.8-2-1.3 c-0.2-0.1-0.5-0.2-0.8-0.3l-0.9-0.3c-0.4-0.1-0.8-0.2-1.1-0.3c-0.4-0.1-0.8-0.3-1.1-0.4c-0.8-0.4-1.5-0.8-2-1.3
c-0.4-0.5-0.7-1.1-0.9-1.8c-0.1-0.5-0.1-1.1,0-1.7c0.2-1.8,1-3.1,2.3-3.8c0.5-0.3,1.1-0.5,1.8-0.6c0.3,0,0.6-0.1,0.9-0.1l0.9-0.1 c-0.4-0.5-0.7-1.1-0.9-1.8c-0.1-0.5-0.1-1.1,0-1.7c0.2-1.8,1-3.1,2.3-3.8c0.5-0.3,1.1-0.5,1.8-0.6c0.3,0,0.6-0.1,0.9-0.1l0.9-0.1
h0.6c0.7,0,1.5,0,2.3,0.1l1,0.1l1.2,0.2l0,3.6c-0.5-0.1-1-0.2-1.7-0.3c-0.9-0.1-1.7-0.2-2.4-0.2c-1.6,0-2.2,0.3-2.5,1.1 h0.6c0.7,0,1.5,0,2.3,0.1l1,0.1l1.2,0.2l0,3.6c-0.5-0.1-1-0.2-1.7-0.3c-0.9-0.1-1.7-0.2-2.4-0.2c-1.6,0-2.2,0.3-2.5,1.1
c-0.1,0.3-0.1,0.6-0.1,0.9c0,0.4,0,0.5,0.7,0.8c0.2,0.1,0.5,0.2,0.8,0.3l2.1,0.6c0.4,0.1,0.8,0.3,1.1,0.4c0.8,0.3,1.4,0.7,1.8,1.1 c-0.1,0.3-0.1,0.6-0.1,0.9c0,0.4,0,0.5,0.7,0.8c0.2,0.1,0.5,0.2,0.8,0.3l2.1,0.6c0.4,0.1,0.8,0.3,1.1,0.4c0.8,0.3,1.4,0.7,1.8,1.1
c0.5,0.5,0.8,1.1,0.9,1.8c0.1,0.5,0.1,1.1,0,1.7c-0.2,1.8-1.1,3.4-2.4,4.1c-0.5,0.3-1.1,0.5-1.8,0.6c-0.3,0-0.6,0.1-0.9,0.1 c0.5,0.5,0.8,1.1,0.9,1.8c0.1,0.5,0.1,1.1,0,1.7c-0.2,1.8-1.1,3.4-2.4,4.1c-0.5,0.3-1.1,0.5-1.8,0.6c-0.3,0-0.6,0.1-0.9,0.1
l-0.8,0.1L1054.6,210.1L1054.6,210.1z"/> l-0.8,0.1L1054.6,210.1L1054.6,210.1z"/>
<path id="XMLID_143_" class="st0" d="M1063.6,197.8h3.2l-0.1,0.8c0.3-0.2,0.6-0.3,1-0.4c0.4-0.2,0.8-0.3,1.1-0.3 <path id="XMLID_143_" class="st0" d="M1063.6,197.8h3.2l-0.1,0.8c0.3-0.2,0.6-0.3,1-0.4c0.4-0.2,0.8-0.3,1.1-0.3
c0.9-0.2,1.8-0.2,2.7,0.1c0.5,0.2,1,0.5,1.4,1c0.2,0.2,0.3,0.4,0.4,0.6l0.1,0.2c0,0.1,0.1,0.1,0.1,0.2c0.2,0.4,0.3,0.9,0.4,1.4 c0.9-0.2,1.8-0.2,2.7,0.1c0.5,0.2,1,0.5,1.4,1c0.2,0.2,0.3,0.4,0.4,0.6l0.1,0.2c0,0.1,0.1,0.1,0.1,0.2c0.2,0.4,0.3,0.9,0.4,1.4
c0.1,0.6,0.2,1.3,0.2,2.2v0.7c0,1.8-0.1,2.7-0.4,3.4c-0.5,1.1-1.6,1.6-3.7,1.7c-0.3,0-0.7,0-1.2,0l-0.8,0c-0.3,0-0.5,0-0.7,0v5.1 c0.1,0.6,0.2,1.3,0.2,2.2v0.7c0,1.8-0.1,2.7-0.4,3.4c-0.5,1.1-1.6,1.6-3.7,1.7c-0.3,0-0.7,0-1.2,0l-0.8,0c-0.3,0-0.5,0-0.7,0v5.1
l-3.6,0.2V197.8L1063.6,197.8z M1067.2,206.1c0.7,0.1,1.1,0.1,1.7,0.1l0.6-0.1c0.7-0.2,1-0.6,1-1.3v-2.3c0-0.3,0-0.6-0.1-0.7 l-3.6,0.2V197.8L1063.6,197.8z M1067.2,206.1c0.7,0.1,1.1,0.1,1.7,0.1l0.6-0.1c0.7-0.2,1-0.6,1-1.3v-2.3c0-0.3,0-0.6-0.1-0.7
c-0.2-0.7-0.8-1-1.8-0.9l-0.4,0.1l-0.7,0.2l-0.3,0.1L1067.2,206.1L1067.2,206.1z"/> c-0.2-0.7-0.8-1-1.8-0.9l-0.4,0.1l-0.7,0.2l-0.3,0.1L1067.2,206.1L1067.2,206.1z"/>
<path id="XMLID_141_" class="st0" d="M1086.5,203.2v6.4h-3.6v-7c0-0.4-0.3-1.1-0.8-1.4c-0.4-0.2-1-0.2-1.2-0.1 <path id="XMLID_141_" class="st0" d="M1086.5,203.2v6.4h-3.6v-7c0-0.4-0.3-1.1-0.8-1.4c-0.4-0.2-1-0.2-1.2-0.1
c-0.5,0.1-1,0.4-1.3,0.6v7.9h-3.6v-17l3.6,0v6c0.4-0.2,0.9-0.3,1.4-0.4c0.4-0.1,0.8-0.1,1.2-0.1c2.1,0,3.2,0.6,3.7,1.7 c-0.5,0.1-1,0.4-1.3,0.6v7.9h-3.6v-17l3.6,0v6c0.4-0.2,0.9-0.3,1.4-0.4c0.4-0.1,0.8-0.1,1.2-0.1c2.1,0,3.2,0.6,3.7,1.7
C1086.2,200.2,1086.5,201.4,1086.5,203.2z"/> C1086.2,200.2,1086.5,201.4,1086.5,203.2z"/>
</g> </g>
<g id="XMLID_136_"> <g id="XMLID_136_">
<path id="XMLID_137_" class="st0" d="M961.7,184.4l13.7,8v16.1l-13.7,8l-13.7-8v-16.1L961.7,184.4 M961.7,183.9l-14.1,8.3v16.5 <path id="XMLID_137_" class="st0" d="M961.7,184.4l13.7,8v16.1l-13.7,8l-13.7-8v-16.1L961.7,184.4 M961.7,183.9l-14.1,8.3v16.5
l14.1,8.3l14.1-8.3v-16.5L961.7,183.9L961.7,183.9z"/> l14.1,8.3l14.1-8.3v-16.5L961.7,183.9L961.7,183.9z"/>
</g> </g>
<polygon id="XMLID_132_" class="st0" points="949.8,193.2 961.7,186.3 973.6,193.2 961.7,200.2 "/> <polygon id="XMLID_132_" class="st0" points="949.8,193.2 961.7,186.3 973.6,193.2 961.7,200.2 "/>
<g id="XMLID_278_"> <g id="XMLID_278_">
<g id="XMLID_42_"> <g id="XMLID_42_">
<path id="XMLID_43_" class="st0" d="M949.6,193.6v13.9l11.9,6.9v-13.9L949.6,193.6z M957.8,209.4v-4.9l-1.8,3.9l-1.5-0.9 <path id="XMLID_43_" class="st0" d="M949.6,193.6v13.9l11.9,6.9v-13.9L949.6,193.6z M957.8,209.4v-4.9l-1.8,3.9l-1.5-0.9
l-0.8-5.4l-0.9,4.3l-2.1-1.3l1.7-6.2l2.6,1.6l0.6,3.8l1.2-2.7l2.6,1.5l0.4,7.5L957.8,209.4z"/> l-0.8-5.4l-0.9,4.3l-2.1-1.3l1.7-6.2l2.6,1.6l0.6,3.8l1.2-2.7l2.6,1.5l0.4,7.5L957.8,209.4z"/>
</g> </g>
</g> </g>
<g id="XMLID_129_"> <g id="XMLID_129_">
<g id="XMLID_37_"> <g id="XMLID_37_">
<path id="XMLID_38_" class="st0" d="M961.9,200.6v13.9l11.9-6.9v-13.9L961.9,200.6z M971.3,205.3c-0.1,0.9-0.5,1.9-1.1,2.5 <path id="XMLID_38_" class="st0" d="M961.9,200.6v13.9l11.9-6.9v-13.9L961.9,200.6z M971.3,205.3c-0.1,0.9-0.5,1.9-1.1,2.5
c-0.2,0.2-0.5,0.5-0.9,0.7c-0.1,0.1-0.3,0.2-0.5,0.2l-0.4,0.2l-0.3,0.1c-0.4,0.2-0.9,0.3-1.4,0.5c-0.2,0.1-0.4,0.1-0.6,0.2 c-0.2,0.2-0.5,0.5-0.9,0.7c-0.1,0.1-0.3,0.2-0.5,0.2l-0.4,0.2l-0.3,0.1c-0.4,0.2-0.9,0.3-1.4,0.5c-0.2,0.1-0.4,0.1-0.6,0.2
l-0.8,0.2l0-2l1.2-0.3c0,0,0.5-0.1,0.7-0.2c0.3-0.1,0.5-0.2,0.7-0.3c0.8-0.3,1.2-0.7,1.3-1.1c0.1-0.2,0.1-0.3,0-0.4 l-0.8,0.2l0-2l1.2-0.3c0,0,0.5-0.1,0.7-0.2c0.3-0.1,0.5-0.2,0.7-0.3c0.8-0.3,1.2-0.7,1.3-1.1c0.1-0.2,0.1-0.3,0-0.4
c-0.1-0.1-0.2-0.2-0.5-0.2c-0.1,0-0.2,0-0.4,0l-0.5,0c-0.2,0-0.4,0.1-0.5,0.1c-0.2,0-0.4,0-0.6,0c-0.4,0-0.8-0.1-1-0.2 c-0.1-0.1-0.2-0.2-0.5-0.2c-0.1,0-0.2,0-0.4,0l-0.5,0c-0.2,0-0.4,0.1-0.5,0.1c-0.2,0-0.4,0-0.6,0c-0.4,0-0.8-0.1-1-0.2
c-0.2-0.1-0.4-0.4-0.5-0.7c-0.1-0.2-0.1-0.5,0-0.8c0.1-0.9,0.4-1.7,1.1-2.3c0.3-0.2,0.5-0.5,0.9-0.7c0.1-0.1,0.3-0.2,0.5-0.2 c-0.2-0.1-0.4-0.4-0.5-0.7c-0.1-0.2-0.1-0.5,0-0.8c0.1-0.9,0.4-1.7,1.1-2.3c0.3-0.2,0.5-0.5,0.9-0.7c0.1-0.1,0.3-0.2,0.5-0.2
l0.5-0.2l0.3-0.1c0.4-0.1,0.7-0.3,1.2-0.4l0.5-0.2l0.6-0.2l0.1,1.8c-0.2,0-0.5,0.1-0.9,0.2c-0.4,0.1-0.9,0.3-1.2,0.4 l0.5-0.2l0.3-0.1c0.4-0.1,0.7-0.3,1.2-0.4l0.5-0.2l0.6-0.2l0.1,1.8c-0.2,0-0.5,0.1-0.9,0.2c-0.4,0.1-0.9,0.3-1.2,0.4
c-0.8,0.3-1.1,0.6-1.2,1c0,0.2,0,0.3,0,0.5c0,0.2,0,0.2,0.4,0.3c0.1,0,0.3,0,0.4,0l1.1-0.1c0.2,0,0.4,0,0.5,0 c-0.8,0.3-1.1,0.6-1.2,1c0,0.2,0,0.3,0,0.5c0,0.2,0,0.2,0.4,0.3c0.1,0,0.3,0,0.4,0l1.1-0.1c0.2,0,0.4,0,0.5,0
c0.4,0,0.7,0.1,0.9,0.2c0.2,0.1,0.4,0.4,0.5,0.7C971.3,204.7,971.3,205,971.3,205.3z"/> c0.4,0,0.7,0.1,0.9,0.2c0.2,0.1,0.4,0.4,0.5,0.7C971.3,204.7,971.3,205,971.3,205.3z"/>
</g> </g>
</g> </g>
</g> </g>
</svg> </svg>

Before

Width:  |  Height:  |  Size: 6.5 KiB

After

Width:  |  Height:  |  Size: 6.4 KiB

View File

@ -171,7 +171,7 @@ export default {
<style scoped> <style scoped>
.report-container { .report-container {
height: calc(100vh - 150px); height: calc(100vh - 155px);
min-height: 600px; min-height: 600px;
overflow-y: auto; overflow-y: auto;
} }

View File

@ -344,7 +344,7 @@ export default {
<style scoped> <style scoped>
.test-container { .test-container {
height: calc(100vh - 150px); height: calc(100vh - 155px);
min-height: 600px; min-height: 600px;
} }

View File

@ -17,7 +17,7 @@
<el-table border :data="tableData" class="adjust-table table-content" @sort-change="sort" <el-table border :data="tableData" class="adjust-table table-content" @sort-change="sort"
@row-click="handleView" @row-click="handleView"
@filter-change="filter" @select-all="handleSelectAll" @select="selectionChange"> @filter-change="filter" @select-all="select" @select="select">
<el-table-column <el-table-column
type="selection"></el-table-column> type="selection"></el-table-column>
<el-table-column prop="name" :label="$t('commons.name')" width="250" show-overflow-tooltip> <el-table-column prop="name" :label="$t('commons.name')" width="250" show-overflow-tooltip>
@ -127,18 +127,7 @@
create() { create() {
this.$router.push('/api/test/create'); this.$router.push('/api/test/create');
}, },
select(selection) {
handleSelectAll(selection) {
this.selectIds.clear()
this.selectProjectNames.clear()
this.selectProjectId.clear()
selection.forEach(s => {
this.selectIds.add(s.id)
this.selectProjectNames.add(s.projectName)
this.selectProjectId.add(s.projectId)
})
},
selectionChange(selection) {
this.selectIds.clear() this.selectIds.clear()
this.selectProjectNames.clear() this.selectProjectNames.clear()
this.selectProjectId.clear() this.selectProjectId.clear()

View File

@ -26,7 +26,7 @@
import MsApiScenarioConfig from "./components/ApiScenarioConfig"; import MsApiScenarioConfig from "./components/ApiScenarioConfig";
import MsApiReportStatus from "../report/ApiReportStatus"; import MsApiReportStatus from "../report/ApiReportStatus";
import MsApiReportDialog from "./ApiReportDialog"; import MsApiReportDialog from "./ApiReportDialog";
import {getUUID} from "../../../../common/js/utils"; import {getUUID} from "@/common/js/utils";
export default { export default {
@ -95,13 +95,12 @@
}, },
checkName(callback) { checkName(callback) {
for (let i of this.selectProjectId) { for (let i of this.selectProjectId) {
this.result = this.$post('/api/checkName', {name: this.ruleForm.testName, projectId: i}, response => { this.result = this.$post('/api/checkName', {name: this.ruleForm.testName, projectId: i}, () => {
if (callback) callback(); if (callback) callback();
}) })
} }
}, },
_getEnvironmentAndRunTest: function (item) { _getEnvironmentAndRunTest: function (item) {
let count = 0;
this.result = this.$get('/api/environment/list/' + item.projectId, response => { this.result = this.$get('/api/environment/list/' + item.projectId, response => {
let environments = response.data; let environments = response.data;
let environmentMap = new Map(); let environmentMap = new Map();
@ -131,7 +130,6 @@
scenarioDefinition: JSON.parse(item.scenarioDefinition), scenarioDefinition: JSON.parse(item.scenarioDefinition),
schedule: {}, schedule: {},
}); });
console.log(test)
this.test = this.test || test; this.test = this.test || test;
if (this.tests.length > 1) { if (this.tests.length > 1) {
this.test.scenarioDefinition = this.test.scenarioDefinition.concat(test.scenarioDefinition); this.test.scenarioDefinition = this.test.scenarioDefinition.concat(test.scenarioDefinition);

View File

@ -1,5 +1,5 @@
<template> <template>
<el-dialog :title="$t('api_test.environment.environment_config')" :visible.sync="visible" class="environment-dialog" <el-dialog :close-on-click-modal="false" :title="$t('api_test.environment.environment_config')" :visible.sync="visible" class="environment-dialog"
@close="close" append-to-body ref="environmentConfig"> @close="close" append-to-body ref="environmentConfig">
<el-container v-loading="result.loading"> <el-container v-loading="result.loading">
<ms-aside-item :enable-aside-hidden="false" :title="$t('api_test.environment.environment_list')" :data="environments" :item-operators="environmentOperators" :add-fuc="addEnvironment" <ms-aside-item :enable-aside-hidden="false" :title="$t('api_test.environment.environment_list')" :data="environments" :item-operators="environmentOperators" :add-fuc="addEnvironment"

View File

@ -166,7 +166,12 @@ export default {
}); });
this.scenarios.forEach(scenario => { this.scenarios.forEach(scenario => {
if (scenario.environmentId) { if (scenario.environmentId) {
scenario.environment = environmentMap.get(scenario.environmentId); let env = environmentMap.get(scenario.environmentId);
if (!env) {
scenario.environmentId = undefined;
} else {
scenario.environment = env;
}
} }
}); });
}); });

View File

@ -7,10 +7,11 @@
<el-row type="flex" :gutter="20" justify="space-between" align="middle"> <el-row type="flex" :gutter="20" justify="space-between" align="middle">
<el-col> <el-col>
<el-input v-if="!suggestions" :disabled="isReadOnly" v-model="item.name" size="small" maxlength="200" @change="change" :placeholder="keyText" show-word-limit> <el-input v-if="!suggestions" :disabled="isReadOnly" v-model="item.name" size="small" maxlength="200"
@change="change" :placeholder="keyText" show-word-limit>
<template v-slot:prepend> <template v-slot:prepend>
<el-select v-if="type === 'body'" :disabled="isReadOnly" class="kv-type" v-model="item.type"> <el-select v-if="type === 'body'" :disabled="isReadOnly" class="kv-type" v-model="item.type">
<el-option value="text" /> <el-option value="text"/>
<el-option value="file"/> <el-option value="file"/>
</el-select> </el-select>
</template> </template>
@ -31,12 +32,12 @@
value-key="name" value-key="name"
highlight-first-item highlight-first-item
@select="change"> @select="change">
<i slot="suffix" class="el-input__icon el-icon-edit" style="cursor: pointer;" @click="advanced(item)"></i> <i slot="suffix" class="el-input__icon el-icon-edit pointer" @click="advanced(item)"></i>
</el-autocomplete> </el-autocomplete>
</el-col> </el-col>
<el-col v-if="item.type === 'file'"> <el-col v-if="item.type === 'file'">
<ms-api-body-file-upload :parameter="item"/> <ms-api-body-file-upload :parameter="item"/>
</el-col> </el-col>
<el-col class="kv-delete"> <el-col class="kv-delete">
<el-button size="mini" class="el-icon-delete-solid" circle @click="remove(index)" <el-button size="mini" class="el-icon-delete-solid" circle @click="remove(index)"
@ -155,31 +156,36 @@ export default {
</script> </script>
<style scoped> <style scoped>
.kv-description { .kv-description {
font-size: 13px; font-size: 13px;
} }
.kv-row { .kv-row {
margin-top: 10px; margin-top: 10px;
} }
.kv-delete { .kv-delete {
width: 60px; width: 60px;
} }
.el-autocomplete { .el-autocomplete {
width: 100%; width: 100%;
} }
.advanced-item-value >>> .el-dialog__body { .advanced-item-value >>> .el-dialog__body {
padding: 15px 25px; padding: 15px 25px;
} }
.el-row { .el-row {
margin-bottom: 5px; margin-bottom: 5px;
} }
.kv-type { .kv-type {
width: 70px; width: 70px;
} }
.pointer {
cursor: pointer;
color: #1E90FF;
}
</style> </style>

View File

@ -1,5 +1,5 @@
<template> <template>
<el-dialog :title="$t('api_test.api_import.title')" :visible.sync="visible" class="api-import" v-loading="result.loading" @close="close"> <el-dialog :close-on-click-modal="false" :title="$t('api_test.api_import.title')" :visible.sync="visible" class="api-import" v-loading="result.loading" @close="close">
<div class="header-bar"> <div class="header-bar">
<div>{{$t('api_test.api_import.data_format')}}</div> <div>{{$t('api_test.api_import.data_format')}}</div>

View File

@ -2,9 +2,10 @@
<div > <div >
<el-row> <el-row>
<el-col :span="20" class="script-content"> <el-col :span="20" class="script-content">
<ms-code-edit v-if="isCodeEditAlive" mode="java" :read-only="isReadOnly" :data.sync="beanShellProcessor.script" theme="eclipse" :modes="['java']" ref="codeEdit"/> <ms-code-edit v-if="isCodeEditAlive" :mode="codeEditModeMap[jsr223Processor.language]" :read-only="isReadOnly" :data.sync="jsr223Processor.script" theme="eclipse" :modes="['java','python']" ref="codeEdit"/>
</el-col> </el-col>
<el-col :span="4" class="script-index"> <el-col :span="4" class="script-index">
<ms-dropdown :default-command="jsr223Processor.language" :commands="languages" @command="languageChange"/>
<div class="template-title">{{$t('api_test.request.processor.code_template')}}</div> <div class="template-title">{{$t('api_test.request.processor.code_template')}}</div>
<div v-for="(template, index) in codeTemplates" :key="index" class="code-template"> <div v-for="(template, index) in codeTemplates" :key="index" class="code-template">
<el-link :disabled="template.disabled" @click="addTemplate(template)">{{template.title}}</el-link> <el-link :disabled="template.disabled" @click="addTemplate(template)">{{template.title}}</el-link>
@ -21,9 +22,13 @@
<script> <script>
import MsCodeEdit from "../../../../common/components/MsCodeEdit"; import MsCodeEdit from "../../../../common/components/MsCodeEdit";
import MsInstructionsIcon from "../../../../common/components/MsInstructionsIcon"; import MsInstructionsIcon from "../../../../common/components/MsInstructionsIcon";
import MsDropdown from "../../../../common/components/MsDropdown";
export default { export default {
name: "MsBeanShellProcessor", name: "MsJsr233Processor",
components: {MsInstructionsIcon, MsCodeEdit}, components: {MsDropdown, MsInstructionsIcon, MsCodeEdit},
data() { data() {
return { return {
codeTemplates: [ codeTemplates: [
@ -51,7 +56,14 @@
disabled: this.isPreProcessor disabled: this.isPreProcessor
} }
], ],
isCodeEditAlive: true isCodeEditAlive: true,
languages: [
'beanshell',"python"
],
codeEditModeMap: {
beanshell: 'java',
python: 'python'
}
} }
}, },
props: { props: {
@ -62,7 +74,7 @@
type: Boolean, type: Boolean,
default: false default: false
}, },
beanShellProcessor: { jsr223Processor: {
type: Object, type: Object,
}, },
isPreProcessor: { isPreProcessor: {
@ -72,15 +84,18 @@
}, },
methods: { methods: {
addTemplate(template) { addTemplate(template) {
if (!this.beanShellProcessor.script) { if (!this.jsr223Processor.script) {
this.beanShellProcessor.script = ""; this.jsr223Processor.script = "";
} }
this.beanShellProcessor.script += template.value; this.jsr223Processor.script += template.value;
this.reload(); this.reload();
}, },
reload() { reload() {
this.isCodeEditAlive = false; this.isCodeEditAlive = false;
this.$nextTick(() => (this.isCodeEditAlive = true)); this.$nextTick(() => (this.isCodeEditAlive = true));
},
languageChange(language) {
this.jsr223Processor.language = language;
} }
} }
} }
@ -100,13 +115,10 @@
padding: 0 20px; padding: 0 20px;
} }
.script-index div:first-child {
font-weight: bold;
font-size: 15px;
}
.template-title { .template-title {
margin-bottom: 5px; margin-bottom: 5px;
font-weight: bold;
font-size: 15px;
} }
.document-url { .document-url {
@ -117,4 +129,8 @@
margin-left: 5px; margin-left: 5px;
} }
.ms-dropdown {
margin-bottom: 20px;
}
</style> </style>

View File

@ -45,10 +45,10 @@
<ms-api-extract :is-read-only="isReadOnly" :extract="request.extract"/> <ms-api-extract :is-read-only="isReadOnly" :extract="request.extract"/>
</el-tab-pane> </el-tab-pane>
<el-tab-pane :label="$t('api_test.request.processor.pre_exec_script')" name="beanShellPreProcessor"> <el-tab-pane :label="$t('api_test.request.processor.pre_exec_script')" name="beanShellPreProcessor">
<ms-bean-shell-processor :is-read-only="isReadOnly" :bean-shell-processor="request.beanShellPreProcessor"/> <ms-jsr233-processor :is-read-only="isReadOnly" :jsr223-processor="request.jsr223PreProcessor"/>
</el-tab-pane> </el-tab-pane>
<el-tab-pane :label="$t('api_test.request.processor.post_exec_script')" name="beanShellPostProcessor"> <el-tab-pane :label="$t('api_test.request.processor.post_exec_script')" name="beanShellPostProcessor">
<ms-bean-shell-processor :is-read-only="isReadOnly" :bean-shell-processor="request.beanShellPostProcessor"/> <ms-jsr233-processor :is-read-only="isReadOnly" :jsr223-processor="request.jsr223PostProcessor"/>
</el-tab-pane> </el-tab-pane>
</el-tabs> </el-tabs>
</el-form> </el-form>
@ -65,12 +65,12 @@
import MsDubboRegistryCenter from "@/business/components/api/test/components/request/dubbo/RegistryCenter"; import MsDubboRegistryCenter from "@/business/components/api/test/components/request/dubbo/RegistryCenter";
import MsDubboConfigCenter from "@/business/components/api/test/components/request/dubbo/ConfigCenter"; import MsDubboConfigCenter from "@/business/components/api/test/components/request/dubbo/ConfigCenter";
import MsDubboConsumerService from "@/business/components/api/test/components/request/dubbo/ConsumerAndService"; import MsDubboConsumerService from "@/business/components/api/test/components/request/dubbo/ConsumerAndService";
import MsBeanShellProcessor from "../processor/BeanShellProcessor"; import MsJsr233Processor from "../processor/Jsr233Processor";
export default { export default {
name: "MsApiDubboRequestForm", name: "MsApiDubboRequestForm",
components: { components: {
MsBeanShellProcessor, MsJsr233Processor,
MsDubboConsumerService, MsDubboConsumerService,
MsDubboConfigCenter, MsDubboConfigCenter,
MsDubboRegistryCenter, MsDubboRegistryCenter,

View File

@ -38,6 +38,7 @@
v-model="request.useEnvironment" v-model="request.useEnvironment"
:active-text="$t('api_test.request.refer_to_environment')" @change="useEnvironmentChange"> :active-text="$t('api_test.request.refer_to_environment')" @change="useEnvironmentChange">
</el-switch> </el-switch>
<el-checkbox class="follow-redirects-item" v-model="request.followRedirects">{{$t('api_test.request.follow_redirects')}}</el-checkbox>
</el-form-item> </el-form-item>
<el-button :disabled="!request.enable || !scenario.enable || isReadOnly" class="debug-button" size="small" type="primary" @click="runDebug">{{ $t('api_test.request.debug') }}</el-button> <el-button :disabled="!request.enable || !scenario.enable || isReadOnly" class="debug-button" size="small" type="primary" @click="runDebug">{{ $t('api_test.request.debug') }}</el-button>
@ -67,11 +68,11 @@
<el-tab-pane :label="$t('api_test.request.extract.label')" name="extract"> <el-tab-pane :label="$t('api_test.request.extract.label')" name="extract">
<ms-api-extract :is-read-only="isReadOnly" :extract="request.extract"/> <ms-api-extract :is-read-only="isReadOnly" :extract="request.extract"/>
</el-tab-pane> </el-tab-pane>
<el-tab-pane :label="$t('api_test.request.processor.pre_exec_script')" name="beanShellPreProcessor"> <el-tab-pane :label="$t('api_test.request.processor.pre_exec_script')" name="jsr223PreProcessor">
<ms-bean-shell-processor :is-pre-processor="true" :is-read-only="isReadOnly" :bean-shell-processor="request.beanShellPreProcessor"/> <ms-jsr233-processor :is-read-only="isReadOnly" :jsr223-processor="request.jsr223PreProcessor"/>
</el-tab-pane> </el-tab-pane>
<el-tab-pane :label="$t('api_test.request.processor.post_exec_script')" name="beanShellPostProcessor"> <el-tab-pane :label="$t('api_test.request.processor.post_exec_script')" name="jsr223PostProcessor">
<ms-bean-shell-processor :is-read-only="isReadOnly" :bean-shell-processor="request.beanShellPostProcessor"/> <ms-jsr233-processor :is-read-only="isReadOnly" :jsr223-processor="request.jsr223PostProcessor"/>
</el-tab-pane> </el-tab-pane>
<el-tab-pane :label="$t('api_test.request.timeout_config')" name="advancedConfig"> <el-tab-pane :label="$t('api_test.request.timeout_config')" name="advancedConfig">
<ms-api-advanced-config :is-read-only="isReadOnly" :request="request"/> <ms-api-advanced-config :is-read-only="isReadOnly" :request="request"/>
@ -89,14 +90,14 @@ import MsApiExtract from "../extract/ApiExtract";
import ApiRequestMethodSelect from "../collapse/ApiRequestMethodSelect"; import ApiRequestMethodSelect from "../collapse/ApiRequestMethodSelect";
import {REQUEST_HEADERS} from "@/common/js/constants"; import {REQUEST_HEADERS} from "@/common/js/constants";
import MsApiVariable from "@/business/components/api/test/components/ApiVariable"; import MsApiVariable from "@/business/components/api/test/components/ApiVariable";
import MsBeanShellProcessor from "../processor/BeanShellProcessor"; import MsJsr233Processor from "../processor/Jsr233Processor";
import MsApiAdvancedConfig from "../ApiAdvancedConfig"; import MsApiAdvancedConfig from "../ApiAdvancedConfig";
export default { export default {
name: "MsApiHttpRequestForm", name: "MsApiHttpRequestForm",
components: { components: {
MsJsr233Processor,
MsApiAdvancedConfig, MsApiAdvancedConfig,
MsBeanShellProcessor,
MsApiVariable, ApiRequestMethodSelect, MsApiExtract, MsApiAssertions, MsApiBody, MsApiKeyValue}, MsApiVariable, ApiRequestMethodSelect, MsApiExtract, MsApiAssertions, MsApiBody, MsApiKeyValue},
props: { props: {
request: HttpRequest, request: HttpRequest,
@ -221,4 +222,8 @@ export default {
color: #F56C6C; color: #F56C6C;
} }
.follow-redirects-item {
margin-left: 30px;
}
</style> </style>

View File

@ -55,6 +55,15 @@ export default {
this.getReport(); this.getReport();
} }
}, },
mounted() {
// beanshell
if (!this.request.jsr223PreProcessor.script && this.request.beanShellPreProcessor) {
this.request.jsr223PreProcessor = this.request.beanShellPreProcessor;
}
if (!this.request.jsr223PostProcessor.script && this.request.beanShellPostProcessor) {
this.request.jsr223PostProcessor = this.request.beanShellPostProcessor;
}
},
methods: { methods: {
getReport() { getReport() {
if (this.debugReportId) { if (this.debugReportId) {

View File

@ -295,8 +295,10 @@ export class HTTPSamplerProxy extends DefaultTestElement {
if (options.responseTimeout) { if (options.responseTimeout) {
this.stringProp('HTTPSampler.response_timeout', options.responseTimeout); this.stringProp('HTTPSampler.response_timeout', options.responseTimeout);
} }
if (options.followRedirects) {
this.boolProp('HTTPSampler.follow_redirects', options.followRedirects, true);
}
this.boolProp("HTTPSampler.follow_redirects", options.follow, true);
this.boolProp("HTTPSampler.use_keepalive", options.keepalive, true); this.boolProp("HTTPSampler.use_keepalive", options.keepalive, true);
} }
} }
@ -441,6 +443,30 @@ export class BeanShellProcessor extends DefaultTestElement {
} }
} }
export class JSR223Processor extends DefaultTestElement {
constructor(tag, guiclass, testclass, testname, processor) {
super(tag, guiclass, testclass, testname);
this.processor = processor || {};
this.stringProp('cacheKey', 'true');
this.stringProp('filename');
this.stringProp('parameters');
this.stringProp('script', this.processor.script);
this.stringProp('scriptLanguage', this.processor.language);
}
}
export class JSR223PreProcessor extends JSR223Processor {
constructor(testName, processor) {
super('JSR223PreProcessor', 'TestBeanGUI', 'JSR223PreProcessor', testName, processor)
}
}
export class JSR223PostProcessor extends JSR223Processor {
constructor(testName, processor) {
super('JSR223PostProcessor', 'TestBeanGUI', 'JSR223PostProcessor', testName, processor)
}
}
export class BeanShellPreProcessor extends BeanShellProcessor { export class BeanShellPreProcessor extends BeanShellProcessor {
constructor(testName, processor) { constructor(testName, processor) {
super('BeanShellPreProcessor', 'TestBeanGUI', 'BeanShellPreProcessor', testName, processor) super('BeanShellPreProcessor', 'TestBeanGUI', 'BeanShellPreProcessor', testName, processor)

View File

@ -9,7 +9,7 @@ import {
HTTPSamplerArguments, HTTPsamplerFiles, HTTPSamplerArguments, HTTPsamplerFiles,
HTTPSamplerProxy, HTTPSamplerProxy,
JSONPathAssertion, JSONPathAssertion,
JSONPostProcessor, JSONPostProcessor, JSR223PostProcessor, JSR223PreProcessor,
RegexExtractor, RegexExtractor,
ResponseCodeAssertion, ResponseCodeAssertion,
ResponseDataAssertion, ResponseDataAssertion,
@ -309,9 +309,12 @@ export class HttpRequest extends Request {
this.debugReport = undefined; this.debugReport = undefined;
this.beanShellPreProcessor = undefined; this.beanShellPreProcessor = undefined;
this.beanShellPostProcessor = undefined; this.beanShellPostProcessor = undefined;
this.jsr223PreProcessor = undefined;
this.jsr223PostProcessor = undefined;
this.enable = true; this.enable = true;
this.connectTimeout = 60*1000; this.connectTimeout = 60*1000;
this.responseTimeout = undefined; this.responseTimeout = undefined;
this.followRedirects = true;
this.set(options); this.set(options);
this.sets({parameters: KeyValue, headers: KeyValue}, options); this.sets({parameters: KeyValue, headers: KeyValue}, options);
@ -323,8 +326,8 @@ export class HttpRequest extends Request {
options.body = new Body(options.body); options.body = new Body(options.body);
options.assertions = new Assertions(options.assertions); options.assertions = new Assertions(options.assertions);
options.extract = new Extract(options.extract); options.extract = new Extract(options.extract);
options.beanShellPreProcessor = new BeanShellProcessor(options.beanShellPreProcessor); options.jsr223PreProcessor = new JSR223Processor(options.jsr223PreProcessor);
options.beanShellPostProcessor = new BeanShellProcessor(options.beanShellPostProcessor); options.jsr223PostProcessor = new JSR223Processor(options.jsr223PostProcessor);
return options; return options;
} }
@ -393,7 +396,9 @@ export class DubboRequest extends Request {
this.debugReport = undefined; this.debugReport = undefined;
this.beanShellPreProcessor = new BeanShellProcessor(options.beanShellPreProcessor); this.beanShellPreProcessor = new BeanShellProcessor(options.beanShellPreProcessor);
this.beanShellPostProcessor = new BeanShellProcessor(options.beanShellPostProcessor); this.beanShellPostProcessor = new BeanShellProcessor(options.beanShellPostProcessor);
this.enable = true; this.enable = options.enable == undefined ? true : options.enable;
this.jsr223PreProcessor = new JSR223Processor(options.jsr223PreProcessor);
this.jsr223PostProcessor = new JSR223Processor(options.jsr223PostProcessor);
this.sets({args: KeyValue, attachmentArgs: KeyValue}, options); this.sets({args: KeyValue, attachmentArgs: KeyValue}, options);
} }
@ -603,6 +608,16 @@ export class BeanShellProcessor extends BaseConfig {
} }
} }
export class JSR223Processor extends BaseConfig {
constructor(options) {
super();
this.script = undefined;
this.language = "beanshell";
this.set(options);
}
}
export class Text extends AssertionType { export class Text extends AssertionType {
constructor(options) { constructor(options) {
super(ASSERTION_TYPE.TEXT); super(ASSERTION_TYPE.TEXT);
@ -749,6 +764,7 @@ class JMXHttpRequest {
} }
this.connectTimeout = request.connectTimeout; this.connectTimeout = request.connectTimeout;
this.responseTimeout = request.responseTimeout; this.responseTimeout = request.responseTimeout;
this.followRedirects = request.followRedirects;
} }
} }
@ -867,11 +883,11 @@ class JMXGenerator {
} }
} }
this.addBeanShellProcessor(sampler, request); this.addRequestExtractor(sampler, request);
this.addRequestAssertion(sampler, request); this.addRequestAssertion(sampler, request);
this.addRequestExtractor(sampler, request); this.addJSR223PreProcessor(sampler, request);
threadGroup.put(sampler); threadGroup.put(sampler);
} }
@ -938,13 +954,13 @@ class JMXGenerator {
} }
} }
addBeanShellProcessor(sampler, request) { addJSR223PreProcessor(sampler, request) {
let name = request.name; let name = request.name;
if (request.beanShellPreProcessor && request.beanShellPreProcessor.script) { if (request.jsr223PreProcessor && request.jsr223PreProcessor.script) {
sampler.put(new BeanShellPreProcessor(name, request.beanShellPreProcessor)); sampler.put(new JSR223PreProcessor(name, request.jsr223PreProcessor));
} }
if (request.beanShellPostProcessor && request.beanShellPostProcessor.script) { if (request.jsr223PostProcessor && request.jsr223PostProcessor.script) {
sampler.put(new BeanShellPostProcessor(name, request.beanShellPostProcessor)); sampler.put(new JSR223PostProcessor(name, request.jsr223PostProcessor));
} }
} }

View File

@ -1,5 +1,6 @@
<template> <template>
<el-dialog :title="title" <el-dialog :close-on-click-modal="false"
:title="title"
:visible.sync="dialogVisible" :visible.sync="dialogVisible"
class="delete-confirm" > class="delete-confirm" >

View File

@ -1,5 +1,5 @@
<template> <template>
<el-dropdown @command="handleCommand"> <el-dropdown @command="handleCommand" class="ms-dropdown">
<slot> <slot>
<span class="el-dropdown-link"> <span class="el-dropdown-link">
{{currentCommand}} {{currentCommand}}

View File

@ -22,9 +22,9 @@
@click="rerun(testId)"> @click="rerun(testId)">
{{ $t('report.test_execute_again') }} {{ $t('report.test_execute_again') }}
</el-button> </el-button>
<!-- <el-button :disabled="isReadOnly" type="info" plain size="mini" @click="exports(reportName)"> <!-- <el-button :disabled="isReadOnly" type="info" plain size="mini" @click="exports(reportName)">
{{$t('report.export')}} {{$t('report.export')}}
</el-button>--> </el-button>-->
<!-- <!--
<el-button :disabled="isReadOnly" type="warning" plain size="mini"> <el-button :disabled="isReadOnly" type="warning" plain size="mini">
{{$t('report.compare')}} {{$t('report.compare')}}
@ -82,252 +82,237 @@
</template> </template>
<script> <script>
import MsReportErrorLog from './components/ErrorLog'; import MsReportErrorLog from './components/ErrorLog';
import MsReportLogDetails from './components/LogDetails'; import MsReportLogDetails from './components/LogDetails';
import MsReportRequestStatistics from './components/RequestStatistics'; import MsReportRequestStatistics from './components/RequestStatistics';
import MsReportTestOverview from './components/TestOverview'; import MsReportTestOverview from './components/TestOverview';
import MsPerformancePressureConfig from "./components/PerformancePressureConfig"; import MsPerformancePressureConfig from "./components/PerformancePressureConfig";
import MsContainer from "../../common/components/MsContainer"; import MsContainer from "../../common/components/MsContainer";
import MsMainContainer from "../../common/components/MsMainContainer"; import MsMainContainer from "../../common/components/MsMainContainer";
import {checkoutTestManagerOrTestUser} from "@/common/js/utils"; import {checkoutTestManagerOrTestUser} from "@/common/js/utils";
import writer from "file-writer";
import ResumeCss from "../../../../common/css/main.css";
export default { export default {
name: "PerformanceReportView", name: "PerformanceReportView",
components: { components: {
MsReportErrorLog, MsReportErrorLog,
MsReportLogDetails, MsReportLogDetails,
MsReportRequestStatistics, MsReportRequestStatistics,
MsReportTestOverview, MsReportTestOverview,
MsContainer, MsContainer,
MsMainContainer, MsMainContainer,
MsPerformancePressureConfig MsPerformancePressureConfig
}, },
data() { data() {
return { return {
result: {}, result: {},
active: '1', active: '1',
reportId: '', reportId: '',
status: '', status: '',
reportName: '', reportName: '',
testId: '', testId: '',
testName: '', testName: '',
projectId: '', projectId: '',
projectName: '', projectName: '',
startTime: '0', startTime: '0',
endTime: '0', endTime: '0',
minutes: '0', minutes: '0',
seconds: '0', seconds: '0',
title: 'Logging', title: 'Logging',
report: {}, report: {},
isReadOnly: false, isReadOnly: false,
websocket: null, websocket: null,
dialogFormVisible: false, dialogFormVisible: false,
testPlan: {testResourcePoolId: null} testPlan: {testResourcePoolId: null}
} }
}, },
methods: { methods: {
initBreadcrumb() { initBreadcrumb(callback) {
if (this.reportId) { if (this.reportId) {
this.result = this.$get("/performance/report/test/pro/info/" + this.reportId, res => { this.result = this.$get("/performance/report/test/pro/info/" + this.reportId, res => {
let data = res.data; let data = res.data;
if (data) { if (data) {
this.reportName = data.name; this.reportName = data.name;
this.testId = data.testId; this.testId = data.testId;
this.testName = data.testName; this.testName = data.testName;
this.projectId = data.projectId; this.projectId = data.projectId;
this.projectName = data.projectName; this.projectName = data.projectName;
} //
}) if (callback) callback(res);
}
},
initReportTimeInfo() {
if (this.reportId) {
this.result = this.$get("/performance/report/content/report_time/" + this.reportId)
.then(res => {
let data = res.data.data;
if (data) {
this.startTime = data.startTime;
this.endTime = data.endTime;
let duration = data.duration;
this.minutes = Math.floor(duration / 60);
this.seconds = duration % 60;
}
}).catch(() => {
this.clearData();
})
}
},
initWebSocket() {
let protocol = "ws://";
if (window.location.protocol === 'https:') {
protocol = "wss://";
}
const uri = protocol + window.location.host + "/performance/report/" + this.reportId;
this.websocket = new WebSocket(uri);
this.websocket.onmessage = this.onMessage;
this.websocket.onopen = this.onOpen;
this.websocket.onerror = this.onError;
this.websocket.onclose = this.onClose;
},
checkReportStatus(status) {
switch (status) {
case 'Error':
this.$warning(this.$t('report.generation_error'));
break;
case 'Starting':
this.$alert(this.$t('report.start_status'));
break;
case 'Reporting':
case 'Running':
case 'Completed':
default:
break;
}
},
clearData() {
this.startTime = '0';
this.endTime = '0';
this.minutes = '0';
this.seconds = '0';
},
stopTest(forceStop) {
this.result = this.$get('/performance/stop/' + this.reportId + '/' + forceStop, () => {
this.$success(this.$t('report.test_stop_success'));
if (forceStop) {
this.$router.push('/performance/report/all');
} else { } else {
this.report.status = 'Completed'; this.$error(this.$t('report.not_exist'));
} }
}); })
this.dialogFormVisible = false;
},
rerun(testId) {
this.$confirm(this.$t('report.test_rerun_confirm'), '', {
confirmButtonText: this.$t('commons.confirm'),
cancelButtonText: this.$t('commons.cancel'),
type: 'warning'
}).then(() => {
this.result = this.$post('/performance/run', {id: testId, triggerMode: 'MANUAL'}, (response) => {
this.reportId = response.data;
this.$router.push({path: '/performance/report/view/' + this.reportId});
// socket
this.initWebSocket();
})
}).catch(() => {
});
},
onOpen() {
window.console.log("socket opening.");
},
onError(e) {
window.console.error(e)
},
onMessage(e) {
this.$set(this.report, "refresh", e.data); //
this.$set(this.report, "status", 'Running');
this.initReportTimeInfo();
window.console.log('receive a message:', e.data);
},
onClose(e) {
this.$set(this.report, "refresh", Math.random()); //
this.$set(this.report, "status", 'Completed');
this.initReportTimeInfo();
window.console.log("socket closed.");
} }
}, },
created() { initReportTimeInfo() {
this.isReadOnly = false; if (this.status === 'Starting') {
if (!checkoutTestManagerOrTestUser()) { this.clearData();
this.isReadOnly = true; return;
} }
this.reportId = this.$route.path.split('/')[4]; if (this.reportId) {
this.result = this.$get("/performance/report/" + this.reportId, res => { this.result = this.$get("/performance/report/content/report_time/" + this.reportId)
let data = res.data; .then(res => {
if (data) { let data = res.data.data;
this.status = data.status; if (data) {
this.$set(this.report, "id", this.reportId); this.startTime = data.startTime;
this.$set(this.report, "status", data.status); this.endTime = data.endTime;
this.$set(this.report, "testId", data.testId); let duration = data.duration;
this.$set(this.report, "loadConfiguration", data.loadConfiguration); this.minutes = Math.floor(duration / 60);
this.checkReportStatus(data.status); this.seconds = duration % 60;
if (this.status === "Completed" || this.status === "Running") { }
this.initReportTimeInfo(); }).catch(() => {
} this.clearData();
this.initBreadcrumb(); });
this.initWebSocket(); }
},
initWebSocket() {
let protocol = "ws://";
if (window.location.protocol === 'https:') {
protocol = "wss://";
}
const uri = protocol + window.location.host + "/performance/report/" + this.reportId;
this.websocket = new WebSocket(uri);
this.websocket.onmessage = this.onMessage;
this.websocket.onopen = this.onOpen;
this.websocket.onerror = this.onError;
this.websocket.onclose = this.onClose;
},
checkReportStatus(status) {
switch (status) {
case 'Error':
this.$warning(this.$t('report.generation_error'));
break;
case 'Starting':
this.$alert(this.$t('report.start_status'));
break;
case 'Reporting':
case 'Running':
case 'Completed':
default:
break;
}
},
clearData() {
this.startTime = '0';
this.endTime = '0';
this.minutes = '0';
this.seconds = '0';
},
stopTest(forceStop) {
this.result = this.$get('/performance/stop/' + this.reportId + '/' + forceStop, () => {
this.$success(this.$t('report.test_stop_success'));
if (forceStop) {
this.$router.push('/performance/report/all');
} else { } else {
this.$error(this.$t('report.not_exist')) this.report.status = 'Completed';
} }
}); });
this.dialogFormVisible = false;
}, },
beforeDestroy() { rerun(testId) {
this.websocket.close() //websocket this.$confirm(this.$t('report.test_rerun_confirm'), '', {
confirmButtonText: this.$t('commons.confirm'),
cancelButtonText: this.$t('commons.cancel'),
type: 'warning'
}).then(() => {
this.result = this.$post('/performance/run', {id: testId, triggerMode: 'MANUAL'}, (response) => {
this.reportId = response.data;
this.$router.push({path: '/performance/report/view/' + this.reportId});
// socket
this.initWebSocket();
})
}).catch(() => {
});
}, },
watch: { onOpen() {
'$route'(to) { window.console.log("socket opening.");
if (to.name === "perReportView") { },
this.isReadOnly = false; onError(e) {
if (!checkoutTestManagerOrTestUser()) { window.console.error(e)
this.isReadOnly = true; },
} onMessage(e) {
let reportId = to.path.split('/')[4]; this.$set(this.report, "refresh", e.data); //
this.reportId = reportId; this.$set(this.report, "status", 'Running');
if (reportId) { this.status = 'Running';
this.$get("/performance/report/test/pro/info/" + reportId, response => { this.initReportTimeInfo();
let data = response.data; window.console.log('receive a message:', e.data);
if (data) { },
this.status = data.status; onClose(e) {
this.reportName = data.name; if (e.code === 1005) {
this.testName = data.testName; // socketreport
this.testId = data.testId; return;
this.projectName = data.projectName; }
this.$set(this.report, "refresh", Math.random()); //
this.$set(this.report, "id", reportId); this.$set(this.report, "status", 'Completed');
this.$set(this.report, "status", data.status); this.initReportTimeInfo();
window.console.log("socket closed.");
this.checkReportStatus(data.status); }
if (this.status === "Completed") { },
this.result = this.$get("/performance/report/content/report_time/" + this.reportId).then(res => { created() {
let data = res.data.data; this.isReadOnly = false;
if (data) { if (!checkoutTestManagerOrTestUser()) {
this.startTime = data.startTime; this.isReadOnly = true;
this.endTime = data.endTime; }
let duration = data.duration; this.reportId = this.$route.path.split('/')[4];
this.minutes = Math.floor(duration / 60); this.result = this.$get("/performance/report/" + this.reportId, res => {
this.seconds = duration % 60; let data = res.data;
} if (data) {
}).catch(() => { this.status = data.status;
this.clearData(); this.$set(this.report, "id", this.reportId);
}) this.$set(this.report, "status", data.status);
} else { this.$set(this.report, "testId", data.testId);
this.clearData(); this.$set(this.report, "loadConfiguration", data.loadConfiguration);
} this.checkReportStatus(data.status);
} else { if (this.status === "Completed" || this.status === "Running") {
this.$error(this.$t('report.not_exist')); this.initReportTimeInfo();
}
});
}
} }
this.initBreadcrumb();
this.initWebSocket();
} else {
this.$error(this.$t('report.not_exist'))
}
});
},
watch: {
'$route'(to) {
if (to.name === "perReportView") {
this.isReadOnly = false;
if (!checkoutTestManagerOrTestUser()) {
this.isReadOnly = true;
}
let reportId = to.path.split('/')[4];
this.reportId = reportId;
this.initBreadcrumb((response) => {
let data = response.data;
this.$set(this.report, "id", reportId);
this.$set(this.report, "status", data.status);
this.checkReportStatus(data.status);
this.initReportTimeInfo();
});
this.initWebSocket();
} else {
console.log("close socket.");
this.websocket.close() //websocket
} }
} }
} }
}
</script> </script>
<style scoped> <style scoped>
.ms-report-view-btns { .ms-report-view-btns {
margin-top: 15px; margin-top: 15px;
} }
.ms-report-time-desc { .ms-report-time-desc {
text-align: left; text-align: left;
display: block; display: block;
color: #5C7878; color: #5C7878;
} }
</style> </style>

View File

@ -58,7 +58,7 @@ import PerformancePressureConfig from "./components/PerformancePressureConfig";
import PerformanceAdvancedConfig from "./components/PerformanceAdvancedConfig"; import PerformanceAdvancedConfig from "./components/PerformanceAdvancedConfig";
import MsContainer from "../../common/components/MsContainer"; import MsContainer from "../../common/components/MsContainer";
import MsMainContainer from "../../common/components/MsMainContainer"; import MsMainContainer from "../../common/components/MsMainContainer";
import {checkoutTestManagerOrTestUser} from "../../../../common/js/utils"; import {checkoutTestManagerOrTestUser} from "@/common/js/utils";
import MsScheduleConfig from "../../common/components/MsScheduleConfig"; import MsScheduleConfig from "../../common/components/MsScheduleConfig";
import {LIST_CHANGE, PerformanceEvent} from "@/business/components/common/head/ListEvent"; import {LIST_CHANGE, PerformanceEvent} from "@/business/components/common/head/ListEvent";

View File

@ -4,7 +4,7 @@
accept=".jmx,.csv" accept=".jmx,.csv"
drag drag
action="" action=""
:limit="2" :limit="5"
multiple multiple
:show-file-list="false" :show-file-list="false"
:before-upload="beforeUpload" :before-upload="beforeUpload"

View File

@ -164,6 +164,7 @@ export default {
} else { } else {
this.calculateChart(); this.calculateChart();
} }
this.getResourcePools();
}, },
}, },
methods: { methods: {

View File

@ -49,7 +49,7 @@
</el-card> </el-card>
</ms-main-container> </ms-main-container>
<el-dialog :title="title" :visible.sync="createVisible" destroy-on-close @close="handleClose"> <el-dialog :close-on-click-modal="false" :title="title" :visible.sync="createVisible" destroy-on-close @close="handleClose">
<el-form :model="form" :rules="rules" ref="form" label-position="right" label-width="100px" size="small"> <el-form :model="form" :rules="rules" ref="form" label-position="right" label-width="100px" size="small">
<el-form-item :label="$t('commons.name')" prop="name"> <el-form-item :label="$t('commons.name')" prop="name">
<el-input v-model="form.name" autocomplete="off"></el-input> <el-input v-model="form.name" autocomplete="off"></el-input>

View File

@ -25,6 +25,9 @@
<el-form-item :label="$t('organization.integration.jira_url')" prop="url" v-if="platform === 'Jira'"> <el-form-item :label="$t('organization.integration.jira_url')" prop="url" v-if="platform === 'Jira'">
<el-input v-model="form.url" :placeholder="$t('organization.integration.input_jira_url')"/> <el-input v-model="form.url" :placeholder="$t('organization.integration.input_jira_url')"/>
</el-form-item> </el-form-item>
<el-form-item :label="$t('organization.integration.jira_issuetype')" prop="issuetype" v-if="platform === 'Jira'">
<el-input v-model="form.issuetype" :placeholder="$t('organization.integration.input_jira_issuetype')"/>
</el-form-item>
</el-form> </el-form>
</div> </div>
@ -43,10 +46,13 @@
<div class="defect-tip"> <div class="defect-tip">
<div>{{$t('organization.integration.use_tip')}}</div> <div>{{$t('organization.integration.use_tip')}}</div>
<div> <div>
1. {{$t('organization.integration.use_tip_one')}} 1. {{$t('organization.integration.use_tip_tapd')}}
</div> </div>
<div> <div>
2. {{$t('organization.integration.use_tip_two')}} 2. {{$t('organization.integration.use_tip_jira')}}
</div>
<div>
3. {{$t('organization.integration.use_tip_two')}}
<router-link to="/track/project/all" style="margin-left: 5px"> <router-link to="/track/project/all" style="margin-left: 5px">
{{$t('organization.integration.link_the_project_now')}} {{$t('organization.integration.link_the_project_now')}}
</router-link> </router-link>
@ -85,6 +91,11 @@
required: true, required: true,
message: this.$t('organization.integration.input_jira_url'), message: this.$t('organization.integration.input_jira_url'),
trigger: ['change', 'blur'] trigger: ['change', 'blur']
},
issuetype: {
required: true,
message: this.$t('organization.integration.input_jira_issuetype'),
trigger: ['change', 'blur']
} }
}, },
} }
@ -105,6 +116,7 @@
this.$set(this.form, 'account', config.account); this.$set(this.form, 'account', config.account);
this.$set(this.form, 'password', config.password); this.$set(this.form, 'password', config.password);
this.$set(this.form, 'url', config.url); this.$set(this.form, 'url', config.url);
this.$set(this.form, 'issuetype', config.issuetype);
} else { } else {
this.clear(); this.clear();
} }
@ -149,17 +161,26 @@
this.$warning(this.$t('organization.integration.choose_platform')); this.$warning(this.$t('organization.integration.choose_platform'));
return; return;
} }
let param = {};
let auth = {
account: this.form.account,
password: this.form.password,
url: this.form.url
};
param.organizationId = getCurrentUser().lastOrganizationId;
param.platform = this.platform;
param.configuration = JSON.stringify(auth);
this.$refs[form].validate(valid => { this.$refs[form].validate(valid => {
if (valid) { if (valid) {
let formatUrl = this.form.url;
if (!formatUrl.endsWith('/')) {
formatUrl = formatUrl + '/';
}
let param = {};
let auth = {
account: this.form.account,
password: this.form.password,
url: formatUrl,
issuetype: this.form.issuetype
};
param.organizationId = getCurrentUser().lastOrganizationId;
param.platform = this.platform;
param.configuration = JSON.stringify(auth);
this.result = this.$post("service/integration/save", param, () => { this.result = this.$post("service/integration/save", param, () => {
this.show = true; this.show = true;
this.showEdit = true; this.showEdit = true;
@ -188,6 +209,7 @@
this.$set(this.form, 'account', config.account); this.$set(this.form, 'account', config.account);
this.$set(this.form, 'password', config.password); this.$set(this.form, 'password', config.password);
this.$set(this.form, 'url', config.url); this.$set(this.form, 'url', config.url);
this.$set(this.form, 'issuetype', config.issuetype);
} else { } else {
this.clear(); this.clear();
} }
@ -197,6 +219,7 @@
this.$set(this.form, 'account', ''); this.$set(this.form, 'account', '');
this.$set(this.form, 'password', ''); this.$set(this.form, 'password', '');
this.$set(this.form, 'url', ''); this.$set(this.form, 'url', '');
this.$set(this.form, 'issuetype', '');
this.$nextTick(() => { this.$nextTick(() => {
this.$refs.form.clearValidate(); this.$refs.form.clearValidate();
}); });

View File

@ -25,7 +25,7 @@
:total="total"/> :total="total"/>
</el-card> </el-card>
<el-dialog :title="$t('member.create')" :visible.sync="createVisible" width="30%" :destroy-on-close="true" <el-dialog :close-on-click-modal="false" :title="$t('member.create')" :visible.sync="createVisible" width="30%" :destroy-on-close="true"
@close="handleClose"> @close="handleClose">
<el-form :model="form" ref="form" :rules="rules" label-position="right" label-width="100px" size="small"> <el-form :model="form" ref="form" :rules="rules" label-position="right" label-width="100px" size="small">
<el-form-item :label="$t('commons.member')" prop="ids" <el-form-item :label="$t('commons.member')" prop="ids"
@ -73,7 +73,7 @@
</template> </template>
</el-dialog> </el-dialog>
<el-dialog :title="$t('member.modify')" :visible.sync="updateVisible" width="30%" :destroy-on-close="true" <el-dialog :close-on-click-modal="false" :title="$t('member.modify')" :visible.sync="updateVisible" width="30%" :destroy-on-close="true"
@close="handleClose"> @close="handleClose">
<el-form :model="form" label-position="right" label-width="100px" size="small" ref="updateUserForm"> <el-form :model="form" label-position="right" label-width="100px" size="small" ref="updateUserForm">
<el-form-item label="ID" prop="id"> <el-form-item label="ID" prop="id">

View File

@ -24,7 +24,7 @@
:total="total"/> :total="total"/>
</el-card> </el-card>
<el-dialog :title="$t('workspace.create')" :visible.sync="dialogWsAddVisible" width="30%" @close="close"> <el-dialog :close-on-click-modal="false" :title="$t('workspace.create')" :visible.sync="dialogWsAddVisible" width="30%" @close="close">
<el-form :model="form" :rules="rules" ref="form" label-position="right" label-width="100px" size="small"> <el-form :model="form" :rules="rules" ref="form" label-position="right" label-width="100px" size="small">
<el-form-item :label="$t('commons.name')" prop="name"> <el-form-item :label="$t('commons.name')" prop="name">
<el-input v-model="form.name" autocomplete="off"/> <el-input v-model="form.name" autocomplete="off"/>
@ -39,7 +39,7 @@
@confirm="submit('form')"/> @confirm="submit('form')"/>
</template> </template>
</el-dialog> </el-dialog>
<el-dialog :title="$t('workspace.update')" :visible.sync="dialogWsUpdateVisible" width="30%"> <el-dialog :close-on-click-modal="false" :title="$t('workspace.update')" :visible.sync="dialogWsUpdateVisible" width="30%">
<el-form :model="form" :rules="rules" ref="form" label-position="right" label-width="100px" size="small"> <el-form :model="form" :rules="rules" ref="form" label-position="right" label-width="100px" size="small">
<el-form-item :label="$t('commons.name')" prop="name"> <el-form-item :label="$t('commons.name')" prop="name">
<el-input v-model="form.name" autocomplete="off"/> <el-input v-model="form.name" autocomplete="off"/>
@ -56,7 +56,7 @@
</el-dialog> </el-dialog>
<!-- dialog of workspace member --> <!-- dialog of workspace member -->
<el-dialog :visible.sync="dialogWsMemberVisible" width="70%" :destroy-on-close="true" @close="close" <el-dialog :close-on-click-modal="false" :visible.sync="dialogWsMemberVisible" width="70%" :destroy-on-close="true" @close="close"
class="dialog-css"> class="dialog-css">
<ms-table-header :condition.sync="dialogCondition" @create="addMember" @search="dialogSearch" <ms-table-header :condition.sync="dialogCondition" @create="addMember" @search="dialogSearch"
:create-tip="$t('member.create')" :title="$t('commons.member')"/> :create-tip="$t('member.create')" :title="$t('commons.member')"/>
@ -82,7 +82,7 @@
</el-dialog> </el-dialog>
<!-- add workspace member dialog --> <!-- add workspace member dialog -->
<el-dialog :title="$t('member.create')" :visible.sync="dialogWsMemberAddVisible" width="30%" <el-dialog :close-on-click-modal="false" :title="$t('member.create')" :visible.sync="dialogWsMemberAddVisible" width="30%"
:destroy-on-close="true" :destroy-on-close="true"
@close="closeFunc"> @close="closeFunc">
<el-form :model="memberForm" ref="form" :rules="wsMemberRule" label-position="right" label-width="100px" <el-form :model="memberForm" ref="form" :rules="wsMemberRule" label-position="right" label-width="100px"
@ -125,7 +125,7 @@
</el-dialog> </el-dialog>
<!-- update workspace member dialog --> <!-- update workspace member dialog -->
<el-dialog :title="$t('member.modify')" :visible.sync="dialogWsMemberUpdateVisible" width="30%" <el-dialog :close-on-click-modal="false" :title="$t('member.modify')" :visible.sync="dialogWsMemberUpdateVisible" width="30%"
:destroy-on-close="true" :destroy-on-close="true"
@close="closeFunc"> @close="closeFunc">
<el-form :model="memberForm" label-position="right" label-width="100px" size="small" ref="updateUserForm"> <el-form :model="memberForm" label-position="right" label-width="100px" size="small" ref="updateUserForm">

View File

@ -32,7 +32,7 @@
</el-card> </el-card>
<!--Modify personal details--> <!--Modify personal details-->
<el-dialog :title="$t('member.modify_personal_info')" :visible.sync="updateVisible" width="30%" <el-dialog :close-on-click-modal="false" :title="$t('member.modify_personal_info')" :visible.sync="updateVisible" width="30%"
:destroy-on-close="true" @close="handleClose"> :destroy-on-close="true" @close="handleClose">
<el-form :model="form" label-position="right" label-width="100px" size="small" :rules="rule" <el-form :model="form" label-position="right" label-width="100px" size="small" :rules="rule"
ref="updateUserForm"> ref="updateUserForm">
@ -57,7 +57,7 @@
</el-dialog> </el-dialog>
<!--Change personal password--> <!--Change personal password-->
<el-dialog :title="$t('member.edit_password')" :visible.sync="editPasswordVisible" width="35%" <el-dialog :close-on-click-modal="false" :title="$t('member.edit_password')" :visible.sync="editPasswordVisible" width="35%"
:destroy-on-close="true" @close="handleClose" left> :destroy-on-close="true" @close="handleClose" left>
<el-form :model="ruleForm" :rules="rules" ref="editPasswordForm" label-width="120px" class="demo-ruleForm"> <el-form :model="ruleForm" :rules="rules" ref="editPasswordForm" label-width="120px" class="demo-ruleForm">
<el-form-item :label="$t('member.old_password')" prop="password" style="margin-bottom: 29px"> <el-form-item :label="$t('member.old_password')" prop="password" style="margin-bottom: 29px">

View File

@ -28,7 +28,7 @@
</el-card> </el-card>
<!-- dialog of organization member --> <!-- dialog of organization member -->
<el-dialog :visible.sync="dialogOrgMemberVisible" width="70%" :destroy-on-close="true" @close="closeFunc" <el-dialog :close-on-click-modal="false" :visible.sync="dialogOrgMemberVisible" width="70%" :destroy-on-close="true" @close="closeFunc"
class="dialog-css"> class="dialog-css">
<ms-table-header :condition.sync="dialogCondition" @create="addMember" @search="dialogSearch" <ms-table-header :condition.sync="dialogCondition" @create="addMember" @search="dialogSearch"
:create-tip="$t('member.create')" :title="$t('commons.member')"/> :create-tip="$t('member.create')" :title="$t('commons.member')"/>
@ -56,7 +56,7 @@
</el-dialog> </el-dialog>
<!-- add organization form --> <!-- add organization form -->
<el-dialog :title="$t('organization.create')" :visible.sync="dialogOrgAddVisible" width="30%" @closed="closeFunc" <el-dialog :close-on-click-modal="false" :title="$t('organization.create')" :visible.sync="dialogOrgAddVisible" width="30%" @closed="closeFunc"
:destroy-on-close="true"> :destroy-on-close="true">
<el-form :model="form" label-position="right" label-width="100px" size="small" :rules="rule" <el-form :model="form" label-position="right" label-width="100px" size="small" :rules="rule"
ref="createOrganization"> ref="createOrganization">
@ -75,7 +75,7 @@
</el-dialog> </el-dialog>
<!-- update organization form --> <!-- update organization form -->
<el-dialog :title="$t('organization.modify')" :visible.sync="dialogOrgUpdateVisible" width="30%" <el-dialog :close-on-click-modal="false" :title="$t('organization.modify')" :visible.sync="dialogOrgUpdateVisible" width="30%"
:destroy-on-close="true" :destroy-on-close="true"
@close="closeFunc"> @close="closeFunc">
<el-form :model="form" label-position="right" label-width="100px" size="small" :rules="rule" <el-form :model="form" label-position="right" label-width="100px" size="small" :rules="rule"
@ -95,7 +95,7 @@
</el-dialog> </el-dialog>
<!-- add organization member form --> <!-- add organization member form -->
<el-dialog :title="$t('member.create')" :visible.sync="dialogOrgMemberAddVisible" width="30%" <el-dialog :close-on-click-modal="false" :title="$t('member.create')" :visible.sync="dialogOrgMemberAddVisible" width="30%"
:destroy-on-close="true" :destroy-on-close="true"
@close="closeFunc"> @close="closeFunc">
<el-form :model="memberForm" ref="form" :rules="orgMemberRule" label-position="right" label-width="100px" <el-form :model="memberForm" ref="form" :rules="orgMemberRule" label-position="right" label-width="100px"
@ -133,7 +133,7 @@
</el-dialog> </el-dialog>
<!-- update organization member form --> <!-- update organization member form -->
<el-dialog :title="$t('member.modify')" :visible.sync="dialogOrgMemberUpdateVisible" width="30%" <el-dialog :close-on-click-modal="false" :title="$t('member.modify')" :visible.sync="dialogOrgMemberUpdateVisible" width="30%"
:destroy-on-close="true" :destroy-on-close="true"
@close="closeFunc"> @close="closeFunc">
<el-form :model="memberForm" label-position="right" label-width="100px" size="small" ref="updateUserForm"> <el-form :model="memberForm" label-position="right" label-width="100px" size="small" ref="updateUserForm">

View File

@ -28,7 +28,7 @@
</el-card> </el-card>
<!-- add workspace dialog --> <!-- add workspace dialog -->
<el-dialog :title="$t('workspace.create')" :visible.sync="dialogWsAddVisible" width="30%" @close="close"> <el-dialog :close-on-click-modal="false" :title="$t('workspace.create')" :visible.sync="dialogWsAddVisible" width="30%" @close="close">
<el-form :model="form" :rules="rules" ref="form" label-position="right" label-width="100px" size="small"> <el-form :model="form" :rules="rules" ref="form" label-position="right" label-width="100px" size="small">
<el-form-item :label="$t('commons.name')" prop="name"> <el-form-item :label="$t('commons.name')" prop="name">
<el-input v-model="form.name" autocomplete="off"/> <el-input v-model="form.name" autocomplete="off"/>
@ -56,7 +56,7 @@
</el-dialog> </el-dialog>
<!-- update workspace dialog --> <!-- update workspace dialog -->
<el-dialog :title="$t('workspace.update')" :visible.sync="dialogWsUpdateVisible" width="30%" @close="close"> <el-dialog :close-on-click-modal="false" :title="$t('workspace.update')" :visible.sync="dialogWsUpdateVisible" width="30%" @close="close">
<el-form :model="form" :rules="rules" ref="updateForm" label-position="right" label-width="100px" size="small"> <el-form :model="form" :rules="rules" ref="updateForm" label-position="right" label-width="100px" size="small">
<el-form-item :label="$t('commons.name')" prop="name"> <el-form-item :label="$t('commons.name')" prop="name">
<el-input v-model="form.name" autocomplete="off"/> <el-input v-model="form.name" autocomplete="off"/>
@ -85,7 +85,7 @@
</el-dialog> </el-dialog>
<!-- dialog of workspace member --> <!-- dialog of workspace member -->
<el-dialog :visible.sync="dialogWsMemberVisible" width="70%" :destroy-on-close="true" @close="closeWsMemberDialog" class="dialog-css"> <el-dialog :close-on-click-modal="false" :visible.sync="dialogWsMemberVisible" width="70%" :destroy-on-close="true" @close="closeWsMemberDialog" class="dialog-css">
<ms-table-header :condition.sync="dialogCondition" @create="addMember" @search="dialogSearch" <ms-table-header :condition.sync="dialogCondition" @create="addMember" @search="dialogSearch"
:create-tip="$t('member.create')" :title="$t('commons.member')"/> :create-tip="$t('member.create')" :title="$t('commons.member')"/>
<!-- organization member table --> <!-- organization member table -->
@ -111,7 +111,7 @@
</el-dialog> </el-dialog>
<!-- add workspace member dialog --> <!-- add workspace member dialog -->
<el-dialog :title="$t('member.create')" :visible.sync="dialogWsMemberAddVisible" width="30%" <el-dialog :close-on-click-modal="false" :title="$t('member.create')" :visible.sync="dialogWsMemberAddVisible" width="30%"
:destroy-on-close="true" :destroy-on-close="true"
@close="handleClose"> @close="handleClose">
<el-form :model="memberForm" ref="form" :rules="wsMemberRule" label-position="right" label-width="100px" <el-form :model="memberForm" ref="form" :rules="wsMemberRule" label-position="right" label-width="100px"
@ -149,7 +149,7 @@
</el-dialog> </el-dialog>
<!-- update workspace member dialog --> <!-- update workspace member dialog -->
<el-dialog :title="$t('member.modify')" :visible.sync="dialogWsMemberUpdateVisible" width="30%" <el-dialog :close-on-click-modal="false" :title="$t('member.modify')" :visible.sync="dialogWsMemberUpdateVisible" width="30%"
:destroy-on-close="true" :destroy-on-close="true"
@close="handleClose"> @close="handleClose">
<el-form :model="memberForm" label-position="right" label-width="100px" size="small" ref="updateUserForm"> <el-form :model="memberForm" label-position="right" label-width="100px" size="small" ref="updateUserForm">

View File

@ -45,6 +45,7 @@
</el-card> </el-card>
<el-dialog <el-dialog
:close-on-click-modal="false"
:title="$t('test_resource_pool.create_resource_pool')" :title="$t('test_resource_pool.create_resource_pool')"
:visible.sync="createVisible" width="70%" :visible.sync="createVisible" width="70%"
@closed="closeFunc" @closed="closeFunc"
@ -109,6 +110,7 @@
</el-dialog> </el-dialog>
<el-dialog <el-dialog
:close-on-click-modal="false"
v-loading="result.loading" v-loading="result.loading"
:title="$t('test_resource_pool.update_resource_pool')" :visible.sync="updateVisible" width="70%" :title="$t('test_resource_pool.update_resource_pool')" :visible.sync="updateVisible" width="70%"
:destroy-on-close="true" :destroy-on-close="true"

View File

@ -50,7 +50,7 @@
</el-card> </el-card>
<!--Create user--> <!--Create user-->
<el-dialog :title="$t('user.create')" :visible.sync="createVisible" width="35%" @closed="handleClose" <el-dialog :close-on-click-modal="false" :title="$t('user.create')" :visible.sync="createVisible" width="35%" @closed="handleClose"
:destroy-on-close="true"> :destroy-on-close="true">
<el-form :model="form" label-position="right" label-width="120px" size="small" :rules="rule" ref="createUserForm"> <el-form :model="form" label-position="right" label-width="120px" size="small" :rules="rule" ref="createUserForm">
<el-form-item label="ID" prop="id"> <el-form-item label="ID" prop="id">
@ -163,7 +163,7 @@
</el-dialog> </el-dialog>
<!--Modify user information in system settings--> <!--Modify user information in system settings-->
<el-dialog :title="$t('user.modify')" :visible.sync="updateVisible" width="35%" :destroy-on-close="true" <el-dialog :close-on-click-modal="false" :title="$t('user.modify')" :visible.sync="updateVisible" width="35%" :destroy-on-close="true"
@close="handleClose" v-loading="result.loading"> @close="handleClose" v-loading="result.loading">
<el-form :model="form" label-position="right" label-width="120px" size="small" :rules="rule" ref="updateUserForm"> <el-form :model="form" label-position="right" label-width="120px" size="small" :rules="rule" ref="updateUserForm">
<el-form-item label="ID" prop="id"> <el-form-item label="ID" prop="id">
@ -268,7 +268,7 @@
</template> </template>
</el-dialog> </el-dialog>
<!--Changing user password in system settings--> <!--Changing user password in system settings-->
<el-dialog :title="$t('member.edit_password')" :visible.sync="editPasswordVisible" width="30%" <el-dialog :close-on-click-modal="false" :title="$t('member.edit_password')" :visible.sync="editPasswordVisible" width="30%"
:destroy-on-close="true" @close="handleClose" left> :destroy-on-close="true" @close="handleClose" left>
<el-form :model="ruleForm" label-position="right" label-width="120px" size="small" :rules="rule" <el-form :model="ruleForm" label-position="right" label-width="120px" size="small" :rules="rule"
ref="editPasswordForm" class="demo-ruleForm"> ref="editPasswordForm" class="demo-ruleForm">

View File

@ -26,7 +26,7 @@
:total="total"/> :total="total"/>
</el-card> </el-card>
<el-dialog :title="$t('member.create')" :visible.sync="createVisible" width="30%" :destroy-on-close="true" <el-dialog :close-on-click-modal="false" :title="$t('member.create')" :visible.sync="createVisible" width="30%" :destroy-on-close="true"
@close="handleClose"> @close="handleClose">
<el-form :model="form" ref="form" :rules="rules" label-position="right" label-width="100px" size="small"> <el-form :model="form" ref="form" :rules="rules" label-position="right" label-width="100px" size="small">
<el-form-item :label="$t('commons.member')" prop="memberSign" :rules="{required: true, message: $t('member.input_id_or_email'), trigger: 'change'}"> <el-form-item :label="$t('commons.member')" prop="memberSign" :rules="{required: true, message: $t('member.input_id_or_email'), trigger: 'change'}">
@ -65,7 +65,7 @@
</template> </template>
</el-dialog> </el-dialog>
<el-dialog :title="$t('member.modify')" :visible.sync="updateVisible" width="30%" :destroy-on-close="true" <el-dialog :close-on-click-modal="false" :title="$t('member.modify')" :visible.sync="updateVisible" width="30%" :destroy-on-close="true"
@close="handleClose"> @close="handleClose">
<el-form :model="form" label-position="right" label-width="100px" size="small" ref="updateUserForm"> <el-form :model="form" label-position="right" label-width="100px" size="small" ref="updateUserForm">
<el-form-item label="ID" prop="id"> <el-form-item label="ID" prop="id">

View File

@ -2,9 +2,10 @@
<div> <div>
<el-dialog @close="close" <el-dialog :close-on-click-modal="false"
@close="close"
:title="operationType == 'edit' ? ( readOnly ? $t('test_track.case.view_case') : $t('test_track.case.edit_case')) : $t('test_track.case.create')" :title="operationType == 'edit' ? ( readOnly ? $t('test_track.case.view_case') : $t('test_track.case.edit_case')) : $t('test_track.case.create')"
:visible.sync="dialogFormVisible" width="65%" :close-on-click-modal="false"> :visible.sync="dialogFormVisible" width="65%">
<el-form :model="form" :rules="rules" ref="caseFrom" v-loading="result.loading"> <el-form :model="form" :rules="rules" ref="caseFrom" v-loading="result.loading">
@ -268,8 +269,8 @@ export default {
type: [{required: true, message: this.$t('test_track.case.input_type'), trigger: 'change'}], type: [{required: true, message: this.$t('test_track.case.input_type'), trigger: 'change'}],
testId: [{required: true, message: this.$t('commons.please_select'), trigger: 'change'}], testId: [{required: true, message: this.$t('commons.please_select'), trigger: 'change'}],
method: [{required: true, message: this.$t('test_track.case.input_method'), trigger: 'change'}], method: [{required: true, message: this.$t('test_track.case.input_method'), trigger: 'change'}],
prerequisite: [{max: 300, message: this.$t('test_track.length_less_than') + '300', trigger: 'blur'}], prerequisite: [{max: 500, message: this.$t('test_track.length_less_than') + '500', trigger: 'blur'}],
remark: [{max: 300, message: this.$t('test_track.length_less_than') + '300', trigger: 'blur'}] remark: [{max: 500, message: this.$t('test_track.length_less_than') + '500', trigger: 'blur'}]
}, },
formLabelWidth: "120px", formLabelWidth: "120px",
operationType: '', operationType: '',
@ -351,8 +352,8 @@ export default {
handleAddStep(index, data) { handleAddStep(index, data) {
let step = {}; let step = {};
step.num = data.num + 1; step.num = data.num + 1;
step.desc = null; step.desc = "";
step.result = null; step.result = "";
this.form.steps.forEach(step => { this.form.steps.forEach(step => {
if (step.num > data.num) { if (step.num > data.num) {
step.num++; step.num++;

View File

@ -1,7 +1,7 @@
<template> <template>
<ms-container> <ms-container>
<ms-main-container> <ms-main-container>
<el-row> <el-row :gutter="20">
<el-col :span="15"> <el-col :span="15">
<related-test-plan-list ref="relatedTestPlanList"/> <related-test-plan-list ref="relatedTestPlanList"/>
</el-col> </el-col>
@ -14,33 +14,34 @@
</template> </template>
<script> <script>
import RelatedTestPlanList from "./components/RelatedTestPlanList"; import RelatedTestPlanList from "./components/RelatedTestPlanList";
import TestCaseSideList from "./components/TestCaseSideList"; import TestCaseSideList from "./components/TestCaseSideList";
import MsContainer from "../../common/components/MsContainer"; import MsContainer from "../../common/components/MsContainer";
import MsMainContainer from "../../common/components/MsMainContainer"; import MsMainContainer from "../../common/components/MsMainContainer";
export default {
name: "TrackHome", export default {
components: {MsMainContainer, MsContainer, TestCaseSideList, RelatedTestPlanList}, name: "TrackHome",
watch: { components: {MsMainContainer, MsContainer, TestCaseSideList, RelatedTestPlanList},
'$route'(to,from) { watch: {
if (to.path.indexOf('/track/home') > -1) { '$route'(to, from) {
this.innitData(); if (to.path.indexOf('/track/home') > -1) {
} this.innitData();
}
},
methods: {
innitData() {
this.$refs.relatedTestPlanList.initTableData();
this.$refs.testCaseRecentList.initTableData();
}
} }
} }
},
methods: {
innitData() {
this.$refs.relatedTestPlanList.initTableData();
this.$refs.testCaseRecentList.initTableData();
}
}
}
</script> </script>
<style scoped> <style scoped>
.ms-main-container >>> .el-table { .ms-main-container >>> .el-table {
cursor:pointer; cursor: pointer;
} }
</style> </style>

View File

@ -1,8 +1,8 @@
<template> <template>
<div class="track-home-component"> <div>
<el-card> <el-card>
<template v-slot:header> <template v-slot:header>
<span class="title">{{title}}</span> <span class="title">{{ title }}</span>
</template> </template>
<slot></slot> <slot></slot>
</el-card> </el-card>
@ -10,27 +10,19 @@
</template> </template>
<script> <script>
export default { export default {
name: "HomeBaseComponent", name: "HomeBaseComponent",
props: { props: {
title: { title: {
type: String, type: String,
default() { default() {
this.$t('commons.title') this.$t('commons.title')
}
}
} }
} }
}
}
</script> </script>
<style scoped> <style scoped>
.el-card {
padding: 15px;
}
.track-home-component {
padding: 0 15px 15px;
}
</style> </style>

View File

@ -2,7 +2,8 @@
<div> <div>
<el-dialog :title="operationType == 'edit' ? $t('test_track.plan.edit_plan') : $t('test_track.plan.create_plan')" <el-dialog :close-on-click-modal="false"
:title="operationType == 'edit' ? $t('test_track.plan.edit_plan') : $t('test_track.plan.create_plan')"
:visible.sync="dialogFormVisible" :visible.sync="dialogFormVisible"
@close="close" @close="close"
width="65%"> width="65%">

View File

@ -23,22 +23,22 @@
</template> </template>
<script> <script>
import {Test} from "../../../../../api/test/model/ScenarioModel" import {Test} from "../../../../../api/test/model/ScenarioModel"
import MsApiScenarioConfig from "../../../../../api/test/components/ApiScenarioConfig"; import MsApiScenarioConfig from "../../../../../api/test/components/ApiScenarioConfig";
import MsContainer from "../../../../../common/components/MsContainer"; import MsContainer from "../../../../../common/components/MsContainer";
import MsMainContainer from "../../../../../common/components/MsMainContainer"; import MsMainContainer from "../../../../../common/components/MsMainContainer";
export default { export default {
name: "ApiTestDetail", name: "ApiTestDetail",
components: {MsMainContainer, MsContainer, MsApiScenarioConfig}, components: {MsMainContainer, MsContainer, MsApiScenarioConfig},
props: { props: {
id: String, id: String,
isReadOnly: { isReadOnly: {
type: Boolean, type: Boolean,
default: false default: false
} }
}, },
data() { data() {
return { return {
result: {}, result: {},
test: new Test(), test: new Test(),
@ -92,7 +92,7 @@
<style scoped> <style scoped>
.test-container { .test-container {
height: calc(100vh - 150px); height: calc(100vh - 155px);
min-height: 600px; min-height: 600px;
padding: 15px; padding: 15px;
} }

View File

@ -30,24 +30,24 @@
<script> <script>
import MsScenarioResult from "../../../../../api/report/components/ScenarioResult"; import MsScenarioResult from "../../../../../api/report/components/ScenarioResult";
import MsMetricChart from "../../../../../api/report/components/MetricChart"; import MsMetricChart from "../../../../../api/report/components/MetricChart";
import MsScenarioResults from "../../../../../api/report/components/ScenarioResults"; import MsScenarioResults from "../../../../../api/report/components/ScenarioResults";
import MsRequestResult from "../../../../../api/report/components/RequestResult"; import MsRequestResult from "../../../../../api/report/components/RequestResult";
import MsContainer from "../../../../../common/components/MsContainer"; import MsContainer from "../../../../../common/components/MsContainer";
import MsMainContainer from "../../../../../common/components/MsMainContainer"; import MsMainContainer from "../../../../../common/components/MsMainContainer";
export default { export default {
name: "ApiTestResult", name: "ApiTestResult",
components: {MsMainContainer, MsContainer, MsRequestResult, MsScenarioResults, MsMetricChart, MsScenarioResult}, components: {MsMainContainer, MsContainer, MsRequestResult, MsScenarioResults, MsMetricChart, MsScenarioResult},
data() { data() {
return { return {
activeName: "total", activeName: "total",
content: {}, content: {},
report: {}, report: {},
loading: true, loading: true,
fails: [], fails: [],
} }
}, },
props:['reportId'], props:['reportId'],
watch: { watch: {
@ -108,7 +108,7 @@
<style scoped> <style scoped>
.report-container { .report-container {
height: calc(100vh - 150px); height: calc(100vh - 155px);
min-height: 600px; min-height: 600px;
overflow-y: auto; overflow-y: auto;
} }

View File

@ -187,11 +187,14 @@ export default {
api_account: 'API account', api_account: 'API account',
api_password: 'API password', api_password: 'API password',
jira_url: 'JIRA url', jira_url: 'JIRA url',
jira_issuetype: 'JIRA issuetype',
input_api_account: 'please enter account', input_api_account: 'please enter account',
input_api_password: 'Please enter password', input_api_password: 'Please enter password',
input_jira_url: 'Please enter Jira address, for example: https://metersphere.atlassian.net/', input_jira_url: 'Please enter Jira address, for example: https://metersphere.atlassian.net/',
input_jira_issuetype: 'Please enter the question type',
use_tip: 'Usage guidelines:', use_tip: 'Usage guidelines:',
use_tip_one: 'Basic Auth account information is queried in "Company Management-Security and Integration-Open Platform"', use_tip_tapd: 'Basic Auth account information is queried in "Company Management-Security and Integration-Open Platform"',
use_tip_jira: 'Jira software server authentication information is account password, Jira software cloud authentication information is account + token (account settings-security-create API token)',
use_tip_two: 'After saving the Basic Auth account information, you need to manually associate the ID/key in the Metersphere project', use_tip_two: 'After saving the Basic Auth account information, you need to manually associate the ID/key in the Metersphere project',
link_the_project_now: 'Link the project now', link_the_project_now: 'Link the project now',
cancel_edit: 'Cancel edit', cancel_edit: 'Cancel edit',
@ -446,6 +449,7 @@ export default {
timeout_config: "Timeout Config", timeout_config: "Timeout Config",
connect_timeout: "Connect Timeout", connect_timeout: "Connect Timeout",
response_timeout: "Response Timeout", response_timeout: "Response Timeout",
follow_redirects: "Follow Redirects",
body_upload_limit_size: "The file size does not exceed 500 MB", body_upload_limit_size: "The file size does not exceed 500 MB",
assertions: { assertions: {
label: "Assertion", label: "Assertion",

View File

@ -188,11 +188,14 @@ export default {
api_account: 'API 账号', api_account: 'API 账号',
api_password: 'API 口令', api_password: 'API 口令',
jira_url: 'JIRA 地址', jira_url: 'JIRA 地址',
jira_issuetype: '问题类型',
input_api_account: '请输入账号', input_api_account: '请输入账号',
input_api_password: '请输入口令', input_api_password: '请输入口令',
input_jira_url: '请输入Jira地址https://metersphere.atlassian.net/', input_jira_url: '请输入Jira地址https://metersphere.atlassian.net/',
input_jira_issuetype: '请输入问题类型',
use_tip: '使用指引:', use_tip: '使用指引:',
use_tip_one: 'Basic Auth 账号信息在"公司管理-安全与集成-开放平台"中查询', use_tip_tapd: 'Tapd Basic Auth 账号信息在"公司管理-安全与集成-开放平台"中查询',
use_tip_jira: 'Jira software server 认证信息为 账号密码Jira software cloud 认证信息为 账号+令牌(账户设置-安全-创建API令牌)',
use_tip_two: '保存 Basic Auth 账号信息后,需要在 Metersphere 项目中手动关联 ID/key', use_tip_two: '保存 Basic Auth 账号信息后,需要在 Metersphere 项目中手动关联 ID/key',
link_the_project_now: '马上关联项目', link_the_project_now: '马上关联项目',
cancel_edit: '取消编辑', cancel_edit: '取消编辑',
@ -447,6 +450,7 @@ export default {
timeout_config: "超时设置", timeout_config: "超时设置",
connect_timeout: "连接超时", connect_timeout: "连接超时",
response_timeout: "响应超时", response_timeout: "响应超时",
follow_redirects: "跟随重定向",
body_upload_limit_size: "上传文件大小不能超过 500 MB!", body_upload_limit_size: "上传文件大小不能超过 500 MB!",
assertions: { assertions: {
label: "断言", label: "断言",

View File

@ -186,11 +186,14 @@ export default {
api_account: 'API 賬號', api_account: 'API 賬號',
api_password: 'API 口令', api_password: 'API 口令',
jira_url: 'JIRA 地址', jira_url: 'JIRA 地址',
jira_issuetype: '問題類型',
input_api_account: '請輸入賬號', input_api_account: '請輸入賬號',
input_api_password: '請輸入口令', input_api_password: '請輸入口令',
input_jira_url: '請輸入Jira地址https://metersphere.atlassian.net/', input_jira_url: '請輸入Jira地址https://metersphere.atlassian.net/',
input_jira_issuetype: '請輸入問題類型',
use_tip: '使用指引:', use_tip: '使用指引:',
use_tip_one: 'Basic Auth 賬號信息在"公司管理-安全與集成-開放平台"中查詢', use_tip_tapd: 'Basic Auth 賬號信息在"公司管理-安全與集成-開放平台"中查詢',
use_tip_jira: 'Jira software server 認證信息為 賬號密碼Jira software cloud 認證信息為 賬號+令牌(賬戶設置-安全-創建API令牌)',
use_tip_two: '保存 Basic Auth 賬號信息後,需要在 Metersphere 項目中手動關聯 ID/key', use_tip_two: '保存 Basic Auth 賬號信息後,需要在 Metersphere 項目中手動關聯 ID/key',
link_the_project_now: '馬上關聯項目', link_the_project_now: '馬上關聯項目',
cancel_edit: '取消編輯', cancel_edit: '取消編輯',