feat(接口定义): 合并master 最新代码

This commit is contained in:
fit2-zhao 2020-11-27 13:58:25 +08:00
commit 22108b3048
77 changed files with 993 additions and 778 deletions

View File

@ -6,11 +6,11 @@ ARG MS_VERSION=dev
RUN mkdir -p /opt/apps && mkdir -p /opt/jmeter RUN mkdir -p /opt/apps && mkdir -p /opt/jmeter
COPY backend/target/backend-1.4.jar /opt/apps COPY backend/target/backend-1.5.jar /opt/apps
COPY backend/target/classes/jmeter/ /opt/jmeter/ COPY backend/target/classes/jmeter/ /opt/jmeter/
ENV JAVA_APP_JAR=/opt/apps/backend-1.4.jar ENV JAVA_APP_JAR=/opt/apps/backend-1.5.jar
ENV AB_OFF=true ENV AB_OFF=true

View File

@ -7,7 +7,7 @@
<parent> <parent>
<artifactId>metersphere-server</artifactId> <artifactId>metersphere-server</artifactId>
<groupId>io.metersphere</groupId> <groupId>io.metersphere</groupId>
<version>1.4</version> <version>1.5</version>
</parent> </parent>
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>
@ -156,7 +156,7 @@
<dependency> <dependency>
<groupId>org.python</groupId> <groupId>org.python</groupId>
<artifactId>jython-standalone</artifactId> <artifactId>jython-standalone</artifactId>
<version>2.7.2</version> <version>2.7.0</version>
</dependency> </dependency>
<dependency> <dependency>

View File

@ -146,7 +146,12 @@ public class APIBackendListenerClient extends AbstractBackendListenerClient impl
ScenarioResult scenarioResult; ScenarioResult scenarioResult;
if (!scenarios.containsKey(scenarioId)) { if (!scenarios.containsKey(scenarioId)) {
scenarioResult = new ScenarioResult(); scenarioResult = new ScenarioResult();
scenarioResult.setId(scenarioId); try {
scenarioResult.setId(Integer.parseInt(scenarioId));
} catch (Exception e) {
scenarioResult.setId(0);
LogUtil.error("场景ID转换异常: " + e.getMessage());
}
scenarioResult.setName(scenarioName); scenarioResult.setName(scenarioName);
scenarios.put(scenarioId, scenarioResult); scenarios.put(scenarioId, scenarioResult);
} else { } else {
@ -203,13 +208,13 @@ public class APIBackendListenerClient extends AbstractBackendListenerClient impl
testPlanTestCaseService.updateTestCaseStates(ids, TestPlanTestCaseStatus.Failure.name()); testPlanTestCaseService.updateTestCaseStates(ids, TestPlanTestCaseStatus.Failure.name());
} }
} catch (Exception e) { } catch (Exception e) {
LogUtil.error(e); LogUtil.error(e.getMessage(), e);
} }
} }
try { try {
sendTask(report, testResult); sendTask(report, testResult);
} catch (Exception e) { } catch (Exception e) {
LogUtil.error(e); LogUtil.error(e.getMessage(), e);
} }
} }

View File

@ -8,7 +8,7 @@ import java.util.List;
@Data @Data
public class ScenarioResult { public class ScenarioResult {
private String id; private Integer id;
private String name; private String name;

View File

@ -50,7 +50,7 @@ public class JmeterDocumentParser {
} }
return documentToBytes(document); return documentToBytes(document);
} catch (Exception e) { } catch (Exception e) {
LogUtil.error(e); LogUtil.error(e.getMessage(), e);
return source; return source;
} }
} }
@ -161,7 +161,9 @@ public class JmeterDocumentParser {
break; break;
case "Argument.value": case "Argument.value":
String textContent = ele.getTextContent(); String textContent = ele.getTextContent();
if (StringUtils.startsWith(textContent, "@")) {
ele.setTextContent(ScriptEngineUtils.calculate(textContent)); ele.setTextContent(ScriptEngineUtils.calculate(textContent));
}
break; break;
default: default:
break; break;

View File

@ -8,6 +8,7 @@ import io.metersphere.api.dto.scenario.request.dubbo.RegistryCenter;
import io.metersphere.api.jmeter.JMeterService; import io.metersphere.api.jmeter.JMeterService;
import io.metersphere.api.parse.ApiImportParser; import io.metersphere.api.parse.ApiImportParser;
import io.metersphere.api.parse.ApiImportParserFactory; import io.metersphere.api.parse.ApiImportParserFactory;
import io.metersphere.api.parse.JmeterDocumentParser;
import io.metersphere.base.domain.*; import io.metersphere.base.domain.*;
import io.metersphere.base.mapper.ApiTestFileMapper; import io.metersphere.base.mapper.ApiTestFileMapper;
import io.metersphere.base.mapper.ApiTestMapper; import io.metersphere.base.mapper.ApiTestMapper;
@ -85,9 +86,9 @@ public class APITestService {
return extApiTestMapper.listByIds(request.getIds()); return extApiTestMapper.listByIds(request.getIds());
} }
public void create(SaveAPITestRequest request, List<MultipartFile> bodyFiles) { public void create(SaveAPITestRequest request, MultipartFile file, List<MultipartFile> bodyFiles) {
List<String> bodyUploadIds = new ArrayList<>(request.getBodyUploadIds()); List<String> bodyUploadIds = new ArrayList<>(request.getBodyUploadIds());
ApiTest test = createTest(request); ApiTest test = createTest(request, file);
createBodyFiles(test, bodyUploadIds, bodyFiles); createBodyFiles(test, bodyUploadIds, bodyFiles);
} }
private ApiTest createTest(SaveAPITestRequest request, MultipartFile file) { private ApiTest createTest(SaveAPITestRequest request, MultipartFile file) {
@ -101,13 +102,17 @@ public class APITestService {
return test; return test;
} }
public void update(SaveAPITestRequest request, List<MultipartFile> bodyFiles) { public void update(SaveAPITestRequest request, MultipartFile file, List<MultipartFile> bodyFiles) {
if (file == null) {
throw new IllegalArgumentException(Translator.get("file_cannot_be_null"));
}
deleteFileByTestId(request.getId()); deleteFileByTestId(request.getId());
List<String> bodyUploadIds = new ArrayList<>(request.getBodyUploadIds()); List<String> bodyUploadIds = new ArrayList<>(request.getBodyUploadIds());
request.setBodyUploadIds(null); request.setBodyUploadIds(null);
ApiTest test = updateTest(request); ApiTest test = updateTest(request);
createBodyFiles(test, bodyUploadIds, bodyFiles); createBodyFiles(test, bodyUploadIds, bodyFiles);
saveFile(test.getId(), file);
} }
private void createBodyFiles(ApiTest test, List<String> bodyUploadIds, List<MultipartFile> bodyFiles) { private void createBodyFiles(ApiTest test, List<String> bodyUploadIds, List<MultipartFile> bodyFiles) {
@ -126,7 +131,7 @@ public class APITestService {
file.createNewFile(); file.createNewFile();
FileUtil.copyStream(in, out); FileUtil.copyStream(in, out);
} catch (IOException e) { } catch (IOException e) {
LogUtil.error(e); LogUtil.error(e.getMessage(), e);
MSException.throwException(Translator.get("upload_fail")); MSException.throwException(Translator.get("upload_fail"));
} }
} }
@ -169,7 +174,7 @@ public class APITestService {
try { try {
FileUtil.copyDir(sourceFile, new File(targetDir)); FileUtil.copyDir(sourceFile, new File(targetDir));
} catch (IOException e) { } catch (IOException e) {
LogUtil.error(e); LogUtil.error(e.getMessage(), e);
MSException.throwException(Translator.get("upload_fail")); MSException.throwException(Translator.get("upload_fail"));
} }
} }
@ -212,14 +217,27 @@ public class APITestService {
} }
} }
public String run(SaveAPITestRequest request,String runMode) { public String run(SaveAPITestRequest request) {
ApiTestFile file = getFileByTestId(request.getId());
if (file == null) {
MSException.throwException(Translator.get("file_cannot_be_null"));
}
byte[] bytes = fileService.loadFileAsBytes(file.getFileId());
// 解析 xml 处理 mock 数据
bytes = JmeterDocumentParser.parse(bytes);
InputStream is = new ByteArrayInputStream(bytes);
APITestResult apiTest = get(request.getId()); APITestResult apiTest = get(request.getId());
if (SessionUtils.getUser() == null) { if (SessionUtils.getUser() == null) {
apiTest.setUserId(request.getUserId()); apiTest.setUserId(request.getUserId());
} }
String reportId = apiReportService.create(apiTest, request.getTriggerMode()); String reportId = apiReportService.create(apiTest, request.getTriggerMode());
/*if (request.getTriggerMode().equals("SCHEDULE")) {
List<Notice> notice = noticeService.queryNotice(request.getId());
mailService.sendHtml(reportId,notice,"api");
}*/
changeStatus(request.getId(), APITestStatus.Running); changeStatus(request.getId(), APITestStatus.Running);
jMeterService.run(request.getId(), request.getName(), request.getScenarioDefinition(), null,runMode); jMeterService.run(request.getId(), null, is);
return reportId; return reportId;
} }
@ -260,8 +278,6 @@ public class APITestService {
} }
private ApiTest createTest(SaveAPITestRequest request) { private ApiTest createTest(SaveAPITestRequest request) {
checkQuota();
request.setBodyUploadIds(null);
checkNameExist(request); checkNameExist(request);
final ApiTest test = new ApiTest(); final ApiTest test = new ApiTest();
test.setId(request.getId()); test.setId(request.getId());
@ -276,6 +292,14 @@ public class APITestService {
return test; return test;
} }
private void saveFile(String testId, MultipartFile file) {
final FileMetadata fileMetadata = fileService.saveFile(file);
ApiTestFile apiTestFile = new ApiTestFile();
apiTestFile.setTestId(testId);
apiTestFile.setFileId(fileMetadata.getId());
apiTestFileMapper.insert(apiTestFile);
}
private void deleteFileByTestId(String testId) { private void deleteFileByTestId(String testId) {
ApiTestFileExample ApiTestFileExample = new ApiTestFileExample(); ApiTestFileExample ApiTestFileExample = new ApiTestFileExample();
ApiTestFileExample.createCriteria().andTestIdEqualTo(testId); ApiTestFileExample.createCriteria().andTestIdEqualTo(testId);
@ -287,12 +311,17 @@ public class APITestService {
fileService.deleteFileByIds(fileIds); fileService.deleteFileByIds(fileIds);
} }
} }
private void saveFile(String testId, MultipartFile file) {
final FileMetadata fileMetadata = fileService.saveFile(file); private ApiTestFile getFileByTestId(String testId) {
ApiTestFile apiTestFile = new ApiTestFile(); ApiTestFileExample ApiTestFileExample = new ApiTestFileExample();
apiTestFile.setTestId(testId); ApiTestFileExample.createCriteria().andTestIdEqualTo(testId);
apiTestFile.setFileId(fileMetadata.getId()); final List<ApiTestFile> ApiTestFiles = apiTestFileMapper.selectByExample(ApiTestFileExample);
apiTestFileMapper.insert(apiTestFile); apiTestFileMapper.selectByExample(ApiTestFileExample);
if (!CollectionUtils.isEmpty(ApiTestFiles)) {
return ApiTestFiles.get(0);
} else {
return null;
}
} }
public void updateSchedule(Schedule request) { public void updateSchedule(Schedule request) {
@ -312,17 +341,6 @@ public class APITestService {
schedule.setType(ScheduleType.CRON.name()); schedule.setType(ScheduleType.CRON.name());
return schedule; return schedule;
} }
private ApiTestFile getFileByTestId(String testId) {
ApiTestFileExample ApiTestFileExample = new ApiTestFileExample();
ApiTestFileExample.createCriteria().andTestIdEqualTo(testId);
final List<ApiTestFile> ApiTestFiles = apiTestFileMapper.selectByExample(ApiTestFileExample);
apiTestFileMapper.selectByExample(ApiTestFileExample);
if (!CollectionUtils.isEmpty(ApiTestFiles)) {
return ApiTestFiles.get(0);
} else {
return null;
}
}
private void addOrUpdateApiTestCronJob(Schedule request) { private void addOrUpdateApiTestCronJob(Schedule request) {
scheduleService.addOrUpdateCronJob(request, ApiTestJob.getJobKey(request.getResourceId()), ApiTestJob.getTriggerKey(request.getResourceId()), ApiTestJob.class); scheduleService.addOrUpdateCronJob(request, ApiTestJob.getJobKey(request.getResourceId()), ApiTestJob.getTriggerKey(request.getResourceId()), ApiTestJob.class);
@ -398,7 +416,10 @@ public class APITestService {
return schedules; return schedules;
} }
public String runDebug(SaveAPITestRequest request, List<MultipartFile> bodyFiles,String runMode) { public String runDebug(SaveAPITestRequest request, MultipartFile file, List<MultipartFile> bodyFiles) {
if (file == null) {
throw new IllegalArgumentException(Translator.get("file_cannot_be_null"));
}
updateTest(request); updateTest(request);
APITestResult apiTest = get(request.getId()); APITestResult apiTest = get(request.getId());
List<String> bodyUploadIds = new ArrayList<>(request.getBodyUploadIds()); List<String> bodyUploadIds = new ArrayList<>(request.getBodyUploadIds());
@ -409,7 +430,17 @@ public class APITestService {
} }
String reportId = apiReportService.createDebugReport(apiTest); String reportId = apiReportService.createDebugReport(apiTest);
jMeterService.run(request.getId(), request.getName(), request.getScenarioDefinition(), reportId,runMode); InputStream is = null;
try {
byte[] bytes = file.getBytes();
// 解析 xml 处理 mock 数据
bytes = JmeterDocumentParser.parse(bytes);
is = new ByteArrayInputStream(bytes);
} catch (IOException e) {
LogUtil.error(e.getMessage(), e);
}
jMeterService.run(request.getId(), reportId, is);
return reportId; return reportId;
} }
@ -420,12 +451,10 @@ public class APITestService {
} }
} }
public void mergeCreate(SaveAPITestRequest request, List<String> selectIds) { public void mergeCreate(SaveAPITestRequest request, MultipartFile file, List<String> selectIds) {
ApiTest test = createTest(request); ApiTest test = createTest(request, file);
selectIds.forEach(sourceId -> copyBodyFiles(test.getId(), sourceId)); selectIds.forEach(sourceId -> {
} copyBodyFiles(test.getId(), sourceId);
});
public String getJMX(SaveAPITestRequest request) {
return jMeterService.getJMX(jMeterService.getHashTree(request.getId(), request.getName(), request.getScenarioDefinition()));
} }
} }

View File

@ -133,6 +133,7 @@
LEFT JOIN user ON user.id = r.user_id LEFT JOIN user ON user.id = r.user_id
<where> <where>
r.test_id = #{testId} r.test_id = #{testId}
and r.status != 'Debug'
</where> </where>
ORDER BY r.update_time DESC ORDER BY r.update_time DESC
</select> </select>

View File

@ -258,7 +258,8 @@
</select> </select>
<select id="list" resultType="io.metersphere.track.dto.TestCaseDTO"> <select id="list" resultType="io.metersphere.track.dto.TestCaseDTO">
select test_case.* from test_case select <include refid="io.metersphere.base.mapper.TestCaseMapper.Base_Column_List"/>
from test_case
<where> <where>
<if test="request.combine != null"> <if test="request.combine != null">
<include refid="combine"> <include refid="combine">

View File

@ -95,8 +95,7 @@ public interface ParamConstants {
PASSWORD("smtp.password", 4), PASSWORD("smtp.password", 4),
SSL("smtp.ssl", 5), SSL("smtp.ssl", 5),
TLS("smtp.tls", 6), TLS("smtp.tls", 6),
SMTP("smtp.smtp", 7); ANON("smtp.anon", 7);
/* ANON("smtp.anon", 7);*/
private String key; private String key;
private Integer value; private Integer value;

View File

@ -88,7 +88,7 @@ public class CompressUtils {
gzip.finish(); gzip.finish();
return obj.toByteArray(); return obj.toByteArray();
} catch (Exception e) { } catch (Exception e) {
LogUtil.error(e); LogUtil.error(e.getMessage(), e);
return data; return data;
} }
} }
@ -116,7 +116,7 @@ public class CompressUtils {
baos.flush(); baos.flush();
return baos.toByteArray(); return baos.toByteArray();
} catch (Exception e) { } catch (Exception e) {
LogUtil.error(e); LogUtil.error(e.getMessage(), e);
return data; return data;
} }
} }

View File

@ -48,10 +48,6 @@ public class JsonPathUtils {
String o_json_path = "$" + jsonPath.next().replaceAll("/", "."); String o_json_path = "$" + jsonPath.next().replaceAll("/", ".");
String value = JSONPath.eval(jsonObject, o_json_path).toString(); String value = JSONPath.eval(jsonObject, o_json_path).toString();
if(o_json_path.toLowerCase().contains("id")) {
continue;
}
if(value.equals("") || value.equals("[]") || o_json_path.equals("")) { if(value.equals("") || value.equals("[]") || o_json_path.equals("")) {
continue; continue;
} }

View File

@ -18,7 +18,7 @@ public class ScriptEngineUtils {
String script = IOUtils.toString(ScriptEngineUtils.class.getResource("/javascript/func.js"), StandardCharsets.UTF_8); String script = IOUtils.toString(ScriptEngineUtils.class.getResource("/javascript/func.js"), StandardCharsets.UTF_8);
engine.eval(script); engine.eval(script);
} catch (Exception e) { } catch (Exception e) {
LogUtil.error(e); LogUtil.error(e.getMessage(), e);
} }
} }
@ -26,7 +26,7 @@ public class ScriptEngineUtils {
try { try {
return engine.eval("calculate('" + input + "')").toString(); return engine.eval("calculate('" + input + "')").toString();
} catch (ScriptException e) { } catch (ScriptException e) {
LogUtil.error(e); LogUtil.error(e.getMessage(), e);
return input; return input;
} }
} }

View File

@ -44,7 +44,7 @@ public class ShiroConfig implements EnvironmentAware {
Map<String, String> filterChainDefinitionMap = shiroFilterFactoryBean.getFilterChainDefinitionMap(); Map<String, String> filterChainDefinitionMap = shiroFilterFactoryBean.getFilterChainDefinitionMap();
ShiroUtils.loadBaseFilterChain(filterChainDefinitionMap); ShiroUtils.loadBaseFilterChain(filterChainDefinitionMap);
filterChainDefinitionMap.put("/display/info", "anon"); filterChainDefinitionMap.put("/display/info", "anon");
filterChainDefinitionMap.put("/display/file/*", "anon"); filterChainDefinitionMap.put("/display/file/**", "anon");
filterChainDefinitionMap.put("/**", "apikey, authc"); filterChainDefinitionMap.put("/**", "apikey, authc");
return shiroFilterFactoryBean; return shiroFilterFactoryBean;
} }

View File

@ -53,13 +53,13 @@ public class TestResourcePoolController {
@GetMapping("list/all/valid") @GetMapping("list/all/valid")
@RequiresRoles(value = {RoleConstants.TEST_MANAGER, RoleConstants.TEST_USER, RoleConstants.TEST_VIEWER}, logical = Logical.OR) @RequiresRoles(value = {RoleConstants.TEST_MANAGER, RoleConstants.TEST_USER, RoleConstants.TEST_VIEWER}, logical = Logical.OR)
public List<TestResourcePool> listValidResourcePools() { public List<TestResourcePoolDTO> listValidResourcePools() {
return testResourcePoolService.listValidResourcePools(); return testResourcePoolService.listValidResourcePools();
} }
@GetMapping("list/quota/valid") @GetMapping("list/quota/valid")
@RequiresRoles(value = {RoleConstants.TEST_MANAGER, RoleConstants.TEST_USER, RoleConstants.TEST_VIEWER}, logical = Logical.OR) @RequiresRoles(value = {RoleConstants.TEST_MANAGER, RoleConstants.TEST_USER, RoleConstants.TEST_VIEWER}, logical = Logical.OR)
public List<TestResourcePool> listValidQuotaResourcePools() { public List<TestResourcePoolDTO> listValidQuotaResourcePools() {
return testResourcePoolService.listValidQuotaResourcePools(); return testResourcePoolService.listValidQuotaResourcePools();
} }

View File

@ -7,4 +7,5 @@ import lombok.Setter;
@Setter @Setter
public class QueryResourcePoolRequest { public class QueryResourcePoolRequest {
private String name; private String name;
private String status;
} }

View File

@ -72,13 +72,15 @@ public class AppStartListener implements ApplicationListener<ApplicationReadyEve
*/ */
private void loadJars() { private void loadJars() {
List<JarConfig> jars = jarConfigService.list(); List<JarConfig> jars = jarConfigService.list();
try {
jars.forEach(jarConfig -> { jars.forEach(jarConfig -> {
try {
NewDriverManager.loadJar(jarConfig.getPath()); NewDriverManager.loadJar(jarConfig.getPath());
});
} catch (Exception e) { } catch (Exception e) {
e.printStackTrace(); e.printStackTrace();
LogUtil.error(e.getMessage(), e); LogUtil.error(e.getMessage(), e);
} }
});
} }
} }

View File

@ -66,7 +66,7 @@ public class DingTaskService {
try { try {
response = client.execute(request); response = client.execute(request);
} catch (ApiException e) { } catch (ApiException e) {
LogUtil.error(e); LogUtil.error(e.getMessage(), e);
} }
System.out.println(response.getErrcode()); System.out.println(response.getErrcode());
} }

View File

@ -2,10 +2,7 @@ package io.metersphere.notice.service;
import io.metersphere.base.domain.*; import io.metersphere.base.domain.*;
import io.metersphere.base.mapper.UserMapper; import io.metersphere.base.mapper.UserMapper;
import io.metersphere.commons.constants.APITestStatus; import io.metersphere.commons.constants.*;
import io.metersphere.commons.constants.NoticeConstants;
import io.metersphere.commons.constants.ParamConstants;
import io.metersphere.commons.constants.PerformanceTestStatus;
import io.metersphere.commons.user.SessionUser; import io.metersphere.commons.user.SessionUser;
import io.metersphere.commons.utils.EncryptUtils; import io.metersphere.commons.utils.EncryptUtils;
import io.metersphere.commons.utils.LogUtil; import io.metersphere.commons.utils.LogUtil;
@ -22,6 +19,7 @@ import io.metersphere.track.request.testreview.SaveTestCaseReviewRequest;
import org.apache.commons.collections4.CollectionUtils; import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.collections4.MapUtils; import org.apache.commons.collections4.MapUtils;
import org.apache.commons.io.IOUtils; import org.apache.commons.io.IOUtils;
import org.apache.commons.lang3.BooleanUtils;
import org.apache.commons.lang3.RegExUtils; import org.apache.commons.lang3.RegExUtils;
import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.StringUtils;
import org.springframework.mail.MailException; import org.springframework.mail.MailException;
@ -67,7 +65,7 @@ public class MailService {
} }
sendApiOrLoadNotification(addresseeIdList(messageDetail, userIds, eventType), context, performanceTemplate, loadTestReport.getTriggerMode()); sendApiOrLoadNotification(addresseeIdList(messageDetail, userIds, eventType), context, performanceTemplate, loadTestReport.getTriggerMode());
} catch (Exception e) { } catch (Exception e) {
LogUtil.error(e); LogUtil.error(e.getMessage(), e);
} }
} }
@ -88,7 +86,7 @@ public class MailService {
} }
sendApiOrLoadNotification(addresseeIdList(messageDetail, userIds, eventType), context, apiTemplate, apiTestReport.getTriggerMode()); sendApiOrLoadNotification(addresseeIdList(messageDetail, userIds, eventType), context, apiTemplate, apiTestReport.getTriggerMode());
} catch (Exception e) { } catch (Exception e) {
LogUtil.error(e); LogUtil.error(e.getMessage(), e);
} }
} }
@ -120,7 +118,7 @@ public class MailService {
try { try {
javaMailSender.send(mimeMessage); javaMailSender.send(mimeMessage);
} catch (MailException e) { } catch (MailException e) {
LogUtil.error(e); LogUtil.error(e.getMessage(), e);
} }
} }
//测试评审 //测试评审
@ -131,7 +129,7 @@ public class MailService {
String endTemplate = IOUtils.toString(this.getClass().getResource("/mail/ReviewEnd.html"), StandardCharsets.UTF_8); String endTemplate = IOUtils.toString(this.getClass().getResource("/mail/ReviewEnd.html"), StandardCharsets.UTF_8);
sendReviewNotice(addresseeIdList(messageDetail, userIds, eventType), context, endTemplate); sendReviewNotice(addresseeIdList(messageDetail, userIds, eventType), context, endTemplate);
} catch (Exception e) { } catch (Exception e) {
LogUtil.error(e); LogUtil.error(e.getMessage(), e);
} }
} }
@ -141,7 +139,7 @@ public class MailService {
String endTemplate = IOUtils.toString(this.getClass().getResource("/mail/ReviewDelete.html"), StandardCharsets.UTF_8); String endTemplate = IOUtils.toString(this.getClass().getResource("/mail/ReviewDelete.html"), StandardCharsets.UTF_8);
sendReviewNotice(addresseeIdList(messageDetail, userIds, eventType), context, endTemplate); sendReviewNotice(addresseeIdList(messageDetail, userIds, eventType), context, endTemplate);
} catch (Exception e) { } catch (Exception e) {
LogUtil.error(e); LogUtil.error(e.getMessage(), e);
} }
} }
@ -158,7 +156,7 @@ public class MailService {
String commentTemplate = IOUtils.toString(this.getClass().getResource("/mail/ReviewComments.html"), StandardCharsets.UTF_8); String commentTemplate = IOUtils.toString(this.getClass().getResource("/mail/ReviewComments.html"), StandardCharsets.UTF_8);
sendReviewNotice(addresseeIdList(messageDetail, userIds, eventType), context, commentTemplate); sendReviewNotice(addresseeIdList(messageDetail, userIds, eventType), context, commentTemplate);
} catch (Exception e) { } catch (Exception e) {
LogUtil.error(e); LogUtil.error(e.getMessage(), e);
} }
} }
@ -168,7 +166,7 @@ public class MailService {
String reviewerTemplate = IOUtils.toString(this.getClass().getResource("/mail/ReviewInitiate.html"), StandardCharsets.UTF_8); String reviewerTemplate = IOUtils.toString(this.getClass().getResource("/mail/ReviewInitiate.html"), StandardCharsets.UTF_8);
sendReviewNotice(addresseeIdList(messageDetail, userIds, eventType), context, reviewerTemplate); sendReviewNotice(addresseeIdList(messageDetail, userIds, eventType), context, reviewerTemplate);
} catch (Exception e) { } catch (Exception e) {
LogUtil.error(e); LogUtil.error(e.getMessage(), e);
} }
} }
@ -207,7 +205,7 @@ public class MailService {
String endTemplate = IOUtils.toString(this.getClass().getResource("/mail/TestPlanStart.html"), StandardCharsets.UTF_8); String endTemplate = IOUtils.toString(this.getClass().getResource("/mail/TestPlanStart.html"), StandardCharsets.UTF_8);
sendTestPlanNotice(addresseeIdList(messageDetail, userIds, eventType), context, endTemplate); sendTestPlanNotice(addresseeIdList(messageDetail, userIds, eventType), context, endTemplate);
} catch (Exception e) { } catch (Exception e) {
LogUtil.error(e); LogUtil.error(e.getMessage(), e);
} }
} }
@ -219,7 +217,7 @@ public class MailService {
String endTemplate = IOUtils.toString(this.getClass().getResource("/mail/TestPlanEnd.html"), StandardCharsets.UTF_8); String endTemplate = IOUtils.toString(this.getClass().getResource("/mail/TestPlanEnd.html"), StandardCharsets.UTF_8);
sendTestPlanNotice(addresseeIdList(messageDetail, userIds, eventType), context, endTemplate); sendTestPlanNotice(addresseeIdList(messageDetail, userIds, eventType), context, endTemplate);
} catch (Exception e) { } catch (Exception e) {
LogUtil.error(e); LogUtil.error(e.getMessage(), e);
} }
} }
@ -231,7 +229,7 @@ public class MailService {
String endTemplate = IOUtils.toString(this.getClass().getResource("/mail/TestPlanDelete.html"), StandardCharsets.UTF_8); String endTemplate = IOUtils.toString(this.getClass().getResource("/mail/TestPlanDelete.html"), StandardCharsets.UTF_8);
sendTestPlanNotice(addresseeIdList(messageDetail, userIds, eventType), context, endTemplate); sendTestPlanNotice(addresseeIdList(messageDetail, userIds, eventType), context, endTemplate);
} catch (Exception e) { } catch (Exception e) {
LogUtil.error(e); LogUtil.error(e.getMessage(), e);
} }
} }
@ -268,7 +266,7 @@ public class MailService {
String endTemplate = IOUtils.toString(this.getClass().getResource("/mail/IssuesCreate.html"), StandardCharsets.UTF_8); String endTemplate = IOUtils.toString(this.getClass().getResource("/mail/IssuesCreate.html"), StandardCharsets.UTF_8);
sendIssuesNotice(addresseeIdList(messageDetail, userIds, eventType), context, endTemplate); sendIssuesNotice(addresseeIdList(messageDetail, userIds, eventType), context, endTemplate);
} catch (Exception e) { } catch (Exception e) {
LogUtil.error(e); LogUtil.error(e.getMessage(), e);
} }
} }
@ -321,6 +319,15 @@ public class MailService {
context.put("start", start); context.put("start", start);
context.put("end", end); context.put("end", end);
context.put("id", reviewRequest.getId()); context.put("id", reviewRequest.getId());
String status = "";
if (StringUtils.equals(TestPlanStatus.Underway.name(), reviewRequest.getStatus())) {
status = "进行中";
} else if (StringUtils.equals(TestPlanStatus.Prepare.name(), reviewRequest.getStatus())) {
status = "未开始";
} else if (StringUtils.equals(TestPlanStatus.Completed.name(), reviewRequest.getStatus())) {
status = "已完成";
}
context.put("status", status);
return context; return context;
} }
@ -347,19 +354,29 @@ public class MailService {
context.put("start", start); context.put("start", start);
context.put("end", end); context.put("end", end);
context.put("id", testPlan.getId()); context.put("id", testPlan.getId());
String status = "";
if (StringUtils.equals(TestPlanStatus.Underway.name(), testPlan.getStatus())) {
status = "进行中";
} else if (StringUtils.equals(TestPlanStatus.Prepare.name(), testPlan.getStatus())) {
status = "未开始";
} else if (StringUtils.equals(TestPlanStatus.Completed.name(), testPlan.getStatus())) {
status = "已完成";
}
context.put("status", status);
User user = userMapper.selectByPrimaryKey(testPlan.getCreator()); User user = userMapper.selectByPrimaryKey(testPlan.getCreator());
context.put("creator", user.getName()); context.put("creator", user.getName());
return context; return context;
} }
private JavaMailSenderImpl getMailSender() { private JavaMailSenderImpl getMailSender() {
Properties props = new Properties();
JavaMailSenderImpl javaMailSender = new JavaMailSenderImpl(); JavaMailSenderImpl javaMailSender = new JavaMailSenderImpl();
List<SystemParameter> paramList = systemParameterService.getParamList(ParamConstants.Classify.MAIL.getValue()); List<SystemParameter> paramList = systemParameterService.getParamList(ParamConstants.Classify.MAIL.getValue());
javaMailSender.setDefaultEncoding("UTF-8"); javaMailSender.setDefaultEncoding("UTF-8");
javaMailSender.setProtocol("smtps"); javaMailSender.setProtocol("smtp");
props.put("mail.smtp.auth", "true");
for (SystemParameter p : paramList) { for (SystemParameter p : paramList) {
switch (p.getParamKey()) { switch (p.getParamKey()) {
case "smtp.host": case "smtp.host":
@ -374,14 +391,30 @@ public class MailService {
case "smtp.password": case "smtp.password":
javaMailSender.setPassword(EncryptUtils.aesDecrypt(p.getParamValue()).toString()); javaMailSender.setPassword(EncryptUtils.aesDecrypt(p.getParamValue()).toString());
break; break;
case "smtp.ssl":
javaMailSender.setProtocol("smtps");
if (BooleanUtils.toBoolean(p.getParamValue())) {
props.put("mail.smtp.socketFactory.class", "javax.net.ssl.SSLSocketFactory");
}
break;
case "smtp.tls":
String result = BooleanUtils.toString(BooleanUtils.toBoolean(p.getParamValue()), "true", "false");
props.put("mail.smtp.starttls.enable", result);
props.put("mail.smtp.starttls.required", result);
break;
case "smtp.anon":
boolean isAnon = BooleanUtils.toBoolean(p.getParamValue());
if (isAnon) {
props.put("mail.smtp.auth", "false");
javaMailSender.setUsername(null);
javaMailSender.setPassword(null);
}
break;
default: default:
break; break;
} }
} }
Properties props = new Properties();
props.put("mail.smtp.auth", "true");
props.put("mail.smtp.starttls.enable", "true");
props.put("mail.smtp.starttls.required", "true");
props.put("mail.smtp.timeout", "30000"); props.put("mail.smtp.timeout", "30000");
props.put("mail.smtp.connectiontimeout", "5000"); props.put("mail.smtp.connectiontimeout", "5000");
javaMailSender.setJavaMailProperties(props); javaMailSender.setJavaMailProperties(props);
@ -396,6 +429,7 @@ public class MailService {
} else { } else {
template = RegExUtils.replaceAll(template, "\\$\\{" + k + "}", "未设置"); template = RegExUtils.replaceAll(template, "\\$\\{" + k + "}", "未设置");
} }
} }
} }
return template; return template;
@ -405,7 +439,7 @@ public class MailService {
List<String> addresseeIdList = new ArrayList<>(); List<String> addresseeIdList = new ArrayList<>();
if (StringUtils.equals(eventType, messageDetail.getEvent())) { if (StringUtils.equals(eventType, messageDetail.getEvent())) {
messageDetail.getUserIds().forEach(u -> { messageDetail.getUserIds().forEach(u -> {
if (!StringUtils.equals(NoticeConstants.EXECUTOR, u) && !StringUtils.equals(NoticeConstants.EXECUTOR, u) && !StringUtils.equals(NoticeConstants.MAINTAINER, u)) { if (!StringUtils.equals(NoticeConstants.EXECUTOR, u) && !StringUtils.equals(NoticeConstants.FOUNDER, u) && !StringUtils.equals(NoticeConstants.MAINTAINER, u)) {
addresseeIdList.add(u); addresseeIdList.add(u);
} }
if (StringUtils.equals(NoticeConstants.CREATE, eventType) && StringUtils.equals(NoticeConstants.EXECUTOR, u)) { if (StringUtils.equals(NoticeConstants.CREATE, eventType) && StringUtils.equals(NoticeConstants.EXECUTOR, u)) {

View File

@ -13,6 +13,7 @@ import io.metersphere.notice.controller.request.MessageRequest;
import io.metersphere.notice.domain.MessageDetail; import io.metersphere.notice.domain.MessageDetail;
import io.metersphere.notice.domain.MessageSettingDetail; import io.metersphere.notice.domain.MessageSettingDetail;
import org.apache.commons.collections.CollectionUtils; import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional; import org.springframework.transaction.annotation.Transactional;
@ -51,7 +52,7 @@ public class NoticeService {
long time = System.currentTimeMillis(); long time = System.currentTimeMillis();
String identification = UUID.randomUUID().toString(); String identification = UUID.randomUUID().toString();
list.getUserIds().forEach(m -> { list.getUserIds().forEach(m -> {
checkUserIdExist(m, list); checkUserIdExist(m, list,orgId);
MessageTask message = new MessageTask(); MessageTask message = new MessageTask();
message.setId(UUID.randomUUID().toString()); message.setId(UUID.randomUUID().toString());
message.setEvent(list.getEvent()); message.setEvent(list.getEvent());
@ -68,9 +69,13 @@ public class NoticeService {
}); });
} }
private void checkUserIdExist(String userId, MessageDetail list) { private void checkUserIdExist(String userId, MessageDetail list,String orgId) {
MessageTaskExample example = new MessageTaskExample(); MessageTaskExample example = new MessageTaskExample();
example.createCriteria().andUserIdEqualTo(userId).andEventEqualTo(list.getEvent()).andTypeEqualTo(list.getType()).andTaskTypeEqualTo(list.getTaskType()).andWebhookEqualTo(list.getWebhook()); if (StringUtils.isBlank(list.getTestId())) {
example.createCriteria().andUserIdEqualTo(userId).andEventEqualTo(list.getEvent()).andTypeEqualTo(list.getType()).andTaskTypeEqualTo(list.getTaskType()).andWebhookEqualTo(list.getWebhook()).andOrganizationIdEqualTo(orgId);
} else {
example.createCriteria().andUserIdEqualTo(userId).andEventEqualTo(list.getEvent()).andTypeEqualTo(list.getType()).andTaskTypeEqualTo(list.getTaskType()).andWebhookEqualTo(list.getWebhook()).andTestIdEqualTo(list.getTestId()).andOrganizationIdEqualTo(orgId);
}
if (messageTaskMapper.countByExample(example) > 0) { if (messageTaskMapper.countByExample(example) > 0) {
MSException.throwException(Translator.get("message_task_already_exists")); MSException.throwException(Translator.get("message_task_already_exists"));
} }

View File

@ -59,7 +59,7 @@ public class WxChatTaskService {
SendResult result = WxChatbotClient.send(Webhook, message); SendResult result = WxChatbotClient.send(Webhook, message);
System.out.println(result); System.out.println(result);
} catch (IOException e) { } catch (IOException e) {
LogUtil.error(e); LogUtil.error(e.getMessage(), e);
} }
} }

View File

@ -139,10 +139,10 @@ public class EngineFactory {
String content = engineSourceParser.parse(engineContext, source); String content = engineSourceParser.parse(engineContext, source);
engineContext.setContent(content); engineContext.setContent(content);
} catch (MSException e) { } catch (MSException e) {
LogUtil.error(e); LogUtil.error(e.getMessage(), e);
throw e; throw e;
} catch (Exception e) { } catch (Exception e) {
LogUtil.error(e); LogUtil.error(e.getMessage(), e);
MSException.throwException(e); MSException.throwException(e);
} }

View File

@ -64,10 +64,10 @@ public class DockerTestEngine extends AbstractEngine {
try { try {
context = EngineFactory.createContext(loadTest, resource.getId(), ratio, this.getStartTime(), this.getReportId(), resourceIndex); context = EngineFactory.createContext(loadTest, resource.getId(), ratio, this.getStartTime(), this.getReportId(), resourceIndex);
} catch (MSException e) { } catch (MSException e) {
LogUtil.error(e); LogUtil.error(e.getMessage(), e);
throw e; throw e;
} catch (Exception e) { } catch (Exception e) {
LogUtil.error(e); LogUtil.error(e.getMessage(), e);
MSException.throwException(e); MSException.throwException(e);
} }

View File

@ -65,7 +65,7 @@ public class PerformanceNoticeTask {
//查询定时任务是否关闭 //查询定时任务是否关闭
Thread.sleep(1000 * 30);// 每分钟检查 loadtest 的状态 Thread.sleep(1000 * 30);// 每分钟检查 loadtest 的状态
} catch (InterruptedException e) { } catch (InterruptedException e) {
LogUtil.error(e); LogUtil.error(e.getMessage(), e);
} }
} }
}); });

View File

@ -258,7 +258,7 @@ public class PerformanceTestService {
soc.close(); soc.close();
} }
} catch (Exception e) { } catch (Exception e) {
LogUtil.error(e); LogUtil.error(e.getMessage(), e);
MSException.throwException(Translator.get("load_test_kafka_invalid")); MSException.throwException(Translator.get("load_test_kafka_invalid"));
} }
} }
@ -304,7 +304,7 @@ public class PerformanceTestService {
} catch (MSException e) { } catch (MSException e) {
// 启动失败之后清理任务 // 启动失败之后清理任务
engine.stop(); engine.stop();
LogUtil.error(e); LogUtil.error(e.getMessage(), e);
loadTest.setStatus(PerformanceTestStatus.Error.name()); loadTest.setStatus(PerformanceTestStatus.Error.name());
loadTest.setDescription(e.getMessage()); loadTest.setDescription(e.getMessage());
loadTestMapper.updateByPrimaryKeySelective(loadTest); loadTestMapper.updateByPrimaryKeySelective(loadTest);

View File

@ -119,7 +119,7 @@ public class JarConfigService {
file.createNewFile(); file.createNewFile();
FileUtil.copyStream(in, out); FileUtil.copyStream(in, out);
} catch (IOException e) { } catch (IOException e) {
LogUtil.error(e); LogUtil.error(e.getMessage(), e);
MSException.throwException(Translator.get("upload_fail")); MSException.throwException(Translator.get("upload_fail"));
} }
return filePath; return filePath;

View File

@ -87,7 +87,14 @@ public class SystemParameterService {
javaMailSender.setUsername(hashMap.get(ParamConstants.MAIL.ACCOUNT.getKey())); javaMailSender.setUsername(hashMap.get(ParamConstants.MAIL.ACCOUNT.getKey()));
javaMailSender.setPassword(hashMap.get(ParamConstants.MAIL.PASSWORD.getKey())); javaMailSender.setPassword(hashMap.get(ParamConstants.MAIL.PASSWORD.getKey()));
Properties props = new Properties(); Properties props = new Properties();
boolean isAnon = Boolean.parseBoolean(hashMap.get(ParamConstants.MAIL.ANON.getKey()));
if (isAnon) {
props.put("mail.smtp.auth", "false");
javaMailSender.setUsername(null);
javaMailSender.setPassword(null);
} else {
props.put("mail.smtp.auth", "true"); props.put("mail.smtp.auth", "true");
}
if (BooleanUtils.toBoolean(hashMap.get(ParamConstants.MAIL.SSL.getKey()))) { if (BooleanUtils.toBoolean(hashMap.get(ParamConstants.MAIL.SSL.getKey()))) {
props.put("mail.smtp.socketFactory.class", "javax.net.ssl.SSLSocketFactory"); props.put("mail.smtp.socketFactory.class", "javax.net.ssl.SSLSocketFactory");
} }
@ -100,7 +107,7 @@ public class SystemParameterService {
try { try {
javaMailSender.testConnection(); javaMailSender.testConnection();
} catch (MessagingException e) { } catch (MessagingException e) {
LogUtil.error(e); LogUtil.error(e.getMessage(), e);
MSException.throwException(Translator.get("connection_failed")); MSException.throwException(Translator.get("connection_failed"));
} }
} }

View File

@ -135,7 +135,7 @@ public class TestResourcePoolService {
MSException.throwException("Resource Pool is invalid."); MSException.throwException("Resource Pool is invalid.");
} }
} catch (IllegalAccessException | InvocationTargetException e) { } catch (IllegalAccessException | InvocationTargetException e) {
LogUtil.error(e); LogUtil.error(e.getMessage(), e);
} }
} }
@ -145,6 +145,9 @@ public class TestResourcePoolService {
if (StringUtils.isNotBlank(request.getName())) { if (StringUtils.isNotBlank(request.getName())) {
criteria.andNameLike(StringUtils.wrapIfMissing(request.getName(), "%")); criteria.andNameLike(StringUtils.wrapIfMissing(request.getName(), "%"));
} }
if (StringUtils.isNotBlank(request.getStatus())) {
criteria.andStatusEqualTo(request.getStatus());
}
example.setOrderByClause("update_time desc"); example.setOrderByClause("update_time desc");
List<TestResourcePool> testResourcePools = testResourcePoolMapper.selectByExample(example); List<TestResourcePool> testResourcePools = testResourcePoolMapper.selectByExample(example);
List<TestResourcePoolDTO> testResourcePoolDTOS = new ArrayList<>(); List<TestResourcePoolDTO> testResourcePoolDTOS = new ArrayList<>();
@ -158,7 +161,7 @@ public class TestResourcePoolService {
testResourcePoolDTO.setResources(testResources); testResourcePoolDTO.setResources(testResources);
testResourcePoolDTOS.add(testResourcePoolDTO); testResourcePoolDTOS.add(testResourcePoolDTO);
} catch (IllegalAccessException | InvocationTargetException e) { } catch (IllegalAccessException | InvocationTargetException e) {
LogUtil.error(e); LogUtil.error(e.getMessage(), e);
} }
}); });
return testResourcePoolDTOS; return testResourcePoolDTOS;
@ -207,7 +210,7 @@ public class TestResourcePoolService {
ResponseEntity<String> entity = restTemplateWithTimeOut.getForEntity(String.format(nodeControllerUrl, node.getIp(), node.getPort()), String.class); ResponseEntity<String> entity = restTemplateWithTimeOut.getForEntity(String.format(nodeControllerUrl, node.getIp(), node.getPort()), String.class);
return HttpStatus.OK.equals(entity.getStatusCode()); return HttpStatus.OK.equals(entity.getStatusCode());
} catch (Exception e) { } catch (Exception e) {
LogUtil.error(e); LogUtil.error(e.getMessage(), e);
return false; return false;
} }
} }
@ -232,7 +235,7 @@ public class TestResourcePoolService {
return testResourcePoolMapper.selectByPrimaryKey(resourcePoolId); return testResourcePoolMapper.selectByPrimaryKey(resourcePoolId);
} }
public List<TestResourcePool> listValidResourcePools() { public List<TestResourcePoolDTO> listValidResourcePools() {
QueryResourcePoolRequest request = new QueryResourcePoolRequest(); QueryResourcePoolRequest request = new QueryResourcePoolRequest();
List<TestResourcePoolDTO> testResourcePools = listResourcePools(request); List<TestResourcePoolDTO> testResourcePools = listResourcePools(request);
// 重新校验 pool // 重新校验 pool
@ -249,16 +252,15 @@ public class TestResourcePoolService {
testResourcePoolMapper.updateByPrimaryKeySelective(pool); testResourcePoolMapper.updateByPrimaryKeySelective(pool);
} }
} }
TestResourcePoolExample example = new TestResourcePoolExample(); request.setStatus(VALID.name());
example.createCriteria().andStatusEqualTo(ResourceStatusEnum.VALID.name()); return listResourcePools(request);
return testResourcePoolMapper.selectByExample(example);
} }
public List<TestResourcePool> listValidQuotaResourcePools() { public List<TestResourcePoolDTO> listValidQuotaResourcePools() {
return filterQuota(listValidResourcePools()); return filterQuota(listValidResourcePools());
} }
private List<TestResourcePool> filterQuota(List<TestResourcePool> list) { private List<TestResourcePoolDTO> filterQuota(List<TestResourcePoolDTO> list) {
QuotaService quotaService = CommonBeanFactory.getBean(QuotaService.class); QuotaService quotaService = CommonBeanFactory.getBean(QuotaService.class);
if (quotaService != null) { if (quotaService != null) {
Set<String> pools = quotaService.getQuotaResourcePools(); Set<String> pools = quotaService.getQuotaResourcePools();

View File

@ -1,26 +0,0 @@
package io.metersphere.track.issue;
import io.metersphere.commons.utils.EncryptUtils;
public class ZentaoUtils {
/**
* @param code Zentao 应用代号
* @param key Zentao 密钥
* @return token
*/
public static String getToken(String code, String key, String time) {
return (String) EncryptUtils.md5Encrypt(code + key + time);
}
/**
* @param url Zentao url
* @param code Zentao 应用代号
* @param key Zentao 密钥
* @return url
*/
public static String getUrl(String url, String code, String key) {
String time = String.valueOf(System.currentTimeMillis());;
return url + "api.php?" + "code=" + code + "&time=" + time + "&token=" + getToken(code, key, time);
}
}

View File

@ -116,7 +116,7 @@ public class IssuesService {
} }
}); });
} catch (Exception e) { } catch (Exception e) {
LogUtil.error(e); LogUtil.error(e.getMessage(), e);
} }
} }

View File

@ -84,7 +84,7 @@ public class TestCaseCommentService {
} }
}); });
} catch (Exception e) { } catch (Exception e) {
LogUtil.error(e); LogUtil.error(e.getMessage(), e);
} }
} }

View File

@ -127,7 +127,7 @@ public class TestCaseReviewService {
} }
}); });
} catch (Exception e) { } catch (Exception e) {
LogUtil.error(e); LogUtil.error(e.getMessage(), e);
} }
} }
@ -187,7 +187,6 @@ public class TestCaseReviewService {
testCaseReviewMapper.updateByPrimaryKeySelective(testCaseReview); testCaseReviewMapper.updateByPrimaryKeySelective(testCaseReview);
List<String> userIds = new ArrayList<>(); List<String> userIds = new ArrayList<>();
userIds.addAll(testCaseReview.getUserIds()); userIds.addAll(testCaseReview.getUserIds());
if (StringUtils.equals(TestPlanStatus.Completed.name(), testCaseReview.getStatus())) {
try { try {
String context = getReviewContext(testCaseReview, NoticeConstants.UPDATE); String context = getReviewContext(testCaseReview, NoticeConstants.UPDATE);
MessageSettingDetail messageSettingDetail = noticeService.searchMessage(); MessageSettingDetail messageSettingDetail = noticeService.searchMessage();
@ -201,13 +200,12 @@ public class TestCaseReviewService {
wxChatTaskService.sendWechatRobot(r, userIds, context, NoticeConstants.UPDATE); wxChatTaskService.sendWechatRobot(r, userIds, context, NoticeConstants.UPDATE);
break; break;
case NoticeConstants.EMAIL: case NoticeConstants.EMAIL:
mailService.sendReviewerNotice(r, userIds, testCaseReview, NoticeConstants.UPDATE); mailService.sendEndNotice(r, userIds, testCaseReview, NoticeConstants.UPDATE);
break; break;
} }
}); });
} catch (Exception e) { } catch (Exception e) {
LogUtil.error(e); LogUtil.error(e.getMessage(), e);
}
} }
} }
@ -318,7 +316,7 @@ public class TestCaseReviewService {
} }
}); });
} catch (Exception e) { } catch (Exception e) {
LogUtil.error(e); LogUtil.error(e.getMessage(), e);
} }
} }
@ -468,7 +466,7 @@ public class TestCaseReviewService {
} }
}); });
} catch (Exception e) { } catch (Exception e) {
LogUtil.error(e); LogUtil.error(e.getMessage(), e);
} }
} }
} }
@ -585,7 +583,15 @@ public class TestCaseReviewService {
if (StringUtils.equals(NoticeConstants.CREATE, type)) { if (StringUtils.equals(NoticeConstants.CREATE, type)) {
context = "测试评审任务通知:" + user.getName() + "发起的" + "'" + reviewRequest.getName() + "'" + "待开始,计划开始时间是" + start + "计划结束时间为" + end + "请跟进"; context = "测试评审任务通知:" + user.getName() + "发起的" + "'" + reviewRequest.getName() + "'" + "待开始,计划开始时间是" + start + "计划结束时间为" + end + "请跟进";
} else if (StringUtils.equals(NoticeConstants.UPDATE, type)) { } else if (StringUtils.equals(NoticeConstants.UPDATE, type)) {
context = "测试评审任务通知:" + user.getName() + "发起的" + "'" + reviewRequest.getName() + "'" + "已完成,计划开始时间是" + start + "计划结束时间为" + end + "已完成"; String status = "";
if (StringUtils.equals(TestPlanStatus.Underway.name(), reviewRequest.getStatus())) {
status = "进行中";
} else if (StringUtils.equals(TestPlanStatus.Prepare.name(), reviewRequest.getStatus())) {
status = "未开始";
} else if (StringUtils.equals(TestPlanStatus.Completed.name(), reviewRequest.getStatus())) {
status = "已完成";
}
context = "测试评审任务通知:" + user.getName() + "发起的" + "'" + reviewRequest.getName() + "'" + "计划开始时间是" + start + "计划结束时间为" + end + status;
} else if (StringUtils.equals(NoticeConstants.DELETE, type)) { } else if (StringUtils.equals(NoticeConstants.DELETE, type)) {
context = "测试评审任务通知:" + user.getName() + "发起的" + "'" + reviewRequest.getName() + "'" + "计划开始时间是" + start + "计划结束时间为" + end + "已删除"; context = "测试评审任务通知:" + user.getName() + "发起的" + "'" + reviewRequest.getName() + "'" + "计划开始时间是" + start + "计划结束时间为" + end + "已删除";
} }

View File

@ -96,7 +96,7 @@ public class TestPlanService {
@Resource @Resource
UserMapper userMapper; UserMapper userMapper;
public void addTestPlan(AddTestPlanRequest testPlan) { public synchronized void addTestPlan(AddTestPlanRequest testPlan) {
if (getTestPlanByName(testPlan.getName()).size() > 0) { if (getTestPlanByName(testPlan.getName()).size() > 0) {
MSException.throwException(Translator.get("plan_name_already_exists")); MSException.throwException(Translator.get("plan_name_already_exists"));
} }
@ -137,11 +137,11 @@ public class TestPlanService {
} }
}); });
} catch (Exception e) { } catch (Exception e) {
LogUtil.error(e); LogUtil.error(e.getMessage(), e);
} }
} }
public synchronized List<TestPlan> getTestPlanByName(String name) { public List<TestPlan> getTestPlanByName(String name) {
TestPlanExample example = new TestPlanExample(); TestPlanExample example = new TestPlanExample();
example.createCriteria().andWorkspaceIdEqualTo(SessionUtils.getCurrentWorkspaceId()) example.createCriteria().andWorkspaceIdEqualTo(SessionUtils.getCurrentWorkspaceId())
.andNameEqualTo(name); .andNameEqualTo(name);
@ -159,13 +159,16 @@ public class TestPlanService {
//进行中状态写入实际开始时间 //进行中状态写入实际开始时间
if (TestPlanStatus.Underway.name().equals(testPlan.getStatus())) { if (TestPlanStatus.Underway.name().equals(testPlan.getStatus())) {
testPlan.setActualStartTime(System.currentTimeMillis()); testPlan.setActualStartTime(System.currentTimeMillis());
} else if (TestPlanStatus.Completed.name().equals(testPlan.getStatus())) { } else if (TestPlanStatus.Completed.name().equals(testPlan.getStatus())) {
//已完成写入实际完成时间
testPlan.setActualEndTime(System.currentTimeMillis());
}
List<String> userIds = new ArrayList<>(); List<String> userIds = new ArrayList<>();
userIds.add(testPlan.getPrincipal()); userIds.add(testPlan.getPrincipal());
AddTestPlanRequest testPlans = new AddTestPlanRequest(); AddTestPlanRequest testPlans = new AddTestPlanRequest();
//已完成写入实际完成时间 int i = testPlanMapper.updateByPrimaryKeySelective(testPlan);
testPlan.setActualEndTime(System.currentTimeMillis()); if (!StringUtils.isBlank(testPlan.getStatus())) {
try { try {
BeanUtils.copyBean(testPlans, getTestPlan(testPlan.getId())); BeanUtils.copyBean(testPlans, getTestPlan(testPlan.getId()));
String context = getTestPlanContext(testPlans, NoticeConstants.UPDATE); String context = getTestPlanContext(testPlans, NoticeConstants.UPDATE);
@ -180,16 +183,15 @@ public class TestPlanService {
wxChatTaskService.sendWechatRobot(r, userIds, context, NoticeConstants.UPDATE); wxChatTaskService.sendWechatRobot(r, userIds, context, NoticeConstants.UPDATE);
break; break;
case NoticeConstants.EMAIL: case NoticeConstants.EMAIL:
mailService.sendTestPlanStartNotice(r, userIds, testPlans, NoticeConstants.UPDATE); mailService.sendTestPlanEndNotice(r, userIds, testPlans, NoticeConstants.UPDATE);
break; break;
} }
}); });
} catch (Exception e) { } catch (Exception e) {
LogUtil.error(e); LogUtil.error(e.getMessage(), e);
} }
} }
return i;
return testPlanMapper.updateByPrimaryKeySelective(testPlan);
} }
private void editTestPlanProject(TestPlanDTO testPlan) { private void editTestPlanProject(TestPlanDTO testPlan) {
@ -270,7 +272,7 @@ public class TestPlanService {
} }
}); });
} catch (Exception e) { } catch (Exception e) {
LogUtil.error(e); LogUtil.error(e.getMessage(), e);
} }
return num; return num;
} }
@ -511,7 +513,7 @@ public class TestPlanService {
} }
}); });
} catch (Exception e) { } catch (Exception e) {
LogUtil.error(e); LogUtil.error(e.getMessage(), e);
} }
} }
@ -557,11 +559,19 @@ public class TestPlanService {
} }
String context = ""; String context = "";
if (StringUtils.equals(NoticeConstants.CREATE, type)) { if (StringUtils.equals(NoticeConstants.CREATE, type)) {
context = "测试计划任务通知:" + user.getName() + "创建的" + "'" + testPlan.getName() + "'" + "待开始,计划开始时间是" + start + "计划结束时间为" + end + "请跟进"; context = "测试计划任务通知:" + user.getName() + "创建的" + "'" + testPlan.getName() + "'" + "待开始,计划开始时间是:" + "'" + start + "'" + ";" + "计划结束时间是:" + "'" + end + "'" + " " + "请跟进";
} else if (StringUtils.equals(NoticeConstants.UPDATE, type)) { } else if (StringUtils.equals(NoticeConstants.UPDATE, type)) {
context = "测试计划任务通知:" + user.getName() + "创建的" + "'" + testPlan.getName() + "'" + "已完成,计划开始时间是" + start + "计划结束时间为" + end + "已完成"; String status = "";
if (StringUtils.equals(TestPlanStatus.Underway.name(), testPlan.getStatus())) {
status = "进行中";
} else if (StringUtils.equals(TestPlanStatus.Prepare.name(), testPlan.getStatus())) {
status = "未开始";
} else if (StringUtils.equals(TestPlanStatus.Completed.name(), testPlan.getStatus())) {
status = "已完成";
}
context = "测试计划任务通知:" + user.getName() + "创建的" + "'" + testPlan.getName() + "'" + "计划开始时间是:" + "'" + start + "'" + ";" + "计划结束时间是:" + "'" + end + "'" + " " + status;
} else if (StringUtils.equals(NoticeConstants.DELETE, type)) { } else if (StringUtils.equals(NoticeConstants.DELETE, type)) {
context = "测试计划任务通知:" + user.getName() + "创建的" + "'" + testPlan.getName() + "'" + "计划开始时间是" + start + "计划结束时间为" + end + "已删除"; context = "测试计划任务通知:" + user.getName() + "创建的" + "'" + testPlan.getName() + "'" + "计划开始时间是:" + "'" + start + "'" + ";" + "计划结束时间是:" + "'" + end + "'" + " " + "已删除";
} }
return context; return context;
} }

View File

@ -106,7 +106,7 @@ public class ReportWebSocket {
} }
Thread.sleep(20 * 1000L); Thread.sleep(20 * 1000L);
} catch (Exception e) { } catch (Exception e) {
LogUtil.error(e); LogUtil.error(e.getMessage(), e);
} }
} }
} }

View File

@ -283,17 +283,20 @@ public class XmindCaseParser {
// 测试步骤处理 // 测试步骤处理
List<Attached> steps = new LinkedList<>(); List<Attached> steps = new LinkedList<>();
StringBuilder rc = new StringBuilder();
if (attacheds != null && !attacheds.isEmpty()) { if (attacheds != null && !attacheds.isEmpty()) {
attacheds.forEach(item -> { attacheds.forEach(item -> {
if (isAvailable(item.getTitle(), PC_REGEX)) { if (isAvailable(item.getTitle(), PC_REGEX)) {
testCase.setPrerequisite(replace(item.getTitle(), PC_REGEX)); testCase.setPrerequisite(replace(item.getTitle(), PC_REGEX));
} else if (isAvailable(item.getTitle(), RC_REGEX)) { } else if (isAvailable(item.getTitle(), RC_REGEX)) {
testCase.setRemark(replace(item.getTitle(), RC_REGEX)); rc.append(replace(item.getTitle(), RC_REGEX));
rc.append("\n");
} else { } else {
steps.add(item); steps.add(item);
} }
}); });
} }
testCase.setRemark(rc.toString());
testCase.setSteps(this.getSteps(steps)); testCase.setSteps(this.getSteps(steps));
testCases.add(testCase); testCases.add(testCase);
// 校验合规性 // 校验合规性

View File

@ -6,7 +6,7 @@
</head> </head>
<body> <body>
<div> <div>
<p style="text-align: left"> ${maintainer} 维护的<br/> <p style="text-align: left"> ${maintainer} <br/>
${testCaseName}<br/> ${testCaseName}<br/>
添加评论:${description}<br/> 添加评论:${description}<br/>
点击下面链接进入用例评审页面</p> 点击下面链接进入用例评审页面</p>

View File

@ -7,10 +7,10 @@
<body> <body>
<div> <div>
<p style="text-align: left">${creator} 发起的:<br> <p style="text-align: left">${creator} 发起的:<br>
${reviewName}已完成<br> ${reviewName}<br>
计划开始时间是:${start}<br> 计划开始时间是:${start}<br>
计划结束时间为:${end}<br> 计划结束时间为:${end}<br>
已完成<br> ${status}<br>
点击下面链接进入用例评审页面</p> 点击下面链接进入用例评审页面</p>
<a href="${url}/#/track/review/view">${url}/#/track/review/view</a> <a href="${url}/#/track/review/view">${url}/#/track/review/view</a>
</div> </div>

View File

@ -7,10 +7,10 @@
<body> <body>
<div> <div>
<p style="text-align: left">${creator} 创建的:<br> <p style="text-align: left">${creator} 创建的:<br>
${testPlanName}已完成<br> ${testPlanName}<br>
计划开始时间是:${start}<br> 计划开始时间是:${start}<br>
计划结束时间为:${end}<br> 计划结束时间为:${end}<br>
已完成<br> ${status}<br>
点击下面链接进入测试计划页面</p> 点击下面链接进入测试计划页面</p>
<a href="${url}/#/track/plan/view/${id}">${url}/#/track/plan/view</a> <a href="${url}/#/track/plan/view/${id}">${url}/#/track/plan/view</a>
</div> </div>

View File

@ -7,7 +7,7 @@
<parent> <parent>
<artifactId>metersphere-server</artifactId> <artifactId>metersphere-server</artifactId>
<groupId>io.metersphere</groupId> <groupId>io.metersphere</groupId>
<version>1.4</version> <version>1.5</version>
</parent> </parent>
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>

View File

@ -7,8 +7,7 @@
</el-row> </el-row>
<el-row id="header-top" type="flex" justify="space-between" align="middle"> <el-row id="header-top" type="flex" justify="space-between" align="middle">
<el-col :span="12"> <el-col :span="12">
<img v-if="logoId" :src="'/display/file/' + logoId" style="width: 156px;height: 37px;" alt=""> <img :src="'/display/file/logo'" style="width: 156px;height: 37px;" alt="">
<a v-else class="logo"/>
<ms-top-menus/> <ms-top-menus/>
</el-col> </el-col>

View File

@ -46,10 +46,9 @@ import MsScenarioResults from "./components/ScenarioResults";
import MsContainer from "@/business/components/common/components/MsContainer"; import MsContainer from "@/business/components/common/components/MsContainer";
import MsMainContainer from "@/business/components/common/components/MsMainContainer"; import MsMainContainer from "@/business/components/common/components/MsMainContainer";
import MsApiReportExport from "./ApiReportExport"; import MsApiReportExport from "./ApiReportExport";
import {exportPdf} from "@/common/js/utils";
import html2canvas from "html2canvas";
import MsApiReportViewHeader from "./ApiReportViewHeader"; import MsApiReportViewHeader from "./ApiReportViewHeader";
import {RequestFactory} from "../test/model/ScenarioModel"; import {RequestFactory} from "../test/model/ScenarioModel";
import {windowPrint} from "../../../../common/js/utils";
export default { export default {
name: "MsApiReportViewDetail", name: "MsApiReportViewDetail",
@ -154,23 +153,16 @@ export default {
this.scenarioName = requestResult.scenarioName; this.scenarioName = requestResult.scenarioName;
}); });
}, },
handleExport(name) { handleExport() {
this.loading = true;
this.reportExportVisible = true; this.reportExportVisible = true;
let reset = this.exportReportReset; let reset = this.exportReportReset;
this.$nextTick(() => {
this.$nextTick(function () { windowPrint('apiTestReport', 0.57);
html2canvas(document.getElementById('apiTestReport'), {
// scale: 2,
}).then(function (canvas) {
exportPdf(name, [canvas]);
reset(); reset();
}); });
});
}, },
exportReportReset() { exportReportReset() {
this.reportExportVisible = false; this.$router.go(0);
this.loading = false;
} }
}, },

View File

@ -72,6 +72,7 @@ export default {
methods: { methods: {
search() { search() {
this.condition.excludeId = this.excludeId; this.condition.excludeId = this.excludeId;
this.condition.projectId = this.projectId;
let url = "/api/list/" + this.currentPage + "/" + this.pageSize; let url = "/api/list/" + this.currentPage + "/" + this.pageSize;
this.result = this.$post(url, this.condition, response => { this.result = this.$post(url, this.condition, response => {
let data = response.data; let data = response.data;

View File

@ -17,10 +17,9 @@
:scenario="scenario" :scenario="scenario"
:extract="extract" :extract="extract"
type="body" type="body"
:description="$t('api_test.request.parameters_desc')"
v-if="body.isKV()"/> v-if="body.isKV()"/>
<div class="body-raw" v-if="body.type == 'Raw'"> <div class="body-raw" v-if="body.type == 'Raw'">
<ms-code-edit :mode="body.format" :read-only="isReadOnly" :data.sync="body.raw" :modes="modes" ref="codeEdit"/> <ms-code-edit :mode="body.format" :enable-format="false" :read-only="isReadOnly" :data.sync="body.raw" :modes="modes" ref="codeEdit"/>
</div> </div>
</div> </div>

View File

@ -29,7 +29,7 @@
</el-form-item> </el-form-item>
<el-form-item :label="$t('api_test.request.sql.pool_max')" prop="poolMax"> <el-form-item :label="$t('api_test.request.sql.pool_max')" prop="poolMax">
<el-input-number size="small" :disabled="isReadOnly" v-model="currentConfig.poolMax" :placeholder="$t('commons.please_select')" :max="1000*10000000" :min="0"/> <el-input-number size="small" :disabled="isReadOnly" v-model="currentConfig.poolMax" :placeholder="$t('commons.please_select')" :max="100" :min="0"/>
</el-form-item> </el-form-item>

View File

@ -157,7 +157,7 @@ export class Test extends BaseConfig {
constructor(options) { constructor(options) {
super(); super();
this.type = "MS API CONFIG"; this.type = "MS API CONFIG";
this.version = '1.4.0'; this.version = '1.5.0';
this.id = uuid(); this.id = uuid();
this.name = undefined; this.name = undefined;
this.projectId = undefined; this.projectId = undefined;
@ -609,8 +609,8 @@ export class DatabaseConfig extends BaseConfig {
super(); super();
this.id = undefined; this.id = undefined;
this.name = undefined; this.name = undefined;
this.poolMax = undefined; this.poolMax = 1;
this.timeout = undefined; this.timeout = 100000;
this.driver = undefined; this.driver = undefined;
this.dbUrl = undefined; this.dbUrl = undefined;
this.username = undefined; this.username = undefined;

View File

@ -28,6 +28,12 @@
init: { init: {
type: Function type: Function
}, },
enableFormat: {
type: Boolean,
default() {
return true;
}
},
readOnly: { readOnly: {
type: Boolean, type: Boolean,
default() { default() {
@ -74,6 +80,7 @@
} }
}, },
format() { format() {
if (this.enableFormat) {
switch (this.mode) { switch (this.mode) {
case 'json': case 'json':
this.formatData = formatJson(this.data); this.formatData = formatJson(this.data);
@ -89,6 +96,9 @@
this.formatData = this.data; this.formatData = this.data;
} }
} }
} else {
this.formatData = this.data;
}
} }
} }
} }

View File

@ -11,6 +11,11 @@
<br/> <br/>
</el-col> </el-col>
</el-row> </el-row>
<el-row class="tip" v-if="withTip">
<span>
<slot class="tip"></slot>
</span>
</el-row>
<el-row> <el-row>
<el-col :span="15"> <el-col :span="15">
<el-input v-model="value" :placeholder="$t('commons.input_content')"/> <el-input v-model="value" :placeholder="$t('commons.input_content')"/>
@ -41,6 +46,12 @@
default() { default() {
return this.$t('commons.title') return this.$t('commons.title')
} }
},
withTip: {
type: Boolean,
default() {
return false
}
} }
}, },
methods: { methods: {
@ -80,5 +91,9 @@
font-weight: bold; font-weight: bold;
} }
.tip {
margin-bottom: 20px;
color: red;
}
</style> </style>

View File

@ -73,7 +73,9 @@
this.$emit('scheduleChange'); this.$emit('scheduleChange');
}, },
flashResultList() { flashResultList() {
if (this.$refs.crontabResult) {
this.$refs.crontabResult.expressionChange(); this.$refs.crontabResult.expressionChange();
}
}, },
cancelRefresh() { cancelRefresh() {
if (this.refreshScheduler) { if (this.refreshScheduler) {

View File

@ -31,7 +31,7 @@
</el-dialog> </el-dialog>
</el-tab-pane> </el-tab-pane>
<el-tab-pane :label="$t('schedule.task_notification')" name="second"> <el-tab-pane :label="$t('schedule.task_notification')" name="second">
<schedule-task-notification :test-id="testId" :schedule-receiver-options="scheduleReceiverOptions"></schedule-task-notification> <schedule-task-notification :is-tester-permission="isTesterPermission" :test-id="testId" :schedule-receiver-options="scheduleReceiverOptions"></schedule-task-notification>
</el-tab-pane> </el-tab-pane>
</el-tabs> </el-tabs>
</div> </div>
@ -46,6 +46,7 @@ import CrontabResult from "../cron/CrontabResult";
import {cronValidate} from "@/common/js/cron"; import {cronValidate} from "@/common/js/cron";
import {listenGoBack, removeGoBackListener} from "@/common/js/utils"; import {listenGoBack, removeGoBackListener} from "@/common/js/utils";
import ScheduleTaskNotification from "../../settings/organization/components/ScheduleTaskNotification"; import ScheduleTaskNotification from "../../settings/organization/components/ScheduleTaskNotification";
import {checkoutTestManagerOrTestUser} from "../../../../common/js/utils";
function defaultCustomValidate() { function defaultCustomValidate() {
return {pass: true}; return {pass: true};
} }
@ -113,10 +114,13 @@ export default {
name: '', name: '',
organizationId: this.currentUser().lastOrganizationId organizationId: this.currentUser().lastOrganizationId
}; };
if (this.isTesterPermission) {
this.result = this.$post('user/org/member/list/all', param, response => { this.result = this.$post('user/org/member/list/all', param, response => {
this.scheduleReceiverOptions = response.data this.scheduleReceiverOptions = response.data
}); });
}
}, },
/* handleClick() { /* handleClick() {
if (this.activeName === "second") { if (this.activeName === "second") {
@ -188,6 +192,11 @@ export default {
let time1 = new Date(resultList[0]); let time1 = new Date(resultList[0]);
let time2 = new Date(resultList[1]); let time2 = new Date(resultList[1]);
return time2 - time1; return time2 - time1;
},
},
computed: {
isTesterPermission() {
return checkoutTestManagerOrTestUser();
} }
} }
} }

View File

@ -9,10 +9,8 @@
</div> </div>
</div> </div>
<div class="report-right"> <div class="report-right">
<div class="test">
<img class="logo" src="@/assets/logo-MeterSphere.png"> <img class="logo" src="@/assets/logo-MeterSphere.png">
</div> </div>
</div>
</div> </div>
</template> </template>

View File

@ -271,12 +271,14 @@ export default {
let reset = this.exportReportReset; let reset = this.exportReportReset;
this.$nextTick(function () { this.$nextTick(function () {
setTimeout(() => {
html2canvas(document.getElementById('performanceReportExport'), { html2canvas(document.getElementById('performanceReportExport'), {
// scale: 2 scale: 2
}).then(function (canvas) { }).then(function (canvas) {
exportPdf(name, [canvas]); exportPdf(name, [canvas]);
reset(); reset();
}); });
}, 1000);
}); });
}, },
exportReportReset() { exportReportReset() {

View File

@ -30,7 +30,7 @@
:placeholder="$t('load_test.input_thread_num')" :placeholder="$t('load_test.input_thread_num')"
v-model="threadGroup.threadNumber" v-model="threadGroup.threadNumber"
@change="calculateChart(threadGroup)" @change="calculateChart(threadGroup)"
:min="1" :min="resourcePoolResourceLength"
size="mini"/> size="mini"/>
</el-form-item> </el-form-item>
<br> <br>
@ -141,6 +141,7 @@ export default {
activeNames: ["0"], activeNames: ["0"],
threadGroups: [], threadGroups: [],
serializeThreadgroups: false, serializeThreadgroups: false,
resourcePoolResourceLength: 1
} }
}, },
mounted() { mounted() {
@ -368,6 +369,11 @@ export default {
if (handler.rampUpTime < handler.step) { if (handler.rampUpTime < handler.step) {
handler.step = handler.rampUpTime; handler.step = handler.rampUpTime;
} }
// 线
let resourcePool = this.resourcePools.filter(v => v.id === this.resourcePool)[0];
if (resourcePool) {
this.resourcePoolResourceLength = resourcePool.resources.length;
}
handler.options = { handler.options = {
xAxis: { xAxis: {
type: 'category', type: 'category',

View File

@ -204,6 +204,7 @@ export default {
}); });
} }
}, },
submit(formName) { submit(formName) {
this.$refs[formName].validate((valid) => { this.$refs[formName].validate((valid) => {
if (valid) { if (valid) {
@ -282,7 +283,18 @@ export default {
}, },
openEnvironmentConfig(project) { openEnvironmentConfig(project) {
this.$refs.environmentConfig.open(project.id); this.$refs.environmentConfig.open(project.id);
},
handleEvent(event) {
if (event.keyCode === 13) {
this.submit('form')
} }
},
},
created() {
document.addEventListener('keydown', this.handleEvent)
},
beforeDestroy() {
document.removeEventListener('keydown', this.handleEvent);
} }
} }
</script> </script>

View File

@ -2,7 +2,7 @@
<div> <div>
<el-row> <el-row>
<el-col :span="10"> <el-col :span="10">
<el-button icon="el-icon-circle-plus-outline" plain size="mini" @click="handleAddTaskModel('scheduleTask')"> <el-button :disabled="!isTesterPermission" icon="el-icon-circle-plus-outline" plain size="mini" @click="handleAddTaskModel('scheduleTask')">
{{ $t('organization.message.create_new_notification') }} {{ $t('organization.message.create_new_notification') }}
</el-button> </el-button>
</el-col> </el-col>
@ -69,12 +69,14 @@
type="primary" type="primary"
size="mini" size="mini"
v-show="scope.row.isSet" v-show="scope.row.isSet"
:disabled="!isTesterPermission"
@click="handleAddTask(scope.$index,scope.row)" @click="handleAddTask(scope.$index,scope.row)"
>{{ $t('commons.add') }} >{{ $t('commons.add') }}
</el-button> </el-button>
<el-button <el-button
size="mini" size="mini"
v-show="scope.row.isSet" v-show="scope.row.isSet"
:disabled="!isTesterPermission"
@click.native.prevent="removeRowTask(scope.$index,form.scheduleTask)" @click.native.prevent="removeRowTask(scope.$index,form.scheduleTask)"
>{{ $t('commons.cancel') }} >{{ $t('commons.cancel') }}
</el-button> </el-button>
@ -82,6 +84,7 @@
type="primary" type="primary"
size="mini" size="mini"
v-show="!scope.row.isSet" v-show="!scope.row.isSet"
:disabled="!isTesterPermission"
@click="handleEditTask(scope.$index,scope.row)" @click="handleEditTask(scope.$index,scope.row)"
>{{ $t('commons.edit') }}</el-button> >{{ $t('commons.edit') }}</el-button>
<el-button <el-button
@ -89,6 +92,7 @@
icon="el-icon-delete" icon="el-icon-delete"
size="mini" size="mini"
v-show="!scope.row.isSet" v-show="!scope.row.isSet"
:disabled="!isTesterPermission"
@click.native.prevent="deleteRowTask(scope.$index,scope.row)" @click.native.prevent="deleteRowTask(scope.$index,scope.row)"
></el-button> ></el-button>
</template> </template>
@ -106,6 +110,10 @@ export default {
props: { props: {
testId:String, testId:String,
scheduleReceiverOptions:Array, scheduleReceiverOptions:Array,
isTesterPermission: {
type: Boolean,
default: true
}
}, },
data() { data() {
return { return {
@ -120,7 +128,6 @@ export default {
identification: "", identification: "",
isReadOnly: false, isReadOnly: false,
testId:this.testId, testId:this.testId,
}], }],
}, },
scheduleEventOptions: [ scheduleEventOptions: [
@ -193,7 +200,6 @@ export default {
}, },
addTask(data) { addTask(data) {
let list = []; let list = [];
data.isSet = false;
list.push(data); list.push(data);
let param = {}; let param = {};
param.messageDetail = list; param.messageDetail = list;

View File

@ -86,6 +86,7 @@
import MsDialogFooter from "../../common/components/MsDialogFooter"; import MsDialogFooter from "../../common/components/MsDialogFooter";
import {getCurrentUser, listenGoBack, removeGoBackListener} from "../../../../common/js/utils"; import {getCurrentUser, listenGoBack, removeGoBackListener} from "../../../../common/js/utils";
import MsTableOperatorButton from "../../common/components/MsTableOperatorButton"; import MsTableOperatorButton from "../../common/components/MsTableOperatorButton";
import {PHONE_REGEX} from "@/common/js/regex";
export default { export default {
name: "MsPersonSetting", name: "MsPersonSetting",
@ -115,7 +116,7 @@
phone: [ phone: [
{ {
required: false, required: false,
pattern: '^1(3|4|5|7|8)\\d{9}$', pattern: PHONE_REGEX,
message: this.$t('member.mobile_number_format_is_incorrect'), message: this.$t('member.mobile_number_format_is_incorrect'),
trigger: 'blur' trigger: 'blur'
} }

View File

@ -45,7 +45,7 @@
<el-checkbox v-model="formInline.TLS" :label="$t('system_parameter_setting.TLS')"></el-checkbox> <el-checkbox v-model="formInline.TLS" :label="$t('system_parameter_setting.TLS')"></el-checkbox>
</div> </div>
<div style="border: 0px;margin-bottom: 20px"> <div style="border: 0px;margin-bottom: 20px">
<el-checkbox v-model="formInline.SMTP" :label="$t('system_parameter_setting.SMTP')"></el-checkbox> <el-checkbox v-model="formInline.ANON" :label="$t('system_parameter_setting.SMTP')"></el-checkbox>
</div> </div>
<template v-slot:footer> <template v-slot:footer>
</template> </template>
@ -120,7 +120,7 @@ export default {
this.$set(this.formInline, "password", response.data[3].paramValue); this.$set(this.formInline, "password", response.data[3].paramValue);
this.$set(this.formInline, "SSL", JSON.parse(response.data[4].paramValue)); this.$set(this.formInline, "SSL", JSON.parse(response.data[4].paramValue));
this.$set(this.formInline, "TLS", JSON.parse(response.data[5].paramValue)); this.$set(this.formInline, "TLS", JSON.parse(response.data[5].paramValue));
this.$set(this.formInline, "SMTP", JSON.parse(response.data[6].paramValue)); this.$set(this.formInline, "ANON", JSON.parse(response.data[6].paramValue));
this.$nextTick(() => { this.$nextTick(() => {
this.$refs.formInline.clearValidate(); this.$refs.formInline.clearValidate();
}) })
@ -143,7 +143,7 @@ export default {
"smtp.password": this.formInline.password, "smtp.password": this.formInline.password,
"smtp.ssl": this.formInline.SSL, "smtp.ssl": this.formInline.SSL,
"smtp.tls": this.formInline.TLS, "smtp.tls": this.formInline.TLS,
"smtp.smtp": this.formInline.SMTP, "smtp.anon": this.formInline.ANON,
}; };
this.$refs[formInline].validate((valid) => { this.$refs[formInline].validate((valid) => {
if (valid) { if (valid) {
@ -173,7 +173,7 @@ export default {
{paramKey: "smtp.password", paramValue: this.formInline.password, type: "password", sort: 4}, {paramKey: "smtp.password", paramValue: this.formInline.password, type: "password", sort: 4},
{paramKey: "smtp.ssl", paramValue: this.formInline.SSL, type: "text", sort: 5}, {paramKey: "smtp.ssl", paramValue: this.formInline.SSL, type: "text", sort: 5},
{paramKey: "smtp.tls", paramValue: this.formInline.TLS, type: "text", sort: 6}, {paramKey: "smtp.tls", paramValue: this.formInline.TLS, type: "text", sort: 6},
{paramKey: "smtp.smtp", paramValue: this.formInline.SMTP, type: "text", sort: 7} {paramKey: "smtp.anon", paramValue: this.formInline.ANON, type: "text", sort: 7}
] ]
this.$refs[formInline].validate(valid => { this.$refs[formInline].validate(valid => {

View File

@ -338,6 +338,7 @@ import {hasRole, listenGoBack, removeGoBackListener} from "@/common/js/utils";
import MsRolesTag from "../../common/components/MsRolesTag"; import MsRolesTag from "../../common/components/MsRolesTag";
import {ROLE_ADMIN} from "@/common/js/constants"; import {ROLE_ADMIN} from "@/common/js/constants";
import {getCurrentUser} from "../../../../common/js/utils"; import {getCurrentUser} from "../../../../common/js/utils";
import {PHONE_REGEX} from "@/common/js/regex";
export default { export default {
name: "MsUser", name: "MsUser",
@ -380,7 +381,7 @@ export default {
rule: { rule: {
id: [ id: [
{required: true, message: this.$t('user.input_id'), trigger: 'blur'}, {required: true, message: this.$t('user.input_id'), trigger: 'blur'},
{min: 2, max: 50, message: this.$t('commons.input_limit', [2, 50]), trigger: 'blur'}, {min: 1, max: 50, message: this.$t('commons.input_limit', [1, 50]), trigger: 'blur'},
{ {
required: true, required: true,
pattern: '^[^\u4e00-\u9fa5]+$', pattern: '^[^\u4e00-\u9fa5]+$',
@ -401,7 +402,7 @@ export default {
{required: true, message: this.$t('user.input_phone'), trigger: 'blur'}, {required: true, message: this.$t('user.input_phone'), trigger: 'blur'},
{ {
required: true, required: true,
pattern: '^1(3|4|5|7|8)\\d{9}$', pattern: PHONE_REGEX,
message: this.$t('user.mobile_number_format_is_incorrect'), message: this.$t('user.mobile_number_format_is_incorrect'),
trigger: 'blur' trigger: 'blur'
} }

View File

@ -71,7 +71,8 @@
name: "TestCase", name: "TestCase",
components: { components: {
MsMainContainer, MsMainContainer,
MsAsideContainer, MsContainer, TestCaseMove, TestCaseList, NodeTree, TestCaseEdit, SelectMenu, BatchMove}, MsAsideContainer, MsContainer, TestCaseMove, TestCaseList, NodeTree, TestCaseEdit, SelectMenu, BatchMove
},
comments: {}, comments: {},
data() { data() {
return { return {

View File

@ -161,6 +161,7 @@ export default {
data() { data() {
return { return {
result: {}, result: {},
testCase: {},
dialogFormVisible: false, dialogFormVisible: false,
readOnly: true, readOnly: true,
form: { form: {
@ -190,9 +191,15 @@ export default {
] ]
}; };
}, },
mounted() {
this.$get('test/case/get/' + this.testCaseId, response => {
this.testCase = response.data;
});
},
methods: {},
props: { props: {
testCase: { testCaseId: {
type: Object type: String
} }
}, },
} }

View File

@ -256,9 +256,9 @@
<script> <script>
import {TokenKey, WORKSPACE_ID} from '../../../../../common/js/constants'; import {TokenKey, WORKSPACE_ID} from '@/common/js/constants';
import MsDialogFooter from '../../../common/components/MsDialogFooter' import MsDialogFooter from '../../../common/components/MsDialogFooter'
import {listenGoBack, removeGoBackListener} from "../../../../../common/js/utils"; import {listenGoBack, removeGoBackListener} from "@/common/js/utils";
import {LIST_CHANGE, TrackEvent} from "@/business/components/common/head/ListEvent"; import {LIST_CHANGE, TrackEvent} from "@/business/components/common/head/ListEvent";
import {Message} from "element-ui"; import {Message} from "element-ui";
import TestCaseAttachment from "@/business/components/track/case/components/TestCaseAttachment"; import TestCaseAttachment from "@/business/components/track/case/components/TestCaseAttachment";

View File

@ -8,7 +8,7 @@
:tip="$t('commons.search_by_name_or_id')" :tip="$t('commons.search_by_name_or_id')"
:create-tip="$t('test_track.case.create')" @create="testCaseCreate"> :create-tip="$t('test_track.case.create')" @create="testCaseCreate">
<template v-slot:title> <template v-slot:title>
<node-breadcrumb class="table-title" :nodes="selectParentNodes" @refresh="showAll"/> <node-breadcrumb class="table-title" :nodes="selectParentNodes" @refresh="refresh"/>
</template> </template>
<template v-slot:button> <template v-slot:button>
<ms-table-button :is-tester-permission="true" icon="el-icon-download" <ms-table-button :is-tester-permission="true" icon="el-icon-download"
@ -35,6 +35,7 @@
@filter-change="filter" @filter-change="filter"
@select-all="handleSelectAll" @select-all="handleSelectAll"
@select="handleSelectionChange" @select="handleSelectionChange"
@cell-mouse-enter="showPopover"
row-key="id" row-key="id"
class="test-content adjust-table"> class="test-content adjust-table">
<el-table-column <el-table-column
@ -65,7 +66,7 @@
width="60%" width="60%"
trigger="hover" trigger="hover"
> >
<test-case-detail :test-case="scope.row"/> <test-case-detail v-if="currentCaseId === scope.row.id" :test-case-id="currentCaseId"/>
<span slot="reference">{{ scope.row.name }}</span> <span slot="reference">{{ scope.row.name }}</span>
</el-popover> </el-popover>
</template> </template>
@ -166,11 +167,11 @@ import MethodTableItem from "../../common/tableItems/planview/MethodTableItem";
import MsTableOperator from "../../../common/components/MsTableOperator"; import MsTableOperator from "../../../common/components/MsTableOperator";
import MsTableOperatorButton from "../../../common/components/MsTableOperatorButton"; import MsTableOperatorButton from "../../../common/components/MsTableOperatorButton";
import MsTableButton from "../../../common/components/MsTableButton"; import MsTableButton from "../../../common/components/MsTableButton";
import {_filter, _sort} from "../../../../../common/js/utils"; import {_filter, _sort} from "@/common/js/utils";
import {TEST_CASE_CONFIGS} from "../../../common/components/search/search-components"; import {TEST_CASE_CONFIGS} from "../../../common/components/search/search-components";
import ShowMoreBtn from "./ShowMoreBtn"; import ShowMoreBtn from "./ShowMoreBtn";
import BatchEdit from "./BatchEdit"; import BatchEdit from "./BatchEdit";
import {WORKSPACE_ID} from "../../../../../common/js/constants"; import {WORKSPACE_ID} from "@/common/js/constants";
import {LIST_CHANGE, TrackEvent} from "@/business/components/common/head/ListEvent"; import {LIST_CHANGE, TrackEvent} from "@/business/components/common/head/ListEvent";
import StatusTableItem from "@/business/components/track/common/tableItems/planview/StatusTableItem"; import StatusTableItem from "@/business/components/track/common/tableItems/planview/StatusTableItem";
import TestCaseDetail from "./TestCaseDetail"; import TestCaseDetail from "./TestCaseDetail";
@ -262,7 +263,8 @@ export default {
{name: this.$t('test_track.case.auto'), id: 'auto'} {name: this.$t('test_track.case.auto'), id: 'auto'}
], ],
maintainer: [], maintainer: [],
} },
currentCaseId: null
} }
}, },
props: { props: {
@ -290,6 +292,8 @@ export default {
}, },
methods: { methods: {
initTableData() { initTableData() {
this.condition.planId = "";
this.condition.nodeIds = [];
if (this.planId) { if (this.planId) {
// param.planId = this.planId; // param.planId = this.planId;
this.condition.planId = this.planId; this.condition.planId = this.planId;
@ -322,10 +326,16 @@ export default {
this.$emit('testCaseEdit'); this.$emit('testCaseEdit');
}, },
handleEdit(testCase) { handleEdit(testCase) {
this.$get('test/case/get/' + testCase.id, response => {
let testCase = response.data;
this.$emit('testCaseEdit', testCase); this.$emit('testCaseEdit', testCase);
});
}, },
handleCopy(testCase) { handleCopy(testCase) {
this.$get('test/case/get/' + testCase.id, response => {
let testCase = response.data;
this.$emit('testCaseCopy', testCase); this.$emit('testCaseCopy', testCase);
});
}, },
handleDelete(testCase) { handleDelete(testCase) {
this.$alert(this.$t('test_track.case.delete_confirm') + '\'' + testCase.name + '\'' + "", '', { this.$alert(this.$t('test_track.case.delete_confirm') + '\'' + testCase.name + '\'' + "", '', {
@ -369,10 +379,6 @@ export default {
this.selectRows.clear(); this.selectRows.clear();
this.$emit('refresh'); this.$emit('refresh');
}, },
showAll() {
this.condition = {components: TEST_CASE_CONFIGS};
this.getData();
},
showDetail(row, event, column) { showDetail(row, event, column) {
this.$emit('testCaseDetail', row); this.$emit('testCaseDetail', row);
}, },
@ -488,6 +494,11 @@ export default {
this.$post('/user/ws/member/tester/list', {workspaceId: workspaceId}, response => { this.$post('/user/ws/member/tester/list', {workspaceId: workspaceId}, response => {
this.valueArr.maintainer = response.data; this.valueArr.maintainer = response.data;
}); });
},
showPopover(row, column, cell) {
if (column.property === 'name') {
this.currentCaseId = row.id;
}
} }
} }
} }

View File

@ -193,8 +193,7 @@ export default {
let param = {}; let param = {};
Object.assign(param, this.form); Object.assign(param, this.form);
param.name = param.name.trim(); param.name = param.name.trim();
if (param.name === '') { if (!this.validate(param)) {
this.$warning(this.$t('test_track.plan.input_plan_name'));
return; return;
} }
param.workspaceId = localStorage.getItem(WORKSPACE_ID); param.workspaceId = localStorage.getItem(WORKSPACE_ID);
@ -227,6 +226,17 @@ export default {
} }
}); });
}, },
validate(param) {
if (param.name === '') {
this.$warning(this.$t('test_track.plan.input_plan_name'));
return false;
}
if (param.plannedStartTime > param.plannedEndTime) {
this.$warning(this.$t('commons.date.data_time_error'));
return false;
}
return true;
},
editTestPlan(param) { editTestPlan(param) {
this.$post('/test/plan/' + this.operationType, param, () => { this.$post('/test/plan/' + this.operationType, param, () => {
this.$success(this.$t('commons.save_success')); this.$success(this.$t('commons.save_success'));

View File

@ -137,7 +137,9 @@
<test-report-template-list @openReport="openReport" ref="testReportTemplateList"/> <test-report-template-list @openReport="openReport" ref="testReportTemplateList"/>
<test-case-report-view @refresh="initTableData" ref="testCaseReportView"/> <test-case-report-view @refresh="initTableData" ref="testCaseReportView"/>
<ms-delete-confirm :title="$t('test_track.plan.plan_delete')" @delete="_handleDelete" ref="deleteConfirm"/> <ms-delete-confirm :title="$t('test_track.plan.plan_delete')" @delete="_handleDelete" ref="deleteConfirm" :with-tip="enableDeleteTip">
{{$t('test_track.plan.plan_delete_tip')}}
</ms-delete-confirm>
</el-card> </el-card>
</template> </template>
@ -171,6 +173,7 @@ export default {
data() { data() {
return { return {
result: {}, result: {},
enableDeleteTip: false,
queryPath: "/test/plan/list", queryPath: "/test/plan/list",
deletePath: "/test/plan/delete", deletePath: "/test/plan/delete",
condition: { condition: {
@ -249,6 +252,7 @@ export default {
}); });
}, },
handleDelete(testPlan) { handleDelete(testPlan) {
this.enableDeleteTip = testPlan.status === 'Underway' ? true : false;
this.$refs.deleteConfirm.open(testPlan); this.$refs.deleteConfirm.open(testPlan);
}, },
_handleDelete(testPlan) { _handleDelete(testPlan) {

View File

@ -215,6 +215,16 @@
item.checked = false; item.checked = false;
}); });
flag ? this.testCases = tableData : this.testCases = this.testCases.concat(tableData); flag ? this.testCases = tableData : this.testCases = this.testCases.concat(tableData);
//
let hash = {}
this.testCases = this.testCases.reduce((item, next) => {
if (!hash[next.id]) {
hash[next.id] = true
item.push(next)
}
return item
}, [])
this.lineStatus = tableData.length === 50 && this.testCases.length < this.total; this.lineStatus = tableData.length === 50 && this.testCases.length < this.total;
}); });
} }

View File

@ -210,14 +210,15 @@
let reset = this.exportReportReset; let reset = this.exportReportReset;
this.$nextTick(function () { this.$nextTick(function () {
setTimeout(() => {
html2canvas(document.getElementById('testCaseReportExport'), { html2canvas(document.getElementById('testCaseReportExport'), {
// scale: 2 scale: 2
}).then(function(canvas) { }).then(function(canvas) {
exportPdf(name, [canvas]); exportPdf(name, [canvas]);
reset(); reset();
}); });
}, 1000);
}); });
}, },
exportReportReset() { exportReportReset() {
this.reportExportVisible = false; this.reportExportVisible = false;
@ -225,7 +226,7 @@
}, },
} }
} }
</script> </script>cd
<style scoped> <style scoped>

View File

@ -23,9 +23,10 @@
resize="none" resize="none"
:autosize="{ minRows: 4, maxRows: 4}" :autosize="{ minRows: 4, maxRows: 4}"
@keyup.ctrl.enter.native="sendComment" @keyup.ctrl.enter.native="sendComment"
:disabled="isReadOnly"
> >
</el-input> </el-input>
<el-button type="primary" size="mini" class="send-btn" @click="sendComment"> <el-button type="primary" size="mini" class="send-btn" @click="sendComment" :disabled="isReadOnly">
{{ $t('test_track.comment.send') }} {{ $t('test_track.comment.send') }}
</el-button> </el-button>
</div> </div>
@ -34,6 +35,7 @@
<script> <script>
import ReviewCommentItem from "./ReviewCommentItem"; import ReviewCommentItem from "./ReviewCommentItem";
import {checkoutTestManagerOrTestUser} from "@/common/js/utils";
export default { export default {
name: "ReviewComment", name: "ReviewComment",
@ -47,8 +49,12 @@ export default {
return { return {
result: {}, result: {},
textarea: '', textarea: '',
isReadOnly: false
} }
}, },
created() {
this.isReadOnly = !checkoutTestManagerOrTestUser();
},
methods: { methods: {
sendComment() { sendComment() {
let comment = {}; let comment = {};

View File

@ -219,6 +219,15 @@
item.checked = false; item.checked = false;
}); });
flag ? this.testReviews = tableData : this.testReviews = this.testReviews.concat(tableData); flag ? this.testReviews = tableData : this.testReviews = this.testReviews.concat(tableData);
//
let hash = {}
this.testReviews = this.testReviews.reduce((item, next) => {
if (!hash[next.id]) {
hash[next.id] = true
item.push(next)
}
return item
}, [])
this.lineStatus = tableData.length === 50 && this.testReviews.length < this.total; this.lineStatus = tableData.length === 50 && this.testReviews.length < this.total;
}); });

View File

@ -108,3 +108,9 @@ body {
margin: 5px 0; margin: 5px 0;
border-radius: 5px; border-radius: 5px;
} }
/* 修复带长度限制的文本框,内容太长造成的无法查看内容的问题 */
.el-input__inner[maxlength] {
padding-right: 60px;
}

View File

@ -43,8 +43,10 @@ export default {
success(response.data); success(response.data);
} else { } else {
window.console.warn(response.data); window.console.warn(response.data);
if (response.data.message) {
Message.warning(response.data.message); Message.warning(response.data.message);
} }
}
result.loading = false; result.loading = false;
} }

View File

@ -0,0 +1 @@
export const PHONE_REGEX = '^1(3|4|5|7|8|9)\\d{9}$';

View File

@ -275,3 +275,17 @@ export function exportPdf(name, canvasList) {
} }
export function windowPrint(id, zoom) {
//根据div标签ID拿到div中的局部内容
let bdhtml=window.document.body.innerHTML;
let el = document.getElementById(id);
var jubuData = el.innerHTML;
document.getElementsByTagName('body')[0].style.zoom=zoom;
//把获取的 局部div内容赋给body标签, 相当于重置了 body里的内容
window.document.body.innerHTML= jubuData;
//调用打印功能
window.print();
window.document.body.innerHTML=bdhtml;//重新给页面内容赋值;
return false;
}

View File

@ -893,6 +893,7 @@ export default {
actual_start_time: "Actual Start Time", actual_start_time: "Actual Start Time",
actual_end_time: "Actual End Time", actual_end_time: "Actual End Time",
plan_delete_confirm: "All use cases under this plan will be deleted,confirm delete test plan: ", plan_delete_confirm: "All use cases under this plan will be deleted,confirm delete test plan: ",
plan_delete_tip: "The test plan is under way, please confirm and delete it!",
plan_delete: "Delete test plan", plan_delete: "Delete test plan",
}, },
review: { review: {

View File

@ -470,7 +470,7 @@ export default {
title: "jar包管理", title: "jar包管理",
jar_file: "jar包", jar_file: "jar包",
delete_tip: "删除需重启服务后生效", delete_tip: "删除需重启服务后生效",
file_exist: "该项目下已存在jar包", file_exist: "该项目下已存在jar包",
upload_limit_size: "上传文件大小不能超过 30MB!", upload_limit_size: "上传文件大小不能超过 30MB!",
}, },
definition: { definition: {
@ -896,6 +896,7 @@ export default {
actual_start_time: "实际开始", actual_start_time: "实际开始",
actual_end_time: "实际结束", actual_end_time: "实际结束",
plan_delete_confirm: "将删除该测试计划下所有用例,确认删除测试计划: ", plan_delete_confirm: "将删除该测试计划下所有用例,确认删除测试计划: ",
plan_delete_tip: "该测试计划正在进行中,请确认再删除!",
plan_delete: "删除计划", plan_delete: "删除计划",
}, },
review: { review: {
@ -1063,7 +1064,7 @@ export default {
SMTP_password: 'SMTP密码', SMTP_password: 'SMTP密码',
SSL: '开启SSL(如果SMTP端口是465通常需要启用SSL)', SSL: '开启SSL(如果SMTP端口是465通常需要启用SSL)',
TLS: '开启TLS(如果SMTP端口是587通常需要启用TLS)', TLS: '开启TLS(如果SMTP端口是587通常需要启用TLS)',
SMTP: '是否匿名 SMTP', SMTP: '是否免密 SMTP',
host: '主机号不能为空', host: '主机号不能为空',
port: '端口号不能为空', port: '端口号不能为空',
account: '账户不能为空', account: '账户不能为空',

View File

@ -470,7 +470,7 @@ export default {
title: "jar包管理", title: "jar包管理",
jar_file: "jar包", jar_file: "jar包",
delete_tip: "刪除需重啟服務後生效", delete_tip: "刪除需重啟服務後生效",
file_exist: "該項目下已存在jar包", file_exist: "該項目下已存在jar包",
upload_limit_size: "上傳文件大小不能超過 30MB!", upload_limit_size: "上傳文件大小不能超過 30MB!",
}, },
definition: { definition: {
@ -894,6 +894,7 @@ export default {
actual_start_time: "實際開始", actual_start_time: "實際開始",
actual_end_time: "實際結束", actual_end_time: "實際結束",
plan_delete_confirm: "將刪除該測試計劃下所有用例,確認刪除測試計劃: ", plan_delete_confirm: "將刪除該測試計劃下所有用例,確認刪除測試計劃: ",
plan_delete_tip: "該測試計劃正在進行中,請確認再刪除!",
plan_delete: "刪除計劃", plan_delete: "刪除計劃",
}, },
review: { review: {
@ -1061,7 +1062,7 @@ export default {
SMTP_password: 'SMTP密碼', SMTP_password: 'SMTP密碼',
SSL: '開啟SSL(如果SMTP端口是465通常需要啟用SSL)', SSL: '開啟SSL(如果SMTP端口是465通常需要啟用SSL)',
TLS: '開啟TLS(如果SMTP端口是587通常需要啟用TLS)', TLS: '開啟TLS(如果SMTP端口是587通常需要啟用TLS)',
SMTP: '是否匿名 SMTP', SMTP: '是否免密 SMTP',
host: '主機號不能為空', host: '主機號不能為空',
port: '端口號不能為空', port: '端口號不能為空',
account: '賬戶不能為空', account: '賬戶不能為空',

View File

@ -4,8 +4,7 @@
<el-col :span="12"> <el-col :span="12">
<el-form :model="form" :rules="rules" ref="form"> <el-form :model="form" :rules="rules" ref="form">
<div class="logo"> <div class="logo">
<img v-if="loginLogoId" :src="'/display/file/' + loginLogoId" style="width: 224px;height: 45px;" alt=""> <img :src="'/display/file/loginLogo'" style="width: 224px;height: 45px;" alt="">
<img v-else src="../assets/logo-dark-MeterSphere.svg" style="width: 224px; " alt="">
</div> </div>
<div class="title"> <div class="title">
<span id="s1">{{ loginTitle }}</span> <span id="s1">{{ loginTitle }}</span>
@ -41,8 +40,7 @@
</el-form> </el-form>
</el-col> </el-col>
<el-col :span="12"> <el-col :span="12">
<img v-if="loginImageId" :src="'/display/file/' + loginImageId" style="height: 560px; width: 100%"> <img :src="'/display/file/loginImage'" style="height: 560px; width: 100%">
<img v-else src="../assets/info.png" style="height: 560px; width: 100%">
</el-col> </el-col>
</el-row> </el-row>
</div> </div>
@ -86,8 +84,6 @@ export default {
msg: '', msg: '',
ready: false, ready: false,
openLdap: false, openLdap: false,
loginLogoId: '_blank',
loginImageId: '_blank',
loginTitle: this.$t("commons.login") + " MeterSphere" loginTitle: this.$t("commons.login") + " MeterSphere"
} }
}, },
@ -264,6 +260,10 @@ export default {
background: url(../assets/info.png); background: url(../assets/info.png);
height: 560px; height: 560px;
} }
.login-logo {
background: url(../assets/logo-dark-MeterSphere.svg);
}
</style> </style>
<style> <style>

View File

@ -4,7 +4,7 @@
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>
<groupId>io.metersphere</groupId> <groupId>io.metersphere</groupId>
<artifactId>metersphere-server</artifactId> <artifactId>metersphere-server</artifactId>
<version>1.4</version> <version>1.5</version>
<packaging>pom</packaging> <packaging>pom</packaging>
<parent> <parent>