Merge branch 'master' of https://github.com/metersphere/metersphere
This commit is contained in:
commit
f6490cb5ed
|
@ -312,24 +312,6 @@
|
|||
<scope>runtime</scope>
|
||||
</dependency>
|
||||
|
||||
<!-- buji-pac4j -->
|
||||
<dependency>
|
||||
<groupId>org.pac4j</groupId>
|
||||
<artifactId>pac4j-cas</artifactId>
|
||||
<version>3.0.2</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>io.buji</groupId>
|
||||
<artifactId>buji-pac4j</artifactId>
|
||||
<version>4.0.0</version>
|
||||
<exclusions>
|
||||
<exclusion>
|
||||
<artifactId>shiro-web</artifactId>
|
||||
<groupId>org.apache.shiro</groupId>
|
||||
</exclusion>
|
||||
</exclusions>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.jsoup</groupId>
|
||||
<artifactId>jsoup</artifactId>
|
||||
|
|
|
@ -27,5 +27,7 @@ public class TaskInfoResult {
|
|||
private String creator;
|
||||
//更新时间
|
||||
private Long updateTime;
|
||||
//定时任务类型 情景定时任务/范围计划任务
|
||||
private String taskType;
|
||||
|
||||
}
|
||||
|
|
|
@ -299,7 +299,7 @@ public class ApiAutomationService {
|
|||
return null;
|
||||
}
|
||||
|
||||
private void createScenarioReport(String id, String scenarioId, String scenarioName, String triggerMode, String execType, String projectId, String userID) {
|
||||
public void createScenarioReport(String id, String scenarioId, String scenarioName, String triggerMode, String execType, String projectId, String userID) {
|
||||
APIScenarioReportResult report = new APIScenarioReportResult();
|
||||
report.setId(id);
|
||||
report.setTestId(id);
|
||||
|
@ -417,88 +417,6 @@ public class ApiAutomationService {
|
|||
return request.getId();
|
||||
}
|
||||
|
||||
/**
|
||||
* 测试计划的定时任务--执行场景案例
|
||||
*
|
||||
* @param request
|
||||
* @return
|
||||
*/
|
||||
public String run(SchedulePlanScenarioExecuteRequest request) {
|
||||
MsTestPlan testPlan = new MsTestPlan();
|
||||
testPlan.setHashTree(new LinkedList<>());
|
||||
HashTree jmeterHashTree = new ListedHashTree();
|
||||
Map<String, Map<String, String>> testPlanScenarioIdMap = request.getTestPlanScenarioIDMap();
|
||||
for (Map.Entry<String, Map<String, String>> entry : testPlanScenarioIdMap.entrySet()) {
|
||||
String testPlanID = entry.getKey();
|
||||
Map<String, String> planScenarioIdMap = entry.getValue();
|
||||
List<ApiScenarioWithBLOBs> apiScenarios = extApiScenarioMapper.selectIds(new ArrayList<>(planScenarioIdMap.keySet()));
|
||||
try {
|
||||
boolean isFirst = true;
|
||||
for (ApiScenarioWithBLOBs item : apiScenarios) {
|
||||
String apiScenarioID = item.getId();
|
||||
String planScenarioID = planScenarioIdMap.get(apiScenarioID);
|
||||
if (StringUtils.isEmpty(planScenarioID)) {
|
||||
continue;
|
||||
}
|
||||
if (item.getStepTotal() == 0) {
|
||||
// 只有一个场景且没有测试步骤,则提示
|
||||
if (apiScenarios.size() == 1) {
|
||||
MSException.throwException((item.getName() + "," + Translator.get("automation_exec_info")));
|
||||
}
|
||||
LogUtil.warn(item.getName() + "," + Translator.get("automation_exec_info"));
|
||||
continue;
|
||||
}
|
||||
MsThreadGroup group = new MsThreadGroup();
|
||||
group.setLabel(item.getName());
|
||||
group.setName(UUID.randomUUID().toString());
|
||||
// 批量执行的结果直接存储为报告
|
||||
if (isFirst) {
|
||||
group.setName(request.getId());
|
||||
isFirst = false;
|
||||
}
|
||||
ObjectMapper mapper = new ObjectMapper();
|
||||
mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
|
||||
JSONObject element = JSON.parseObject(item.getScenarioDefinition());
|
||||
MsScenario scenario = JSONObject.parseObject(item.getScenarioDefinition(), MsScenario.class);
|
||||
|
||||
// 多态JSON普通转换会丢失内容,需要通过 ObjectMapper 获取
|
||||
if (element != null && StringUtils.isNotEmpty(element.getString("hashTree"))) {
|
||||
LinkedList<MsTestElement> elements = mapper.readValue(element.getString("hashTree"),
|
||||
new TypeReference<LinkedList<MsTestElement>>() {
|
||||
});
|
||||
scenario.setHashTree(elements);
|
||||
}
|
||||
if (StringUtils.isNotEmpty(element.getString("variables"))) {
|
||||
LinkedList<ScenarioVariable> variables = mapper.readValue(element.getString("variables"),
|
||||
new TypeReference<LinkedList<ScenarioVariable>>() {
|
||||
});
|
||||
scenario.setVariables(variables);
|
||||
}
|
||||
group.setEnableCookieShare(scenario.isEnableCookieShare());
|
||||
LinkedList<MsTestElement> scenarios = new LinkedList<>();
|
||||
scenarios.add(scenario);
|
||||
// 创建场景报告
|
||||
//不同的运行模式,第二个参数入参不同
|
||||
createScenarioReport(group.getName(),
|
||||
planScenarioID + ":" + request.getTestPlanReportId(),
|
||||
item.getName(), request.getTriggerMode() == null ? ReportTriggerMode.MANUAL.name() : request.getTriggerMode(),
|
||||
request.getExecuteType(), item.getProjectId(), request.getReportUserID());
|
||||
group.setHashTree(scenarios);
|
||||
testPlan.getHashTree().add(group);
|
||||
|
||||
}
|
||||
} catch (Exception ex) {
|
||||
MSException.throwException(ex.getMessage());
|
||||
}
|
||||
}
|
||||
testPlan.toHashTree(jmeterHashTree, testPlan.getHashTree(), new ParameterConfig());
|
||||
String runMode = ApiRunMode.SCHEDULE_SCENARIO_PLAN.name();
|
||||
// 调用执行方法
|
||||
jMeterService.runDefinition(request.getId(), jmeterHashTree, request.getReportId(), runMode);
|
||||
return request.getId();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 获取前台查询条件查询的所有(未经分页筛选)数据ID
|
||||
*
|
||||
|
|
|
@ -50,10 +50,18 @@
|
|||
AND create_time BETWEEN #{startTime} and #{endTime}
|
||||
</select>
|
||||
<select id="findRunningTaskInfoByProjectID" resultType="io.metersphere.api.dto.datacount.response.TaskInfoResult">
|
||||
SELECT apiScene.id AS scenarioId,apiScene.`name` AS scenario,sch.id AS taskID,sch.`value` AS rule,sch.`enable` AS `taskStatus`,u.`name` AS creator,sch.update_time AS updateTime
|
||||
SELECT apiScene.id AS scenarioId,apiScene.`name` AS scenario,sch.id AS taskID,sch.`value` AS rule,sch.`enable` AS `taskStatus`,u.`name` AS creator,sch.update_time AS updateTime,
|
||||
'scenario' AS taskType
|
||||
FROM api_scenario apiScene
|
||||
INNER JOIN `schedule` sch ON apiScene.id = sch.resource_id
|
||||
INNER JOIN `user` u ON u.id = sch.user_id
|
||||
WHERE sch.`enable` = true AND apiScene.project_id = #{0,jdbcType=VARCHAR}
|
||||
UNION
|
||||
SELECT testPlan.id AS scenarioId,testPlan.`name` AS scenario,sch.id AS taskID,sch.`value` AS rule,sch.`enable` AS `taskStatus`,u.`name` AS creator,sch.update_time AS updateTime,
|
||||
'testPlan' AS taskType
|
||||
FROM test_plan testPlan
|
||||
INNER JOIN `schedule` sch ON testPlan.id = sch.resource_id
|
||||
INNER JOIN `user` u ON u.id = sch.user_id
|
||||
WHERE sch.`enable` = true AND testPlan.project_id = #{0,jdbcType=VARCHAR}
|
||||
</select>
|
||||
</mapper>
|
|
@ -98,7 +98,9 @@
|
|||
|
||||
<select id="list" resultType="io.metersphere.track.dto.TestPlanDTOWithMetric"
|
||||
parameterType="io.metersphere.track.request.testcase.QueryTestPlanRequest">
|
||||
select DISTINCT test_plan.*, user.name as user_name, project.name as projectName,schedule.id as scheduleId from test_plan
|
||||
select DISTINCT test_plan.*, user.name as user_name, project.name as projectName,schedule.id as scheduleId,
|
||||
IF(schedule.enable = true,true,false) as scheduleOpen
|
||||
from test_plan
|
||||
LEFT JOIN user ON user.id = test_plan.principal
|
||||
LEFT JOIN schedule ON schedule.resource_id = test_plan.id
|
||||
JOIN project on project.id = test_plan.project_id
|
||||
|
@ -235,7 +237,7 @@
|
|||
|
||||
<select id="findIdByPerformanceReportId" resultType="java.lang.String">
|
||||
SELECT report.id FROM test_plan_report report INNER JOIN test_plan_report_data reportData ON report.id = reportData.test_plan_report_id
|
||||
WHERE reportData.performance_info like CONCAT('%', #{0}'%')
|
||||
WHERE reportData.performance_info like CONCAT('%', #{0},'%')
|
||||
</select>
|
||||
|
||||
</mapper>
|
|
@ -22,8 +22,6 @@ public class LoadTestConsumer {
|
|||
LoadTestReport loadTestReport = JSON.parseObject(record.value(), LoadTestReport.class);
|
||||
Reflections reflections = new Reflections(Application.class);
|
||||
Set<Class<? extends LoadTestFinishEvent>> subTypes = reflections.getSubTypesOf(LoadTestFinishEvent.class);
|
||||
LogUtil.info("Execute Over: LoadTestConsumer");
|
||||
System.out.println("Execute Over: LoadTestConsumer");
|
||||
subTypes.forEach(s -> {
|
||||
try {
|
||||
CommonBeanFactory.getBean(s).execute(loadTestReport);
|
||||
|
|
|
@ -21,7 +21,12 @@ public class ShiroUtils {
|
|||
filterChainDefinitionMap.put("/js/**", "anon");
|
||||
filterChainDefinitionMap.put("/img/**", "anon");
|
||||
filterChainDefinitionMap.put("/fonts/**", "anon");
|
||||
|
||||
filterChainDefinitionMap.put("/display/info", "anon");
|
||||
filterChainDefinitionMap.put("/favicon.ico", "anon");
|
||||
filterChainDefinitionMap.put("/display/file/**", "anon");
|
||||
filterChainDefinitionMap.put("/jmeter/download/**", "anon");
|
||||
filterChainDefinitionMap.put("/authsource/list/allenable", "anon");
|
||||
filterChainDefinitionMap.put("/sso/signin", "anon");
|
||||
// for swagger
|
||||
filterChainDefinitionMap.put("/swagger-ui.html", "anon");
|
||||
filterChainDefinitionMap.put("/swagger-ui/**", "anon");
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
package io.metersphere.config;
|
||||
|
||||
import io.metersphere.commons.user.UserModularRealmAuthenticator;
|
||||
import io.metersphere.commons.utils.ShiroUtils;
|
||||
import io.metersphere.security.ApiKeyFilter;
|
||||
import io.metersphere.security.LdapRealm;
|
||||
import io.metersphere.security.ShiroDBRealm;
|
||||
import io.metersphere.security.UserModularRealmAuthenticator;
|
||||
import io.metersphere.security.realm.LdapRealm;
|
||||
import io.metersphere.security.realm.ShiroDBRealm;
|
||||
import org.apache.shiro.authc.pam.FirstSuccessfulStrategy;
|
||||
import org.apache.shiro.authc.pam.ModularRealmAuthenticator;
|
||||
import org.apache.shiro.cache.MemoryConstrainedCacheManager;
|
||||
|
@ -46,10 +46,7 @@ public class ShiroConfig implements EnvironmentAware {
|
|||
shiroFilterFactoryBean.getFilters().put("apikey", new ApiKeyFilter());
|
||||
Map<String, String> filterChainDefinitionMap = shiroFilterFactoryBean.getFilterChainDefinitionMap();
|
||||
ShiroUtils.loadBaseFilterChain(filterChainDefinitionMap);
|
||||
filterChainDefinitionMap.put("/display/info", "anon");
|
||||
filterChainDefinitionMap.put("/favicon.ico", "anon");
|
||||
filterChainDefinitionMap.put("/display/file/**", "anon");
|
||||
filterChainDefinitionMap.put("/jmeter/download/**", "anon");
|
||||
|
||||
filterChainDefinitionMap.put("/**", "apikey, authc");
|
||||
return shiroFilterFactoryBean;
|
||||
}
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
package io.metersphere.controller;
|
||||
|
||||
import io.metersphere.commons.utils.SessionUtils;
|
||||
import org.apache.shiro.SecurityUtils;
|
||||
import org.springframework.stereotype.Controller;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
|
@ -23,15 +22,4 @@ public class IndexController {
|
|||
return "redirect:/";
|
||||
}
|
||||
}
|
||||
|
||||
@GetMapping(value = "/sso/login")
|
||||
public String ossLogin() {
|
||||
return "redirect:/";
|
||||
}
|
||||
|
||||
@GetMapping(value = "/sso/logout")
|
||||
public void ossLogout() {
|
||||
SecurityUtils.getSubject().logout();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -8,4 +8,5 @@ import lombok.Setter;
|
|||
public class LoginRequest {
|
||||
private String username;
|
||||
private String password;
|
||||
private String authenticate;
|
||||
}
|
||||
|
|
|
@ -40,22 +40,24 @@ public class TestPlanTestJob extends MsScheduleJob {
|
|||
private Map<String,String> apiTestCaseIdMap;
|
||||
private Map<String,String> performanceIdMap;
|
||||
|
||||
private ApiAutomationService apiAutomationService;
|
||||
private PerformanceTestService performanceTestService;
|
||||
private TestPlanScenarioCaseService testPlanScenarioCaseService;
|
||||
private TestPlanApiCaseService testPlanApiCaseService;
|
||||
private ApiTestCaseService apiTestCaseService;
|
||||
private TestPlanReportService testPlanReportService;
|
||||
private TestPlanLoadCaseService testPlanLoadCaseService;
|
||||
private TestPlanService testPlanService;
|
||||
|
||||
public TestPlanTestJob() {
|
||||
this.apiAutomationService = CommonBeanFactory.getBean(ApiAutomationService.class);
|
||||
this.performanceTestService = CommonBeanFactory.getBean(PerformanceTestService.class);
|
||||
this.testPlanScenarioCaseService = CommonBeanFactory.getBean(TestPlanScenarioCaseService.class);
|
||||
this.testPlanApiCaseService = CommonBeanFactory.getBean(TestPlanApiCaseService.class);
|
||||
this.apiTestCaseService = CommonBeanFactory.getBean(ApiTestCaseService.class);
|
||||
this.testPlanReportService = CommonBeanFactory.getBean(TestPlanReportService.class);
|
||||
this.testPlanLoadCaseService = CommonBeanFactory.getBean(TestPlanLoadCaseService.class);
|
||||
this.testPlanService = CommonBeanFactory.getBean(TestPlanService.class);
|
||||
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -128,7 +130,7 @@ public class TestPlanTestJob extends MsScheduleJob {
|
|||
scenarioRequest.setTestPlanID(this.resourceId);
|
||||
scenarioRequest.setRunMode(ApiRunMode.SCHEDULE_SCENARIO_PLAN.name());
|
||||
scenarioRequest.setTestPlanReportId(testPlanReport.getId());
|
||||
apiAutomationService.run(scenarioRequest);
|
||||
testPlanService.runApiCase(scenarioRequest);
|
||||
LogUtil.info("-------------- testplan schedule ---------- scenario case over -----------------");
|
||||
|
||||
//执行性能测试任务
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
package io.metersphere.security;
|
||||
|
||||
import io.metersphere.commons.user.MsUserToken;
|
||||
import io.metersphere.commons.utils.LogUtil;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.apache.shiro.SecurityUtils;
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
package io.metersphere.commons.user;
|
||||
package io.metersphere.security;
|
||||
|
||||
import org.apache.shiro.authc.UsernamePasswordToken;
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
package io.metersphere.commons.user;
|
||||
package io.metersphere.security;
|
||||
|
||||
import io.metersphere.commons.exception.MSException;
|
||||
import org.apache.shiro.authc.AuthenticationException;
|
|
@ -1,4 +1,4 @@
|
|||
package io.metersphere.security;
|
||||
package io.metersphere.security.realm;
|
||||
|
||||
|
||||
import io.metersphere.base.domain.Role;
|
|
@ -1,4 +1,4 @@
|
|||
package io.metersphere.security;
|
||||
package io.metersphere.security.realm;
|
||||
|
||||
|
||||
import io.metersphere.base.domain.Role;
|
|
@ -8,7 +8,6 @@ import io.metersphere.commons.constants.RoleConstants;
|
|||
import io.metersphere.commons.constants.UserSource;
|
||||
import io.metersphere.commons.constants.UserStatus;
|
||||
import io.metersphere.commons.exception.MSException;
|
||||
import io.metersphere.commons.user.MsUserToken;
|
||||
import io.metersphere.commons.user.SessionUser;
|
||||
import io.metersphere.commons.utils.CodingUtil;
|
||||
import io.metersphere.commons.utils.SessionUtils;
|
||||
|
@ -24,6 +23,7 @@ import io.metersphere.dto.UserDTO;
|
|||
import io.metersphere.dto.UserRoleDTO;
|
||||
import io.metersphere.i18n.Translator;
|
||||
import io.metersphere.notice.domain.UserDetail;
|
||||
import io.metersphere.security.MsUserToken;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.apache.shiro.SecurityUtils;
|
||||
import org.apache.shiro.authc.*;
|
||||
|
@ -559,16 +559,14 @@ public class UserService {
|
|||
String login = (String) SecurityUtils.getSubject().getSession().getAttribute("authenticate");
|
||||
String username = StringUtils.trim(request.getUsername());
|
||||
String password = "";
|
||||
String loginType = UserSource.LDAP.name();
|
||||
if (!StringUtils.equals(login, UserSource.LDAP.name())) {
|
||||
loginType = UserSource.LOCAL.name();
|
||||
password = StringUtils.trim(request.getPassword());
|
||||
if (StringUtils.isBlank(username) || StringUtils.isBlank(password)) {
|
||||
return ResultHolder.error("user or password can't be null");
|
||||
}
|
||||
}
|
||||
|
||||
MsUserToken token = new MsUserToken(username, password, loginType);
|
||||
MsUserToken token = new MsUserToken(username, password, login);
|
||||
Subject subject = SecurityUtils.getSubject();
|
||||
try {
|
||||
subject.login(token);
|
||||
|
|
|
@ -59,4 +59,12 @@ public class TestPlanReportController {
|
|||
TestPlanReport report = testPlanReportService.genTestPlanReport(planId,userId,ReportTriggerMode.API.name());
|
||||
testPlanReportService.countReportByTestPlanReportId(report.getId(),null, ReportTriggerMode.API.name());
|
||||
}
|
||||
|
||||
@GetMapping("/saveTestPlanReport/{planId}/{triggerMode}")
|
||||
public String saveTestPlanReport(@PathVariable String planId,@PathVariable String triggerMode) {
|
||||
String userId = SessionUtils.getUser().getId();
|
||||
TestPlanReport report = testPlanReportService.genTestPlanReport(planId,userId,triggerMode);
|
||||
testPlanReportService.countReportByTestPlanReportId(report.getId(),null, triggerMode);
|
||||
return "success";
|
||||
}
|
||||
}
|
||||
|
|
|
@ -12,5 +12,13 @@ public class TestPlanDTO extends TestPlan {
|
|||
private String projectName;
|
||||
private String userName;
|
||||
private List<String> projectIds;
|
||||
|
||||
/**
|
||||
* 定时任务ID
|
||||
*/
|
||||
private String scheduleId;
|
||||
/**
|
||||
* 定时任务是否开启
|
||||
*/
|
||||
private boolean scheduleOpen;
|
||||
}
|
||||
|
|
|
@ -1,21 +1,29 @@
|
|||
package io.metersphere.track.service;
|
||||
|
||||
|
||||
import com.alibaba.fastjson.JSON;
|
||||
import com.alibaba.fastjson.JSONArray;
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
import com.fasterxml.jackson.core.type.TypeReference;
|
||||
import com.fasterxml.jackson.databind.DeserializationFeature;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import io.metersphere.api.dto.automation.ApiScenarioDTO;
|
||||
import io.metersphere.api.dto.automation.ScenarioStatus;
|
||||
import io.metersphere.api.dto.automation.SchedulePlanScenarioExecuteRequest;
|
||||
import io.metersphere.api.dto.automation.TestPlanScenarioRequest;
|
||||
import io.metersphere.api.dto.definition.ApiTestCaseRequest;
|
||||
import io.metersphere.api.dto.definition.TestPlanApiCaseDTO;
|
||||
import io.metersphere.api.dto.definition.request.*;
|
||||
import io.metersphere.api.dto.definition.request.variable.ScenarioVariable;
|
||||
import io.metersphere.api.jmeter.JMeterService;
|
||||
import io.metersphere.api.service.ApiAutomationService;
|
||||
import io.metersphere.base.domain.*;
|
||||
import io.metersphere.base.mapper.*;
|
||||
import io.metersphere.base.mapper.ext.ExtApiScenarioMapper;
|
||||
import io.metersphere.base.mapper.ext.ExtTestCaseMapper;
|
||||
import io.metersphere.base.mapper.ext.ExtTestPlanMapper;
|
||||
import io.metersphere.base.mapper.ext.ExtTestPlanTestCaseMapper;
|
||||
import io.metersphere.commons.constants.NoticeConstants;
|
||||
import io.metersphere.commons.constants.TestPlanStatus;
|
||||
import io.metersphere.commons.constants.TestPlanTestCaseStatus;
|
||||
import io.metersphere.commons.constants.*;
|
||||
import io.metersphere.commons.exception.MSException;
|
||||
import io.metersphere.commons.user.SessionUser;
|
||||
import io.metersphere.commons.utils.*;
|
||||
|
@ -37,6 +45,8 @@ import org.apache.ibatis.annotations.Param;
|
|||
import org.apache.ibatis.session.ExecutorType;
|
||||
import org.apache.ibatis.session.SqlSession;
|
||||
import org.apache.ibatis.session.SqlSessionFactory;
|
||||
import org.apache.jorphan.collections.HashTree;
|
||||
import org.apache.jorphan.collections.ListedHashTree;
|
||||
import org.springframework.context.annotation.Lazy;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
@ -61,6 +71,8 @@ public class TestPlanService {
|
|||
@Resource
|
||||
TestPlanTestCaseMapper testPlanTestCaseMapper;
|
||||
@Resource
|
||||
ExtApiScenarioMapper extApiScenarioMapper;
|
||||
@Resource
|
||||
SqlSessionFactory sqlSessionFactory;
|
||||
@Lazy
|
||||
@Resource
|
||||
|
@ -87,6 +99,10 @@ public class TestPlanService {
|
|||
private TestPlanScenarioCaseService testPlanScenarioCaseService;
|
||||
@Resource
|
||||
private TestPlanLoadCaseService testPlanLoadCaseService;
|
||||
@Resource
|
||||
private JMeterService jMeterService;
|
||||
@Resource
|
||||
private ApiAutomationService apiAutomationService;
|
||||
|
||||
public synchronized void addTestPlan(AddTestPlanRequest testPlan) {
|
||||
if (getTestPlanByName(testPlan.getName()).size() > 0) {
|
||||
|
@ -728,4 +744,85 @@ public class TestPlanService {
|
|||
public String findScheduleCreateUserById(String testPlanId) {
|
||||
return extTestPlanMapper.findScheduleCreateUserById(testPlanId);
|
||||
}
|
||||
|
||||
/**
|
||||
* 测试计划的定时任务--执行场景案例
|
||||
*
|
||||
* @param request
|
||||
* @return
|
||||
*/
|
||||
public String runApiCase(SchedulePlanScenarioExecuteRequest request) {
|
||||
MsTestPlan testPlan = new MsTestPlan();
|
||||
testPlan.setHashTree(new LinkedList<>());
|
||||
HashTree jmeterHashTree = new ListedHashTree();
|
||||
Map<String, Map<String, String>> testPlanScenarioIdMap = request.getTestPlanScenarioIDMap();
|
||||
for (Map.Entry<String, Map<String, String>> entry : testPlanScenarioIdMap.entrySet()) {
|
||||
String testPlanID = entry.getKey();
|
||||
Map<String, String> planScenarioIdMap = entry.getValue();
|
||||
List<ApiScenarioWithBLOBs> apiScenarios = extApiScenarioMapper.selectIds(new ArrayList<>(planScenarioIdMap.keySet()));
|
||||
try {
|
||||
boolean isFirst = true;
|
||||
for (ApiScenarioWithBLOBs item : apiScenarios) {
|
||||
String apiScenarioID = item.getId();
|
||||
String planScenarioID = planScenarioIdMap.get(apiScenarioID);
|
||||
if (StringUtils.isEmpty(planScenarioID)) {
|
||||
continue;
|
||||
}
|
||||
if (item.getStepTotal() == 0) {
|
||||
// 只有一个场景且没有测试步骤,则提示
|
||||
if (apiScenarios.size() == 1) {
|
||||
MSException.throwException((item.getName() + "," + Translator.get("automation_exec_info")));
|
||||
}
|
||||
LogUtil.warn(item.getName() + "," + Translator.get("automation_exec_info"));
|
||||
continue;
|
||||
}
|
||||
MsThreadGroup group = new MsThreadGroup();
|
||||
group.setLabel(item.getName());
|
||||
group.setName(UUID.randomUUID().toString());
|
||||
// 批量执行的结果直接存储为报告
|
||||
if (isFirst) {
|
||||
group.setName(request.getId());
|
||||
isFirst = false;
|
||||
}
|
||||
ObjectMapper mapper = new ObjectMapper();
|
||||
mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
|
||||
JSONObject element = JSON.parseObject(item.getScenarioDefinition());
|
||||
MsScenario scenario = JSONObject.parseObject(item.getScenarioDefinition(), MsScenario.class);
|
||||
|
||||
// 多态JSON普通转换会丢失内容,需要通过 ObjectMapper 获取
|
||||
if (element != null && StringUtils.isNotEmpty(element.getString("hashTree"))) {
|
||||
LinkedList<MsTestElement> elements = mapper.readValue(element.getString("hashTree"),
|
||||
new TypeReference<LinkedList<MsTestElement>>() {
|
||||
});
|
||||
scenario.setHashTree(elements);
|
||||
}
|
||||
if (StringUtils.isNotEmpty(element.getString("variables"))) {
|
||||
LinkedList<ScenarioVariable> variables = mapper.readValue(element.getString("variables"),
|
||||
new TypeReference<LinkedList<ScenarioVariable>>() {
|
||||
});
|
||||
scenario.setVariables(variables);
|
||||
}
|
||||
group.setEnableCookieShare(scenario.isEnableCookieShare());
|
||||
LinkedList<MsTestElement> scenarios = new LinkedList<>();
|
||||
scenarios.add(scenario);
|
||||
// 创建场景报告
|
||||
//不同的运行模式,第二个参数入参不同
|
||||
apiAutomationService.createScenarioReport(group.getName(),
|
||||
planScenarioID + ":" + request.getTestPlanReportId(),
|
||||
item.getName(), request.getTriggerMode() == null ? ReportTriggerMode.MANUAL.name() : request.getTriggerMode(),
|
||||
request.getExecuteType(), item.getProjectId(), request.getReportUserID());
|
||||
group.setHashTree(scenarios);
|
||||
testPlan.getHashTree().add(group);
|
||||
|
||||
}
|
||||
} catch (Exception ex) {
|
||||
MSException.throwException(ex.getMessage());
|
||||
}
|
||||
}
|
||||
testPlan.toHashTree(jmeterHashTree, testPlan.getHashTree(), new ParameterConfig());
|
||||
String runMode = ApiRunMode.SCHEDULE_SCENARIO_PLAN.name();
|
||||
// 调用执行方法
|
||||
jMeterService.runDefinition(request.getId(), jmeterHashTree, request.getReportId(), runMode);
|
||||
return request.getId();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1 +1 @@
|
|||
Subproject commit 36116c1bff736377e6b8a3b828c5fa9bd8b2f2f8
|
||||
Subproject commit c2ed883e9be6fc7e01589f81916bf4ddc62148c0
|
|
@ -65,14 +65,24 @@
|
|||
<el-table-column :label="$t('commons.operating')" width="200px" v-if="!referenced">
|
||||
<template v-slot:default="{row}">
|
||||
<div v-if="trashEnable">
|
||||
<el-button type="text" @click="reductionApi(row)" v-tester>{{ $t('commons.reduction') }}</el-button>
|
||||
<el-button type="text" @click="remove(row)" v-tester>{{ $t('api_test.automation.remove') }}</el-button>
|
||||
<!-- <el-button type="text" @click="reductionApi(row)" v-tester>{{ $t('commons.reduction') }}</el-button>-->
|
||||
<!-- <el-button type="text" @click="remove(row)" v-tester>{{ $t('api_test.automation.remove') }}</el-button>-->
|
||||
<ms-table-operator-button :tip="$t('commons.reduction')" icon="el-icon-refresh-left" @exec="reductionApi(row)" v-tester/>
|
||||
<ms-table-operator-button :tip="$t('api_test.automation.remove')" icon="el-icon-delete" @exec="remove(row)" type="danger" v-tester/>
|
||||
</div>
|
||||
<div v-else>
|
||||
<el-button type="text" @click="edit(row)" v-tester>{{ $t('api_test.automation.edit') }}</el-button>
|
||||
<el-button type="text" @click="execute(row)" v-tester>{{ $t('api_test.automation.execute') }}</el-button>
|
||||
<el-button type="text" @click="copy(row)" v-tester>{{ $t('api_test.automation.copy') }}</el-button>
|
||||
<el-button type="text" @click="remove(row)" v-tester>{{ $t('api_test.automation.remove') }}</el-button>
|
||||
<ms-table-operator-button :tip="$t('api_test.automation.edit')" icon="el-icon-edit" @exec="edit(row)" v-tester/>
|
||||
<ms-table-operator-button class="run-button" :is-tester-permission="true" :tip="$t('api_test.automation.execute')"
|
||||
icon="el-icon-video-play"
|
||||
@exec="execute(row)" v-tester/>
|
||||
<ms-table-operator-button :tip="$t('api_test.automation.copy')" icon="el-icon-document"
|
||||
@exec="copy(row)"/>
|
||||
<ms-table-operator-button :tip="$t('api_test.automation.remove')" icon="el-icon-delete" @exec="remove(row)" type="danger" v-tester/>
|
||||
|
||||
<!-- <el-button type="text" @click="edit(row)" v-tester>{{ $t('api_test.automation.edit') }}</el-button>-->
|
||||
<!-- <el-button type="text" @click="execute(row)" v-tester>{{ $t('api_test.automation.execute') }}</el-button>-->
|
||||
<!-- <el-button type="text" @click="copy(row)" v-tester>{{ $t('api_test.automation.copy') }}</el-button>-->
|
||||
<!-- <el-button type="text" @click="remove(row)" v-tester>{{ $t('api_test.automation.remove') }}</el-button>-->
|
||||
<ms-scenario-extend-buttons :row="row"/>
|
||||
</div>
|
||||
</template>
|
||||
|
@ -109,6 +119,7 @@
|
|||
import MsTestPlanList from "./testplan/TestPlanList";
|
||||
import MsTableSelectAll from "../../../common/components/table/MsTableSelectAll";
|
||||
import {API_CASE_CONFIGS} from "@/business/components/common/components/search/search-components";
|
||||
import MsTableOperatorButton from "@/business/components/common/components/MsTableOperatorButton";
|
||||
|
||||
export default {
|
||||
name: "MsApiScenarioList",
|
||||
|
@ -121,7 +132,8 @@
|
|||
MsTag,
|
||||
MsApiReportDetail,
|
||||
MsScenarioExtendButtons,
|
||||
MsTestPlanList
|
||||
MsTestPlanList,
|
||||
MsTableOperatorButton
|
||||
},
|
||||
props: {
|
||||
referenced: {
|
||||
|
@ -426,5 +438,8 @@
|
|||
/deep/ .el-drawer__header {
|
||||
margin-bottom: 0px;
|
||||
}
|
||||
|
||||
/deep/ .run-button {
|
||||
background-color: #409EFF;
|
||||
border-color: #409EFF;
|
||||
}
|
||||
</style>
|
||||
|
|
|
@ -9,7 +9,7 @@
|
|||
<el-dropdown-item command="create_performance" v-tester>{{ $t('api_test.create_performance_test') }}</el-dropdown-item>
|
||||
</el-dropdown-menu>
|
||||
<ms-reference-view ref="viewRef"/>
|
||||
<ms-schedule-maintain ref="scheduleMaintain" />
|
||||
<ms-schedule-maintain ref="scheduleMaintain" @refreshTable="refreshTable" />
|
||||
</el-dropdown>
|
||||
</template>
|
||||
|
||||
|
@ -61,6 +61,9 @@
|
|||
})
|
||||
});
|
||||
},
|
||||
refreshTable(){
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
|
|
@ -115,7 +115,6 @@
|
|||
<span>{{ scope.row.actualEndTime | timestampFormatDate }}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
|
||||
</el-table>
|
||||
|
||||
<ms-table-pagination :change="initTableData" :current-page.sync="currentPage" :page-size.sync="pageSize"
|
||||
|
|
|
@ -203,6 +203,7 @@ export default {
|
|||
|
||||
this.$post(url, param, () => {
|
||||
this.$success(this.$t('commons.save_success'));
|
||||
this.$emit("refreshTable");
|
||||
});
|
||||
},
|
||||
checkScheduleEdit() {
|
||||
|
|
|
@ -69,12 +69,13 @@
|
|||
<el-table-column v-if="!isReadOnly" :label="$t('commons.operating')" min-width="130" align="center">
|
||||
<template v-slot:default="scope">
|
||||
<!--<el-button type="text" @click="reductionApi(scope.row)" v-if="trashEnable">{{$t('commons.reduction')}}</el-button>-->
|
||||
<el-button type="text" @click="handleTestCase(scope.row)" v-if="!trashEnable">{{ $t('commons.edit') }}
|
||||
</el-button>
|
||||
<el-button type="text" @click="handleDelete(scope.row)" style="color: #F56C6C">{{ $t('commons.delete') }}
|
||||
</el-button>
|
||||
<!-- <el-button type="text" @click="handleTestCase(scope.row)" v-if="!trashEnable">{{ $t('commons.edit') }}-->
|
||||
<!-- </el-button>-->
|
||||
<!-- <el-button type="text" @click="handleDelete(scope.row)" style="color: #F56C6C">{{ $t('commons.delete') }}-->
|
||||
<!-- </el-button>-->
|
||||
<ms-table-operator-button :tip="$t('commons.edit')" icon="el-icon-edit" @exec="handleTestCase(scope.row)" v-tester/>
|
||||
<ms-table-operator-button :tip="$t('commons.delete')" icon="el-icon-delete" @exec="handleDelete(scope.row)" type="danger" v-tester/>
|
||||
<ms-api-case-table-extend-btns @showCaseRef="showCaseRef" @showEnvironment="showEnvironment" @createPerformance="createPerformance" :row="scope.row" v-tester/>
|
||||
|
||||
</template>
|
||||
</el-table-column>
|
||||
|
||||
|
|
|
@ -112,10 +112,20 @@
|
|||
|
||||
<el-table-column v-if="!isReadOnly" :label="$t('commons.operating')" min-width="130" align="center">
|
||||
<template v-slot:default="scope">
|
||||
<el-button type="text" @click="reductionApi(scope.row)" v-if="trashEnable" v-tester>{{ $t('commons.reduction') }}</el-button>
|
||||
<el-button type="text" @click="editApi(scope.row)" v-else v-tester>{{ $t('commons.edit') }}</el-button>
|
||||
<el-button type="text" @click="handleTestCase(scope.row)">{{ $t('api_test.definition.request.case') }}</el-button>
|
||||
<el-button type="text" @click="handleDelete(scope.row)" style="color: #F56C6C" v-tester>{{ $t('commons.delete') }}</el-button>
|
||||
<ms-table-operator-button :tip="$t('commons.reduction')" icon="el-icon-refresh-left" @exec="reductionApi(scope.row)" v-if="trashEnable" v-tester/>
|
||||
<ms-table-operator-button :tip="$t('commons.edit')" icon="el-icon-edit" @exec="editApi(scope.row)" v-else v-tester/>
|
||||
<el-tooltip :content="$t('api_test.definition.request.case')"
|
||||
placement="bottom"
|
||||
:enterable="false"
|
||||
effect="dark" >
|
||||
<el-button @click="handleTestCase(scope.row)"
|
||||
@keydown.enter.native.prevent
|
||||
circle
|
||||
style="padding: 9px 1px;font-size: 1px"
|
||||
size="mini" >Case
|
||||
</el-button>
|
||||
</el-tooltip>
|
||||
<ms-table-operator-button :tip="$t('commons.delete')" icon="el-icon-delete" @exec="handleDelete(scope.row)" type="danger" v-tester/>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
|
@ -153,6 +163,7 @@
|
|||
import ApiStatus from "@/business/components/api/definition/components/list/ApiStatus";
|
||||
import MsTableAdvSearchBar from "@/business/components/common/components/search/MsTableAdvSearchBar";
|
||||
import {API_DEFINITION_CONFIGS} from "@/business/components/common/components/search/search-components";
|
||||
import MsTipButton from "@/business/components/common/components/MsTipButton";
|
||||
|
||||
export default {
|
||||
name: "ApiList",
|
||||
|
@ -171,6 +182,7 @@
|
|||
MsBottomContainer,
|
||||
ShowMoreBtn,
|
||||
MsBatchEdit,
|
||||
MsTipButton,
|
||||
MsTableAdvSearchBar
|
||||
},
|
||||
data() {
|
||||
|
|
|
@ -9,7 +9,7 @@
|
|||
<el-table-column prop="index" :label="$t('api_test.home_page.running_task_list.table_coloum.index')" width="80" show-overflow-tooltip/>
|
||||
<el-table-column prop="scenario" :label="$t('api_test.home_page.running_task_list.table_coloum.scenario')" width="200" >
|
||||
<template v-slot:default="{row}">
|
||||
<el-link type="info" @click="redirect(row.scenarioId)">
|
||||
<el-link type="info" @click="redirect(row)">
|
||||
{{ row.scenario }}
|
||||
</el-link>
|
||||
</template>
|
||||
|
@ -88,7 +88,11 @@ export default {
|
|||
});
|
||||
},
|
||||
redirect(param){
|
||||
this.$emit('redirectPage','scenario','scenario', 'edit:'+param);
|
||||
if(param.taskType === 'testPlan'){
|
||||
this.$emit('redirectPage','testPlanEdit','', param.scenarioId);
|
||||
}else{
|
||||
this.$emit('redirectPage','scenario','scenario', 'edit:'+param.scenarioId);
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
<template>
|
||||
<el-dropdown size="medium" @command="handleCommand" class="align-right">
|
||||
<span class="dropdown-link">
|
||||
{{currentUser.name}}<i class="el-icon-caret-bottom el-icon--right"/>
|
||||
{{ currentUser.name }}<i class="el-icon-caret-bottom el-icon--right"/>
|
||||
</span>
|
||||
<template v-slot:dropdown>
|
||||
<el-dropdown-menu>
|
||||
|
@ -23,11 +23,11 @@
|
|||
</template>
|
||||
|
||||
<script>
|
||||
import {getCurrentUser} from "../../../../common/js/utils";
|
||||
import AboutUs from "./AboutUs";
|
||||
import axios from "axios";
|
||||
import {getCurrentUser} from "@/common/js/utils";
|
||||
import AboutUs from "./AboutUs";
|
||||
import axios from "axios";
|
||||
|
||||
export default {
|
||||
export default {
|
||||
name: "MsUser",
|
||||
components: {AboutUs},
|
||||
data() {
|
||||
|
@ -52,11 +52,6 @@
|
|||
if (response.data.success) {
|
||||
localStorage.clear();
|
||||
window.location.href = "/login";
|
||||
} else {
|
||||
if (response.data.message === 'sso') {
|
||||
localStorage.clear();
|
||||
window.location.href = "/sso/logout"
|
||||
}
|
||||
}
|
||||
}).catch(error => {
|
||||
localStorage.clear();
|
||||
|
@ -77,28 +72,28 @@
|
|||
this.isReadOnly = !this.isReadOnly
|
||||
this.$store.commit('setFlag', this.isReadOnly);
|
||||
this.$store.commit('setValue', item);
|
||||
if(item=="old"){
|
||||
if (item == "old") {
|
||||
window.location.href = "/#/api/home_obsolete";
|
||||
}else {
|
||||
} else {
|
||||
window.location.href = "/#/api/home";
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.dropdown-link {
|
||||
.dropdown-link {
|
||||
cursor: pointer;
|
||||
font-size: 12px;
|
||||
color: rgb(245, 245, 245);
|
||||
line-height: 40px;
|
||||
}
|
||||
}
|
||||
|
||||
.align-right {
|
||||
.align-right {
|
||||
float: right;
|
||||
}
|
||||
}
|
||||
|
||||
</style>
|
||||
|
||||
|
|
|
@ -128,10 +128,10 @@
|
|||
@exec="openReport(scope.row.id, scope.row.reportId)"/>
|
||||
</template>
|
||||
</ms-table-operator>
|
||||
<ms-table-operator-button style="margin-left: 10px;color:#85888E;border-color: #85888E; border-width: thin;" v-if="!scope.row.scheduleId" type="text"
|
||||
<ms-table-operator-button style="margin-left: 10px;color:#85888E;border-color: #85888E; border-width: thin;" v-if="!scope.row.scheduleOpen" type="text"
|
||||
:tip="$t('commons.trigger_mode.schedule')" icon="el-icon-time"
|
||||
@exec="scheduleTask(scope.row)"/>
|
||||
<ms-table-operator-button style="margin-left: 10px;color:#6C317C; border-color: #6C317C; border-width: thin;" v-if="scope.row.scheduleId" type="text"
|
||||
<ms-table-operator-button style="margin-left: 10px;color:#6C317C; border-color: #6C317C; border-width: thin;" v-if="scope.row.scheduleOpen" type="text"
|
||||
:tip="$t('commons.trigger_mode.schedule')" icon="el-icon-time"
|
||||
@exec="scheduleTask(scope.row)"/>
|
||||
</template>
|
||||
|
@ -145,7 +145,7 @@
|
|||
<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>
|
||||
<ms-schedule-maintain ref="scheduleMaintain" />
|
||||
<ms-schedule-maintain ref="scheduleMaintain" @refreshTable="initTableData" />
|
||||
</el-card>
|
||||
</template>
|
||||
|
||||
|
|
|
@ -18,10 +18,10 @@
|
|||
@click="dialogFormVisible=true">
|
||||
{{ $t('report.test_stop_now') }}
|
||||
</el-button>
|
||||
<el-button :disabled="isReadOnly || report.status !== 'Completed'" type="success" plain size="mini"
|
||||
@click="rerun(testId)">
|
||||
{{ $t('report.test_execute_again') }}
|
||||
</el-button>
|
||||
<!-- <el-button :disabled="isReadOnly || report.status !== 'Completed'" type="success" plain size="mini"-->
|
||||
<!-- @click="rerun(testId)">-->
|
||||
<!-- {{ $t('report.test_execute_again') }}-->
|
||||
<!-- </el-button>-->
|
||||
<el-button :disabled="isReadOnly" type="info" plain size="mini" @click="handleExport(reportName)">
|
||||
{{ $t('test_track.plan_view.export_report') }}
|
||||
</el-button>
|
||||
|
|
|
@ -193,19 +193,17 @@ export default {
|
|||
}
|
||||
this.$post("/test/plan/load/case/list/" + this.currentPage + "/" + this.pageSize, param, response => {
|
||||
let data = response.data;
|
||||
this.total = data.itemCount;
|
||||
this.tableData = data.listObject;
|
||||
let {itemCount, listObject} = data;
|
||||
this.total = itemCount;
|
||||
this.tableData = listObject;
|
||||
})
|
||||
},
|
||||
refreshStatus() {
|
||||
this.refreshScheduler = setInterval(() => {
|
||||
let arr = this.tableData.filter(data => data.status !== 'Completed' && data.status !== 'Error' && data.status !== "Saved");
|
||||
if (arr.length > 0) {
|
||||
this.initTable();
|
||||
} else {
|
||||
clearInterval(this.refreshScheduler);
|
||||
}
|
||||
}, 4000);
|
||||
// 如果有状态不是最终状态则定时查询
|
||||
let arr = this.tableData.filter(data => data.status !== 'Completed' && data.status !== 'Error' && data.status !== 'Saved');
|
||||
arr.length > 0 ? this.initTable() : clearInterval(this.refreshScheduler);
|
||||
}, 8000);
|
||||
},
|
||||
handleSelectAll(selection) {
|
||||
if (selection.length > 0) {
|
||||
|
@ -263,20 +261,18 @@ export default {
|
|||
testPlanLoadId: loadCase.id,
|
||||
triggerMode: 'CASE'
|
||||
}).then(() => {
|
||||
this.$notify({
|
||||
this.$notify.success({
|
||||
title: loadCase.caseName,
|
||||
message: this.$t('test_track.plan.load_case.exec'),
|
||||
type: 'success'
|
||||
message: this.$t('test_track.plan.load_case.exec').toString()
|
||||
});
|
||||
this.initTable();
|
||||
}).catch(() => {
|
||||
//todo 用例出错
|
||||
this.$post('/test/plan/load/case/update', {id: loadCase.id, status: "error"}, () => {
|
||||
this.initTable();
|
||||
});
|
||||
this.$notify.error({
|
||||
title: loadCase.caseName,
|
||||
message: this.$t('test_track.plan.load_case.error')
|
||||
message: this.$t('test_track.plan.load_case.error').toString()
|
||||
});
|
||||
})
|
||||
},
|
||||
|
@ -289,15 +285,15 @@ export default {
|
|||
},
|
||||
sort(column) {
|
||||
// 每次只对一个字段排序
|
||||
if (this.condition.orders) {
|
||||
this.condition.orders = [];
|
||||
}
|
||||
_sort(column, this.condition);
|
||||
this.initTableData();
|
||||
// if (this.condition.orders) {
|
||||
// this.condition.orders = [];
|
||||
// }
|
||||
// _sort(column, this.condition);
|
||||
// this.initTable();
|
||||
},
|
||||
filter(filters) {
|
||||
_filter(filters, this.condition);
|
||||
this.initTableData();
|
||||
// _filter(filters, this.condition);
|
||||
// this.initTable();
|
||||
},
|
||||
getReport(data) {
|
||||
const {loadReportId} = data;
|
||||
|
|
|
@ -150,9 +150,12 @@
|
|||
handleSave() {
|
||||
let param = {};
|
||||
this.buildParam(param);
|
||||
this.$get('/test/plan/report/saveTestPlanReport/'+this.planId+'/MANUAL', () => {
|
||||
this.result = this.$post('/case/report/edit', param, () => {
|
||||
this.$success(this.$t('commons.save_success'));
|
||||
});
|
||||
});
|
||||
|
||||
},
|
||||
buildParam(param) {
|
||||
let content = {};
|
||||
|
|
|
@ -139,9 +139,11 @@
|
|||
handleSave() {
|
||||
let param = {};
|
||||
this.buildParam(param);
|
||||
this.$get('/test/plan/report/saveTestPlanReport/'+this.planId+'/MANUAL', () => {
|
||||
this.result = this.$post('/case/report/edit', param, () => {
|
||||
this.$success(this.$t('commons.save_success'));
|
||||
});
|
||||
});
|
||||
},
|
||||
buildParam(param) {
|
||||
let content = {};
|
||||
|
|
|
@ -19,12 +19,12 @@
|
|||
</div>
|
||||
</el-col>
|
||||
<el-col :span="12" class="head-right">
|
||||
<el-button :disabled="!isTestManagerOrTestUser" plain size="mini" @click="handleSave">
|
||||
{{$t('commons.save')}}
|
||||
</el-button>
|
||||
<el-button :disabled="!isTestManagerOrTestUser" plain size="mini" @click="handleEdit">
|
||||
{{$t('test_track.plan_view.edit_component')}}
|
||||
</el-button>
|
||||
<!-- <el-button :disabled="!isTestManagerOrTestUser" plain size="mini" @click="handleSave">-->
|
||||
<!-- {{$t('commons.save')}}-->
|
||||
<!-- </el-button>-->
|
||||
<!-- <el-button :disabled="!isTestManagerOrTestUser" plain size="mini" @click="handleEdit">-->
|
||||
<!-- {{$t('test_track.plan_view.edit_component')}}-->
|
||||
<!-- </el-button>-->
|
||||
<el-button :disabled="!isTestManagerOrTestUser" plain size="mini" @click="handleExport(report.name)">
|
||||
{{$t('test_track.plan_view.export_report')}}
|
||||
</el-button>
|
||||
|
|
|
@ -226,7 +226,7 @@ export default {
|
|||
if (response.success) {
|
||||
this.projects = response.data.filter(da => da.id !== getCurrentProjectID());
|
||||
} else {
|
||||
this.$warning()(response.message);
|
||||
this.$warning(response.message);
|
||||
}
|
||||
});
|
||||
},
|
||||
|
|
|
@ -1 +1 @@
|
|||
Subproject commit 3d96d7c61bc50f32f18311d23f447663e02d7d44
|
||||
Subproject commit cea763d974b213104f6d6fc30ab48434b72e10f4
|
|
@ -18,6 +18,7 @@
|
|||
<el-radio-group v-model="form.authenticate">
|
||||
<el-radio label="LDAP" size="mini" v-if="openLdap">LDAP</el-radio>
|
||||
<el-radio label="LOCAL" size="mini" v-if="openLdap">普通登录</el-radio>
|
||||
<el-radio :label="auth.id" size="mini" v-for="auth in authSources" :key="auth.id">{{ auth.type }} {{ auth.name }}</el-radio>
|
||||
</el-radio-group>
|
||||
</el-form-item>
|
||||
<el-form-item prop="username">
|
||||
|
@ -52,6 +53,7 @@ import {DEFAULT_LANGUAGE} from "@/common/js/constants";
|
|||
|
||||
const requireComponent = require.context('@/business/components/xpack/', true, /\.vue$/);
|
||||
const display = requireComponent.keys().length > 0 ? requireComponent("./display/Display.vue") : {};
|
||||
const auth = requireComponent.keys().length > 0 ? requireComponent("./auth/Auth.vue") : {};
|
||||
|
||||
export default {
|
||||
name: "Login",
|
||||
|
@ -84,7 +86,9 @@ export default {
|
|||
msg: '',
|
||||
ready: false,
|
||||
openLdap: false,
|
||||
loginTitle: this.$t("commons.login") + " MeterSphere"
|
||||
loginTitle: this.$t("commons.login") + " MeterSphere",
|
||||
authSources: [],
|
||||
loginUrl: 'signin',
|
||||
}
|
||||
},
|
||||
beforeCreate() {
|
||||
|
@ -94,17 +98,17 @@ export default {
|
|||
display.default.showLogin(this);
|
||||
}
|
||||
|
||||
if (!response.data.success) {
|
||||
if (response.data.message === 'sso') {
|
||||
window.location.href = "/sso/login"
|
||||
} else {
|
||||
this.ready = true;
|
||||
if (auth.default !== undefined) {
|
||||
auth.default.getAuthSources(this);
|
||||
}
|
||||
|
||||
if (!response.data.success) {
|
||||
this.ready = true;
|
||||
} else {
|
||||
let user = response.data.data;
|
||||
saveLocalStorage(response.data);
|
||||
this.getLanguage(user.language);
|
||||
window.location.href = "/"
|
||||
window.location.href = "/";
|
||||
}
|
||||
});
|
||||
this.$get("/ldap/open", response => {
|
||||
|
@ -135,28 +139,24 @@ export default {
|
|||
if (valid) {
|
||||
switch (this.form.authenticate) {
|
||||
case "LOCAL":
|
||||
this.normalLogin();
|
||||
this.loginUrl = "/signin";
|
||||
this.doLogin();
|
||||
break;
|
||||
case "LDAP":
|
||||
this.ldapLogin();
|
||||
this.loginUrl = "/ldap/signin";
|
||||
this.doLogin();
|
||||
break;
|
||||
default:
|
||||
this.normalLogin();
|
||||
this.loginUrl = "/sso/signin";
|
||||
this.doLogin();
|
||||
}
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
});
|
||||
},
|
||||
normalLogin() {
|
||||
this.result = this.$post("signin", this.form, response => {
|
||||
saveLocalStorage(response);
|
||||
sessionStorage.setItem('loginSuccess', 'true');
|
||||
this.getLanguage(response.data.language);
|
||||
});
|
||||
},
|
||||
ldapLogin() {
|
||||
this.result = this.$post("ldap/signin", this.form, response => {
|
||||
doLogin() {
|
||||
this.result = this.$post(this.loginUrl, this.form, response => {
|
||||
saveLocalStorage(response);
|
||||
sessionStorage.setItem('loginSuccess', 'true');
|
||||
this.getLanguage(response.data.language);
|
||||
|
|
Loading…
Reference in New Issue