Merge branch 'master' of https://github.com/metersphere/metersphere
Conflicts: backend/pom.xml
This commit is contained in:
commit
8bcf1ebc4c
|
@ -60,6 +60,7 @@
|
|||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-mail</artifactId>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.projectlombok</groupId>
|
||||
<artifactId>lombok</artifactId>
|
||||
|
@ -75,6 +76,7 @@
|
|||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-websocket</artifactId>
|
||||
</dependency>
|
||||
|
||||
<!-- flyway -->
|
||||
<dependency>
|
||||
<groupId>org.flywaydb</groupId>
|
||||
|
@ -153,6 +155,12 @@
|
|||
<version>2.1.7</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.quartz-scheduler</groupId>
|
||||
<artifactId>quartz</artifactId>
|
||||
<version>2.3.0</version>
|
||||
</dependency>
|
||||
|
||||
<!-- LDAP Module -->
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
|
|
|
@ -50,6 +50,11 @@ public class APITestController {
|
|||
return apiTestService.getApiTestByProjectId(projectId);
|
||||
}
|
||||
|
||||
@PostMapping(value = "/schedule/update")
|
||||
public void updateSchedule(@RequestBody SaveAPITestRequest request) {
|
||||
apiTestService.updateSchedule(request);
|
||||
}
|
||||
|
||||
@PostMapping(value = "/create", consumes = {"multipart/form-data"})
|
||||
public void create(@RequestPart("request") SaveAPITestRequest request, @RequestPart(value = "files") List<MultipartFile> files) {
|
||||
apiTestService.create(request, files);
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
package io.metersphere.api.dto;
|
||||
|
||||
import io.metersphere.api.dto.scenario.Scenario;
|
||||
import io.metersphere.dto.ScheduleDTO;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
|
||||
|
@ -17,4 +18,6 @@ public class SaveAPITestRequest {
|
|||
private String name;
|
||||
|
||||
private List<Scenario> scenarioDefinition;
|
||||
|
||||
private ScheduleDTO schedule;
|
||||
}
|
||||
|
|
|
@ -207,4 +207,14 @@ public class APITestService {
|
|||
}
|
||||
}
|
||||
|
||||
public void updateSchedule(SaveAPITestRequest request) {
|
||||
|
||||
// todo 开启调度线程
|
||||
|
||||
ApiTestWithBLOBs apiTest = new ApiTestWithBLOBs();
|
||||
apiTest.setId(request.getId());
|
||||
apiTest.setSchedule(JSONObject.toJSONString(request.getSchedule()));
|
||||
apiTest.setUpdateTime(System.currentTimeMillis());
|
||||
apiTestMapper.updateByPrimaryKeySelective(apiTest);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,22 @@
|
|||
package io.metersphere.base.domain;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
@Data
|
||||
public class UserKey implements Serializable {
|
||||
private String id;
|
||||
|
||||
private String userId;
|
||||
|
||||
private String accessKey;
|
||||
|
||||
private String secretKey;
|
||||
|
||||
private Long createTime;
|
||||
|
||||
private String status;
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
}
|
|
@ -0,0 +1,610 @@
|
|||
package io.metersphere.base.domain;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public class UserKeyExample {
|
||||
protected String orderByClause;
|
||||
|
||||
protected boolean distinct;
|
||||
|
||||
protected List<Criteria> oredCriteria;
|
||||
|
||||
public UserKeyExample() {
|
||||
oredCriteria = new ArrayList<Criteria>();
|
||||
}
|
||||
|
||||
public void setOrderByClause(String orderByClause) {
|
||||
this.orderByClause = orderByClause;
|
||||
}
|
||||
|
||||
public String getOrderByClause() {
|
||||
return orderByClause;
|
||||
}
|
||||
|
||||
public void setDistinct(boolean distinct) {
|
||||
this.distinct = distinct;
|
||||
}
|
||||
|
||||
public boolean isDistinct() {
|
||||
return distinct;
|
||||
}
|
||||
|
||||
public List<Criteria> getOredCriteria() {
|
||||
return oredCriteria;
|
||||
}
|
||||
|
||||
public void or(Criteria criteria) {
|
||||
oredCriteria.add(criteria);
|
||||
}
|
||||
|
||||
public Criteria or() {
|
||||
Criteria criteria = createCriteriaInternal();
|
||||
oredCriteria.add(criteria);
|
||||
return criteria;
|
||||
}
|
||||
|
||||
public Criteria createCriteria() {
|
||||
Criteria criteria = createCriteriaInternal();
|
||||
if (oredCriteria.size() == 0) {
|
||||
oredCriteria.add(criteria);
|
||||
}
|
||||
return criteria;
|
||||
}
|
||||
|
||||
protected Criteria createCriteriaInternal() {
|
||||
Criteria criteria = new Criteria();
|
||||
return criteria;
|
||||
}
|
||||
|
||||
public void clear() {
|
||||
oredCriteria.clear();
|
||||
orderByClause = null;
|
||||
distinct = false;
|
||||
}
|
||||
|
||||
protected abstract static class GeneratedCriteria {
|
||||
protected List<Criterion> criteria;
|
||||
|
||||
protected GeneratedCriteria() {
|
||||
super();
|
||||
criteria = new ArrayList<Criterion>();
|
||||
}
|
||||
|
||||
public boolean isValid() {
|
||||
return criteria.size() > 0;
|
||||
}
|
||||
|
||||
public List<Criterion> getAllCriteria() {
|
||||
return criteria;
|
||||
}
|
||||
|
||||
public List<Criterion> getCriteria() {
|
||||
return criteria;
|
||||
}
|
||||
|
||||
protected void addCriterion(String condition) {
|
||||
if (condition == null) {
|
||||
throw new RuntimeException("Value for condition cannot be null");
|
||||
}
|
||||
criteria.add(new Criterion(condition));
|
||||
}
|
||||
|
||||
protected void addCriterion(String condition, Object value, String property) {
|
||||
if (value == null) {
|
||||
throw new RuntimeException("Value for " + property + " cannot be null");
|
||||
}
|
||||
criteria.add(new Criterion(condition, value));
|
||||
}
|
||||
|
||||
protected void addCriterion(String condition, Object value1, Object value2, String property) {
|
||||
if (value1 == null || value2 == null) {
|
||||
throw new RuntimeException("Between values for " + property + " cannot be null");
|
||||
}
|
||||
criteria.add(new Criterion(condition, value1, value2));
|
||||
}
|
||||
|
||||
public Criteria andIdIsNull() {
|
||||
addCriterion("id is null");
|
||||
return (Criteria) this;
|
||||
}
|
||||
|
||||
public Criteria andIdIsNotNull() {
|
||||
addCriterion("id is not null");
|
||||
return (Criteria) this;
|
||||
}
|
||||
|
||||
public Criteria andIdEqualTo(String value) {
|
||||
addCriterion("id =", value, "id");
|
||||
return (Criteria) this;
|
||||
}
|
||||
|
||||
public Criteria andIdNotEqualTo(String value) {
|
||||
addCriterion("id <>", value, "id");
|
||||
return (Criteria) this;
|
||||
}
|
||||
|
||||
public Criteria andIdGreaterThan(String value) {
|
||||
addCriterion("id >", value, "id");
|
||||
return (Criteria) this;
|
||||
}
|
||||
|
||||
public Criteria andIdGreaterThanOrEqualTo(String value) {
|
||||
addCriterion("id >=", value, "id");
|
||||
return (Criteria) this;
|
||||
}
|
||||
|
||||
public Criteria andIdLessThan(String value) {
|
||||
addCriterion("id <", value, "id");
|
||||
return (Criteria) this;
|
||||
}
|
||||
|
||||
public Criteria andIdLessThanOrEqualTo(String value) {
|
||||
addCriterion("id <=", value, "id");
|
||||
return (Criteria) this;
|
||||
}
|
||||
|
||||
public Criteria andIdLike(String value) {
|
||||
addCriterion("id like", value, "id");
|
||||
return (Criteria) this;
|
||||
}
|
||||
|
||||
public Criteria andIdNotLike(String value) {
|
||||
addCriterion("id not like", value, "id");
|
||||
return (Criteria) this;
|
||||
}
|
||||
|
||||
public Criteria andIdIn(List<String> values) {
|
||||
addCriterion("id in", values, "id");
|
||||
return (Criteria) this;
|
||||
}
|
||||
|
||||
public Criteria andIdNotIn(List<String> values) {
|
||||
addCriterion("id not in", values, "id");
|
||||
return (Criteria) this;
|
||||
}
|
||||
|
||||
public Criteria andIdBetween(String value1, String value2) {
|
||||
addCriterion("id between", value1, value2, "id");
|
||||
return (Criteria) this;
|
||||
}
|
||||
|
||||
public Criteria andIdNotBetween(String value1, String value2) {
|
||||
addCriterion("id not between", value1, value2, "id");
|
||||
return (Criteria) this;
|
||||
}
|
||||
|
||||
public Criteria andUserIdIsNull() {
|
||||
addCriterion("user_id is null");
|
||||
return (Criteria) this;
|
||||
}
|
||||
|
||||
public Criteria andUserIdIsNotNull() {
|
||||
addCriterion("user_id is not null");
|
||||
return (Criteria) this;
|
||||
}
|
||||
|
||||
public Criteria andUserIdEqualTo(String value) {
|
||||
addCriterion("user_id =", value, "userId");
|
||||
return (Criteria) this;
|
||||
}
|
||||
|
||||
public Criteria andUserIdNotEqualTo(String value) {
|
||||
addCriterion("user_id <>", value, "userId");
|
||||
return (Criteria) this;
|
||||
}
|
||||
|
||||
public Criteria andUserIdGreaterThan(String value) {
|
||||
addCriterion("user_id >", value, "userId");
|
||||
return (Criteria) this;
|
||||
}
|
||||
|
||||
public Criteria andUserIdGreaterThanOrEqualTo(String value) {
|
||||
addCriterion("user_id >=", value, "userId");
|
||||
return (Criteria) this;
|
||||
}
|
||||
|
||||
public Criteria andUserIdLessThan(String value) {
|
||||
addCriterion("user_id <", value, "userId");
|
||||
return (Criteria) this;
|
||||
}
|
||||
|
||||
public Criteria andUserIdLessThanOrEqualTo(String value) {
|
||||
addCriterion("user_id <=", value, "userId");
|
||||
return (Criteria) this;
|
||||
}
|
||||
|
||||
public Criteria andUserIdLike(String value) {
|
||||
addCriterion("user_id like", value, "userId");
|
||||
return (Criteria) this;
|
||||
}
|
||||
|
||||
public Criteria andUserIdNotLike(String value) {
|
||||
addCriterion("user_id not like", value, "userId");
|
||||
return (Criteria) this;
|
||||
}
|
||||
|
||||
public Criteria andUserIdIn(List<String> values) {
|
||||
addCriterion("user_id in", values, "userId");
|
||||
return (Criteria) this;
|
||||
}
|
||||
|
||||
public Criteria andUserIdNotIn(List<String> values) {
|
||||
addCriterion("user_id not in", values, "userId");
|
||||
return (Criteria) this;
|
||||
}
|
||||
|
||||
public Criteria andUserIdBetween(String value1, String value2) {
|
||||
addCriterion("user_id between", value1, value2, "userId");
|
||||
return (Criteria) this;
|
||||
}
|
||||
|
||||
public Criteria andUserIdNotBetween(String value1, String value2) {
|
||||
addCriterion("user_id not between", value1, value2, "userId");
|
||||
return (Criteria) this;
|
||||
}
|
||||
|
||||
public Criteria andAccessKeyIsNull() {
|
||||
addCriterion("access_key is null");
|
||||
return (Criteria) this;
|
||||
}
|
||||
|
||||
public Criteria andAccessKeyIsNotNull() {
|
||||
addCriterion("access_key is not null");
|
||||
return (Criteria) this;
|
||||
}
|
||||
|
||||
public Criteria andAccessKeyEqualTo(String value) {
|
||||
addCriterion("access_key =", value, "accessKey");
|
||||
return (Criteria) this;
|
||||
}
|
||||
|
||||
public Criteria andAccessKeyNotEqualTo(String value) {
|
||||
addCriterion("access_key <>", value, "accessKey");
|
||||
return (Criteria) this;
|
||||
}
|
||||
|
||||
public Criteria andAccessKeyGreaterThan(String value) {
|
||||
addCriterion("access_key >", value, "accessKey");
|
||||
return (Criteria) this;
|
||||
}
|
||||
|
||||
public Criteria andAccessKeyGreaterThanOrEqualTo(String value) {
|
||||
addCriterion("access_key >=", value, "accessKey");
|
||||
return (Criteria) this;
|
||||
}
|
||||
|
||||
public Criteria andAccessKeyLessThan(String value) {
|
||||
addCriterion("access_key <", value, "accessKey");
|
||||
return (Criteria) this;
|
||||
}
|
||||
|
||||
public Criteria andAccessKeyLessThanOrEqualTo(String value) {
|
||||
addCriterion("access_key <=", value, "accessKey");
|
||||
return (Criteria) this;
|
||||
}
|
||||
|
||||
public Criteria andAccessKeyLike(String value) {
|
||||
addCriterion("access_key like", value, "accessKey");
|
||||
return (Criteria) this;
|
||||
}
|
||||
|
||||
public Criteria andAccessKeyNotLike(String value) {
|
||||
addCriterion("access_key not like", value, "accessKey");
|
||||
return (Criteria) this;
|
||||
}
|
||||
|
||||
public Criteria andAccessKeyIn(List<String> values) {
|
||||
addCriterion("access_key in", values, "accessKey");
|
||||
return (Criteria) this;
|
||||
}
|
||||
|
||||
public Criteria andAccessKeyNotIn(List<String> values) {
|
||||
addCriterion("access_key not in", values, "accessKey");
|
||||
return (Criteria) this;
|
||||
}
|
||||
|
||||
public Criteria andAccessKeyBetween(String value1, String value2) {
|
||||
addCriterion("access_key between", value1, value2, "accessKey");
|
||||
return (Criteria) this;
|
||||
}
|
||||
|
||||
public Criteria andAccessKeyNotBetween(String value1, String value2) {
|
||||
addCriterion("access_key not between", value1, value2, "accessKey");
|
||||
return (Criteria) this;
|
||||
}
|
||||
|
||||
public Criteria andSecretKeyIsNull() {
|
||||
addCriterion("secret_key is null");
|
||||
return (Criteria) this;
|
||||
}
|
||||
|
||||
public Criteria andSecretKeyIsNotNull() {
|
||||
addCriterion("secret_key is not null");
|
||||
return (Criteria) this;
|
||||
}
|
||||
|
||||
public Criteria andSecretKeyEqualTo(String value) {
|
||||
addCriterion("secret_key =", value, "secretKey");
|
||||
return (Criteria) this;
|
||||
}
|
||||
|
||||
public Criteria andSecretKeyNotEqualTo(String value) {
|
||||
addCriterion("secret_key <>", value, "secretKey");
|
||||
return (Criteria) this;
|
||||
}
|
||||
|
||||
public Criteria andSecretKeyGreaterThan(String value) {
|
||||
addCriterion("secret_key >", value, "secretKey");
|
||||
return (Criteria) this;
|
||||
}
|
||||
|
||||
public Criteria andSecretKeyGreaterThanOrEqualTo(String value) {
|
||||
addCriterion("secret_key >=", value, "secretKey");
|
||||
return (Criteria) this;
|
||||
}
|
||||
|
||||
public Criteria andSecretKeyLessThan(String value) {
|
||||
addCriterion("secret_key <", value, "secretKey");
|
||||
return (Criteria) this;
|
||||
}
|
||||
|
||||
public Criteria andSecretKeyLessThanOrEqualTo(String value) {
|
||||
addCriterion("secret_key <=", value, "secretKey");
|
||||
return (Criteria) this;
|
||||
}
|
||||
|
||||
public Criteria andSecretKeyLike(String value) {
|
||||
addCriterion("secret_key like", value, "secretKey");
|
||||
return (Criteria) this;
|
||||
}
|
||||
|
||||
public Criteria andSecretKeyNotLike(String value) {
|
||||
addCriterion("secret_key not like", value, "secretKey");
|
||||
return (Criteria) this;
|
||||
}
|
||||
|
||||
public Criteria andSecretKeyIn(List<String> values) {
|
||||
addCriterion("secret_key in", values, "secretKey");
|
||||
return (Criteria) this;
|
||||
}
|
||||
|
||||
public Criteria andSecretKeyNotIn(List<String> values) {
|
||||
addCriterion("secret_key not in", values, "secretKey");
|
||||
return (Criteria) this;
|
||||
}
|
||||
|
||||
public Criteria andSecretKeyBetween(String value1, String value2) {
|
||||
addCriterion("secret_key between", value1, value2, "secretKey");
|
||||
return (Criteria) this;
|
||||
}
|
||||
|
||||
public Criteria andSecretKeyNotBetween(String value1, String value2) {
|
||||
addCriterion("secret_key not between", value1, value2, "secretKey");
|
||||
return (Criteria) this;
|
||||
}
|
||||
|
||||
public Criteria andCreateTimeIsNull() {
|
||||
addCriterion("create_time is null");
|
||||
return (Criteria) this;
|
||||
}
|
||||
|
||||
public Criteria andCreateTimeIsNotNull() {
|
||||
addCriterion("create_time is not null");
|
||||
return (Criteria) this;
|
||||
}
|
||||
|
||||
public Criteria andCreateTimeEqualTo(Long value) {
|
||||
addCriterion("create_time =", value, "createTime");
|
||||
return (Criteria) this;
|
||||
}
|
||||
|
||||
public Criteria andCreateTimeNotEqualTo(Long value) {
|
||||
addCriterion("create_time <>", value, "createTime");
|
||||
return (Criteria) this;
|
||||
}
|
||||
|
||||
public Criteria andCreateTimeGreaterThan(Long value) {
|
||||
addCriterion("create_time >", value, "createTime");
|
||||
return (Criteria) this;
|
||||
}
|
||||
|
||||
public Criteria andCreateTimeGreaterThanOrEqualTo(Long value) {
|
||||
addCriterion("create_time >=", value, "createTime");
|
||||
return (Criteria) this;
|
||||
}
|
||||
|
||||
public Criteria andCreateTimeLessThan(Long value) {
|
||||
addCriterion("create_time <", value, "createTime");
|
||||
return (Criteria) this;
|
||||
}
|
||||
|
||||
public Criteria andCreateTimeLessThanOrEqualTo(Long value) {
|
||||
addCriterion("create_time <=", value, "createTime");
|
||||
return (Criteria) this;
|
||||
}
|
||||
|
||||
public Criteria andCreateTimeIn(List<Long> values) {
|
||||
addCriterion("create_time in", values, "createTime");
|
||||
return (Criteria) this;
|
||||
}
|
||||
|
||||
public Criteria andCreateTimeNotIn(List<Long> values) {
|
||||
addCriterion("create_time not in", values, "createTime");
|
||||
return (Criteria) this;
|
||||
}
|
||||
|
||||
public Criteria andCreateTimeBetween(Long value1, Long value2) {
|
||||
addCriterion("create_time between", value1, value2, "createTime");
|
||||
return (Criteria) this;
|
||||
}
|
||||
|
||||
public Criteria andCreateTimeNotBetween(Long value1, Long value2) {
|
||||
addCriterion("create_time not between", value1, value2, "createTime");
|
||||
return (Criteria) this;
|
||||
}
|
||||
|
||||
public Criteria andStatusIsNull() {
|
||||
addCriterion("status is null");
|
||||
return (Criteria) this;
|
||||
}
|
||||
|
||||
public Criteria andStatusIsNotNull() {
|
||||
addCriterion("status is not null");
|
||||
return (Criteria) this;
|
||||
}
|
||||
|
||||
public Criteria andStatusEqualTo(String value) {
|
||||
addCriterion("status =", value, "status");
|
||||
return (Criteria) this;
|
||||
}
|
||||
|
||||
public Criteria andStatusNotEqualTo(String value) {
|
||||
addCriterion("status <>", value, "status");
|
||||
return (Criteria) this;
|
||||
}
|
||||
|
||||
public Criteria andStatusGreaterThan(String value) {
|
||||
addCriterion("status >", value, "status");
|
||||
return (Criteria) this;
|
||||
}
|
||||
|
||||
public Criteria andStatusGreaterThanOrEqualTo(String value) {
|
||||
addCriterion("status >=", value, "status");
|
||||
return (Criteria) this;
|
||||
}
|
||||
|
||||
public Criteria andStatusLessThan(String value) {
|
||||
addCriterion("status <", value, "status");
|
||||
return (Criteria) this;
|
||||
}
|
||||
|
||||
public Criteria andStatusLessThanOrEqualTo(String value) {
|
||||
addCriterion("status <=", value, "status");
|
||||
return (Criteria) this;
|
||||
}
|
||||
|
||||
public Criteria andStatusLike(String value) {
|
||||
addCriterion("status like", value, "status");
|
||||
return (Criteria) this;
|
||||
}
|
||||
|
||||
public Criteria andStatusNotLike(String value) {
|
||||
addCriterion("status not like", value, "status");
|
||||
return (Criteria) this;
|
||||
}
|
||||
|
||||
public Criteria andStatusIn(List<String> values) {
|
||||
addCriterion("status in", values, "status");
|
||||
return (Criteria) this;
|
||||
}
|
||||
|
||||
public Criteria andStatusNotIn(List<String> values) {
|
||||
addCriterion("status not in", values, "status");
|
||||
return (Criteria) this;
|
||||
}
|
||||
|
||||
public Criteria andStatusBetween(String value1, String value2) {
|
||||
addCriterion("status between", value1, value2, "status");
|
||||
return (Criteria) this;
|
||||
}
|
||||
|
||||
public Criteria andStatusNotBetween(String value1, String value2) {
|
||||
addCriterion("status not between", value1, value2, "status");
|
||||
return (Criteria) this;
|
||||
}
|
||||
}
|
||||
|
||||
public static class Criteria extends GeneratedCriteria {
|
||||
|
||||
protected Criteria() {
|
||||
super();
|
||||
}
|
||||
}
|
||||
|
||||
public static class Criterion {
|
||||
private String condition;
|
||||
|
||||
private Object value;
|
||||
|
||||
private Object secondValue;
|
||||
|
||||
private boolean noValue;
|
||||
|
||||
private boolean singleValue;
|
||||
|
||||
private boolean betweenValue;
|
||||
|
||||
private boolean listValue;
|
||||
|
||||
private String typeHandler;
|
||||
|
||||
public String getCondition() {
|
||||
return condition;
|
||||
}
|
||||
|
||||
public Object getValue() {
|
||||
return value;
|
||||
}
|
||||
|
||||
public Object getSecondValue() {
|
||||
return secondValue;
|
||||
}
|
||||
|
||||
public boolean isNoValue() {
|
||||
return noValue;
|
||||
}
|
||||
|
||||
public boolean isSingleValue() {
|
||||
return singleValue;
|
||||
}
|
||||
|
||||
public boolean isBetweenValue() {
|
||||
return betweenValue;
|
||||
}
|
||||
|
||||
public boolean isListValue() {
|
||||
return listValue;
|
||||
}
|
||||
|
||||
public String getTypeHandler() {
|
||||
return typeHandler;
|
||||
}
|
||||
|
||||
protected Criterion(String condition) {
|
||||
super();
|
||||
this.condition = condition;
|
||||
this.typeHandler = null;
|
||||
this.noValue = true;
|
||||
}
|
||||
|
||||
protected Criterion(String condition, Object value, String typeHandler) {
|
||||
super();
|
||||
this.condition = condition;
|
||||
this.value = value;
|
||||
this.typeHandler = typeHandler;
|
||||
if (value instanceof List<?>) {
|
||||
this.listValue = true;
|
||||
} else {
|
||||
this.singleValue = true;
|
||||
}
|
||||
}
|
||||
|
||||
protected Criterion(String condition, Object value) {
|
||||
this(condition, value, null);
|
||||
}
|
||||
|
||||
protected Criterion(String condition, Object value, Object secondValue, String typeHandler) {
|
||||
super();
|
||||
this.condition = condition;
|
||||
this.value = value;
|
||||
this.secondValue = secondValue;
|
||||
this.typeHandler = typeHandler;
|
||||
this.betweenValue = true;
|
||||
}
|
||||
|
||||
protected Criterion(String condition, Object value, Object secondValue) {
|
||||
this(condition, value, secondValue, null);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,31 @@
|
|||
package io.metersphere.base.mapper;
|
||||
|
||||
import io.metersphere.base.domain.UserKey;
|
||||
import io.metersphere.base.domain.UserKeyExample;
|
||||
import org.apache.ibatis.annotations.Param;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public interface UserKeyMapper {
|
||||
long countByExample(UserKeyExample example);
|
||||
|
||||
int deleteByExample(UserKeyExample example);
|
||||
|
||||
int deleteByPrimaryKey(String id);
|
||||
|
||||
int insert(UserKey record);
|
||||
|
||||
int insertSelective(UserKey record);
|
||||
|
||||
List<UserKey> selectByExample(UserKeyExample example);
|
||||
|
||||
UserKey selectByPrimaryKey(String id);
|
||||
|
||||
int updateByExampleSelective(@Param("record") UserKey record, @Param("example") UserKeyExample example);
|
||||
|
||||
int updateByExample(@Param("record") UserKey record, @Param("example") UserKeyExample example);
|
||||
|
||||
int updateByPrimaryKeySelective(UserKey record);
|
||||
|
||||
int updateByPrimaryKey(UserKey record);
|
||||
}
|
|
@ -0,0 +1,228 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
|
||||
<mapper namespace="io.metersphere.base.mapper.UserKeyMapper">
|
||||
<resultMap id="BaseResultMap" type="io.metersphere.base.domain.UserKey">
|
||||
<id column="id" jdbcType="VARCHAR" property="id" />
|
||||
<result column="user_id" jdbcType="VARCHAR" property="userId" />
|
||||
<result column="access_key" jdbcType="VARCHAR" property="accessKey" />
|
||||
<result column="secret_key" jdbcType="VARCHAR" property="secretKey" />
|
||||
<result column="create_time" jdbcType="BIGINT" property="createTime" />
|
||||
<result column="status" jdbcType="VARCHAR" property="status" />
|
||||
</resultMap>
|
||||
<sql id="Example_Where_Clause">
|
||||
<where>
|
||||
<foreach collection="oredCriteria" item="criteria" separator="or">
|
||||
<if test="criteria.valid">
|
||||
<trim prefix="(" prefixOverrides="and" suffix=")">
|
||||
<foreach collection="criteria.criteria" item="criterion">
|
||||
<choose>
|
||||
<when test="criterion.noValue">
|
||||
and ${criterion.condition}
|
||||
</when>
|
||||
<when test="criterion.singleValue">
|
||||
AND ${criterion.condition} #{criterion.value}
|
||||
</when>
|
||||
<when test="criterion.betweenValue">
|
||||
AND ${criterion.condition} #{criterion.value} AND #{criterion.secondValue}
|
||||
</when>
|
||||
<when test="criterion.listValue">
|
||||
AND ${criterion.condition}
|
||||
<foreach close=")" collection="criterion.value" item="listItem" open="(" separator=",">
|
||||
#{listItem}
|
||||
</foreach>
|
||||
</when>
|
||||
</choose>
|
||||
</foreach>
|
||||
</trim>
|
||||
</if>
|
||||
</foreach>
|
||||
</where>
|
||||
</sql>
|
||||
<sql id="Update_By_Example_Where_Clause">
|
||||
<where>
|
||||
<foreach collection="example.oredCriteria" item="criteria" separator="or">
|
||||
<if test="criteria.valid">
|
||||
<trim prefix="(" prefixOverrides="and" suffix=")">
|
||||
<foreach collection="criteria.criteria" item="criterion">
|
||||
<choose>
|
||||
<when test="criterion.noValue">
|
||||
and ${criterion.condition}
|
||||
</when>
|
||||
<when test="criterion.singleValue">
|
||||
AND ${criterion.condition} #{criterion.value}
|
||||
</when>
|
||||
<when test="criterion.betweenValue">
|
||||
AND ${criterion.condition} #{criterion.value} AND #{criterion.secondValue}
|
||||
</when>
|
||||
<when test="criterion.listValue">
|
||||
AND ${criterion.condition}
|
||||
<foreach close=")" collection="criterion.value" item="listItem" open="(" separator=",">
|
||||
#{listItem}
|
||||
</foreach>
|
||||
</when>
|
||||
</choose>
|
||||
</foreach>
|
||||
</trim>
|
||||
</if>
|
||||
</foreach>
|
||||
</where>
|
||||
</sql>
|
||||
<sql id="Base_Column_List">
|
||||
id, user_id, access_key, secret_key, create_time, status
|
||||
</sql>
|
||||
<select id="selectByExample" parameterType="io.metersphere.base.domain.UserKeyExample" resultMap="BaseResultMap">
|
||||
SELECT
|
||||
<if test="distinct">
|
||||
DISTINCT
|
||||
</if>
|
||||
<include refid="Base_Column_List" />
|
||||
FROM user_key
|
||||
<if test="_parameter != null">
|
||||
<include refid="Example_Where_Clause" />
|
||||
</if>
|
||||
<if test="orderByClause != null">
|
||||
ORDER BY ${orderByClause}
|
||||
</if>
|
||||
</select>
|
||||
<select id="selectByPrimaryKey" parameterType="java.lang.String" resultMap="BaseResultMap">
|
||||
SELECT
|
||||
<include refid="Base_Column_List" />
|
||||
FROM user_key
|
||||
WHERE id = #{id,jdbcType=VARCHAR}
|
||||
</select>
|
||||
<delete id="deleteByPrimaryKey" parameterType="java.lang.String">
|
||||
DELETE FROM user_key
|
||||
WHERE id = #{id,jdbcType=VARCHAR}
|
||||
</delete>
|
||||
<delete id="deleteByExample" parameterType="io.metersphere.base.domain.UserKeyExample">
|
||||
DELETE FROM user_key
|
||||
<if test="_parameter != null">
|
||||
<include refid="Example_Where_Clause" />
|
||||
</if>
|
||||
</delete>
|
||||
<insert id="insert" parameterType="io.metersphere.base.domain.UserKey">
|
||||
INSERT INTO user_key (id, user_id, access_key,
|
||||
secret_key, create_time, status
|
||||
)
|
||||
VALUES (#{id,jdbcType=VARCHAR}, #{userId,jdbcType=VARCHAR}, #{accessKey,jdbcType=VARCHAR},
|
||||
#{secretKey,jdbcType=VARCHAR}, #{createTime,jdbcType=BIGINT}, #{status,jdbcType=VARCHAR}
|
||||
)
|
||||
</insert>
|
||||
<insert id="insertSelective" parameterType="io.metersphere.base.domain.UserKey">
|
||||
INSERT INTO user_key
|
||||
<trim prefix="(" suffix=")" suffixOverrides=",">
|
||||
<if test="id != null">
|
||||
id,
|
||||
</if>
|
||||
<if test="userId != null">
|
||||
user_id,
|
||||
</if>
|
||||
<if test="accessKey != null">
|
||||
access_key,
|
||||
</if>
|
||||
<if test="secretKey != null">
|
||||
secret_key,
|
||||
</if>
|
||||
<if test="createTime != null">
|
||||
create_time,
|
||||
</if>
|
||||
<if test="status != null">
|
||||
status,
|
||||
</if>
|
||||
</trim>
|
||||
<trim prefix="values (" suffix=")" suffixOverrides=",">
|
||||
<if test="id != null">
|
||||
#{id,jdbcType=VARCHAR},
|
||||
</if>
|
||||
<if test="userId != null">
|
||||
#{userId,jdbcType=VARCHAR},
|
||||
</if>
|
||||
<if test="accessKey != null">
|
||||
#{accessKey,jdbcType=VARCHAR},
|
||||
</if>
|
||||
<if test="secretKey != null">
|
||||
#{secretKey,jdbcType=VARCHAR},
|
||||
</if>
|
||||
<if test="createTime != null">
|
||||
#{createTime,jdbcType=BIGINT},
|
||||
</if>
|
||||
<if test="status != null">
|
||||
#{status,jdbcType=VARCHAR},
|
||||
</if>
|
||||
</trim>
|
||||
</insert>
|
||||
<select id="countByExample" parameterType="io.metersphere.base.domain.UserKeyExample" resultType="java.lang.Long">
|
||||
SELECT count(*) FROM user_key
|
||||
<if test="_parameter != null">
|
||||
<include refid="Example_Where_Clause" />
|
||||
</if>
|
||||
</select>
|
||||
<update id="updateByExampleSelective" parameterType="map">
|
||||
UPDATE user_key
|
||||
<set>
|
||||
<if test="record.id != null">
|
||||
id = #{record.id,jdbcType=VARCHAR},
|
||||
</if>
|
||||
<if test="record.userId != null">
|
||||
user_id = #{record.userId,jdbcType=VARCHAR},
|
||||
</if>
|
||||
<if test="record.accessKey != null">
|
||||
access_key = #{record.accessKey,jdbcType=VARCHAR},
|
||||
</if>
|
||||
<if test="record.secretKey != null">
|
||||
secret_key = #{record.secretKey,jdbcType=VARCHAR},
|
||||
</if>
|
||||
<if test="record.createTime != null">
|
||||
create_time = #{record.createTime,jdbcType=BIGINT},
|
||||
</if>
|
||||
<if test="record.status != null">
|
||||
status = #{record.status,jdbcType=VARCHAR},
|
||||
</if>
|
||||
</set>
|
||||
<if test="_parameter != null">
|
||||
<include refid="Update_By_Example_Where_Clause" />
|
||||
</if>
|
||||
</update>
|
||||
<update id="updateByExample" parameterType="map">
|
||||
UPDATE user_key
|
||||
SET id = #{record.id,jdbcType=VARCHAR},
|
||||
user_id = #{record.userId,jdbcType=VARCHAR},
|
||||
access_key = #{record.accessKey,jdbcType=VARCHAR},
|
||||
secret_key = #{record.secretKey,jdbcType=VARCHAR},
|
||||
create_time = #{record.createTime,jdbcType=BIGINT},
|
||||
status = #{record.status,jdbcType=VARCHAR}
|
||||
<if test="_parameter != null">
|
||||
<include refid="Update_By_Example_Where_Clause" />
|
||||
</if>
|
||||
</update>
|
||||
<update id="updateByPrimaryKeySelective" parameterType="io.metersphere.base.domain.UserKey">
|
||||
UPDATE user_key
|
||||
<set>
|
||||
<if test="userId != null">
|
||||
user_id = #{userId,jdbcType=VARCHAR},
|
||||
</if>
|
||||
<if test="accessKey != null">
|
||||
access_key = #{accessKey,jdbcType=VARCHAR},
|
||||
</if>
|
||||
<if test="secretKey != null">
|
||||
secret_key = #{secretKey,jdbcType=VARCHAR},
|
||||
</if>
|
||||
<if test="createTime != null">
|
||||
create_time = #{createTime,jdbcType=BIGINT},
|
||||
</if>
|
||||
<if test="status != null">
|
||||
status = #{status,jdbcType=VARCHAR},
|
||||
</if>
|
||||
</set>
|
||||
WHERE id = #{id,jdbcType=VARCHAR}
|
||||
</update>
|
||||
<update id="updateByPrimaryKey" parameterType="io.metersphere.base.domain.UserKey">
|
||||
UPDATE user_key
|
||||
SET user_id = #{userId,jdbcType=VARCHAR},
|
||||
access_key = #{accessKey,jdbcType=VARCHAR},
|
||||
secret_key = #{secretKey,jdbcType=VARCHAR},
|
||||
create_time = #{createTime,jdbcType=BIGINT},
|
||||
status = #{status,jdbcType=VARCHAR}
|
||||
WHERE id = #{id,jdbcType=VARCHAR}
|
||||
</update>
|
||||
</mapper>
|
|
@ -0,0 +1,5 @@
|
|||
package io.metersphere.commons.constants;
|
||||
|
||||
public enum ApiKeyConstants {
|
||||
ACTIVE, DISABLED
|
||||
}
|
|
@ -1,5 +1,6 @@
|
|||
package io.metersphere.config;
|
||||
|
||||
import io.metersphere.security.ApiKeyFilter;
|
||||
import io.metersphere.security.LoginFilter;
|
||||
import io.metersphere.security.ShiroDBRealm;
|
||||
import org.apache.shiro.cache.MemoryConstrainedCacheManager;
|
||||
|
@ -37,6 +38,7 @@ public class ShiroConfig {
|
|||
shiroFilterFactoryBean.setUnauthorizedUrl("/403");
|
||||
shiroFilterFactoryBean.setSuccessUrl("/");
|
||||
|
||||
shiroFilterFactoryBean.getFilters().put("apikey", new ApiKeyFilter());
|
||||
|
||||
Map<String, String> filterChainDefinitionMap = shiroFilterFactoryBean.getFilterChainDefinitionMap();
|
||||
filterChainDefinitionMap.put("/resource/**", "anon");
|
||||
|
@ -51,7 +53,7 @@ public class ShiroConfig {
|
|||
filterChainDefinitionMap.put("/api/**", "anon");
|
||||
filterChainDefinitionMap.put("/403", "anon");
|
||||
filterChainDefinitionMap.put("/anonymous/**", "anon");
|
||||
filterChainDefinitionMap.put("/**", "authc");
|
||||
filterChainDefinitionMap.put("/**", "apikey, authc");
|
||||
return shiroFilterFactoryBean;
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,47 @@
|
|||
package io.metersphere.controller;
|
||||
|
||||
import io.metersphere.base.domain.UserKey;
|
||||
import io.metersphere.commons.utils.SessionUtils;
|
||||
import io.metersphere.service.UserKeyService;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.PathVariable;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import java.util.List;
|
||||
|
||||
@RestController
|
||||
@RequestMapping("user/key")
|
||||
public class UserKeysController {
|
||||
|
||||
@Resource
|
||||
private UserKeyService userKeyService;
|
||||
|
||||
@GetMapping("info")
|
||||
public List<UserKey> getUserKeysInfo() {
|
||||
String userId = SessionUtils.getUser().getId();
|
||||
return userKeyService.getUserKeysInfo(userId);
|
||||
}
|
||||
|
||||
@GetMapping("generate")
|
||||
public void generateUserKey() {
|
||||
String userId = SessionUtils.getUser().getId();
|
||||
userKeyService.generateUserKey(userId);
|
||||
}
|
||||
|
||||
@GetMapping("delete/{id}")
|
||||
public void deleteUserKey(@PathVariable String id) {
|
||||
userKeyService.deleteUserKey(id);
|
||||
}
|
||||
|
||||
@GetMapping("active/{id}")
|
||||
public void activeUserKey(@PathVariable String id) {
|
||||
userKeyService.activeUserKey(id);
|
||||
}
|
||||
|
||||
@GetMapping("disable/{id}")
|
||||
public void disabledUserKey(@PathVariable String id) {
|
||||
userKeyService.disableUserKey(id);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
package io.metersphere.dto;
|
||||
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
|
||||
@Getter
|
||||
@Setter
|
||||
public class ScheduleDTO {
|
||||
private Boolean enable;
|
||||
private String cronExpression;
|
||||
}
|
|
@ -0,0 +1,21 @@
|
|||
package io.metersphere.schedule.job;
|
||||
|
||||
import io.metersphere.api.service.APITestService;
|
||||
import io.metersphere.commons.utils.CommonBeanFactory;
|
||||
import org.quartz.Job;
|
||||
import org.quartz.JobExecutionContext;
|
||||
import org.quartz.JobExecutionException;
|
||||
|
||||
public class ApiTestJob implements Job {
|
||||
|
||||
private APITestService apiTestService;
|
||||
|
||||
public ApiTestJob() {
|
||||
apiTestService = (APITestService) CommonBeanFactory.getBean("apiTestService");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void execute(JobExecutionContext context) throws JobExecutionException {
|
||||
|
||||
}
|
||||
}
|
|
@ -0,0 +1,46 @@
|
|||
package io.metersphere.security;
|
||||
|
||||
import io.metersphere.commons.utils.LogUtil;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.apache.shiro.SecurityUtils;
|
||||
import org.apache.shiro.authc.UsernamePasswordToken;
|
||||
import org.apache.shiro.web.filter.authc.AnonymousFilter;
|
||||
import org.apache.shiro.web.util.WebUtils;
|
||||
|
||||
import javax.servlet.ServletRequest;
|
||||
import javax.servlet.ServletResponse;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
public class ApiKeyFilter extends AnonymousFilter {
|
||||
|
||||
@Override
|
||||
protected boolean onPreHandle(ServletRequest request, ServletResponse response, Object mappedValue) {
|
||||
try {
|
||||
if (!SecurityUtils.getSubject().isAuthenticated()) {
|
||||
String userId = ApiKeyHandler.getUser(WebUtils.toHttp(request));
|
||||
if (StringUtils.isNotBlank(userId)) {
|
||||
if (LogUtil.getLogger().isDebugEnabled()) {
|
||||
LogUtil.getLogger().debug("user auth: " + userId);
|
||||
}
|
||||
SecurityUtils.getSubject().login(new UsernamePasswordToken(userId, ApiKeySessionHandler.random));
|
||||
}
|
||||
} else {
|
||||
if (ApiKeyHandler.isApiKeyCall(WebUtils.toHttp(request))) {
|
||||
String userId = ApiKeyHandler.getUser(WebUtils.toHttp(request));
|
||||
SecurityUtils.getSubject().login(new UsernamePasswordToken(userId, ApiKeySessionHandler.random));
|
||||
}
|
||||
}
|
||||
|
||||
if (!SecurityUtils.getSubject().isAuthenticated()) {
|
||||
((HttpServletResponse) response).setHeader("Authentication-Status", "invalid");
|
||||
}
|
||||
} catch (Exception e) {
|
||||
if (ApiKeyHandler.isApiKeyCall(WebUtils.toHttp(request))) {
|
||||
throw e;
|
||||
}
|
||||
LogUtil.getLogger().error("failed to handle single sign on..", e);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,64 @@
|
|||
package io.metersphere.security;
|
||||
|
||||
import io.metersphere.base.domain.UserKey;
|
||||
import io.metersphere.commons.utils.CodingUtil;
|
||||
import io.metersphere.commons.utils.CommonBeanFactory;
|
||||
import io.metersphere.service.UserKeyService;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
|
||||
public class ApiKeyHandler {
|
||||
|
||||
public static final String API_ACCESS_KEY = "accessKey";
|
||||
|
||||
public static final String API_SIGNATURE = "signature";
|
||||
|
||||
public static String getUser(HttpServletRequest request) {
|
||||
if (request == null) {
|
||||
return null;
|
||||
}
|
||||
return getUser(request.getHeader(API_ACCESS_KEY), request.getHeader(API_SIGNATURE));
|
||||
}
|
||||
|
||||
public static Boolean isApiKeyCall(HttpServletRequest request) {
|
||||
if (request == null) {
|
||||
return false;
|
||||
}
|
||||
return !StringUtils.isBlank(request.getHeader(API_ACCESS_KEY)) && !StringUtils.isBlank(request.getHeader(API_SIGNATURE));
|
||||
}
|
||||
|
||||
public static String getUser(String accessKey, String signature) {
|
||||
if (StringUtils.isBlank(accessKey) || StringUtils.isBlank(signature)) {
|
||||
return null;
|
||||
}
|
||||
UserKey userKey = CommonBeanFactory.getBean(UserKeyService.class).getUserKey(accessKey);
|
||||
if (userKey == null) {
|
||||
throw new RuntimeException("invalid accessKey");
|
||||
}
|
||||
String signatureDecrypt;
|
||||
try {
|
||||
signatureDecrypt = CodingUtil.aesDecrypt(signature, userKey.getSecretKey(), accessKey);
|
||||
} catch (Throwable t) {
|
||||
throw new RuntimeException("invalid signature");
|
||||
}
|
||||
String[] signatureArray = StringUtils.split(StringUtils.trimToNull(signatureDecrypt), "|");
|
||||
if (signatureArray.length < 2) {
|
||||
throw new RuntimeException("invalid signature");
|
||||
}
|
||||
if (!StringUtils.equals(accessKey, signatureArray[0])) {
|
||||
throw new RuntimeException("invalid signature");
|
||||
}
|
||||
long signatureTime;
|
||||
try {
|
||||
signatureTime = Long.parseLong(signatureArray[signatureArray.length - 1]);
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
if (Math.abs(System.currentTimeMillis() - signatureTime) > 1800000) {
|
||||
//签名30分钟超时
|
||||
throw new RuntimeException("expired signature");
|
||||
}
|
||||
return userKey.getUserId();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,59 @@
|
|||
package io.metersphere.security;
|
||||
|
||||
import io.metersphere.commons.utils.EncryptUtils;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import java.util.UUID;
|
||||
|
||||
|
||||
public class ApiKeySessionHandler {
|
||||
|
||||
private static Logger logger = LoggerFactory.getLogger(ApiKeySessionHandler.class);
|
||||
|
||||
|
||||
public static String random = UUID.randomUUID().toString() + UUID.randomUUID().toString();
|
||||
|
||||
public static String generateId(String authInfo) {
|
||||
return SessionGenerator.generateId(authInfo);
|
||||
}
|
||||
|
||||
public static String validate(HttpServletRequest request) {
|
||||
try {
|
||||
String v = request.getHeader(ApiKeyHandler.API_SIGNATURE);
|
||||
if (StringUtils.isNotBlank(v)) {
|
||||
return SessionGenerator.fromId(v);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
logger.error("failed to validate", e);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
public static class SessionGenerator {
|
||||
public SessionGenerator() {
|
||||
}
|
||||
|
||||
public static String generateId(String authInfo) {
|
||||
return EncryptUtils.aesEncrypt(parse2Str(authInfo)).toString();
|
||||
}
|
||||
|
||||
public static String fromId(String sessionId) {
|
||||
String authInfoString = EncryptUtils.aesDecrypt(sessionId).toString();
|
||||
return fromStr(authInfoString);
|
||||
}
|
||||
|
||||
private static String parse2Str(String authInfo) {
|
||||
return UUID.randomUUID().toString() + "|" + authInfo + "|" + System.currentTimeMillis();
|
||||
}
|
||||
|
||||
private static String fromStr(String authInfoString) {
|
||||
String[] sp = authInfoString.split("\\|");
|
||||
return sp[1];
|
||||
}
|
||||
}
|
||||
}
|
|
@ -83,6 +83,12 @@ public class ShiroDBRealm extends AuthorizingRealm {
|
|||
SessionUtils.putUser(sessionUser);
|
||||
return new SimpleAuthenticationInfo(userId, password, getName());
|
||||
}
|
||||
// apikey 校验不验证密码
|
||||
if (ApiKeySessionHandler.random.equalsIgnoreCase(password)) {
|
||||
SessionUser sessionUser = SessionUser.fromUser(user);
|
||||
SessionUtils.putUser(sessionUser);
|
||||
return new SimpleAuthenticationInfo(userId, password, getName());
|
||||
}
|
||||
// 密码验证
|
||||
if (!userService.checkUserPassword(userId, password)) {
|
||||
throw new IncorrectCredentialsException(Translator.get("password_is_incorrect"));
|
||||
|
|
|
@ -0,0 +1,83 @@
|
|||
package io.metersphere.service;
|
||||
|
||||
import io.metersphere.base.domain.UserKey;
|
||||
import io.metersphere.base.domain.UserKeyExample;
|
||||
import io.metersphere.base.mapper.UserKeyMapper;
|
||||
import io.metersphere.commons.constants.ApiKeyConstants;
|
||||
import io.metersphere.commons.exception.MSException;
|
||||
import io.metersphere.i18n.Translator;
|
||||
import org.apache.commons.lang3.RandomStringUtils;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.util.CollectionUtils;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
|
||||
@Service
|
||||
public class UserKeyService {
|
||||
|
||||
@Resource
|
||||
private UserKeyMapper userKeyMapper;
|
||||
|
||||
@Resource
|
||||
private UserService userService;
|
||||
|
||||
public List<UserKey> getUserKeysInfo(String userId) {
|
||||
UserKeyExample userKeysExample = new UserKeyExample();
|
||||
userKeysExample.createCriteria().andUserIdEqualTo(userId);
|
||||
userKeysExample.setOrderByClause("create_time");
|
||||
return userKeyMapper.selectByExample(userKeysExample);
|
||||
}
|
||||
|
||||
public UserKey generateUserKey(String userId) {
|
||||
if (userService.getUserDTO(userId) == null) {
|
||||
MSException.throwException(Translator.get("user_not_exist") + userId);
|
||||
}
|
||||
UserKeyExample userKeysExample = new UserKeyExample();
|
||||
userKeysExample.createCriteria().andUserIdEqualTo(userId);
|
||||
List<UserKey> userKeysList = userKeyMapper.selectByExample(userKeysExample);
|
||||
|
||||
if (!CollectionUtils.isEmpty(userKeysList) && userKeysList.size() >= 5) {
|
||||
MSException.throwException(Translator.get("user_apikey_limit"));
|
||||
}
|
||||
|
||||
UserKey userKeys = new UserKey();
|
||||
userKeys.setId(UUID.randomUUID().toString());
|
||||
userKeys.setUserId(userId);
|
||||
userKeys.setStatus(ApiKeyConstants.ACTIVE.name());
|
||||
userKeys.setAccessKey(RandomStringUtils.randomAlphanumeric(16));
|
||||
userKeys.setSecretKey(RandomStringUtils.randomAlphanumeric(16));
|
||||
userKeys.setCreateTime(System.currentTimeMillis());
|
||||
userKeyMapper.insert(userKeys);
|
||||
return userKeyMapper.selectByPrimaryKey(userKeys.getId());
|
||||
}
|
||||
|
||||
public void deleteUserKey(String id) {
|
||||
userKeyMapper.deleteByPrimaryKey(id);
|
||||
}
|
||||
|
||||
public void activeUserKey(String id) {
|
||||
UserKey userKeys = new UserKey();
|
||||
userKeys.setId(id);
|
||||
userKeys.setStatus(ApiKeyConstants.ACTIVE.name());
|
||||
userKeyMapper.updateByPrimaryKeySelective(userKeys);
|
||||
}
|
||||
|
||||
public void disableUserKey(String id) {
|
||||
UserKey userKeys = new UserKey();
|
||||
userKeys.setId(id);
|
||||
userKeys.setStatus(ApiKeyConstants.DISABLED.name());
|
||||
userKeyMapper.updateByPrimaryKeySelective(userKeys);
|
||||
}
|
||||
|
||||
public UserKey getUserKey(String accessKey) {
|
||||
UserKeyExample userKeyExample = new UserKeyExample();
|
||||
userKeyExample.createCriteria().andAccessKeyEqualTo(accessKey).andStatusEqualTo(ApiKeyConstants.ACTIVE.name());
|
||||
List<UserKey> userKeysList = userKeyMapper.selectByExample(userKeyExample);
|
||||
if (!CollectionUtils.isEmpty(userKeysList)) {
|
||||
return userKeysList.get(0);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,14 @@
|
|||
CREATE TABLE `user_key` (
|
||||
`id` varchar(50) NOT NULL DEFAULT '' COMMENT 'user_key ID',
|
||||
`user_id` varchar(50) NOT NULL COMMENT '用户ID',
|
||||
`access_key` varchar(50) NOT NULL COMMENT 'access_key',
|
||||
`secret_key` varchar(50) NOT NULL COMMENT 'secret key',
|
||||
`create_time` bigint(13) NOT NULL COMMENT '创建时间',
|
||||
`status` varchar(10) DEFAULT NULL COMMENT '状态',
|
||||
PRIMARY KEY (`id`),
|
||||
UNIQUE KEY `IDX_AK` (`access_key`),
|
||||
KEY `IDX_USER_ID` (`user_id`)
|
||||
)
|
||||
ENGINE = InnoDB
|
||||
DEFAULT CHARSET = utf8mb4;
|
||||
|
|
@ -27,6 +27,7 @@ user_locked=the user has been locked.
|
|||
user_expires=user expires.
|
||||
not_authorized=not authorized.
|
||||
login_fail=Login fail
|
||||
user_apikey_limit=Can have up to 5 api keys
|
||||
#load test
|
||||
edit_load_test_not_found=Cannot edit test, test not found=
|
||||
run_load_test_not_found=Cannot run test, test not found=
|
||||
|
|
|
@ -27,6 +27,7 @@ excessive_attempts=操作频繁
|
|||
user_locked=用户被锁定
|
||||
user_expires=用户过期
|
||||
not_authorized=未经授权
|
||||
user_apikey_limit=最多能有5个Api key
|
||||
#load test
|
||||
edit_load_test_not_found=无法编辑测试,未找到测试:
|
||||
run_load_test_not_found=无法运行测试,未找到测试:
|
||||
|
|
|
@ -27,6 +27,7 @@ user_locked=用戶被鎖定
|
|||
user_expires=用戶過期
|
||||
not_authorized=未經授權。
|
||||
login_fail=登入失敗
|
||||
user_apikey_limit=最多能有5個Api key
|
||||
#load test
|
||||
edit_load_test_not_found=無法編輯測試,未找到測試:
|
||||
run_load_test_not_found=無法運行測試,未找到測試:
|
||||
|
|
File diff suppressed because one or more lines are too long
|
@ -48,7 +48,9 @@
|
|||
"rules": {
|
||||
"vue/no-unused-components": "off",
|
||||
"no-console": "off",
|
||||
"no-unused-vars": "off"
|
||||
"no-unused-vars": "off",
|
||||
"no-unused-expressions": "off",
|
||||
"no-unused-labels": "off"
|
||||
},
|
||||
"parserOptions": {
|
||||
"parser": "babel-eslint"
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
<el-card>
|
||||
<el-container class="test-container" v-loading="result.loading">
|
||||
<el-header>
|
||||
<el-row type="flex" align="middle">
|
||||
<el-row>
|
||||
<el-input :disabled="isReadOnly" class="test-name" v-model="test.name" maxlength="60"
|
||||
:placeholder="$t('api_test.input_name')"
|
||||
show-word-limit>
|
||||
|
@ -46,6 +46,8 @@
|
|||
</el-dropdown>
|
||||
|
||||
<ms-api-report-dialog :test-id="id" ref="reportDialog"/>
|
||||
|
||||
<ms-schedule-config :schedule="test.schedule" :save="saveCronExpression" @scheduleChange="saveSchedule" :check-open="checkScheduleEdit"/>
|
||||
</el-row>
|
||||
</el-header>
|
||||
<ms-api-scenario-config :is-read-only="isReadOnly" :scenarios="test.scenarioDefinition" ref="config"/>
|
||||
|
@ -61,11 +63,12 @@
|
|||
import MsApiReportStatus from "../report/ApiReportStatus";
|
||||
import MsApiReportDialog from "./ApiReportDialog";
|
||||
import {checkoutTestManagerOrTestUser, downloadFile} from "../../../../common/js/utils";
|
||||
import MsScheduleConfig from "../../common/components/MsScheduleConfig";
|
||||
|
||||
export default {
|
||||
name: "MsApiTestConfig",
|
||||
|
||||
components: {MsApiReportDialog, MsApiReportStatus, MsApiScenarioConfig},
|
||||
components: {MsScheduleConfig, MsApiReportDialog, MsApiReportStatus, MsApiScenarioConfig},
|
||||
|
||||
props: ["id"],
|
||||
|
||||
|
@ -126,6 +129,7 @@
|
|||
name: item.name,
|
||||
status: item.status,
|
||||
scenarioDefinition: JSON.parse(item.scenarioDefinition),
|
||||
schedule: item.schedule ? JSON.parse(item.schedule) : {},
|
||||
});
|
||||
this.$refs.config.reset();
|
||||
}
|
||||
|
@ -208,6 +212,31 @@
|
|||
downloadFile(this.test.name + ".json", this.test.export());
|
||||
break;
|
||||
}
|
||||
},
|
||||
saveCronExpression(cronExpression) {
|
||||
this.test.schedule.enable = true;
|
||||
this.test.schedule.cronExpression = cronExpression;
|
||||
this.saveSchedule();
|
||||
},
|
||||
saveSchedule() {
|
||||
if (this.create) {
|
||||
this.$message('请先保存测试,在设置定时任务');
|
||||
return;
|
||||
}
|
||||
let param = {};
|
||||
param.id = this.test.id;
|
||||
param.schedule = this.test.schedule;
|
||||
this.$post('/api/schedule/update', param, response => {
|
||||
this.$success('保存成功');
|
||||
this.getTest(this.test.id);
|
||||
});
|
||||
},
|
||||
checkScheduleEdit() {
|
||||
if (this.create) {
|
||||
this.$message('请先保存测试');
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
},
|
||||
|
||||
|
@ -245,4 +274,8 @@
|
|||
.test-container .more {
|
||||
margin-left: 10px;
|
||||
}
|
||||
|
||||
.schedule-config {
|
||||
float: right;
|
||||
}
|
||||
</style>
|
||||
|
|
|
@ -100,6 +100,7 @@ export class Test extends BaseConfig {
|
|||
this.name = undefined;
|
||||
this.projectId = undefined;
|
||||
this.scenarioDefinition = [];
|
||||
this.schedule = {};
|
||||
|
||||
this.set(options);
|
||||
this.sets({scenarioDefinition: Scenario}, options);
|
||||
|
|
|
@ -0,0 +1,101 @@
|
|||
<template>
|
||||
<div class="schedule-config">
|
||||
<div>
|
||||
<span class="cron-ico">
|
||||
<i class="el-icon-date" size="small"></i>
|
||||
<span class="character" @click="scheduleEdit">SCHEDULER</span>
|
||||
</span>
|
||||
<el-switch :disabled="!schedule.cronExpression" v-model="schedule.enable" @change="scheduleChange"/>
|
||||
<ms-schedule-edit :schedule="schedule" :save="save" ref="scheduleEdit"/>
|
||||
<crontab-result v-show="false" :ex="schedule.cronExpression" ref="crontabResult" @resultListChange="recentListChange"/>
|
||||
</div>
|
||||
<div>
|
||||
<span :class="{'disable-character': !schedule.enable}"> 下次执行时间:{{this.recentList.length > 0 ? this.recentList[0] : ''}} </span>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import MsScheduleEdit from "./MsScheduleEdit";
|
||||
import CrontabResult from "../cron/CrontabResult";
|
||||
export default {
|
||||
name: "MsScheduleConfig",
|
||||
components: {CrontabResult, MsScheduleEdit},
|
||||
data() {
|
||||
return {
|
||||
recentList: [],
|
||||
}
|
||||
},
|
||||
props: {
|
||||
save: Function,
|
||||
schedule: {},
|
||||
checkOpen: {
|
||||
type: Function,
|
||||
default() {
|
||||
return new Function()
|
||||
}
|
||||
},
|
||||
},
|
||||
// mounted() {
|
||||
// console.log(this.schedule);
|
||||
// // this.recentList = this.$refs.crontabResult.resultList;
|
||||
// // console.log(this.recentList);
|
||||
// console.log(this.recentList+ "====");
|
||||
// },
|
||||
// watch: {
|
||||
// 'schedule.cronExpression'() {
|
||||
// console.log(this.schedule);
|
||||
// this.$refs.crontabResult.expressionChange();
|
||||
// this.recentList = this.$refs.crontabResult.resultList;
|
||||
// console.log(this.recentList);
|
||||
// }
|
||||
// },
|
||||
methods: {
|
||||
scheduleEdit() {
|
||||
if (!this.checkOpen()) {
|
||||
return;
|
||||
}
|
||||
this.$refs.scheduleEdit.open();
|
||||
},
|
||||
scheduleChange() {
|
||||
this.$emit('scheduleChange');
|
||||
},
|
||||
recentListChange(resultList) {
|
||||
this.recentList = resultList;
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
|
||||
.schedule-config {
|
||||
float: right;
|
||||
width: 250px;
|
||||
height: 15px;
|
||||
line-height: 25px;
|
||||
}
|
||||
|
||||
.el-icon-date {
|
||||
font-size: 20px;
|
||||
margin-left: 5px;
|
||||
}
|
||||
|
||||
.character {
|
||||
font-weight: bold;
|
||||
margin: 0 5px;
|
||||
}
|
||||
|
||||
.disable-character {
|
||||
color: #cccccc;
|
||||
}
|
||||
|
||||
.el-switch {
|
||||
margin: 0 5px;
|
||||
}
|
||||
|
||||
.cron-ico {
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
</style>
|
|
@ -0,0 +1,97 @@
|
|||
<template>
|
||||
<el-dialog width="30%" class="schedule-edit" :title="'编辑定时任务'" :visible.sync="dialogVisible" @close="close">
|
||||
<div id="app">
|
||||
<el-form :model="form" :rules="rules" ref="from">
|
||||
<el-form-item
|
||||
:placeholder="'请输入 Cron 表达式'"
|
||||
prop="cronValue">
|
||||
<el-input v-model="form.cronValue" placeholder class="inp"/>
|
||||
<el-button type="primary" @click="showCronDialog">生成 Cron</el-button>
|
||||
<el-button type="primary" @click="saveCron">保存</el-button>
|
||||
</el-form-item>
|
||||
<crontab-result :ex="schedule.cronExpression" ref="crontabResult"/>
|
||||
</el-form>
|
||||
<el-dialog title="生成 cron" :visible.sync="showCron" :modal="false">
|
||||
<crontab @hide="showCron=false" @fill="crontabFill" :expression="schedule.cronExpression"/>
|
||||
</el-dialog>
|
||||
</div>
|
||||
</el-dialog>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
|
||||
import Crontab from "../cron/Crontab";
|
||||
import CrontabResult from "../cron/CrontabResult";
|
||||
import {cronValidate} from "../../../../common/js/cron";
|
||||
|
||||
export default {
|
||||
name: "MsScheduleEdit",
|
||||
components: {CrontabResult, Crontab},
|
||||
props: {
|
||||
save: Function,
|
||||
schedule: {},
|
||||
},
|
||||
watch: {
|
||||
'schedule.cronExpression'() {
|
||||
this.form.cronValue = this.schedule.cronExpression;
|
||||
}
|
||||
},
|
||||
data() {
|
||||
const validateCron = (rule, cronValue, callback) => {
|
||||
if (!cronValidate(cronValue)) {
|
||||
callback(new Error('Cron 表达式格式错误'));
|
||||
} else {
|
||||
this.schedule.cronExpression = cronValue;
|
||||
callback();
|
||||
}
|
||||
};
|
||||
return {
|
||||
dialogVisible: false,
|
||||
showCron: false,
|
||||
form: {
|
||||
cronValue: ""
|
||||
},
|
||||
rules: {
|
||||
cronValue :[{required: true, validator: validateCron, trigger: 'blur'}],
|
||||
}
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
open() {
|
||||
this.dialogVisible = true;
|
||||
},
|
||||
crontabFill(value) {
|
||||
//确定后回传的值
|
||||
this.schedule.cronExpression = value;
|
||||
this.form.cronValue = value;
|
||||
this.$refs['from'].validate();
|
||||
},
|
||||
showCronDialog() {
|
||||
this.showCron = true;
|
||||
},
|
||||
saveCron () {
|
||||
this.$refs['from'].validate((valid) => {
|
||||
if (valid) {
|
||||
this.save(this.form.cronValue);
|
||||
this.dialogVisible = false;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
});
|
||||
},
|
||||
close() {
|
||||
this.$refs['from'].resetFields();
|
||||
this.$refs.crontabResult.resultList = [];
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
|
||||
.inp {
|
||||
width: 50%;
|
||||
margin-right: 20px;
|
||||
}
|
||||
|
||||
</style>
|
|
@ -0,0 +1,422 @@
|
|||
<template>
|
||||
<div>
|
||||
<el-tabs type="border-card">
|
||||
<el-tab-pane label="秒" v-if="shouldHide('second')">
|
||||
<crontab-second
|
||||
@update="updateContabValue"
|
||||
:check="checkNumber"
|
||||
ref="cronsecond"
|
||||
/>
|
||||
</el-tab-pane>
|
||||
|
||||
<el-tab-pane label="分钟" v-if="shouldHide('min')">
|
||||
<crontab-min
|
||||
@update="updateContabValue"
|
||||
:check="checkNumber"
|
||||
:cron="contabValueObj"
|
||||
ref="cronmin"
|
||||
/>
|
||||
</el-tab-pane>
|
||||
|
||||
<el-tab-pane label="小时" v-if="shouldHide('hour')">
|
||||
<crontab-hour
|
||||
@update="updateContabValue"
|
||||
:check="checkNumber"
|
||||
:cron="contabValueObj"
|
||||
ref="cronhour"
|
||||
/>
|
||||
</el-tab-pane>
|
||||
|
||||
<el-tab-pane label="日" v-if="shouldHide('day')">
|
||||
<crontab-day
|
||||
@update="updateContabValue"
|
||||
:check="checkNumber"
|
||||
:cron="contabValueObj"
|
||||
ref="cronday"
|
||||
/>
|
||||
</el-tab-pane>
|
||||
|
||||
<el-tab-pane label="月" v-if="shouldHide('mouth')">
|
||||
<crontab-mouth
|
||||
@update="updateContabValue"
|
||||
:check="checkNumber"
|
||||
:cron="contabValueObj"
|
||||
ref="cronmouth"
|
||||
/>
|
||||
</el-tab-pane>
|
||||
|
||||
<el-tab-pane label="周" v-if="shouldHide('week')">
|
||||
<crontab-week
|
||||
@update="updateContabValue"
|
||||
:check="checkNumber"
|
||||
:cron="contabValueObj"
|
||||
ref="cronweek"
|
||||
/>
|
||||
</el-tab-pane>
|
||||
|
||||
<el-tab-pane label="年" v-if="shouldHide('year')">
|
||||
<crontab-year @update="updateContabValue"
|
||||
:check="checkNumber"
|
||||
:cron="contabValueObj"
|
||||
ref="cronyear"/>
|
||||
</el-tab-pane>
|
||||
</el-tabs>
|
||||
|
||||
<div class="popup-main">
|
||||
<div class="popup-result-container">
|
||||
<p class="title">时间表达式</p>
|
||||
<table>
|
||||
<thead>
|
||||
<th v-for="item of tabTitles" width="40" :key="item">{{item}}</th>
|
||||
<th>crontab完整表达式</th>
|
||||
</thead>
|
||||
<tbody>
|
||||
<td>
|
||||
<span>{{contabValueObj.second}}</span>
|
||||
</td>
|
||||
<td>
|
||||
<span>{{contabValueObj.min}}</span>
|
||||
</td>
|
||||
<td>
|
||||
<span>{{contabValueObj.hour}}</span>
|
||||
</td>
|
||||
<td>
|
||||
<span>{{contabValueObj.day}}</span>
|
||||
</td>
|
||||
<td>
|
||||
<span>{{contabValueObj.mouth}}</span>
|
||||
</td>
|
||||
<td>
|
||||
<span>{{contabValueObj.week}}</span>
|
||||
</td>
|
||||
<td>
|
||||
<span>{{contabValueObj.year}}</span>
|
||||
</td>
|
||||
<td>
|
||||
<span>{{contabValueString}}</span>
|
||||
</td>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
<crontab-result :ex="contabValueString"/>
|
||||
|
||||
<div class="pop_btn">
|
||||
<el-button size="small" type="primary" @click="submitFill">确定</el-button>
|
||||
<el-button size="small" type="warning" @click="clearCron">重置</el-button>
|
||||
<el-button size="small" @click="hidePopup">取消</el-button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import CrontabSecond from "./CrontabSecond.vue";
|
||||
import CrontabMin from "./CrontabMin.vue";
|
||||
import CrontabHour from "./CrontabHour.vue";
|
||||
import CrontabDay from "./CrontabDay.vue";
|
||||
import CrontabMouth from "./CrontabMouth.vue";
|
||||
import CrontabWeek from "./CrontabWeek.vue";
|
||||
import CrontabYear from "./CrontabYear.vue";
|
||||
import CrontabResult from "./CrontabResult.vue";
|
||||
|
||||
export default {
|
||||
name: "Crontab",
|
||||
data() {
|
||||
return {
|
||||
tabTitles: ["秒", "分钟", "小时", "日", "月", "周", "年"],
|
||||
tabActive: 0,
|
||||
myindex: 0,
|
||||
contabValueObj: {
|
||||
second: "*",
|
||||
min: "*",
|
||||
hour: "*",
|
||||
day: "*",
|
||||
mouth: "*",
|
||||
week: "?",
|
||||
year: "",
|
||||
},
|
||||
};
|
||||
},
|
||||
props: ["expression", "hideComponent"],
|
||||
methods: {
|
||||
shouldHide(key) {
|
||||
if (this.hideComponent && this.hideComponent.includes(key)) return false;
|
||||
return true;
|
||||
},
|
||||
resolveExp() {
|
||||
//反解析 表达式
|
||||
if (this.expression) {
|
||||
let arr = this.expression.split(" ");
|
||||
if (arr.length >= 6) {
|
||||
//6 位以上是合法表达式
|
||||
let obj = {
|
||||
second: arr[0],
|
||||
min: arr[1],
|
||||
hour: arr[2],
|
||||
day: arr[3],
|
||||
mouth: arr[4],
|
||||
week: arr[5],
|
||||
year: arr[6] ? arr[6] : "",
|
||||
};
|
||||
this.contabValueObj = {
|
||||
...obj,
|
||||
};
|
||||
for (let i in obj) {
|
||||
if (obj[i]) this.changeRadio(i, obj[i]);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
//没有传入的表达式 则还原
|
||||
this.clearCron();
|
||||
}
|
||||
},
|
||||
// tab切换值
|
||||
tabCheck(index) {
|
||||
this.tabActive = index;
|
||||
},
|
||||
// 由子组件触发,更改表达式组成的字段值
|
||||
updateContabValue(name, value, from) {
|
||||
"updateContabValue", name, value, from;
|
||||
this.contabValueObj[name] = value;
|
||||
if (from && from !== name) {
|
||||
console.log(`来自组件 ${from} 改变了 ${name} ${value}`);
|
||||
this.changeRadio(name, value);
|
||||
}
|
||||
},
|
||||
//赋值到组件
|
||||
changeRadio(name, value) {
|
||||
let arr = ["second", "min", "hour", "mouth"],
|
||||
refName = "cron" + name,
|
||||
insVlaue;
|
||||
|
||||
if (!this.$refs[refName]) return;
|
||||
|
||||
if (arr.includes(name)) {
|
||||
if (value === "*") {
|
||||
insVlaue = 1;
|
||||
} else if (value.indexOf("-") > -1) {
|
||||
let indexArr = value.split("-");
|
||||
isNaN(indexArr[0])
|
||||
? (this.$refs[refName].cycle01 = 0)
|
||||
: (this.$refs[refName].cycle01 = indexArr[0]);
|
||||
this.$refs[refName].cycle02 = indexArr[1];
|
||||
insVlaue = 2;
|
||||
} else if (value.indexOf("/") > -1) {
|
||||
let indexArr = value.split("/");
|
||||
isNaN(indexArr[0])
|
||||
? (this.$refs[refName].average01 = 0)
|
||||
: (this.$refs[refName].average01 = indexArr[0]);
|
||||
this.$refs[refName].average02 = indexArr[1];
|
||||
insVlaue = 3;
|
||||
} else {
|
||||
insVlaue = 4;
|
||||
this.$refs[refName].checkboxList = value.split(",");
|
||||
}
|
||||
} else if (name == "day") {
|
||||
if (value === "*") {
|
||||
insVlaue = 1;
|
||||
} else if (value == "?") {
|
||||
insVlaue = 2;
|
||||
} else if (value.indexOf("-") > -1) {
|
||||
let indexArr = value.split("-");
|
||||
isNaN(indexArr[0])
|
||||
? (this.$refs[refName].cycle01 = 0)
|
||||
: (this.$refs[refName].cycle01 = indexArr[0]);
|
||||
this.$refs[refName].cycle02 = indexArr[1];
|
||||
insVlaue = 3;
|
||||
} else if (value.indexOf("/") > -1) {
|
||||
let indexArr = value.split("/");
|
||||
isNaN(indexArr[0])
|
||||
? (this.$refs[refName].average01 = 0)
|
||||
: (this.$refs[refName].average01 = indexArr[0]);
|
||||
this.$refs[refName].average02 = indexArr[1];
|
||||
insVlaue = 4;
|
||||
} else if (value.indexOf("W") > -1) {
|
||||
let indexArr = value.split("W");
|
||||
isNaN(indexArr[0])
|
||||
? (this.$refs[refName].workday = 0)
|
||||
: (this.$refs[refName].workday = indexArr[0]);
|
||||
insVlaue = 5;
|
||||
} else if (value === "L") {
|
||||
insVlaue = 6;
|
||||
} else {
|
||||
this.$refs[refName].checkboxList = value.split(",");
|
||||
insVlaue = 7;
|
||||
}
|
||||
} else if (name == "week") {
|
||||
if (value === "*") {
|
||||
insVlaue = 1;
|
||||
} else if (value == "?") {
|
||||
insVlaue = 2;
|
||||
} else if (value.indexOf("-") > -1) {
|
||||
let indexArr = value.split("-");
|
||||
isNaN(indexArr[0])
|
||||
? (this.$refs[refName].cycle01 = 0)
|
||||
: (this.$refs[refName].cycle01 = indexArr[0]);
|
||||
this.$refs[refName].cycle02 = indexArr[1];
|
||||
insVlaue = 3;
|
||||
} else if (value.indexOf("#") > -1) {
|
||||
let indexArr = value.split("#");
|
||||
isNaN(indexArr[0])
|
||||
? (this.$refs[refName].average01 = 1)
|
||||
: (this.$refs[refName].average01 = indexArr[0]);
|
||||
this.$refs[refName].average02 = indexArr[1];
|
||||
insVlaue = 4;
|
||||
} else if (value.indexOf("L") > -1) {
|
||||
let indexArr = value.split("L");
|
||||
isNaN(indexArr[0])
|
||||
? (this.$refs[refName].weekday = 1)
|
||||
: (this.$refs[refName].weekday = indexArr[0]);
|
||||
insVlaue = 5;
|
||||
} else {
|
||||
this.$refs[refName].checkboxList = value.split(",");
|
||||
insVlaue = 7;
|
||||
}
|
||||
} else if (name == "year") {
|
||||
if (value == "") {
|
||||
insVlaue = 1;
|
||||
} else if (value == "*") {
|
||||
insVlaue = 2;
|
||||
} else if (value.indexOf("-") > -1) {
|
||||
insVlaue = 3;
|
||||
} else if (value.indexOf("/") > -1) {
|
||||
insVlaue = 4;
|
||||
} else {
|
||||
this.$refs[refName].checkboxList = value.split(",");
|
||||
insVlaue = 5;
|
||||
}
|
||||
}
|
||||
this.$refs[refName].radioValue = insVlaue;
|
||||
},
|
||||
// 表单选项的子组件校验数字格式(通过-props传递)
|
||||
checkNumber(value, minLimit, maxLimit) {
|
||||
//检查必须为整数
|
||||
value = Math.floor(value);
|
||||
if (value < minLimit) {
|
||||
value = minLimit;
|
||||
} else if (value > maxLimit) {
|
||||
value = maxLimit;
|
||||
}
|
||||
return value;
|
||||
},
|
||||
// 隐藏弹窗
|
||||
hidePopup() {
|
||||
this.$emit("hide");
|
||||
},
|
||||
// 填充表达式
|
||||
submitFill() {
|
||||
this.$emit("fill", this.contabValueString);
|
||||
this.hidePopup();
|
||||
},
|
||||
clearCron() {
|
||||
// 还原选择项
|
||||
("准备还原");
|
||||
this.contabValueObj = {
|
||||
second: "*",
|
||||
min: "*",
|
||||
hour: "*",
|
||||
day: "*",
|
||||
mouth: "*",
|
||||
week: "?",
|
||||
year: "",
|
||||
};
|
||||
for (let j in this.contabValueObj) {
|
||||
this.changeRadio(j, this.contabValueObj[j]);
|
||||
}
|
||||
},
|
||||
},
|
||||
computed: {
|
||||
contabValueString: function() {
|
||||
let obj = this.contabValueObj;
|
||||
let str =
|
||||
obj.second +
|
||||
" " +
|
||||
obj.min +
|
||||
" " +
|
||||
obj.hour +
|
||||
" " +
|
||||
obj.day +
|
||||
" " +
|
||||
obj.mouth +
|
||||
" " +
|
||||
obj.week +
|
||||
(obj.year == "" ? "" : " " + obj.year);
|
||||
return str;
|
||||
},
|
||||
},
|
||||
components: {
|
||||
CrontabSecond,
|
||||
CrontabMin,
|
||||
CrontabHour,
|
||||
CrontabDay,
|
||||
CrontabMouth,
|
||||
CrontabWeek,
|
||||
CrontabYear,
|
||||
CrontabResult,
|
||||
},
|
||||
watch: {
|
||||
expression: "resolveExp",
|
||||
hideComponent(value) {
|
||||
// 隐藏部分组件
|
||||
},
|
||||
},
|
||||
mounted: function() {
|
||||
this.resolveExp();
|
||||
},
|
||||
};
|
||||
</script>
|
||||
<style scoped>
|
||||
.pop_btn {
|
||||
text-align: center;
|
||||
margin-top: 20px;
|
||||
}
|
||||
.popup-main {
|
||||
position: relative;
|
||||
margin: 10px auto;
|
||||
background: #fff;
|
||||
border-radius: 5px;
|
||||
font-size: 12px;
|
||||
overflow: hidden;
|
||||
}
|
||||
.popup-title {
|
||||
overflow: hidden;
|
||||
line-height: 34px;
|
||||
padding-top: 6px;
|
||||
background: #f2f2f2;
|
||||
}
|
||||
.popup-result-container {
|
||||
box-sizing: border-box;
|
||||
line-height: 24px;
|
||||
margin: 25px auto;
|
||||
padding: 15px 10px 10px;
|
||||
border: 1px solid #ccc;
|
||||
position: relative;
|
||||
}
|
||||
.popup-result-container .title {
|
||||
position: absolute;
|
||||
top: -28px;
|
||||
left: 50%;
|
||||
width: 140px;
|
||||
font-size: 14px;
|
||||
margin-left: -70px;
|
||||
text-align: center;
|
||||
line-height: 30px;
|
||||
background: #fff;
|
||||
}
|
||||
.popup-result-container table {
|
||||
text-align: center;
|
||||
width: 100%;
|
||||
margin: 0 auto;
|
||||
}
|
||||
.popup-result-container table span {
|
||||
display: block;
|
||||
width: 100%;
|
||||
font-family: arial;
|
||||
line-height: 30px;
|
||||
height: 30px;
|
||||
white-space: nowrap;
|
||||
overflow: hidden;
|
||||
border: 1px solid #e8e8e8;
|
||||
}
|
||||
|
||||
</style>
|
|
@ -0,0 +1,179 @@
|
|||
<template>
|
||||
<el-form size="small">
|
||||
<el-form-item>
|
||||
<el-radio v-model='radioValue' :label="1">
|
||||
日,允许的通配符[, - * / L M]
|
||||
</el-radio>
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item>
|
||||
<el-radio v-model='radioValue' :label="2">
|
||||
不指定
|
||||
</el-radio>
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item>
|
||||
<el-radio v-model='radioValue' :label="3">
|
||||
周期从
|
||||
<el-input-number v-model='cycle01' :min="0" :max="31" /> -
|
||||
<el-input-number v-model='cycle02' :min="0" :max="31" /> 日
|
||||
</el-radio>
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item>
|
||||
<el-radio v-model='radioValue' :label="4">
|
||||
从
|
||||
<el-input-number v-model='average01' :min="0" :max="31" /> 号开始,每
|
||||
<el-input-number v-model='average02' :min="0" :max="31" /> 日执行一次
|
||||
</el-radio>
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item>
|
||||
<el-radio v-model='radioValue' :label="5">
|
||||
每月
|
||||
<el-input-number v-model='workday' :min="0" :max="31" /> 号最近的那个工作日
|
||||
</el-radio>
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item>
|
||||
<el-radio v-model='radioValue' :label="6">
|
||||
本月最后一天
|
||||
</el-radio>
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item>
|
||||
<el-radio v-model='radioValue' :label="7">
|
||||
指定
|
||||
<el-select clearable v-model="checkboxList" placeholder="可多选" multiple style="width:100%">
|
||||
<el-option v-for="item in 31" :key="item" :value="item">{{item}}</el-option>
|
||||
</el-select>
|
||||
</el-radio>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
radioValue: 1,
|
||||
workday: 1,
|
||||
cycle01: 1,
|
||||
cycle02: 2,
|
||||
average01: 1,
|
||||
average02: 1,
|
||||
checkboxList: [],
|
||||
checkNum: this.$options.propsData.check
|
||||
}
|
||||
},
|
||||
name: 'CrontabDay',
|
||||
props: ['check', 'cron'],
|
||||
methods: {
|
||||
// 单选按钮值变化时
|
||||
radioChange() {
|
||||
('day rachange');
|
||||
if (this.radioValue === 1) {
|
||||
this.$emit('update', 'day', '*', 'day');
|
||||
this.$emit('update', 'week', '?', 'day');
|
||||
this.$emit('update', 'mouth', '*', 'day');
|
||||
} else {
|
||||
if (this.cron.hour === '*') {
|
||||
this.$emit('update', 'hour', '0', 'day');
|
||||
}
|
||||
if (this.cron.min === '*') {
|
||||
this.$emit('update', 'min', '0', 'day');
|
||||
}
|
||||
if (this.cron.second === '*') {
|
||||
this.$emit('update', 'second', '0', 'day');
|
||||
}
|
||||
}
|
||||
|
||||
switch (this.radioValue) {
|
||||
case 2:
|
||||
this.$emit('update', 'day', '?');
|
||||
break;
|
||||
case 3:
|
||||
this.$emit('update', 'day', this.cycle01 + '-' + this.cycle02);
|
||||
break;
|
||||
case 4:
|
||||
this.$emit('update', 'day', this.average01 + '/' + this.average02);
|
||||
break;
|
||||
case 5:
|
||||
this.$emit('update', 'day', this.workday + 'W');
|
||||
break;
|
||||
case 6:
|
||||
this.$emit('update', 'day', 'L');
|
||||
break;
|
||||
case 7:
|
||||
this.$emit('update', 'day', this.checkboxString);
|
||||
break;
|
||||
}
|
||||
('day rachange end');
|
||||
},
|
||||
// 周期两个值变化时
|
||||
cycleChange() {
|
||||
if (this.radioValue == '3') {
|
||||
this.$emit('update', 'day', this.cycleTotal);
|
||||
}
|
||||
},
|
||||
// 平均两个值变化时
|
||||
averageChange() {
|
||||
if (this.radioValue == '4') {
|
||||
this.$emit('update', 'day', this.averageTotal);
|
||||
}
|
||||
},
|
||||
// 最近工作日值变化时
|
||||
workdayChange() {
|
||||
if (this.radioValue == '5') {
|
||||
this.$emit('update', 'day', this.workday + 'W');
|
||||
}
|
||||
},
|
||||
// checkbox值变化时
|
||||
checkboxChange() {
|
||||
if (this.radioValue == '7') {
|
||||
this.$emit('update', 'day', this.checkboxString);
|
||||
}
|
||||
},
|
||||
// 父组件传递的week发生变化触发
|
||||
weekChange() {
|
||||
//判断week值与day不能同时为“?”
|
||||
if (this.cron.week == '?' && this.radioValue == '2') {
|
||||
this.radioValue = '1';
|
||||
} else if (this.cron.week !== '?' && this.radioValue != '2') {
|
||||
this.radioValue = '2';
|
||||
}
|
||||
},
|
||||
},
|
||||
watch: {
|
||||
"radioValue": "radioChange",
|
||||
'cycleTotal': 'cycleChange',
|
||||
'averageTotal': 'averageChange',
|
||||
'workdayCheck': 'workdayChange',
|
||||
'checkboxString': 'checkboxChange',
|
||||
},
|
||||
computed: {
|
||||
// 计算两个周期值
|
||||
cycleTotal: function () {
|
||||
this.cycle01 = this.checkNum(this.cycle01, 1, 31)
|
||||
this.cycle02 = this.checkNum(this.cycle02, 1, 31)
|
||||
return this.cycle01 + '-' + this.cycle02;
|
||||
},
|
||||
// 计算平均用到的值
|
||||
averageTotal: function () {
|
||||
this.average01 = this.checkNum(this.average01, 1, 31)
|
||||
this.average02 = this.checkNum(this.average02, 1, 31)
|
||||
return this.average01 + '/' + this.average02;
|
||||
},
|
||||
// 计算工作日格式
|
||||
workdayCheck: function () {
|
||||
this.workday = this.checkNum(this.workday, 1, 31)
|
||||
return this.workday;
|
||||
},
|
||||
// 计算勾选的checkbox值合集
|
||||
checkboxString: function () {
|
||||
let str = this.checkboxList.join();
|
||||
return str == '' ? '*' : str;
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
|
@ -0,0 +1,122 @@
|
|||
<template>
|
||||
<el-form size="small">
|
||||
<el-form-item>
|
||||
<el-radio v-model='radioValue' :label="1">
|
||||
小时,允许的通配符[, - * /]
|
||||
</el-radio>
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item>
|
||||
<el-radio v-model='radioValue' :label="2">
|
||||
周期从
|
||||
<el-input-number v-model='cycle01' :min="0" :max="60" /> -
|
||||
<el-input-number v-model='cycle02' :min="0" :max="60" /> 小时
|
||||
</el-radio>
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item>
|
||||
<el-radio v-model='radioValue' :label="3">
|
||||
从
|
||||
<el-input-number v-model='average01' :min="0" :max="60" /> 小时开始,每
|
||||
<el-input-number v-model='average02' :min="0" :max="60" /> 小时执行一次
|
||||
</el-radio>
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item>
|
||||
<el-radio v-model='radioValue' :label="4">
|
||||
指定
|
||||
<el-select clearable v-model="checkboxList" placeholder="可多选" multiple style="width:100%">
|
||||
<el-option v-for="item in 60" :key="item" :value="item-1">{{item-1}}</el-option>
|
||||
</el-select>
|
||||
</el-radio>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
radioValue: 1,
|
||||
cycle01: 0,
|
||||
cycle02: 1,
|
||||
average01: 0,
|
||||
average02: 1,
|
||||
checkboxList: [],
|
||||
checkNum: this.$options.propsData.check
|
||||
}
|
||||
},
|
||||
name: 'CrontabHour',
|
||||
props: ['check', 'cron'],
|
||||
methods: {
|
||||
// 单选按钮值变化时
|
||||
radioChange() {
|
||||
if (this.radioValue === 1) {
|
||||
this.$emit('update', 'hour', '*', 'hour');
|
||||
this.$emit('update', 'day', '*', 'hour');
|
||||
} else {
|
||||
if (this.cron.min === '*') {
|
||||
this.$emit('update', 'min', '0', 'hour');
|
||||
}
|
||||
if (this.cron.second === '*') {
|
||||
this.$emit('update', 'second', '0', 'hour');
|
||||
}
|
||||
}
|
||||
switch (this.radioValue) {
|
||||
case 2:
|
||||
this.$emit('update', 'hour', this.cycle01 + '-' + this.cycle02);
|
||||
break;
|
||||
case 3:
|
||||
this.$emit('update', 'hour', this.average01 + '/' + this.average02);
|
||||
break;
|
||||
case 4:
|
||||
this.$emit('update', 'hour', this.checkboxString);
|
||||
break;
|
||||
}
|
||||
},
|
||||
// 周期两个值变化时
|
||||
cycleChange() {
|
||||
if (this.radioValue == '2') {
|
||||
this.$emit('update', 'hour', this.cycleTotal);
|
||||
}
|
||||
},
|
||||
// 平均两个值变化时
|
||||
averageChange() {
|
||||
if (this.radioValue == '3') {
|
||||
this.$emit('update', 'hour', this.averageTotal);
|
||||
}
|
||||
},
|
||||
// checkbox值变化时
|
||||
checkboxChange() {
|
||||
if (this.radioValue == '4') {
|
||||
this.$emit('update', 'hour', this.checkboxString);
|
||||
}
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
"radioValue": "radioChange",
|
||||
'cycleTotal': 'cycleChange',
|
||||
'averageTotal': 'averageChange',
|
||||
'checkboxString': 'checkboxChange'
|
||||
},
|
||||
computed: {
|
||||
// 计算两个周期值
|
||||
cycleTotal: function () {
|
||||
this.cycle01 = this.checkNum(this.cycle01, 0, 23)
|
||||
this.cycle02 = this.checkNum(this.cycle02, 0, 23)
|
||||
return this.cycle01 + '-' + this.cycle02;
|
||||
},
|
||||
// 计算平均用到的值
|
||||
averageTotal: function () {
|
||||
this.average01 = this.checkNum(this.average01, 0, 23)
|
||||
this.average02 = this.checkNum(this.average02, 1, 23)
|
||||
return this.average01 + '/' + this.average02;
|
||||
},
|
||||
// 计算勾选的checkbox值合集
|
||||
checkboxString: function () {
|
||||
let str = this.checkboxList.join();
|
||||
return str == '' ? '*' : str;
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
|
@ -0,0 +1,120 @@
|
|||
<template>
|
||||
<el-form size="small">
|
||||
<el-form-item>
|
||||
<el-radio v-model='radioValue' :label="1">
|
||||
分钟,允许的通配符[, - * /]
|
||||
</el-radio>
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item>
|
||||
<el-radio v-model='radioValue' :label="2">
|
||||
周期从
|
||||
<el-input-number v-model='cycle01' :min="0" :max="60" /> -
|
||||
<el-input-number v-model='cycle02' :min="0" :max="60" /> 分钟
|
||||
</el-radio>
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item>
|
||||
<el-radio v-model='radioValue' :label="3">
|
||||
从
|
||||
<el-input-number v-model='average01' :min="0" :max="60" /> 分钟开始,每
|
||||
<el-input-number v-model='average02' :min="0" :max="60" /> 分钟执行一次
|
||||
</el-radio>
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item>
|
||||
<el-radio v-model='radioValue' :label="4">
|
||||
指定
|
||||
<el-select clearable v-model="checkboxList" placeholder="可多选" multiple style="width:100%">
|
||||
<el-option v-for="item in 60" :key="item" :value="item-1">{{item-1}}</el-option>
|
||||
</el-select>
|
||||
</el-radio>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
radioValue: 1,
|
||||
cycle01: 1,
|
||||
cycle02: 2,
|
||||
average01: 0,
|
||||
average02: 1,
|
||||
checkboxList: [],
|
||||
checkNum: this.$options.propsData.check
|
||||
}
|
||||
},
|
||||
name: 'CrontabMin',
|
||||
props: ['check', 'cron'],
|
||||
methods: {
|
||||
// 单选按钮值变化时
|
||||
radioChange() {
|
||||
if (this.radioValue !== 1 && this.cron.second === '*') {
|
||||
this.$emit('update', 'second', '0', 'min');
|
||||
}
|
||||
switch (this.radioValue) {
|
||||
case 1:
|
||||
this.$emit('update', 'min', '*', 'min');
|
||||
this.$emit('update', 'hour', '*', 'min');
|
||||
break;
|
||||
case 2:
|
||||
this.$emit('update', 'min', this.cycle01 + '-' + this.cycle02, 'min');
|
||||
break;
|
||||
case 3:
|
||||
this.$emit('update', 'min', this.average01 + '/' + this.average02, 'min');
|
||||
break;
|
||||
case 4:
|
||||
this.$emit('update', 'min', this.checkboxString, 'min');
|
||||
break;
|
||||
}
|
||||
},
|
||||
// 周期两个值变化时
|
||||
cycleChange() {
|
||||
if (this.radioValue == '2') {
|
||||
this.$emit('update', 'min', this.cycleTotal, 'min');
|
||||
}
|
||||
},
|
||||
// 平均两个值变化时
|
||||
averageChange() {
|
||||
if (this.radioValue == '3') {
|
||||
this.$emit('update', 'min', this.averageTotal, 'min');
|
||||
}
|
||||
},
|
||||
// checkbox值变化时
|
||||
checkboxChange() {
|
||||
if (this.radioValue == '4') {
|
||||
this.$emit('update', 'min', this.checkboxString, 'min');
|
||||
}
|
||||
},
|
||||
|
||||
},
|
||||
watch: {
|
||||
"radioValue": "radioChange",
|
||||
'cycleTotal': 'cycleChange',
|
||||
'averageTotal': 'averageChange',
|
||||
'checkboxString': 'checkboxChange',
|
||||
},
|
||||
computed: {
|
||||
// 计算两个周期值
|
||||
cycleTotal: function () {
|
||||
this.cycle01 = this.checkNum(this.cycle01, 0, 59)
|
||||
this.cycle02 = this.checkNum(this.cycle02, 0, 59)
|
||||
return this.cycle01 + '-' + this.cycle02;
|
||||
},
|
||||
// 计算平均用到的值
|
||||
averageTotal: function () {
|
||||
this.average01 = this.checkNum(this.average01, 0, 59)
|
||||
this.average02 = this.checkNum(this.average02, 1, 59)
|
||||
return this.average01 + '/' + this.average02;
|
||||
},
|
||||
// 计算勾选的checkbox值合集
|
||||
checkboxString: function () {
|
||||
let str = this.checkboxList.join();
|
||||
return str == '' ? '*' : str;
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
|
@ -0,0 +1,128 @@
|
|||
<template>
|
||||
<el-form size='small'>
|
||||
<el-form-item>
|
||||
<el-radio v-model='radioValue' :label="1">
|
||||
月,允许的通配符[, - * /]
|
||||
</el-radio>
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item>
|
||||
<el-radio v-model='radioValue' :label="2">
|
||||
周期从
|
||||
<el-input-number v-model='cycle01' :min="1" :max="12" /> -
|
||||
<el-input-number v-model='cycle02' :min="1" :max="12" /> 月
|
||||
</el-radio>
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item>
|
||||
<el-radio v-model='radioValue' :label="3">
|
||||
从
|
||||
<el-input-number v-model='average01' :min="1" :max="12" /> 月开始,每
|
||||
<el-input-number v-model='average02' :min="1" :max="12" /> 月月执行一次
|
||||
</el-radio>
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item>
|
||||
<el-radio v-model='radioValue' :label="4">
|
||||
指定
|
||||
<el-select clearable v-model="checkboxList" placeholder="可多选" multiple style="width:100%">
|
||||
<el-option v-for="item in 12" :key="item" :value="item">{{item}}</el-option>
|
||||
</el-select>
|
||||
</el-radio>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
radioValue: 1,
|
||||
cycle01: 1,
|
||||
cycle02: 2,
|
||||
average01: 1,
|
||||
average02: 1,
|
||||
checkboxList: [],
|
||||
checkNum: this.check
|
||||
}
|
||||
},
|
||||
name: 'CrontabMouth',
|
||||
props: ['check', 'cron'],
|
||||
methods: {
|
||||
// 单选按钮值变化时
|
||||
radioChange() {
|
||||
if (this.radioValue === 1) {
|
||||
this.$emit('update', 'mouth', '*');
|
||||
this.$emit('update', 'year', '*');
|
||||
} else {
|
||||
if (this.cron.day === '*') {
|
||||
this.$emit('update', 'day', '1', 'mouth');
|
||||
}
|
||||
if (this.cron.hour === '*') {
|
||||
this.$emit('update', 'hour', '0', 'mouth');
|
||||
}
|
||||
if (this.cron.min === '*') {
|
||||
this.$emit('update', 'min', '0', 'mouth');
|
||||
}
|
||||
if (this.cron.second === '*') {
|
||||
this.$emit('update', 'second', '0', 'mouth');
|
||||
}
|
||||
}
|
||||
switch (this.radioValue) {
|
||||
case 2:
|
||||
this.$emit('update', 'mouth', this.cycle01 + '-' + this.cycle02);
|
||||
break;
|
||||
case 3:
|
||||
this.$emit('update', 'mouth', this.average01 + '/' + this.average02);
|
||||
break;
|
||||
case 4:
|
||||
this.$emit('update', 'mouth', this.checkboxString);
|
||||
break;
|
||||
}
|
||||
},
|
||||
// 周期两个值变化时
|
||||
cycleChange() {
|
||||
if (this.radioValue == '2') {
|
||||
this.$emit('update', 'mouth', this.cycleTotal);
|
||||
}
|
||||
},
|
||||
// 平均两个值变化时
|
||||
averageChange() {
|
||||
if (this.radioValue == '3') {
|
||||
this.$emit('update', 'mouth', this.averageTotal);
|
||||
}
|
||||
},
|
||||
// checkbox值变化时
|
||||
checkboxChange() {
|
||||
if (this.radioValue == '4') {
|
||||
this.$emit('update', 'mouth', this.checkboxString);
|
||||
}
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
"radioValue": "radioChange",
|
||||
'cycleTotal': 'cycleChange',
|
||||
'averageTotal': 'averageChange',
|
||||
'checkboxString': 'checkboxChange'
|
||||
},
|
||||
computed: {
|
||||
// 计算两个周期值
|
||||
cycleTotal: function () {
|
||||
this.cycle01 = this.checkNum(this.cycle01, 1, 12)
|
||||
this.cycle02 = this.checkNum(this.cycle02, 1, 12)
|
||||
return this.cycle01 + '-' + this.cycle02;
|
||||
},
|
||||
// 计算平均用到的值
|
||||
averageTotal: function () {
|
||||
this.average01 = this.checkNum(this.average01, 1, 12)
|
||||
this.average02 = this.checkNum(this.average02, 1, 12)
|
||||
return this.average01 + '/' + this.average02;
|
||||
},
|
||||
// 计算勾选的checkbox值合集
|
||||
checkboxString: function () {
|
||||
let str = this.checkboxList.join();
|
||||
return str == '' ? '*' : str;
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
|
@ -0,0 +1,592 @@
|
|||
<template>
|
||||
<div class="popup-result">
|
||||
<p class="title">最近5次运行时间</p>
|
||||
<ul class="popup-result-scroll">
|
||||
<template>
|
||||
<li v-for='item in resultList' :key="item">{{item}}</li>
|
||||
</template>
|
||||
</ul>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: 'CrontabResult',
|
||||
data() {
|
||||
return {
|
||||
dayRule: '',
|
||||
dayRuleSup: '',
|
||||
dateArr: [],
|
||||
resultList: [],
|
||||
isShow: false
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
'ex': 'expressionChange'
|
||||
},
|
||||
props: ['ex'],
|
||||
mounted: function () {
|
||||
// 初始化 获取一次结果
|
||||
this.expressionChange();
|
||||
},
|
||||
methods: {
|
||||
// 表达式值变化时,开始去计算结果
|
||||
expressionChange() {
|
||||
// 计算开始-隐藏结果
|
||||
this.isShow = false;
|
||||
if (!this.ex) {
|
||||
this.resultList = [];
|
||||
return;
|
||||
}
|
||||
// 获取规则数组[0秒、1分、2时、3日、4月、5星期、6年]
|
||||
let ruleArr = this.$options.propsData.ex.split(' ');
|
||||
// 用于记录进入循环的次数
|
||||
let nums = 0;
|
||||
// 用于暂时存符号时间规则结果的数组
|
||||
let resultArr = [];
|
||||
// 获取当前时间精确至[年、月、日、时、分、秒]
|
||||
let nTime = new Date();
|
||||
let nYear = nTime.getFullYear();
|
||||
let nMouth = nTime.getMonth() + 1;
|
||||
let nDay = nTime.getDate();
|
||||
let nHour = nTime.getHours();
|
||||
let nMin = nTime.getMinutes();
|
||||
let nSecond = nTime.getSeconds();
|
||||
// 根据规则获取到近100年可能年数组、月数组等等
|
||||
this.getSecondArr(ruleArr[0]);
|
||||
this.getMinArr(ruleArr[1]);
|
||||
this.getHourArr(ruleArr[2]);
|
||||
this.getDayArr(ruleArr[3]);
|
||||
this.getMouthArr(ruleArr[4]);
|
||||
this.getWeekArr(ruleArr[5]);
|
||||
this.getYearArr(ruleArr[6], nYear);
|
||||
// 将获取到的数组赋值-方便使用
|
||||
let sDate = this.dateArr[0];
|
||||
let mDate = this.dateArr[1];
|
||||
let hDate = this.dateArr[2];
|
||||
let DDate = this.dateArr[3];
|
||||
let MDate = this.dateArr[4];
|
||||
let YDate = this.dateArr[5];
|
||||
// 获取当前时间在数组中的索引
|
||||
let sIdx = this.getIndex(sDate, nSecond);
|
||||
let mIdx = this.getIndex(mDate, nMin);
|
||||
let hIdx = this.getIndex(hDate, nHour);
|
||||
let DIdx = this.getIndex(DDate, nDay);
|
||||
let MIdx = this.getIndex(MDate, nMouth);
|
||||
let YIdx = this.getIndex(YDate, nYear);
|
||||
// 重置月日时分秒的函数(后面用的比较多)
|
||||
const resetSecond = function () {
|
||||
sIdx = 0;
|
||||
nSecond = sDate[sIdx]
|
||||
}
|
||||
const resetMin = function () {
|
||||
mIdx = 0;
|
||||
nMin = mDate[mIdx]
|
||||
resetSecond();
|
||||
}
|
||||
const resetHour = function () {
|
||||
hIdx = 0;
|
||||
nHour = hDate[hIdx]
|
||||
resetMin();
|
||||
}
|
||||
const resetDay = function () {
|
||||
DIdx = 0;
|
||||
nDay = DDate[DIdx]
|
||||
resetHour();
|
||||
}
|
||||
const resetMouth = function () {
|
||||
MIdx = 0;
|
||||
nMouth = MDate[MIdx]
|
||||
resetDay();
|
||||
}
|
||||
// 如果当前年份不为数组中当前值
|
||||
if (nYear !== YDate[YIdx]) {
|
||||
resetMouth();
|
||||
}
|
||||
// 如果当前月份不为数组中当前值
|
||||
if (nMouth !== MDate[MIdx]) {
|
||||
resetDay();
|
||||
}
|
||||
// 如果当前“日”不为数组中当前值
|
||||
if (nDay !== DDate[DIdx]) {
|
||||
resetHour();
|
||||
}
|
||||
// 如果当前“时”不为数组中当前值
|
||||
if (nHour !== hDate[hIdx]) {
|
||||
resetMin();
|
||||
}
|
||||
// 如果当前“分”不为数组中当前值
|
||||
if (nMin !== mDate[mIdx]) {
|
||||
resetSecond();
|
||||
}
|
||||
|
||||
// 循环年份数组
|
||||
goYear: for (let Yi = YIdx; Yi < YDate.length; Yi++) {
|
||||
let YY = YDate[Yi];
|
||||
// 如果到达最大值时
|
||||
if (nMouth > MDate[MDate.length - 1]) {
|
||||
resetMouth();
|
||||
continue;
|
||||
}
|
||||
// 循环月份数组
|
||||
goMouth: for (let Mi = MIdx; Mi < MDate.length; Mi++) {
|
||||
// 赋值、方便后面运算
|
||||
let MM = MDate[Mi];
|
||||
MM = MM < 10 ? '0' + MM : MM;
|
||||
// 如果到达最大值时
|
||||
if (nDay > DDate[DDate.length - 1]) {
|
||||
resetDay();
|
||||
if (Mi == MDate.length - 1) {
|
||||
resetMouth();
|
||||
continue goYear;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
// 循环日期数组
|
||||
goDay: for (let Di = DIdx; Di < DDate.length; Di++) {
|
||||
// 赋值、方便后面运算
|
||||
let DD = DDate[Di];
|
||||
let thisDD = DD < 10 ? '0' + DD : DD;
|
||||
|
||||
// 如果到达最大值时
|
||||
if (nHour > hDate[hDate.length - 1]) {
|
||||
resetHour();
|
||||
if (Di == DDate.length - 1) {
|
||||
resetDay();
|
||||
if (Mi == MDate.length - 1) {
|
||||
resetMouth();
|
||||
continue goYear;
|
||||
}
|
||||
continue goMouth;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
// 判断日期的合法性,不合法的话也是跳出当前循环
|
||||
if (this.checkDate(YY + '-' + MM + '-' + thisDD + ' 00:00:00') !== true && this.dayRule !== 'workDay' && this.dayRule !== 'lastWeek' && this.dayRule !== 'lastDay') {
|
||||
resetDay();
|
||||
continue goMouth;
|
||||
}
|
||||
// 如果日期规则中有值时
|
||||
if (this.dayRule == 'lastDay') {
|
||||
//如果不是合法日期则需要将前将日期调到合法日期即月末最后一天
|
||||
|
||||
if (this.checkDate(YY + '-' + MM + '-' + thisDD + ' 00:00:00') !== true) {
|
||||
while (DD > 0 && this.checkDate(YY + '-' + MM + '-' + thisDD + ' 00:00:00') !== true) {
|
||||
DD--;
|
||||
|
||||
thisDD = DD < 10 ? '0' + DD : DD;
|
||||
}
|
||||
}
|
||||
} else if (this.dayRule == 'workDay') {
|
||||
//校验并调整如果是2月30号这种日期传进来时需调整至正常月底
|
||||
if (this.checkDate(YY + '-' + MM + '-' + thisDD + ' 00:00:00') !== true) {
|
||||
while (DD > 0 && this.checkDate(YY + '-' + MM + '-' + thisDD + ' 00:00:00') !== true) {
|
||||
DD--;
|
||||
thisDD = DD < 10 ? '0' + DD : DD;
|
||||
}
|
||||
}
|
||||
// 获取达到条件的日期是星期X
|
||||
let thisWeek = this.formatDate(new Date(YY + '-' + MM + '-' + thisDD + ' 00:00:00'), 'week');
|
||||
// 当星期日时
|
||||
if (thisWeek == 0) {
|
||||
//先找下一个日,并判断是否为月底
|
||||
DD++;
|
||||
thisDD = DD < 10 ? '0' + DD : DD;
|
||||
//判断下一日已经不是合法日期
|
||||
if (this.checkDate(YY + '-' + MM + '-' + thisDD + ' 00:00:00') !== true) {
|
||||
DD -= 3;
|
||||
}
|
||||
} else if (thisWeek == 6) {
|
||||
//当星期6时只需判断不是1号就可进行操作
|
||||
if (this.dayRuleSup !== 1) {
|
||||
DD--;
|
||||
} else {
|
||||
DD += 2;
|
||||
}
|
||||
}
|
||||
} else if (this.dayRule == 'weekDay') {
|
||||
//如果指定了是星期几
|
||||
//获取当前日期是属于星期几
|
||||
let thisWeek = this.formatDate(new Date(YY + '-' + MM + '-' + DD + ' 00:00:00'), 'week');
|
||||
//校验当前星期是否在星期池(dayRuleSup)中
|
||||
if (Array.indexOf(this.dayRuleSup, thisWeek) < 0) {
|
||||
// 如果到达最大值时
|
||||
if (Di == DDate.length - 1) {
|
||||
resetDay();
|
||||
if (Mi == MDate.length - 1) {
|
||||
resetMouth();
|
||||
continue goYear;
|
||||
}
|
||||
continue goMouth;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
} else if (this.dayRule == 'assWeek') {
|
||||
//如果指定了是第几周的星期几
|
||||
//获取每月1号是属于星期几
|
||||
let thisWeek = this.formatDate(new Date(YY + '-' + MM + '-' + DD + ' 00:00:00'), 'week');
|
||||
if (this.dayRuleSup[1] >= thisWeek) {
|
||||
DD = (this.dayRuleSup[0] - 1) * 7 + this.dayRuleSup[1] - thisWeek + 1;
|
||||
} else {
|
||||
DD = this.dayRuleSup[0] * 7 + this.dayRuleSup[1] - thisWeek + 1;
|
||||
}
|
||||
} else if (this.dayRule == 'lastWeek') {
|
||||
//如果指定了每月最后一个星期几
|
||||
//校验并调整如果是2月30号这种日期传进来时需调整至正常月底
|
||||
if (this.checkDate(YY + '-' + MM + '-' + thisDD + ' 00:00:00') !== true) {
|
||||
while (DD > 0 && this.checkDate(YY + '-' + MM + '-' + thisDD + ' 00:00:00') !== true) {
|
||||
DD--;
|
||||
thisDD = DD < 10 ? '0' + DD : DD;
|
||||
}
|
||||
}
|
||||
//获取月末最后一天是星期几
|
||||
let thisWeek = this.formatDate(new Date(YY + '-' + MM + '-' + thisDD + ' 00:00:00'), 'week');
|
||||
//找到要求中最近的那个星期几
|
||||
if (this.dayRuleSup < thisWeek) {
|
||||
DD -= thisWeek - this.dayRuleSup;
|
||||
} else if (this.dayRuleSup > thisWeek) {
|
||||
DD -= 7 - (this.dayRuleSup - thisWeek)
|
||||
}
|
||||
}
|
||||
// 判断时间值是否小于10置换成“05”这种格式
|
||||
DD = DD < 10 ? '0' + DD : DD;
|
||||
|
||||
// 循环“时”数组
|
||||
goHour: for (let hi = hIdx; hi < hDate.length; hi++) {
|
||||
let hh = hDate[hi] < 10 ? '0' + hDate[hi] : hDate[hi]
|
||||
|
||||
// 如果到达最大值时
|
||||
if (nMin > mDate[mDate.length - 1]) {
|
||||
resetMin();
|
||||
if (hi == hDate.length - 1) {
|
||||
resetHour();
|
||||
if (Di == DDate.length - 1) {
|
||||
resetDay();
|
||||
if (Mi == MDate.length - 1) {
|
||||
resetMouth();
|
||||
continue goYear;
|
||||
}
|
||||
continue goMouth;
|
||||
}
|
||||
continue goDay;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
// 循环"分"数组
|
||||
goMin: for (let mi = mIdx; mi < mDate.length; mi++) {
|
||||
let mm = mDate[mi] < 10 ? '0' + mDate[mi] : mDate[mi];
|
||||
|
||||
// 如果到达最大值时
|
||||
if (nSecond > sDate[sDate.length - 1]) {
|
||||
resetSecond();
|
||||
if (mi == mDate.length - 1) {
|
||||
resetMin();
|
||||
if (hi == hDate.length - 1) {
|
||||
resetHour();
|
||||
if (Di == DDate.length - 1) {
|
||||
resetDay();
|
||||
if (Mi == MDate.length - 1) {
|
||||
resetMouth();
|
||||
continue goYear;
|
||||
}
|
||||
continue goMouth;
|
||||
}
|
||||
continue goDay;
|
||||
}
|
||||
continue goHour;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
// 循环"秒"数组
|
||||
goSecond: for (let si = sIdx; si <= sDate.length - 1; si++) {
|
||||
let ss = sDate[si] < 10 ? '0' + sDate[si] : sDate[si];
|
||||
// 添加当前时间(时间合法性在日期循环时已经判断)
|
||||
if (MM !== '00' && DD !== '00') {
|
||||
resultArr.push(YY + '-' + MM + '-' + DD + ' ' + hh + ':' + mm + ':' + ss)
|
||||
nums++;
|
||||
}
|
||||
//如果条数满了就退出循环
|
||||
if (nums == 5) break goYear;
|
||||
//如果到达最大值时
|
||||
if (si == sDate.length - 1) {
|
||||
resetSecond();
|
||||
if (mi == mDate.length - 1) {
|
||||
resetMin();
|
||||
if (hi == hDate.length - 1) {
|
||||
resetHour();
|
||||
if (Di == DDate.length - 1) {
|
||||
resetDay();
|
||||
if (Mi == MDate.length - 1) {
|
||||
resetMouth();
|
||||
continue goYear;
|
||||
}
|
||||
continue goMouth;
|
||||
}
|
||||
continue goDay;
|
||||
}
|
||||
continue goHour;
|
||||
}
|
||||
continue goMin;
|
||||
}
|
||||
} //goSecond
|
||||
} //goMin
|
||||
}//goHour
|
||||
}//goDay
|
||||
}//goMouth
|
||||
}
|
||||
// 判断100年内的结果条数
|
||||
if (resultArr.length == 0) {
|
||||
this.resultList = ['没有达到条件的结果!'];
|
||||
} else {
|
||||
this.resultList = resultArr;
|
||||
if (resultArr.length !== 5) {
|
||||
this.resultList.push('最近100年内只有上面' + resultArr.length + '条结果!')
|
||||
}
|
||||
}
|
||||
|
||||
this.$emit("resultListChange", this.resultList);
|
||||
// 计算完成-显示结果
|
||||
this.isShow = true;
|
||||
|
||||
},
|
||||
//用于计算某位数字在数组中的索引
|
||||
getIndex(arr, value) {
|
||||
if (value <= arr[0] || value > arr[arr.length - 1]) {
|
||||
return 0;
|
||||
} else {
|
||||
for (let i = 0; i < arr.length - 1; i++) {
|
||||
if (value > arr[i] && value <= arr[i + 1]) {
|
||||
return i + 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
// 获取"年"数组
|
||||
getYearArr(rule, year) {
|
||||
this.dateArr[5] = this.getOrderArr(year, year + 100);
|
||||
if (rule !== undefined) {
|
||||
if (rule.indexOf('-') >= 0) {
|
||||
this.dateArr[5] = this.getCycleArr(rule, year + 100, false)
|
||||
} else if (rule.indexOf('/') >= 0) {
|
||||
this.dateArr[5] = this.getAverageArr(rule, year + 100)
|
||||
} else if (rule !== '*') {
|
||||
this.dateArr[5] = this.getAssignArr(rule)
|
||||
}
|
||||
}
|
||||
},
|
||||
// 获取"月"数组
|
||||
getMouthArr(rule) {
|
||||
this.dateArr[4] = this.getOrderArr(1, 12);
|
||||
if (rule.indexOf('-') >= 0) {
|
||||
this.dateArr[4] = this.getCycleArr(rule, 12, false)
|
||||
} else if (rule.indexOf('/') >= 0) {
|
||||
this.dateArr[4] = this.getAverageArr(rule, 12)
|
||||
} else if (rule !== '*') {
|
||||
this.dateArr[4] = this.getAssignArr(rule)
|
||||
}
|
||||
},
|
||||
// 获取"日"数组-主要为日期规则
|
||||
getWeekArr(rule) {
|
||||
//只有当日期规则的两个值均为“”时则表达日期是有选项的
|
||||
if (this.dayRule == '' && this.dayRuleSup == '') {
|
||||
if (rule.indexOf('-') >= 0) {
|
||||
this.dayRule = 'weekDay';
|
||||
this.dayRuleSup = this.getCycleArr(rule, 7, false)
|
||||
} else if (rule.indexOf('#') >= 0) {
|
||||
this.dayRule = 'assWeek';
|
||||
let matchRule = rule.match(/[0-9]{1}/g);
|
||||
this.dayRuleSup = [Number(matchRule[0]), Number(matchRule[1])];
|
||||
this.dateArr[3] = [1];
|
||||
if (this.dayRuleSup[1] == 7) {
|
||||
this.dayRuleSup[1] = 0;
|
||||
}
|
||||
} else if (rule.indexOf('L') >= 0) {
|
||||
this.dayRule = 'lastWeek';
|
||||
this.dayRuleSup = Number(rule.match(/[0-9]{1,2}/g)[0]);
|
||||
this.dateArr[3] = [31];
|
||||
if (this.dayRuleSup == 7) {
|
||||
this.dayRuleSup = 0;
|
||||
}
|
||||
} else if (rule !== '*' && rule !== '?') {
|
||||
this.dayRule = 'weekDay';
|
||||
this.dayRuleSup = this.getAssignArr(rule)
|
||||
}
|
||||
//如果weekDay时将7调整为0【week值0即是星期日】
|
||||
if (this.dayRule == 'weekDay') {
|
||||
for (let i = 0; i < this.dayRuleSup.length; i++) {
|
||||
if (this.dayRuleSup[i] == 7) {
|
||||
this.dayRuleSup[i] = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
// 获取"日"数组-少量为日期规则
|
||||
getDayArr(rule) {
|
||||
this.dateArr[3] = this.getOrderArr(1, 31);
|
||||
this.dayRule = '';
|
||||
this.dayRuleSup = '';
|
||||
if (rule.indexOf('-') >= 0) {
|
||||
this.dateArr[3] = this.getCycleArr(rule, 31, false)
|
||||
this.dayRuleSup = 'null';
|
||||
} else if (rule.indexOf('/') >= 0) {
|
||||
this.dateArr[3] = this.getAverageArr(rule, 31)
|
||||
this.dayRuleSup = 'null';
|
||||
} else if (rule.indexOf('W') >= 0) {
|
||||
this.dayRule = 'workDay';
|
||||
this.dayRuleSup = Number(rule.match(/[0-9]{1,2}/g)[0]);
|
||||
this.dateArr[3] = [this.dayRuleSup];
|
||||
} else if (rule.indexOf('L') >= 0) {
|
||||
this.dayRule = 'lastDay';
|
||||
this.dayRuleSup = 'null';
|
||||
this.dateArr[3] = [31];
|
||||
} else if (rule !== '*' && rule !== '?') {
|
||||
this.dateArr[3] = this.getAssignArr(rule)
|
||||
this.dayRuleSup = 'null';
|
||||
} else if (rule == '*') {
|
||||
this.dayRuleSup = 'null';
|
||||
}
|
||||
},
|
||||
// 获取"时"数组
|
||||
getHourArr(rule) {
|
||||
this.dateArr[2] = this.getOrderArr(0, 23);
|
||||
if (rule.indexOf('-') >= 0) {
|
||||
this.dateArr[2] = this.getCycleArr(rule, 24, true)
|
||||
} else if (rule.indexOf('/') >= 0) {
|
||||
this.dateArr[2] = this.getAverageArr(rule, 23)
|
||||
} else if (rule !== '*') {
|
||||
this.dateArr[2] = this.getAssignArr(rule)
|
||||
}
|
||||
},
|
||||
// 获取"分"数组
|
||||
getMinArr(rule) {
|
||||
this.dateArr[1] = this.getOrderArr(0, 59);
|
||||
if (rule.indexOf('-') >= 0) {
|
||||
this.dateArr[1] = this.getCycleArr(rule, 60, true)
|
||||
} else if (rule.indexOf('/') >= 0) {
|
||||
this.dateArr[1] = this.getAverageArr(rule, 59)
|
||||
} else if (rule !== '*') {
|
||||
this.dateArr[1] = this.getAssignArr(rule)
|
||||
}
|
||||
},
|
||||
// 获取"秒"数组
|
||||
getSecondArr(rule) {
|
||||
this.dateArr[0] = this.getOrderArr(0, 59);
|
||||
if (rule.indexOf('-') >= 0) {
|
||||
this.dateArr[0] = this.getCycleArr(rule, 60, true)
|
||||
} else if (rule.indexOf('/') >= 0) {
|
||||
this.dateArr[0] = this.getAverageArr(rule, 59)
|
||||
} else if (rule !== '*') {
|
||||
this.dateArr[0] = this.getAssignArr(rule)
|
||||
}
|
||||
},
|
||||
// 根据传进来的min-max返回一个顺序的数组
|
||||
getOrderArr(min, max) {
|
||||
let arr = [];
|
||||
for (let i = min; i <= max; i++) {
|
||||
arr.push(i);
|
||||
}
|
||||
return arr;
|
||||
},
|
||||
// 根据规则中指定的零散值返回一个数组
|
||||
getAssignArr(rule) {
|
||||
let arr = [];
|
||||
let assiginArr = rule.split(',');
|
||||
for (let i = 0; i < assiginArr.length; i++) {
|
||||
arr[i] = Number(assiginArr[i])
|
||||
}
|
||||
arr.sort(this.compare)
|
||||
return arr;
|
||||
},
|
||||
// 根据一定算术规则计算返回一个数组
|
||||
getAverageArr(rule, limit) {
|
||||
let arr = [];
|
||||
let agArr = rule.split('/');
|
||||
let min = Number(agArr[0]);
|
||||
let step = Number(agArr[1]);
|
||||
while (min <= limit) {
|
||||
arr.push(min);
|
||||
min += step;
|
||||
}
|
||||
return arr;
|
||||
},
|
||||
// 根据规则返回一个具有周期性的数组
|
||||
getCycleArr(rule, limit, status) {
|
||||
//status--表示是否从0开始(则从1开始)
|
||||
let arr = [];
|
||||
let cycleArr = rule.split('-');
|
||||
let min = Number(cycleArr[0]);
|
||||
let max = Number(cycleArr[1]);
|
||||
if (min > max) {
|
||||
max += limit;
|
||||
}
|
||||
for (let i = min; i <= max; i++) {
|
||||
let add = 0;
|
||||
if (status == false && i % limit == 0) {
|
||||
add = limit;
|
||||
}
|
||||
arr.push(Math.round(i % limit + add))
|
||||
}
|
||||
arr.sort(this.compare)
|
||||
return arr;
|
||||
},
|
||||
//比较数字大小(用于Array.sort)
|
||||
compare(value1, value2) {
|
||||
if (value2 - value1 > 0) {
|
||||
return -1;
|
||||
} else {
|
||||
return 1;
|
||||
}
|
||||
},
|
||||
// 格式化日期格式如:2017-9-19 18:04:33
|
||||
formatDate(value, type) {
|
||||
// 计算日期相关值
|
||||
let time = typeof value == 'number' ? new Date(value) : value;
|
||||
let Y = time.getFullYear();
|
||||
let M = time.getMonth() + 1;
|
||||
let D = time.getDate();
|
||||
let h = time.getHours();
|
||||
let m = time.getMinutes();
|
||||
let s = time.getSeconds();
|
||||
let week = time.getDay();
|
||||
// 如果传递了type的话
|
||||
if (type == undefined) {
|
||||
return Y + '-' + (M < 10 ? '0' + M : M) + '-' + (D < 10 ? '0' + D : D) + ' ' + (h < 10 ? '0' + h : h) + ':' + (m < 10 ? '0' + m : m) + ':' + (s < 10 ? '0' + s : s);
|
||||
} else if (type == 'week') {
|
||||
return week;
|
||||
}
|
||||
},
|
||||
// 检查日期是否存在
|
||||
checkDate(value) {
|
||||
let time = new Date(value);
|
||||
let format = this.formatDate(time)
|
||||
return value == format ? true : false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
</script>
|
||||
<style>
|
||||
|
||||
.title {
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.popup-result-scroll {
|
||||
font-size: 12px;
|
||||
line-height: 24px;
|
||||
height: 10em;
|
||||
overflow-y: auto;
|
||||
}
|
||||
|
||||
.popup-result {
|
||||
box-sizing: border-box;
|
||||
line-height: 24px;
|
||||
margin: 25px auto;
|
||||
padding: 15px 10px 10px;
|
||||
border: 1px solid #ccc;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
</style>
|
|
@ -0,0 +1,133 @@
|
|||
<template>
|
||||
<el-form size="small">
|
||||
<el-form-item>
|
||||
<el-radio v-model='radioValue' :label="1">
|
||||
秒,允许的通配符[, - * /]
|
||||
</el-radio>
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item>
|
||||
<el-radio v-model='radioValue' :label="2">
|
||||
周期从
|
||||
<el-input-number v-model='cycle01' :min="0" :max="60" /> -
|
||||
<el-input-number v-model='cycle02' :min="0" :max="60" /> 秒
|
||||
</el-radio>
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item>
|
||||
<el-radio v-model='radioValue' :label="3">
|
||||
从
|
||||
<el-input-number v-model='average01' :min="0" :max="60" /> 秒开始,每
|
||||
<el-input-number v-model='average02' :min="0" :max="60" /> 秒执行一次
|
||||
</el-radio>
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item>
|
||||
<el-radio v-model='radioValue' :label="4">
|
||||
指定
|
||||
<el-select clearable v-model="checkboxList" placeholder="可多选" multiple style="width:100%">
|
||||
<el-option v-for="item in 60" :key="item" :value="item-1">{{item-1}}</el-option>
|
||||
</el-select>
|
||||
</el-radio>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
radioValue: 1,
|
||||
cycle01: 1,
|
||||
cycle02: 2,
|
||||
average01: 0,
|
||||
average02: 1,
|
||||
checkboxList: [],
|
||||
checkNum: this.$options.propsData.check
|
||||
}
|
||||
},
|
||||
name: 'CrontabSecond',
|
||||
props: ['check', 'radioParent'],
|
||||
methods: {
|
||||
// 单选按钮值变化时
|
||||
radioChange() {
|
||||
switch (this.radioValue) {
|
||||
case 1:
|
||||
this.$emit('update', 'second', '*', 'second');
|
||||
this.$emit('update', 'min', '*', 'second');
|
||||
break;
|
||||
case 2:
|
||||
this.$emit('update', 'second', this.cycle01 + '-' + this.cycle02);
|
||||
break;
|
||||
case 3:
|
||||
this.$emit('update', 'second', this.average01 + '/' + this.average02);
|
||||
break;
|
||||
case 4:
|
||||
this.$emit('update', 'second', this.checkboxString);
|
||||
break;
|
||||
}
|
||||
},
|
||||
// 周期两个值变化时
|
||||
cycleChange() {
|
||||
if (this.radioValue == '2') {
|
||||
this.$emit('update', 'second', this.cycleTotal);
|
||||
}
|
||||
},
|
||||
// 平均两个值变化时
|
||||
averageChange() {
|
||||
if (this.radioValue == '3') {
|
||||
this.$emit('update', 'second', this.averageTotal);
|
||||
}
|
||||
},
|
||||
// checkbox值变化时
|
||||
checkboxChange() {
|
||||
if (this.radioValue == '4') {
|
||||
this.$emit('update', 'second', this.checkboxString);
|
||||
}
|
||||
},
|
||||
othChange() {
|
||||
//反解析
|
||||
let ins = this.cron.second
|
||||
// ('反解析 second', ins);
|
||||
if (ins === '*') {
|
||||
this.radioValue = 1;
|
||||
} else if (ins.indexOf('-') > -1) {
|
||||
this.radioValue = 2
|
||||
} else if (ins.indexOf('/') > -1) {
|
||||
this.radioValue = 3
|
||||
} else {
|
||||
this.radioValue = 4
|
||||
this.checkboxList = ins.split(',')
|
||||
}
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
"radioValue": "radioChange",
|
||||
'cycleTotal': 'cycleChange',
|
||||
'averageTotal': 'averageChange',
|
||||
'checkboxString': 'checkboxChange',
|
||||
radioParent() {
|
||||
this.radioValue = this.radioParent
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
// 计算两个周期值
|
||||
cycleTotal: function () {
|
||||
this.cycle01 = this.checkNum(this.cycle01, 0, 59);
|
||||
this.cycle02 = this.checkNum(this.cycle02, 0, 59);
|
||||
return this.cycle01 + '-' + this.cycle02;
|
||||
},
|
||||
// 计算平均用到的值
|
||||
averageTotal: function () {
|
||||
this.average01 = this.checkNum(this.average01, 0, 59)
|
||||
this.average02 = this.checkNum(this.average02, 1, 59)
|
||||
return this.average01 + '/' + this.average02;
|
||||
},
|
||||
// 计算勾选的checkbox值合集
|
||||
checkboxString: function () {
|
||||
let str = this.checkboxList.join();
|
||||
return str == '' ? '*' : str;
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
|
@ -0,0 +1,167 @@
|
|||
<template>
|
||||
<el-form size='small'>
|
||||
<el-form-item>
|
||||
<el-radio v-model='radioValue' :label="1">
|
||||
周,允许的通配符[, - * / L #]
|
||||
</el-radio>
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item>
|
||||
<el-radio v-model='radioValue' :label="2">
|
||||
不指定
|
||||
</el-radio>
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item>
|
||||
<el-radio v-model='radioValue' :label="3">
|
||||
周期从星期
|
||||
<el-input-number v-model='cycle01' :min="1" :max="7" /> -
|
||||
<el-input-number v-model='cycle02' :min="1" :max="7" />
|
||||
</el-radio>
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item>
|
||||
<el-radio v-model='radioValue' :label="4">
|
||||
第
|
||||
<el-input-number v-model='average01' :min="1" :max="4" /> 周的星期
|
||||
<el-input-number v-model='average02' :min="1" :max="7" />
|
||||
</el-radio>
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item>
|
||||
<el-radio v-model='radioValue' :label="5">
|
||||
本月最后一个星期
|
||||
<el-input-number v-model='weekday' :min="1" :max="7" />
|
||||
</el-radio>
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item>
|
||||
<el-radio v-model='radioValue' :label="6">
|
||||
指定
|
||||
<el-select clearable v-model="checkboxList" placeholder="可多选" multiple style="width:100%">
|
||||
<el-option v-for="(item,index) of weekList" :key="index" :value="index+1">{{item}}</el-option>
|
||||
</el-select>
|
||||
</el-radio>
|
||||
</el-form-item>
|
||||
|
||||
</el-form>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
radioValue: 2,
|
||||
weekday: 1,
|
||||
cycle01: 1,
|
||||
cycle02: 2,
|
||||
average01: 1,
|
||||
average02: 1,
|
||||
checkboxList: [],
|
||||
weekList: ['周一', '周二', '周三', '周四', '周五', '周六', '周日'],
|
||||
checkNum: this.$options.propsData.check
|
||||
}
|
||||
},
|
||||
name: 'CrontabWeek',
|
||||
props: ['check', 'cron'],
|
||||
methods: {
|
||||
// 单选按钮值变化时
|
||||
radioChange() {
|
||||
if (this.radioValue === 1) {
|
||||
this.$emit('update', 'week', '*');
|
||||
this.$emit('update', 'year', '*');
|
||||
} else {
|
||||
if (this.cron.mouth === '*') {
|
||||
this.$emit('update', 'mouth', '1', 'week');
|
||||
}
|
||||
if (this.cron.day === '*') {
|
||||
this.$emit('update', 'day', '1', 'week');
|
||||
}
|
||||
if (this.cron.hour === '*') {
|
||||
this.$emit('update', 'hour', '0', 'week');
|
||||
}
|
||||
if (this.cron.min === '*') {
|
||||
this.$emit('update', 'min', '0', 'week');
|
||||
}
|
||||
if (this.cron.second === '*') {
|
||||
this.$emit('update', 'second', '0', 'week');
|
||||
}
|
||||
}
|
||||
switch (this.radioValue) {
|
||||
case 2:
|
||||
this.$emit('update', 'week', '?');
|
||||
break;
|
||||
case 3:
|
||||
this.$emit('update', 'week', this.cycle01 + '-' + this.cycle02);
|
||||
break;
|
||||
case 4:
|
||||
this.$emit('update', 'week', this.average01 + '#' + this.average02);
|
||||
break;
|
||||
case 5:
|
||||
this.$emit('update', 'week', this.weekday + 'L');
|
||||
break;
|
||||
case 6:
|
||||
this.$emit('update', 'week', this.checkboxString);
|
||||
break;
|
||||
}
|
||||
},
|
||||
// 根据互斥事件,更改radio的值
|
||||
|
||||
// 周期两个值变化时
|
||||
cycleChange() {
|
||||
if (this.radioValue == '3') {
|
||||
this.$emit('update', 'week', this.cycleTotal);
|
||||
}
|
||||
},
|
||||
// 平均两个值变化时
|
||||
averageChange() {
|
||||
if (this.radioValue == '4') {
|
||||
this.$emit('update', 'week', this.averageTotal);
|
||||
}
|
||||
},
|
||||
// 最近工作日值变化时
|
||||
weekdayChange() {
|
||||
if (this.radioValue == '5') {
|
||||
this.$emit('update', 'week', this.weekday + 'L');
|
||||
}
|
||||
},
|
||||
// checkbox值变化时
|
||||
checkboxChange() {
|
||||
if (this.radioValue == '6') {
|
||||
this.$emit('update', 'week', this.checkboxString);
|
||||
}
|
||||
},
|
||||
},
|
||||
watch: {
|
||||
"radioValue": "radioChange",
|
||||
'cycleTotal': 'cycleChange',
|
||||
'averageTotal': 'averageChange',
|
||||
'weekdayCheck': 'weekdayChange',
|
||||
'checkboxString': 'checkboxChange',
|
||||
},
|
||||
computed: {
|
||||
// 计算两个周期值
|
||||
cycleTotal: function () {
|
||||
this.cycle01 = this.checkNum(this.cycle01, 1, 7)
|
||||
this.cycle02 = this.checkNum(this.cycle02, 1, 7)
|
||||
return this.cycle01 + '-' + this.cycle02;
|
||||
},
|
||||
// 计算平均用到的值
|
||||
averageTotal: function () {
|
||||
this.average01 = this.checkNum(this.average01, 1, 4)
|
||||
this.average02 = this.checkNum(this.average02, 1, 7)
|
||||
return this.average01 + '#' + this.average02;
|
||||
},
|
||||
// 最近的工作日(格式)
|
||||
weekdayCheck: function () {
|
||||
this.weekday = this.checkNum(this.weekday, 1, 7)
|
||||
return this.weekday;
|
||||
},
|
||||
// 计算勾选的checkbox值合集
|
||||
checkboxString: function () {
|
||||
let str = this.checkboxList.join();
|
||||
return str == '' ? '?' : str;
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
|
@ -0,0 +1,144 @@
|
|||
<template>
|
||||
<el-form size="small">
|
||||
<el-form-item>
|
||||
<el-radio :label="1" v-model='radioValue'>
|
||||
不填,允许的通配符[, - * /]
|
||||
</el-radio>
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item>
|
||||
<el-radio :label="2" v-model='radioValue'>
|
||||
每年
|
||||
</el-radio>
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item>
|
||||
<el-radio :label="3" v-model='radioValue'>
|
||||
周期从
|
||||
<el-input-number v-model='cycle01' :min='fullYear' /> -
|
||||
<el-input-number v-model='cycle02' :min='fullYear' />
|
||||
</el-radio>
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item>
|
||||
<el-radio :label="4" v-model='radioValue'>
|
||||
从
|
||||
<el-input-number v-model='average01' :min='fullYear' /> 年开始,每
|
||||
<el-input-number v-model='average02' :min='fullYear' /> 年执行一次
|
||||
</el-radio>
|
||||
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item>
|
||||
<el-radio :label="5" v-model='radioValue'>
|
||||
指定
|
||||
<el-select clearable v-model="checkboxList" placeholder="可多选" multiple>
|
||||
<el-option v-for="item in 9" :key="item" :value="item - 1 + fullYear" :label="item -1 + fullYear" />
|
||||
</el-select>
|
||||
</el-radio>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
fullYear: 0,
|
||||
radioValue: 1,
|
||||
cycle01: 0,
|
||||
cycle02: 0,
|
||||
average01: 0,
|
||||
average02: 1,
|
||||
checkboxList: [],
|
||||
checkNum: this.$options.propsData.check
|
||||
}
|
||||
},
|
||||
name: 'CrontabYear',
|
||||
props: ['check', 'mouth', 'cron'],
|
||||
methods: {
|
||||
// 单选按钮值变化时
|
||||
radioChange() {
|
||||
if (this.cron.mouth === '*') {
|
||||
this.$emit('update', 'mouth', '1', 'year');
|
||||
}
|
||||
if (this.cron.day === '*') {
|
||||
this.$emit('update', 'day', '1', 'year');
|
||||
}
|
||||
if (this.cron.hour === '*') {
|
||||
this.$emit('update', 'hour', '0', 'year');
|
||||
}
|
||||
if (this.cron.min === '*') {
|
||||
this.$emit('update', 'min', '0', 'year');
|
||||
}
|
||||
if (this.cron.second === '*') {
|
||||
this.$emit('update', 'second', '0', 'year');
|
||||
}
|
||||
switch (this.radioValue) {
|
||||
case 1:
|
||||
this.$emit('update', 'year', '');
|
||||
break;
|
||||
case 2:
|
||||
this.$emit('update', 'year', '*');
|
||||
break;
|
||||
case 3:
|
||||
this.$emit('update', 'year', this.cycle01 + '-' + this.cycle02);
|
||||
break;
|
||||
case 4:
|
||||
this.$emit('update', 'year', this.average01 + '/' + this.average02);
|
||||
break;
|
||||
case 5:
|
||||
this.$emit('update', 'year', this.checkboxString);
|
||||
break;
|
||||
}
|
||||
},
|
||||
// 周期两个值变化时
|
||||
cycleChange() {
|
||||
if (this.radioValue == '3') {
|
||||
this.$emit('update', 'year', this.cycleTotal);
|
||||
}
|
||||
},
|
||||
// 平均两个值变化时
|
||||
averageChange() {
|
||||
if (this.radioValue == '4') {
|
||||
this.$emit('update', 'year', this.averageTotal);
|
||||
}
|
||||
},
|
||||
// checkbox值变化时
|
||||
checkboxChange() {
|
||||
if (this.radioValue == '5') {
|
||||
this.$emit('update', 'year', this.checkboxString);
|
||||
}
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
"radioValue": "radioChange",
|
||||
'cycleTotal': 'cycleChange',
|
||||
'averageTotal': 'averageChange',
|
||||
'checkboxString': 'checkboxChange'
|
||||
},
|
||||
computed: {
|
||||
// 计算两个周期值
|
||||
cycleTotal: function () {
|
||||
this.cycle01 = this.checkNum(this.cycle01, this.fullYear, this.fullYear + 100)
|
||||
this.cycle02 = this.checkNum(this.cycle02, this.fullYear + 1, this.fullYear + 101)
|
||||
return this.cycle01 + '-' + this.cycle02;
|
||||
},
|
||||
// 计算平均用到的值
|
||||
averageTotal: function () {
|
||||
this.average01 = this.checkNum(this.average01, this.fullYear, this.fullYear + 100)
|
||||
this.average02 = this.checkNum(this.average02, 1, 10)
|
||||
return this.average01 + '/' + this.average02;
|
||||
},
|
||||
// 计算勾选的checkbox值合集
|
||||
checkboxString: function () {
|
||||
let str = this.checkboxList.join();
|
||||
return str;
|
||||
}
|
||||
},
|
||||
mounted: function () {
|
||||
// 仅获取当前年份
|
||||
this.fullYear = Number(new Date().getFullYear());
|
||||
}
|
||||
}
|
||||
</script>
|
|
@ -32,6 +32,7 @@ import TestCase from "../../track/case/TestCase";
|
|||
import TestTrack from "../../track/TestTrack";
|
||||
import ApiReportList from "../../api/report/ApiReportList";
|
||||
import axios from "axios";
|
||||
import ApiKeys from "../../settings/personal/ApiKeys";
|
||||
|
||||
Vue.use(VueRouter);
|
||||
|
||||
|
@ -70,6 +71,10 @@ const router = new VueRouter({
|
|||
path: 'personsetting',
|
||||
component: PersonSetting
|
||||
},
|
||||
{
|
||||
path: 'apikeys',
|
||||
component: ApiKeys
|
||||
},
|
||||
{
|
||||
path: 'member',
|
||||
component: Member
|
||||
|
|
|
@ -38,6 +38,7 @@
|
|||
<span>{{$t('commons.personal_info')}}</span>
|
||||
</template>
|
||||
<el-menu-item index="/setting/personsetting">{{$t('commons.personal_setting')}}</el-menu-item>
|
||||
<el-menu-item index="/setting/apikeys">API Keys</el-menu-item>
|
||||
</el-submenu>
|
||||
|
||||
</el-menu>
|
||||
|
|
|
@ -0,0 +1,125 @@
|
|||
<template>
|
||||
<div v-loading="result.loading">
|
||||
<el-card class="table-card">
|
||||
<template v-slot:header>
|
||||
<div>
|
||||
<el-row class="table-title" type="flex" justify="space-between" align="middle">
|
||||
<span class="title">API Keys</span>
|
||||
</el-row>
|
||||
<el-row type="flex" justify="space-between" align="middle">
|
||||
<el-button @click="createApiKey()" plain type="el-icon-question" icon="el-icon-circle-plus-outline"
|
||||
size="mini">
|
||||
{{$t('commons.create')}}
|
||||
</el-button>
|
||||
</el-row>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<el-table :data="tableData" style="width: 100%">
|
||||
<el-table-column prop="accessKey" label="Access Key"/>
|
||||
<el-table-column prop="secretKey" label="Secret Key"/>
|
||||
<el-table-column prop="status" :label="$t('commons.status')">
|
||||
<template v-slot:default="scope">
|
||||
<el-switch v-model="scope.row.status"
|
||||
active-color="#13ce66"
|
||||
inactive-color="#ff4949"
|
||||
active-value="ACTIVE"
|
||||
inactive-value="DISABLED"
|
||||
@change="changeSwitch(scope.row)"
|
||||
/>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="createTime" :label="$t('commons.create_time')">
|
||||
<template v-slot:default="scope">
|
||||
<span>{{ scope.row.createTime | timestampFormatDate }}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column :label="$t('commons.operating')">
|
||||
<template v-slot:default="scope">
|
||||
<ms-table-operator-button :tip="$t('commons.delete')" icon="el-icon-delete"
|
||||
type="danger" @exec="deleteApiKey(scope.row)"/>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
</el-card>
|
||||
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import MsDialogFooter from "../../common/components/MsDialogFooter";
|
||||
import {getCurrentUser} from "../../../../common/js/utils";
|
||||
import MsTableOperatorButton from "../../common/components/MsTableOperatorButton";
|
||||
import MsTableHeader from "../../common/components/MsTableHeader";
|
||||
|
||||
export default {
|
||||
name: "MsApiKeys",
|
||||
components: {MsDialogFooter, MsTableOperatorButton, MsTableHeader},
|
||||
data() {
|
||||
return {
|
||||
result: {},
|
||||
updateVisible: false,
|
||||
editPasswordVisible: false,
|
||||
apiKeysVisible: false,
|
||||
condition: {},
|
||||
tableData: [],
|
||||
}
|
||||
},
|
||||
|
||||
activated() {
|
||||
this.search();
|
||||
},
|
||||
|
||||
methods: {
|
||||
currentUser: () => {
|
||||
return getCurrentUser();
|
||||
},
|
||||
search() {
|
||||
this.result = this.$get("/user/key/info", response => {
|
||||
this.tableData = response.data;
|
||||
this.tableData.forEach(d => d.show = false);
|
||||
}
|
||||
)
|
||||
},
|
||||
deleteApiKey(row) {
|
||||
this.$confirm(this.$t('user.apikey_delete_confirm'), '', {
|
||||
confirmButtonText: this.$t('commons.confirm'),
|
||||
cancelButtonText: this.$t('commons.cancel'),
|
||||
type: 'warning'
|
||||
}).then(() => {
|
||||
this.result = this.$get("/user/key/delete/" + row.id, response => {
|
||||
this.$success(this.$t('commons.delete_success'));
|
||||
this.search();
|
||||
})
|
||||
}).catch(() => {
|
||||
this.$info(this.$t('commons.delete_cancel'));
|
||||
});
|
||||
|
||||
},
|
||||
|
||||
createApiKey() {
|
||||
this.result = this.$get("/user/key/generate", response => {
|
||||
this.$success(this.$t('commons.save_success'));
|
||||
this.search();
|
||||
})
|
||||
},
|
||||
|
||||
changeSwitch(row) {
|
||||
if (row.status === 'ACTIVE') {
|
||||
this.result = this.$get("/user/key/active/" + row.id, response => {
|
||||
this.$success(this.$t('commons.save_success'));
|
||||
});
|
||||
}
|
||||
if (row.status === 'DISABLED') {
|
||||
this.result = this.$get("/user/key/disable/" + row.id, response => {
|
||||
this.$success(this.$t('commons.save_success'));
|
||||
});
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
|
||||
</style>
|
|
@ -0,0 +1,334 @@
|
|||
/**
|
||||
* Validates a cron expression.
|
||||
*
|
||||
* @param cronExpression The expression to validate
|
||||
* @return True is expression is valid
|
||||
*/
|
||||
export function cronValidate(cronExpression ){
|
||||
//alert("校验函数的开始!");
|
||||
var cronParams = cronExpression.split(" ");
|
||||
|
||||
if (cronParams.length < 6 || cronParams.length > 7) {
|
||||
return false;
|
||||
}
|
||||
|
||||
//CronTrigger cronTrigger = new CronTrigger();
|
||||
//cronTrigger.setCronExpression( cronExpression );
|
||||
|
||||
if (cronParams[3] == "?" || cronParams[5]=="?") {
|
||||
//Check seconds param
|
||||
if (!checkSecondsField(cronParams[0])) {
|
||||
return false;
|
||||
}
|
||||
|
||||
//Check minutes param
|
||||
if (!checkMinutesField(cronParams[1])) {
|
||||
return false;
|
||||
}
|
||||
|
||||
//Check hours param
|
||||
if (!checkHoursField(cronParams[2])) {
|
||||
return false;
|
||||
}
|
||||
|
||||
//Check day-of-month param
|
||||
if (!checkDayOfMonthField(cronParams[3])) {
|
||||
return false;
|
||||
}
|
||||
|
||||
//Check months param
|
||||
if (!checkMonthsField(cronParams[4])) {
|
||||
return false;
|
||||
}
|
||||
|
||||
//Check day-of-week param
|
||||
if (!checkDayOfWeekField(cronParams[5])) {
|
||||
return false;
|
||||
}
|
||||
|
||||
//Check year param
|
||||
if (cronParams.length == 7) {
|
||||
if (!checkYearField(cronParams[6])) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
function checkSecondsField(secondsField) {
|
||||
return checkField(secondsField, 0, 59);
|
||||
}
|
||||
|
||||
|
||||
function checkField(secondsField, minimal, maximal) {
|
||||
if (secondsField.indexOf("-") > -1 ) {
|
||||
var startValue = secondsField.substring(0, secondsField.indexOf( "-" ));
|
||||
var endValue = secondsField.substring(secondsField.indexOf( "-" ) + 1);
|
||||
|
||||
if (!(checkIntValue(startValue, minimal, maximal, true) && checkIntValue(endValue, minimal, maximal, true))) {
|
||||
return false;
|
||||
}
|
||||
try {
|
||||
var startVal = parseInt(startValue, 10);
|
||||
var endVal = parseInt(endValue, 10);
|
||||
|
||||
return endVal > startVal;
|
||||
} catch (e) {
|
||||
return false;
|
||||
}
|
||||
} else if (secondsField.indexOf(",") > -1) {
|
||||
return checkListField(secondsField, minimal, maximal);
|
||||
} else if (secondsField.indexOf( "/" ) > -1) {
|
||||
return checkIncrementField( secondsField, minimal, maximal );
|
||||
} else if (secondsField.indexOf( "*" ) != -1) {
|
||||
return true;
|
||||
} else {
|
||||
return checkIntValue(secondsField, minimal, maximal);
|
||||
}
|
||||
}
|
||||
|
||||
function checkIntValue(value, minimal, maximal, checkExtremity) {
|
||||
try {
|
||||
var val = parseInt(value, 10);
|
||||
//判断是否为整数
|
||||
if (value == val) {
|
||||
if (checkExtremity) {
|
||||
if (val < minimal || val > maximal) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
} catch (e) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
function checkMinutesField(minutesField) {
|
||||
return checkField(minutesField, 0, 59);
|
||||
}
|
||||
|
||||
function checkHoursField(hoursField) {
|
||||
return checkField(hoursField, 0, 23);
|
||||
}
|
||||
|
||||
function checkDayOfMonthField(dayOfMonthField) {
|
||||
if (dayOfMonthField == "?") {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (dayOfMonthField.indexOf("L") >= 0) {
|
||||
return checkFieldWithLetter(dayOfMonthField, "L", 1, 7, -1, -1);
|
||||
} else if ( dayOfMonthField.indexOf("W") >= 0) {
|
||||
return checkFieldWithLetter(dayOfMonthField, "W", 1, 31, -1, -1);
|
||||
} else if (dayOfMonthField.indexOf("C") >= 0) {
|
||||
return checkFieldWithLetter(dayOfMonthField, "C", 1, 31, -1, -1);
|
||||
} else {
|
||||
return checkField( dayOfMonthField, 1, 31 );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
function checkMonthsField(monthsField) {
|
||||
/* monthsField = StringUtils.replace( monthsField, "JAN", "1" );
|
||||
monthsField = StringUtils.replace( monthsField, "FEB", "2" );
|
||||
monthsField = StringUtils.replace( monthsField, "MAR", "3" );
|
||||
monthsField = StringUtils.replace( monthsField, "APR", "4" );
|
||||
monthsField = StringUtils.replace( monthsField, "MAY", "5" );
|
||||
monthsField = StringUtils.replace( monthsField, "JUN", "6" );
|
||||
monthsField = StringUtils.replace( monthsField, "JUL", "7" );
|
||||
monthsField = StringUtils.replace( monthsField, "AUG", "8" );
|
||||
monthsField = StringUtils.replace( monthsField, "SEP", "9" );
|
||||
monthsField = StringUtils.replace( monthsField, "OCT", "10" );
|
||||
monthsField = StringUtils.replace( monthsField, "NOV", "11" );
|
||||
monthsField = StringUtils.replace( monthsField, "DEC", "12" );*/
|
||||
|
||||
monthsField.replace("JAN", "1");
|
||||
monthsField.replace("FEB", "2");
|
||||
monthsField.replace("MAR", "3");
|
||||
monthsField.replace("APR", "4");
|
||||
monthsField.replace("MAY", "5");
|
||||
monthsField.replace("JUN", "6");
|
||||
monthsField.replace("JUL", "7");
|
||||
monthsField.replace("AUG", "8");
|
||||
monthsField.replace("SEP", "9");
|
||||
monthsField.replace("OCT", "10");
|
||||
monthsField.replace("NOV", "11");
|
||||
monthsField.replace("DEC", "12");
|
||||
|
||||
return checkField(monthsField, 1, 31);
|
||||
}
|
||||
|
||||
function checkDayOfWeekField(dayOfWeekField) {
|
||||
/* dayOfWeekField = StringUtils.replace( dayOfWeekField, "SUN", "1" );
|
||||
dayOfWeekField = StringUtils.replace( dayOfWeekField, "MON", "2" );
|
||||
dayOfWeekField = StringUtils.replace( dayOfWeekField, "TUE", "3" );
|
||||
dayOfWeekField = StringUtils.replace( dayOfWeekField, "WED", "4" );
|
||||
dayOfWeekField = StringUtils.replace( dayOfWeekField, "THU", "5" );
|
||||
dayOfWeekField = StringUtils.replace( dayOfWeekField, "FRI", "6" );
|
||||
dayOfWeekField = StringUtils.replace( dayOfWeekField, "SAT", "7" );*/
|
||||
|
||||
dayOfWeekField.replace("SUN", "1" );
|
||||
dayOfWeekField.replace("MON", "2" );
|
||||
dayOfWeekField.replace("TUE", "3" );
|
||||
dayOfWeekField.replace("WED", "4" );
|
||||
dayOfWeekField.replace("THU", "5" );
|
||||
dayOfWeekField.replace("FRI", "6" );
|
||||
dayOfWeekField.replace("SAT", "7" );
|
||||
|
||||
if (dayOfWeekField == "?") {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (dayOfWeekField.indexOf("L") >= 0) {
|
||||
return checkFieldWithLetter(dayOfWeekField, "L", 1, 7, -1, -1);
|
||||
} else if (dayOfWeekField.indexOf("C") >= 0) {
|
||||
return checkFieldWithLetter(dayOfWeekField, "C", 1, 7, -1, -1);
|
||||
} else if (dayOfWeekField.indexOf("#") >= 0) {
|
||||
return checkFieldWithLetter(dayOfWeekField, "#", 1, 7, 1, 5);
|
||||
} else {
|
||||
return checkField(dayOfWeekField, 1, 7);
|
||||
}
|
||||
}
|
||||
|
||||
function checkYearField(yearField) {
|
||||
return checkField(yearField, 1970, 2099);
|
||||
}
|
||||
|
||||
|
||||
function checkFieldWithLetter(value, letter, minimalBefore, maximalBefore,
|
||||
minimalAfter, maximalAfter) {
|
||||
var canBeAlone = false;
|
||||
var canHaveIntBefore = false;
|
||||
var canHaveIntAfter = false;
|
||||
var mustHaveIntBefore = false;
|
||||
var mustHaveIntAfter = false;
|
||||
|
||||
if (letter == "L") {
|
||||
canBeAlone = true;
|
||||
canHaveIntBefore = true;
|
||||
canHaveIntAfter = false;
|
||||
mustHaveIntBefore = false;
|
||||
mustHaveIntAfter = false;
|
||||
}
|
||||
if (letter == "W" || letter == "C") {
|
||||
canBeAlone = false;
|
||||
canHaveIntBefore = true;
|
||||
canHaveIntAfter = false;
|
||||
mustHaveIntBefore = true;
|
||||
mustHaveIntAfter = false;
|
||||
}
|
||||
if (letter == "#") {
|
||||
canBeAlone = false;
|
||||
canHaveIntBefore = true;
|
||||
canHaveIntAfter = true;
|
||||
mustHaveIntBefore = true;
|
||||
mustHaveIntAfter = true;
|
||||
}
|
||||
|
||||
var beforeLetter = "";
|
||||
var afterLetter = "";
|
||||
|
||||
if (value.indexOf(letter) >= 0 ) {
|
||||
beforeLetter = value.substring( 0, value.indexOf(letter));
|
||||
}
|
||||
|
||||
if (!value.endsWith(letter)) {
|
||||
afterLetter = value.substring( value.indexOf( letter ) + 1 );
|
||||
}
|
||||
|
||||
if (value.indexOf(letter) >= 0) {
|
||||
if (letter == value) {
|
||||
return canBeAlone;
|
||||
}
|
||||
|
||||
if (canHaveIntBefore) {
|
||||
if (mustHaveIntBefore && beforeLetter.length == 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!checkIntValue(beforeLetter, minimalBefore, maximalBefore, true)){
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
if (beforeLetter.length > 0 ) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (canHaveIntAfter) {
|
||||
if ( mustHaveIntAfter && afterLetter.length == 0 ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!checkIntValue(afterLetter, minimalAfter, maximalAfter, true)) {
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
if (afterLetter.length > 0) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/* function checkIntValue(value, minimal, maximal) {
|
||||
return checkIntValue(value, minimal, maximal, true);
|
||||
} */
|
||||
|
||||
function checkIncrementField(value, minimal, maximal) {
|
||||
var start = value.substring(0, value.indexOf("/"));
|
||||
|
||||
var increment = value.substring(value.indexOf("/") + 1);
|
||||
|
||||
if (!("*" == start)) {
|
||||
return checkIntValue(start, minimal, maximal, true) && checkIntValue(increment, minimal, maximal, false);
|
||||
} else {
|
||||
return checkIntValue(increment, minimal, maximal, true);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
function checkListField(value, minimal, maximal ) {
|
||||
var st = value.split(",");
|
||||
|
||||
var values = new Array(st.length);
|
||||
|
||||
for(var j = 0; j < st.length; j++) {
|
||||
values[j] = st[j];
|
||||
}
|
||||
|
||||
var previousValue = -1;
|
||||
|
||||
for (var i= 0; i < values.length; i++) {
|
||||
var currentValue = values[i];
|
||||
|
||||
if (!checkIntValue(currentValue, minimal, maximal, true)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
try {
|
||||
var val = parseInt(currentValue, 10);
|
||||
|
||||
if (val <= previousValue) {
|
||||
return false;
|
||||
} else {
|
||||
previousValue = val;
|
||||
}
|
||||
} catch (e) {
|
||||
// we have always an int
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
|
@ -174,6 +174,7 @@ export default {
|
|||
'mobile_number_format_is_incorrect': 'Mobile number format is incorrect',
|
||||
'email_format_is_incorrect': 'Email format is incorrect',
|
||||
'delete_confirm': 'Are you sure you want to delete this User?',
|
||||
'apikey_delete_confirm': 'Are you sure you want to delete this API Key?',
|
||||
'input_id_placeholder': 'Please enter ID (only supports numbers and English letters)'
|
||||
},
|
||||
role: {
|
||||
|
|
|
@ -173,6 +173,7 @@ export default {
|
|||
'mobile_number_format_is_incorrect': '手机号码格式不正确',
|
||||
'email_format_is_incorrect': '邮箱格式不正确',
|
||||
'delete_confirm': '这个用户确定要删除吗?',
|
||||
'apikey_delete_confirm': '这个 API Key 确定要删除吗?',
|
||||
'input_id_placeholder': '请输入ID (只支持数字、英文字母)'
|
||||
},
|
||||
role: {
|
||||
|
|
|
@ -171,6 +171,7 @@ export default {
|
|||
'mobile_number_format_is_incorrect': '手機號碼格式不正確',
|
||||
'email_format_is_incorrect': '郵箱格式不正確',
|
||||
'delete_confirm': '這個用戶確定要刪除嗎?',
|
||||
'apikey_delete_confirm': '這個 API Key 確定要刪除嗎?',
|
||||
'input_id_placeholder': '請輸入ID (只支持數字、英文字母)'
|
||||
},
|
||||
role: {
|
||||
|
|
Loading…
Reference in New Issue