Browse Source

Merge remote-tracking branch 'remotes/upstream/dev-20190415' into dev-20190415

pull/2/head
ligang 5 years ago
parent
commit
25eba673a3
  1. 58
      escheduler-api/src/main/java/cn/escheduler/api/controller/DataAnalysisController.java
  2. 5
      escheduler-api/src/main/java/cn/escheduler/api/enums/Status.java
  3. 19
      escheduler-api/src/main/java/cn/escheduler/api/interceptor/LoginHandlerInterceptor.java
  4. 175
      escheduler-api/src/main/java/cn/escheduler/api/service/DataAnalysisService.java
  5. 7
      escheduler-api/src/main/java/cn/escheduler/api/service/ProcessInstanceService.java
  6. 2
      escheduler-dao/src/main/java/cn/escheduler/dao/mapper/AccessTokenMapperProvider.java
  7. 16
      escheduler-dao/src/main/java/cn/escheduler/dao/mapper/CommandMapper.java
  8. 29
      escheduler-dao/src/main/java/cn/escheduler/dao/mapper/CommandMapperProvider.java
  9. 14
      escheduler-dao/src/main/java/cn/escheduler/dao/mapper/ErrorCommandMapper.java
  10. 28
      escheduler-dao/src/main/java/cn/escheduler/dao/mapper/ErrorCommandMapperProvider.java
  11. 14
      escheduler-dao/src/main/java/cn/escheduler/dao/mapper/TaskInstanceMapper.java
  12. 40
      escheduler-dao/src/main/java/cn/escheduler/dao/mapper/TaskInstanceMapperProvider.java
  13. 2
      escheduler-dao/src/main/java/cn/escheduler/dao/mapper/UserMapperProvider.java
  14. 8
      escheduler-dao/src/main/java/cn/escheduler/dao/model/ExecuteStatusCount.java
  15. 2
      escheduler-ui/.env
  16. 2
      escheduler-ui/src/js/conf/home/pages/dag/_source/dag.vue
  17. 2
      escheduler-ui/src/js/conf/home/pages/dag/_source/formModel/_source/selectInput.vue
  18. 2
      escheduler-ui/src/js/conf/home/pages/dag/_source/formModel/_source/timeoutAlarm.vue
  19. 55
      escheduler-ui/src/js/conf/home/pages/dag/_source/formModel/_source/workerGroups.vue
  20. 109
      escheduler-ui/src/js/conf/home/pages/dag/_source/formModel/formModel.scss
  21. 134
      escheduler-ui/src/js/conf/home/pages/dag/_source/formModel/formModel.vue
  22. 73
      escheduler-ui/src/js/conf/home/pages/dag/_source/formModel/tasks/_source/localParams.vue
  23. 12
      escheduler-ui/src/js/conf/home/pages/dag/_source/plugIn/jsPlumbHandle.js
  24. 4
      escheduler-ui/src/js/conf/home/pages/dag/_source/plugIn/util.js
  25. 12
      escheduler-ui/src/js/conf/home/pages/dag/_source/udp/udp.vue
  26. 42
      escheduler-ui/src/js/conf/home/pages/dag/_source/variable/variablesView.vue
  27. 5
      escheduler-ui/src/js/conf/home/pages/dag/definitionDetails.vue
  28. 5
      escheduler-ui/src/js/conf/home/pages/dag/index.vue
  29. 5
      escheduler-ui/src/js/conf/home/pages/dag/instanceDetails.vue
  30. 40
      escheduler-ui/src/js/conf/home/pages/monitor/index.vue
  31. 0
      escheduler-ui/src/js/conf/home/pages/monitor/pages/servers/_source/list.vue
  32. 49
      escheduler-ui/src/js/conf/home/pages/monitor/pages/servers/alert.vue
  33. 40
      escheduler-ui/src/js/conf/home/pages/monitor/pages/servers/apiserver.vue
  34. 49
      escheduler-ui/src/js/conf/home/pages/monitor/pages/servers/master.vue
  35. 40
      escheduler-ui/src/js/conf/home/pages/monitor/pages/servers/mysql.vue
  36. 40
      escheduler-ui/src/js/conf/home/pages/monitor/pages/servers/rpcserver.vue
  37. 2
      escheduler-ui/src/js/conf/home/pages/monitor/pages/servers/worker.vue
  38. 4
      escheduler-ui/src/js/conf/home/pages/monitor/pages/servers/zookeeper.vue
  39. 21
      escheduler-ui/src/js/conf/home/pages/projects/pages/definition/pages/list/_source/start.vue
  40. 18
      escheduler-ui/src/js/conf/home/pages/projects/pages/definition/pages/list/_source/timing.vue
  41. 8
      escheduler-ui/src/js/conf/home/pages/security/pages/servers/index.vue
  42. 118
      escheduler-ui/src/js/conf/home/pages/security/pages/workerGroups/_source/createWorker.vue
  43. 119
      escheduler-ui/src/js/conf/home/pages/security/pages/workerGroups/_source/list.vue
  44. 114
      escheduler-ui/src/js/conf/home/pages/security/pages/workerGroups/index.vue
  45. 2
      escheduler-ui/src/js/conf/home/pages/user/pages/token/_source/list.vue
  46. 100
      escheduler-ui/src/js/conf/home/router/index.js
  47. 48
      escheduler-ui/src/js/conf/home/store/security/actions.js
  48. 2
      escheduler-ui/src/js/conf/home/store/security/state.js
  49. 1
      escheduler-ui/src/js/module/components/priority/priority.vue
  50. 103
      escheduler-ui/src/js/module/components/secondaryMenu/_source/menu.js
  51. 1
      escheduler-ui/src/js/module/i18n/locale/zh_CN.js
  52. 1
      escheduler-ui/src/js/module/permissions/index.js

58
escheduler-api/src/main/java/cn/escheduler/api/controller/DataAnalysisController.java

@ -57,8 +57,7 @@ public class DataAnalysisController extends BaseController{
public Result countTaskState(@RequestAttribute(value = Constants.SESSION_USER) User loginUser,
@RequestParam(value="startDate", required=false) String startDate,
@RequestParam(value="endDate", required=false) String endDate,
@RequestParam(value="projectId", required=false, defaultValue = "0") int projectId
){
@RequestParam(value="projectId", required=false, defaultValue = "0") int projectId){
try{
logger.info("count task state, user:{}, start date: {}, end date:{}, project id {}",
loginUser.getUserName(), startDate, endDate, projectId);
@ -82,12 +81,11 @@ public class DataAnalysisController extends BaseController{
public Result countProcessInstanceState(@RequestAttribute(value = Constants.SESSION_USER) User loginUser,
@RequestParam(value="startDate", required=false) String startDate,
@RequestParam(value="endDate", required=false) String endDate,
@RequestParam(value="projectId", required=false, defaultValue = "0") int projectId
){
@RequestParam(value="projectId", required=false, defaultValue = "0") int projectId){
try{
logger.info("count process instance state, user:{}, start date: {}, end date:{}, project id",
loginUser.getUserName(), startDate, endDate, projectId);
Map<String, Object> result = dataAnalysisService.countProcessInstanceStateByProject(loginUser,projectId, startDate, endDate);
Map<String, Object> result = dataAnalysisService.countProcessInstanceStateByProject(loginUser, projectId, startDate, endDate);
return returnDataList(result);
}catch (Exception e){
logger.error(COUNT_PROCESS_INSTANCE_STATE_ERROR.getMsg(),e);
@ -105,8 +103,7 @@ public class DataAnalysisController extends BaseController{
@GetMapping(value="/define-user-count")
@ResponseStatus(HttpStatus.OK)
public Result countDefinitionByUser(@RequestAttribute(value = Constants.SESSION_USER) User loginUser,
@RequestParam(value="projectId", required=false, defaultValue = "0") int projectId
){
@RequestParam(value="projectId", required=false, defaultValue = "0") int projectId){
try{
logger.info("count process definition , user:{}, project id",
loginUser.getUserName(), projectId);
@ -119,4 +116,51 @@ public class DataAnalysisController extends BaseController{
}
/**
* statistical command status data
*
* @param loginUser
* @param projectId
* @return
*/
@GetMapping(value="/command-state-count")
@ResponseStatus(HttpStatus.OK)
public Result countCommandState(@RequestAttribute(value = Constants.SESSION_USER) User loginUser,
@RequestParam(value="startDate", required=false) String startDate,
@RequestParam(value="endDate", required=false) String endDate,
@RequestParam(value="projectId", required=false, defaultValue = "0") int projectId){
try{
logger.info("count command state, user:{}, start date: {}, end date:{}, project id {}",
loginUser.getUserName(), startDate, endDate, projectId);
Map<String, Object> result = dataAnalysisService.countCommandState(loginUser, projectId, startDate, endDate);
return returnDataList(result);
}catch (Exception e){
logger.error(COMMAND_STATE_COUNT_ERROR.getMsg(),e);
return error(COMMAND_STATE_COUNT_ERROR.getCode(), COMMAND_STATE_COUNT_ERROR.getMsg());
}
}
/**
* queue count
*
* @param loginUser
* @param projectId
* @return
*/
@GetMapping(value="/queue-count")
@ResponseStatus(HttpStatus.OK)
public Result countQueueState(@RequestAttribute(value = Constants.SESSION_USER) User loginUser,
@RequestParam(value="projectId", required=false, defaultValue = "0") int projectId){
try{
logger.info("count command state, user:{}, start date: {}, end date:{}, project id {}",
loginUser.getUserName(), projectId);
Map<String, Object> result = dataAnalysisService.countQueueState(loginUser, projectId);
return returnDataList(result);
}catch (Exception e){
logger.error(QUEUE_COUNT_ERROR.getMsg(),e);
return error(QUEUE_COUNT_ERROR.getCode(), QUEUE_COUNT_ERROR.getMsg());
}
}
}

5
escheduler-api/src/main/java/cn/escheduler/api/enums/Status.java

@ -205,6 +205,11 @@ public enum Status {
GENERATE_TOKEN_ERROR(70002,"generate token error"),
QUERY_ACCESSTOKEN_LIST_PAGING_ERROR(70003,"query access token list paging error"),
COMMAND_STATE_COUNT_ERROR(80001,"task instance state count error"),
QUEUE_COUNT_ERROR(90001,"queue count error"),
;
private int code;

19
escheduler-api/src/main/java/cn/escheduler/api/interceptor/LoginHandlerInterceptor.java

@ -79,15 +79,20 @@ public class LoginHandlerInterceptor implements HandlerInterceptor {
//get user object from session
user = userMapper.queryById(session.getUserId());
// if user is null
if (user == null) {
response.setStatus(HttpStatus.SC_UNAUTHORIZED);
logger.info("user does not exist");
return false;
}
}else {
user = userMapper.queryUserByToken(token);
}
// if user is null
if (user == null) {
response.setStatus(HttpStatus.SC_UNAUTHORIZED);
logger.info("user does not exist");
return false;
if (user == null) {
response.setStatus(HttpStatus.SC_UNAUTHORIZED);
logger.info("user token has expired");
return false;
}
}
request.setAttribute(Constants.SESSION_USER, user);
return true;

175
escheduler-api/src/main/java/cn/escheduler/api/service/DataAnalysisService.java

@ -21,15 +21,17 @@ import cn.escheduler.api.dto.DefineUserDto;
import cn.escheduler.api.dto.TaskCountDto;
import cn.escheduler.api.enums.Status;
import cn.escheduler.api.utils.Constants;
import cn.escheduler.common.enums.ExecutionStatus;
import cn.escheduler.common.enums.UserType;
import cn.escheduler.common.queue.ITaskQueue;
import cn.escheduler.common.queue.TaskQueueFactory;
import cn.escheduler.common.utils.DateUtils;
import cn.escheduler.dao.mapper.ProcessDefinitionMapper;
import cn.escheduler.dao.mapper.ProcessInstanceMapper;
import cn.escheduler.dao.mapper.ProjectMapper;
import cn.escheduler.dao.mapper.TaskInstanceMapper;
import cn.escheduler.dao.mapper.*;
import cn.escheduler.dao.model.DefinitionGroupByUser;
import cn.escheduler.dao.model.ExecuteStatusCount;
import cn.escheduler.dao.model.Project;
import cn.escheduler.dao.model.User;
import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
@ -55,15 +57,21 @@ public class DataAnalysisService {
@Autowired
ProjectService projectService;
@Autowired
TaskInstanceMapper taskInstanceMapper;
@Autowired
ProcessInstanceMapper processInstanceMapper;
@Autowired
ProcessDefinitionMapper processDefinitionMapper;
@Autowired
CommandMapper commandMapper;
@Autowired
ErrorCommandMapper errorCommandMapper;
@Autowired
TaskInstanceMapper taskInstanceMapper;
/**
* statistical task instance status data
*
@ -206,4 +214,157 @@ public class DataAnalysisService {
}
return false;
}
/**
* statistical command status data
*
* @param loginUser
* @param projectId
* @param startDate
* @param endDate
* @return
*/
public Map<String, Object> countCommandState(User loginUser, int projectId, String startDate, String endDate) {
Map<String, Object> result = new HashMap<>(5);
if(projectId != 0){
Project project = projectMapper.queryById(projectId);
result = projectService.checkProjectAndAuth(loginUser, project, String.valueOf(projectId));
if (getResultStatus(result)){
return result;
}
}
/**
* find all the task lists in the project under the user
* statistics based on task status execution, failure, completion, wait, total
*/
Date start = null;
Date end = null;
try {
start = DateUtils.getScheduleDate(startDate);
end = DateUtils.getScheduleDate(endDate);
} catch (Exception e) {
logger.error(e.getMessage(),e);
putErrorRequestParamsMsg(result);
return result;
}
// count command state
List<ExecuteStatusCount> commandStateCounts =
commandMapper.countCommandState(loginUser.getId(),
loginUser.getUserType(), start, end, projectId);
// count error command state
List<ExecuteStatusCount> errorCommandStateCounts =
errorCommandMapper.countCommandState(loginUser.getId(),
loginUser.getUserType(), start, end, projectId);
//
Map<ExecutionStatus,Map<String,Integer>> dataMap = new HashMap<>();
Map<String,Integer> commonCommand = new HashMap<>();
commonCommand.put("commandState",0);
commonCommand.put("errorCommandState",0);
// init data map
dataMap.put(ExecutionStatus.SUBMITTED_SUCCESS,commonCommand);
dataMap.put(ExecutionStatus.RUNNING_EXEUTION,commonCommand);
dataMap.put(ExecutionStatus.READY_PAUSE,commonCommand);
dataMap.put(ExecutionStatus.PAUSE,commonCommand);
dataMap.put(ExecutionStatus.READY_STOP,commonCommand);
dataMap.put(ExecutionStatus.STOP,commonCommand);
dataMap.put(ExecutionStatus.FAILURE,commonCommand);
dataMap.put(ExecutionStatus.SUCCESS,commonCommand);
dataMap.put(ExecutionStatus.NEED_FAULT_TOLERANCE,commonCommand);
dataMap.put(ExecutionStatus.KILL,commonCommand);
dataMap.put(ExecutionStatus.WAITTING_THREAD,commonCommand);
dataMap.put(ExecutionStatus.WAITTING_DEPEND,commonCommand);
// put command state
for (ExecuteStatusCount executeStatusCount : commandStateCounts){
Map<String,Integer> commandStateCountsMap = new HashMap<>(dataMap.get(executeStatusCount.getExecutionStatus()));
commandStateCountsMap.put("commandState", executeStatusCount.getCount());
dataMap.put(executeStatusCount.getExecutionStatus(),commandStateCountsMap);
}
// put error command state
for (ExecuteStatusCount errorExecutionStatus : errorCommandStateCounts){
Map<String,Integer> errorCommandStateCountsMap = new HashMap<>(dataMap.get(errorExecutionStatus.getExecutionStatus()));
errorCommandStateCountsMap.put("errorCommandState",errorExecutionStatus.getCount());
dataMap.put(errorExecutionStatus.getExecutionStatus(),errorCommandStateCountsMap);
}
result.put(Constants.DATA_LIST, dataMap);
putMsg(result, Status.SUCCESS);
return result;
}
/**
* count queue state
* @param loginUser
* @param projectId
* @return
*/
public Map<String, Object> countQueueState(User loginUser, int projectId) {
Map<String, Object> result = new HashMap<>(5);
if(projectId != 0){
Project project = projectMapper.queryById(projectId);
result = projectService.checkProjectAndAuth(loginUser, project, String.valueOf(projectId));
if (getResultStatus(result)){
return result;
}
}
ITaskQueue tasksQueue = TaskQueueFactory.getTaskQueueInstance();
List<String> tasksQueueList = tasksQueue.getAllTasks(cn.escheduler.common.Constants.SCHEDULER_TASKS_QUEUE);
List<String> tasksKillList = tasksQueue.getAllTasks(cn.escheduler.common.Constants.SCHEDULER_TASKS_KILL);
Map<String,Integer> dataMap = new HashMap<>();
if (loginUser.getUserType() == UserType.ADMIN_USER){
dataMap.put("taskQueue",tasksQueueList.size());
dataMap.put("taskKill",tasksKillList.size());
result.put(Constants.DATA_LIST, dataMap);
putMsg(result, Status.SUCCESS);
return result;
}
int[] tasksQueueIds = new int[tasksQueueList.size()];
int[] tasksKillIds = new int[tasksKillList.size()];
int i =0;
for (String taskQueueStr : tasksQueueList){
if (StringUtils.isNotEmpty(taskQueueStr)){
String[] splits = taskQueueStr.split("_");
if (splits.length == 4){
tasksQueueIds[i++]=Integer.parseInt(splits[3]);
}
}
}
i = 0;
for (String taskKillStr : tasksKillList){
if (StringUtils.isNotEmpty(taskKillStr)){
String[] splits = taskKillStr.split("_");
if (splits.length == 2){
tasksKillIds[i++]=Integer.parseInt(splits[1]);
}
}
}
Integer taskQueueCount = taskInstanceMapper.countTask(loginUser.getId(),loginUser.getUserType(),projectId, tasksQueueIds);
Integer taskKillCount = taskInstanceMapper.countTask(loginUser.getId(),loginUser.getUserType(),projectId, tasksQueueIds);
dataMap.put("taskQueue",taskQueueCount);
dataMap.put("taskKill",taskKillCount);
result.put(Constants.DATA_LIST, dataMap);
putMsg(result, Status.SUCCESS);
return result;
}
}

7
escheduler-api/src/main/java/cn/escheduler/api/service/ProcessInstanceService.java

@ -509,7 +509,7 @@ public class ProcessInstanceService extends BaseDAGService {
}
// local params
Map<String, List<Property>> localUserDefParams = new HashMap<>();
Map<String, Map<String,Object>> localUserDefParams = new HashMap<>();
for (TaskNode taskNode : taskNodeList) {
String parameter = taskNode.getParams();
Map<String, String> map = JSONUtils.toMap(parameter);
@ -517,8 +517,11 @@ public class ProcessInstanceService extends BaseDAGService {
if (localParams != null && !localParams.isEmpty()) {
localParams = ParameterUtils.convertParameterPlaceholders(localParams, timeParams);
List<Property> localParamsList = JSON.parseArray(localParams, Property.class);
Map<String,Object> localParamsMap = new HashMap<>();
localParamsMap.put("taskType",taskNode.getType());
localParamsMap.put("localParamsList",localParamsList);
if (localParamsList.size() > 0) {
localUserDefParams.put(taskNode.getName(), localParamsList);
localUserDefParams.put(taskNode.getName(), localParamsMap);
}
}

2
escheduler-dao/src/main/java/cn/escheduler/dao/mapper/AccessTokenMapperProvider.java

@ -80,7 +80,7 @@ public class AccessTokenMapperProvider {
SET("`expire_time`=#{accessToken.expireTime}");
SET("`update_time`=#{accessToken.updateTime}");
WHERE("`id`=#{user.id}");
WHERE("`id`=#{accessToken.id}");
}
}.toString();
}

16
escheduler-dao/src/main/java/cn/escheduler/dao/mapper/CommandMapper.java

@ -18,12 +18,15 @@ package cn.escheduler.dao.mapper;
import cn.escheduler.common.enums.*;
import cn.escheduler.dao.model.Command;
import cn.escheduler.dao.model.ExecuteStatusCount;
import org.apache.ibatis.annotations.*;
import org.apache.ibatis.type.EnumOrdinalTypeHandler;
import org.apache.ibatis.type.JdbcType;
import java.sql.Timestamp;
import java.util.Date;
import java.util.List;
import java.util.Map;
/**
* command mapper
@ -103,4 +106,17 @@ public interface CommandMapper {
@SelectProvider(type = CommandMapperProvider.class, method = "queryAllCommand")
List<Command> queryAllCommand();
@Results(value = {
@Result(property = "state", column = "state", typeHandler = EnumOrdinalTypeHandler.class, javaType = ExecutionStatus.class, jdbcType = JdbcType.TINYINT),
@Result(property = "count", column = "count", javaType = Integer.class, jdbcType = JdbcType.INTEGER),
})
@SelectProvider(type = CommandMapperProvider.class, method = "countCommandState")
List<ExecuteStatusCount> countCommandState(
@Param("userId") int userId,
@Param("userType") UserType userType,
@Param("startTime") Date startTime,
@Param("endTime") Date endTime,
@Param("projectId") int projectId);
}

29
escheduler-dao/src/main/java/cn/escheduler/dao/mapper/CommandMapperProvider.java

@ -139,6 +139,35 @@ public class CommandMapperProvider {
}.toString();
}
/**
*
* count command type
* @param parameter
* @return
*/
public String countCommandState(Map<String, Object> parameter){
return new SQL(){
{
SELECT ("command_type as state,COUNT(*) AS count");
FROM(TABLE_NAME + " cmd,t_escheduler_process_definition process");
WHERE("cmd.process_definition_id = process.id");
if(parameter.get("projectId") != null && (int)parameter.get("projectId") != 0){
WHERE( "process.project_id = #{projectId} ");
}else{
if(parameter.get("userType") != null && String.valueOf(parameter.get("userType")) == "GENERAL_USER") {
AND();
WHERE("process.project_id in (select id as project_id from t_escheduler_project tp where tp.user_id= #{userId} " +
"union select project_id from t_escheduler_relation_project_user tr where tr.user_id= #{userId} )");
}
}
WHERE("cmd.start_time >= #{startTime} and cmd.update_time <= #{endTime}");
GROUP_BY("cmd.command_type");
}
}.toString();
}
}

14
escheduler-dao/src/main/java/cn/escheduler/dao/mapper/ErrorCommandMapper.java

@ -19,11 +19,13 @@ package cn.escheduler.dao.mapper;
import cn.escheduler.common.enums.*;
import cn.escheduler.dao.model.Command;
import cn.escheduler.dao.model.ErrorCommand;
import cn.escheduler.dao.model.ExecuteStatusCount;
import org.apache.ibatis.annotations.*;
import org.apache.ibatis.type.EnumOrdinalTypeHandler;
import org.apache.ibatis.type.JdbcType;
import java.sql.Timestamp;
import java.util.Date;
import java.util.List;
/**
@ -41,5 +43,17 @@ public interface ErrorCommandMapper {
@SelectKey(statement = "SELECT LAST_INSERT_ID()", keyProperty = "errorCommand.id", before = false, resultType = int.class)
int insert(@Param("errorCommand") ErrorCommand errorCommand);
@Results(value = {
@Result(property = "state", column = "state", typeHandler = EnumOrdinalTypeHandler.class, javaType = ExecutionStatus.class, jdbcType = JdbcType.TINYINT),
@Result(property = "count", column = "count", javaType = Integer.class, jdbcType = JdbcType.INTEGER),
})
@SelectProvider(type = ErrorCommandMapperProvider.class, method = "countCommandState")
List<ExecuteStatusCount> countCommandState(
@Param("userId") int userId,
@Param("userType") UserType userType,
@Param("startTime") Date startTime,
@Param("endTime") Date endTime,
@Param("projectId") int projectId);
}

28
escheduler-dao/src/main/java/cn/escheduler/dao/mapper/ErrorCommandMapperProvider.java

@ -38,4 +38,32 @@ public class ErrorCommandMapperProvider {
}
}.toString();
}
/**
*
* count command type
* @param parameter
* @return
*/
public String countCommandState(Map<String, Object> parameter){
return new SQL(){
{
SELECT("command_type as state,COUNT(*) AS count");
FROM(TABLE_NAME + " cmd,t_escheduler_process_definition process");
WHERE("cmd.process_definition_id = process.id");
if(parameter.get("projectId") != null && (int)parameter.get("projectId") != 0){
WHERE( "process.project_id = #{projectId} ");
}else{
if(parameter.get("userType") != null && String.valueOf(parameter.get("userType")) == "GENERAL_USER") {
AND();
WHERE("process.project_id in (select id as project_id from t_escheduler_project tp where tp.user_id= #{userId} " +
"union select project_id from t_escheduler_relation_project_user tr where tr.user_id= #{userId} )");
}
}
WHERE("cmd.start_time >= #{startTime} and cmd.update_time <= #{endTime}");
GROUP_BY("cmd.command_type");
}
}.toString();
}
}

14
escheduler-dao/src/main/java/cn/escheduler/dao/mapper/TaskInstanceMapper.java

@ -304,4 +304,18 @@ public interface TaskInstanceMapper {
@SelectProvider(type = TaskInstanceMapperProvider.class, method = "queryByInstanceIdAndName")
TaskInstance queryByInstanceIdAndName(@Param("processInstanceId") int processInstanceId,
@Param("name") String name);
/**
* count task
* @param userId
* @param userType
* @param projectId
* @return
*/
@SelectProvider(type = TaskInstanceMapperProvider.class, method = "countTask")
Integer countTask(@Param("userId") int userId,
@Param("userType") UserType userType,
@Param("projectId") int projectId,
@Param("taskIds") int[] taskIds);
}

40
escheduler-dao/src/main/java/cn/escheduler/dao/mapper/TaskInstanceMapperProvider.java

@ -185,7 +185,7 @@ public class TaskInstanceMapperProvider {
{
SELECT ("state, count(0) as count");
FROM(TABLE_NAME + " t");
LEFT_OUTER_JOIN(DEFINE_TABLE_NAME+ " d on d.id=t.process_definition_id");
LEFT_OUTER_JOIN(DEFINE_TABLE_NAME + " d on d.id=t.process_definition_id");
LEFT_OUTER_JOIN("t_escheduler_project p on p.id=d.project_id");
if(parameter.get("projectId") != null && (int)parameter.get("projectId") != 0){
WHERE( "p.id = #{projectId} ");
@ -404,4 +404,42 @@ public class TaskInstanceMapperProvider {
}
/**
*
* count task
* @param parameter
* @return
*/
public String countTask(Map<String, Object> parameter){
StringBuffer taskIdsStr = new StringBuffer();
int[] stateArray = (int[]) parameter.get("taskIds");
for(int i=0;i<stateArray.length;i++){
taskIdsStr.append(stateArray[i]);
if(i<stateArray.length-1){
taskIdsStr.append(",");
}
}
return new SQL(){
{
SELECT("count(1) as count");
FROM(TABLE_NAME + " task,t_escheduler_process_definition process");
WHERE("task.process_definition_id=process.id");
if(parameter.get("projectId") != null && (int)parameter.get("projectId") != 0){
WHERE( "process.project_id = #{projectId} ");
}else{
if(parameter.get("userType") != null && String.valueOf(parameter.get("userType")) == "GENERAL_USER") {
AND();
WHERE("process.project_id in (select id as project_id from t_escheduler_project tp where tp.user_id= #{userId} " +
"union select project_id from t_escheduler_relation_project_user tr where tr.user_id= #{userId} )");
}
}
WHERE("task.id in (" + taskIdsStr.toString() + ")");
}
}.toString();
}
}

2
escheduler-dao/src/main/java/cn/escheduler/dao/mapper/UserMapperProvider.java

@ -276,7 +276,7 @@ public class UserMapperProvider {
{
SELECT("u.*");
FROM(TABLE_NAME + " u ,t_escheduler_access_token t");
WHERE(" u.id = t.user_id and token=#{token}");
WHERE(" u.id = t.user_id and token=#{token} and t.expire_time > NOW()");
}
}.toString();
}

8
escheduler-dao/src/main/java/cn/escheduler/dao/model/ExecuteStatusCount.java

@ -50,4 +50,12 @@ public class ExecuteStatusCount {
public void setCount(int count) {
this.count = count;
}
@Override
public String toString() {
return "ExecuteStatusCount{" +
"state=" + state +
", count=" + count +
'}';
}
}

2
escheduler-ui/.env

@ -1,6 +1,6 @@
# 后端接口地址
API_BASE = http://192.168.220.247:12345
API_BASE = http://192.168.220.154:12345
# 本地开发如需ip访问项目把"#"号去掉
#DEV_HOST = 192.168.xx.xx

2
escheduler-ui/src/js/conf/home/pages/dag/_source/dag.vue

@ -474,5 +474,5 @@
</script>
<style lang="scss" rel="stylesheet/scss">
@import "dag";
@import "./dag";
</style>

2
escheduler-ui/src/js/conf/home/pages/dag/_source/formModel/_source/selectInput.vue

@ -33,7 +33,7 @@
import disabledState from '@/module/mixin/disabledState'
export default {
name: 'select-input',
name: 'form-select-input',
data () {
return {
isIconState: false,

2
escheduler-ui/src/js/conf/home/pages/dag/_source/formModel/_source/timeoutAlarm.vue

@ -46,7 +46,7 @@
import disabledState from '@/module/mixin/disabledState'
export default {
name: 'timeout-alarm',
name: 'form-timeout-alarm',
data () {
return {
// Timeout display hiding

55
escheduler-ui/src/js/conf/home/pages/dag/_source/formModel/_source/workerGroups.vue

@ -0,0 +1,55 @@
<template>
<x-select
@on-change="_onChange"
v-model="value"
style="width: 180px">
<x-option
v-for="item in workerGroupsList"
:key="item.id"
:value="item.id"
:label="item.name">
</x-option>
</x-select>
</template>
<script>
import disabledState from '@/module/mixin/disabledState'
export default {
name: 'form-worker-group',
data () {
return {
workerGroupsList: []
}
},
mixins: [disabledState],
props: {
value: {
type: Number,
default: -1
}
},
model: {
prop: 'value',
event: 'workerGroupsEvent'
},
methods: {
_onChange (o) {
this.value = o.value
this.$emit('workerGroupsEvent', o.value)
}
},
watch: {
},
created () {
let stateWorkerGroupsList = this.store.state.security.workerGroupsListAll || []
if (stateWorkerGroupsList.length) {
this.workerGroupsList = stateWorkerGroupsList
} else {
this.store.dispatch('security/getWorkerGroupsAll').then(res => {
this.$nextTick(() => {
this.workerGroupsList = res
})
})
}
}
}
</script>

109
escheduler-ui/src/js/conf/home/pages/dag/_source/formModel/formModel.scss

@ -0,0 +1,109 @@
.form-model-model {
width: 720px;
position: relative;
.title-box {
height: 61px;
border-bottom: 1px solid #DCDEDC;
position: relative;
.name {
position: absolute;
left: 24px;
top: 18px;
font-size: 16px;
}
.go-subtask {
position: absolute;
right: 30px;
top: 17px;
a {
font-size: 14px;
color: #0097e0;
margin-left: 10px;
i.iconfont {
font-size: 18px;
vertical-align: middle;
}
em {
color: #333;
vertical-align: middle;
font-style: normal;
vertical-align: middle;
padding-left: 2px;
}
&:hover {
em {
text-decoration: underline;
}
}
}
}
}
.bottom-box {
position: absolute;
bottom: 0;
left: 0;
width: 100%;
text-align: right;
height: 60px;
line-height: 60px;
border-top: 1px solid #DCDEDC;
background: #fff;
.submit {
padding-right: 20px;
position: relative;
z-index: 9;
}
}
.content-box {
overflow-y: scroll;
height: calc(100vh - 61px);
padding-bottom: 60px;
}
}
.from-model {
padding-top: 26px;
>div {
clear: both;
}
.list {
position: relative;
margin-bottom: 10px;
.text-box {
width: 112px;
float: left;
text-align: right;
margin-right: 8px;
>span {
font-size: 14px;
color: #777;
display: inline-block;
padding-top: 6px;
}
}
.cont-box {
width: 580px;
float: left;
.label-box {
width: 100%;
}
.text-b {
font-size: 14px;
color: #777;
display: inline-block;
padding:0 6px 0 20px;
}
}
.add {
line-height: 32px;
a {
color: #0097e0;
}
}
&:hover {
}
.list-t {
width: 50%;
float: left;
}
}
}

134
escheduler-ui/src/js/conf/home/pages/dag/_source/formModel/formModel.vue

@ -13,7 +13,6 @@
</div>
<div class="content-box" v-if="isContentBox">
<div class="from-model">
<!-- Node name -->
<div class="clearfix list">
<div class="text-box"><span>{{$t('Node name')}}</span></div>
@ -51,7 +50,6 @@
<span>{{$t('Description')}}</span>
</div>
<div class="cont-box">
<label class="label-box">
<x-input
resize
@ -72,9 +70,11 @@
<span>{{$t('Task priority')}}</span>
</div>
<div class="cont-box">
<label class="label-box">
<m-priority v-model="taskInstancePriority" style="width: 180px;"></m-priority>
</label>
<span class="label-box" style="width: 193px;display: inline-block;">
<m-priority v-model="taskInstancePriority"></m-priority>
</span>
<span class="text-b">Worker分组</span>
<m-worker-groups v-model="workerGroupId"></m-worker-groups>
</div>
</div>
@ -178,15 +178,16 @@
import mShell from './tasks/shell'
import mSpark from './tasks/spark'
import mPython from './tasks/python'
import { isNameExDag, rtBantpl } from './../plugIn/util'
import JSP from './../plugIn/jsPlumbHandle'
import mProcedure from './tasks/procedure'
import mDependent from './tasks/dependent'
import mSubProcess from './tasks/sub_process'
import mSelectInput from './_source/selectInput'
import mTimeoutAlarm from './_source/timeoutAlarm'
import mWorkerGroups from './_source/workerGroups'
import clickoutside from '@/module/util/clickoutside'
import disabledState from '@/module/mixin/disabledState'
import { isNameExDag, rtBantpl } from './../plugIn/util'
import mPriority from '@/module/components/priority/priority'
export default {
@ -218,7 +219,9 @@
// Task timeout alarm
timeout: {},
// Task priority
taskInstancePriority: 'MEDIUM'
taskInstancePriority: 'MEDIUM',
// worker group id
workerGroupId: -1
}
},
/**
@ -349,7 +352,8 @@
maxRetryTimes: this.maxRetryTimes,
retryInterval: this.retryInterval,
timeout: this.timeout,
taskInstancePriority: this.taskInstancePriority
taskInstancePriority: this.taskInstancePriority,
workerGroupId: this.workerGroupId
},
fromThis: this
})
@ -420,6 +424,7 @@
this.desc = o.desc
this.maxRetryTimes = o.maxRetryTimes
this.retryInterval = o.retryInterval
this.workerGroupId = o.workerGroupId
}
}
this.isContentBox = true
@ -451,119 +456,12 @@
mDependent,
mSelectInput,
mTimeoutAlarm,
mPriority
mPriority,
mWorkerGroups
}
}
</script>
<style lang="scss" rel="stylesheet/scss">
.form-model-model {
width: 720px;
position: relative;
.title-box {
height: 61px;
border-bottom: 1px solid #DCDEDC;
position: relative;
.name {
position: absolute;
left: 24px;
top: 18px;
font-size: 16px;
}
.go-subtask {
position: absolute;
right: 30px;
top: 17px;
a {
font-size: 14px;
color: #0097e0;
margin-left: 10px;
i.iconfont {
font-size: 18px;
vertical-align: middle;
}
em {
color: #333;
vertical-align: middle;
font-style: normal;
vertical-align: middle;
padding-left: 2px;
}
&:hover {
em {
text-decoration: underline;
}
}
}
}
}
.bottom-box {
position: absolute;
bottom: 0;
left: 0;
width: 100%;
text-align: right;
height: 60px;
line-height: 60px;
border-top: 1px solid #DCDEDC;
background: #fff;
.submit {
padding-right: 20px;
position: relative;
z-index: 9;
}
}
.content-box {
overflow-y: scroll;
height: calc(100vh - 61px);
padding-bottom: 60px;
}
}
.from-model {
padding-top: 26px;
>div {
clear: both;
}
.list {
position: relative;
margin-bottom: 10px;
.text-box {
width: 112px;
float: left;
text-align: right;
margin-right: 8px;
>span {
font-size: 14px;
color: #777;
display: inline-block;
padding-top: 6px;
}
}
.cont-box {
width: 580px;
float: left;
.label-box {
width: 100%;
}
.text-b {
font-size: 14px;
color: #777;
display: inline-block;
padding:0 6px 0 20px;
}
}
.add {
line-height: 32px;
a {
color: #0097e0;
}
}
&:hover {
}
.list-t {
width: 50%;
float: left;
}
}
}
@import "./formModel";
</style>

73
escheduler-ui/src/js/conf/home/pages/dag/_source/formModel/tasks/_source/localParams.vue

@ -11,32 +11,34 @@
:placeholder="$t('prop(required)')"
maxlength="64"
@on-blur="_verifProp()"
style="width: 164px;">
:style="inputStyle">
</x-input>
<x-select
style="width: 80px;"
@change="_handleDirectChanged"
v-model="localParamsList[$index].direct"
:disabled="isDetails || !hide">
<x-option
v-for="city in directList"
:key="city.code"
:value="city.code"
:label="city.code">
</x-option>
</x-select>
<x-select
style="width: 118px;"
@change="_handleTypeChanged"
v-model="localParamsList[$index].type"
:disabled="isDetails || !hide">
<x-option
v-for="city in typeList"
:key="city.code"
:value="city.code"
:label="city.code">
</x-option>
</x-select>
<template v-if="hide">
<x-select
style="width: 80px;"
@change="_handleDirectChanged"
v-model="localParamsList[$index].direct"
:disabled="isDetails">
<x-option
v-for="city in directList"
:key="city.code"
:value="city.code"
:label="city.code">
</x-option>
</x-select>
<x-select
style="width: 118px;"
@change="_handleTypeChanged"
v-model="localParamsList[$index].type"
:disabled="isDetails">
<x-option
v-for="city in typeList"
:key="city.code"
:value="city.code"
:label="city.code">
</x-option>
</x-select>
</template>
<x-input
:disabled="isDetails"
type="text"
@ -44,7 +46,7 @@
:placeholder="$t('value(optional)')"
maxlength="64"
@on-blur="_handleValue()"
style="width: 150px;position: relative;margin-bottom: -2px;">
:style="inputStyle">
</x-input>
<span class="lt-add">
<a href="javascript:" style="color:red;" @click="!isDetails && _removeUdp($index)" >
@ -57,7 +59,7 @@
</a>
</span>
</div>
<span class="add" v-if="!localParamsList.length">
<span class="add-dp" v-if="!localParamsList.length">
<a href="javascript:" @click="!isDetails && _addUdp()" >
<i class="iconfont" :class="_isDetails" data-toggle="tooltip" :title="$t('Add')">&#xe636;</i>
</a>
@ -173,6 +175,11 @@
created () {
this.localParamsList = this.udpList
},
computed: {
inputStyle () {
return `width:${this.hide ? 160 : 262}px`
}
},
mounted () {
},
components: { }
@ -197,6 +204,7 @@
}
.add {
a {
color: #000;
.iconfont {
font-size: 18px;
vertical-align: middle;
@ -205,5 +213,16 @@
}
}
}
.add-dp{
a {
color: #0097e0;
.iconfont {
font-size: 18px;
vertical-align: middle;
display: inline-block;
margin-top: 2px;
}
}
}
}
</style>

12
escheduler-ui/src/js/conf/home/pages/dag/_source/plugIn/jsPlumbHandle.js

@ -668,26 +668,21 @@ JSP.prototype.saveStore = function () {
/**
* Event processing
*/
JSP.prototype.handleEvent = function () {
this.JspInstance.bind('beforeDrop', function (info) {
let sourceId = info['sourceId']// 出
let targetId = info['targetId']// 入
/**
* Recursive search for nodes
*/
let recursiveVal
const recursiveTargetarr = (arr, targetId) => {
for (var i in arr) {
for (let i in arr) {
if (arr[i] === targetId) {
recursiveVal = targetId
} else {
let recTargetarrArr = rtTargetarrArr(arr[i])
if (recTargetarrArr.length) {
recursiveTargetarr(recTargetarrArr, targetId)
} else {
return recursiveTargetarr(targetId)
}
recursiveTargetarr(rtTargetarrArr(arr[i]), targetId)
}
}
return recursiveVal
@ -700,7 +695,6 @@ JSP.prototype.handleEvent = function () {
// Recursive form to find if the target Targetarr has a sourceId
if (recursiveTargetarr(rtTargetarrArr(sourceId), targetId)) {
// setRecursiveVal(null)
return false
}

4
escheduler-ui/src/js/conf/home/pages/dag/_source/plugIn/util.js

@ -24,8 +24,8 @@ import store from '@/conf/home/store'
* Node, to array
*/
const rtTargetarrArr = (id) => {
let a = $(`#${id}`).attr('data-targetarr')
return a ? a.split(',') : []
let ids = $(`#${id}`).attr('data-targetarr')
return ids ? ids.split(',') : []
}
/**

12
escheduler-ui/src/js/conf/home/pages/dag/_source/udp/udp.vue

@ -138,8 +138,8 @@
<style lang="scss" rel="stylesheet/scss">
.udp-model {
width: 616px;
min-height: 326px;
width: 624px;
min-height: 420px;
background: #fff;
border-radius: 3px;
padding:20px 0 ;
@ -182,6 +182,14 @@
}
.content {
padding-bottom: 50px;
.user-def-params-model {
.add {
a {
color: #0097e0;
}
}
}
}
}
</style>

42
escheduler-ui/src/js/conf/home/pages/dag/_source/variable/variablesView.vue

@ -1,9 +1,19 @@
<template>
<div class="variable-model">
<template v-if="list">
<div class="list">
<div class="name"><i class="fa fa-code"></i><b style="padding-top: 3px;display: inline-block">{{$t('Global parameters')}}</b></div>
<div class="var-cont">
<x-button size="xsmall" type="ghost" v-for="(item,$index) in list.globalParams" @click="_copy('gbudp-' + $index)" :data-clipboard-text="item.prop + ' = ' +item.value" :class="'gbudp-' + $index"><b style="color: #2A455B;">{{item.prop}}</b> = {{item.value}}</x-button>
<template v-for="(item,$index) in list.globalParams">
<x-button
size="xsmall"
type="ghost"
@click="_copy('gbudp-' + $index)"
:data-clipboard-text="item.prop + ' = ' +item.value"
:class="'gbudp-' + $index">
<b style="color: #2A455B;">{{item.prop}}</b> = {{item.value}}
</x-button>
</template>
</div>
</div>
<div class="list" style="height: 30px;">
@ -14,15 +24,25 @@
</div>
<div class="list list-t" v-for="(item,key,$index) in list.localParams">
<div class="task-name">Task({{$index}}){{key}}</div>
<div class="var-cont" v-if="item.length">
<template v-for="(el,index) in item">
<x-button size="xsmall" type="ghost" @click="_copy('copy-part-' + index)" :data-clipboard-text="_rtClipboard(el)" :class="'copy-part-' + index">
<span v-for="(e,k,i) in el"><b style="color: #2A455B;">{{k}}</b> = {{e}} </span>
<div class="var-cont" v-if="item.localParamsList.length">
<template v-for="(el,index) in item.localParamsList">
<x-button size="xsmall" type="ghost" @click="_copy('copy-part-' + index)" :data-clipboard-text="_rtClipboard(el,item.taskType)" :class="'copy-part-' + index">
<span v-for="(e,k,i) in el">
<template v-if="item.taskType === 'SQL' || item.taskType === 'PROCEDURE'">
<template v-if="(k !== 'direct' && k !== 'type')">
<b style="color: #2A455B;">{{k}}</b> = {{e}}
</template>
</template>
<template v-else>
<b style="color: #2A455B;">{{k}}</b> = {{e}}
</template>
</span>
</x-button>
</template>
</div>
</div>
</div>
</template>
</div>
</template>
<script>
import i18n from '@/module/i18n'
@ -71,10 +91,16 @@
/**
* Copyed text processing
*/
_rtClipboard (el) {
_rtClipboard (el, taskType) {
let arr = []
Object.keys(el).forEach((key) => {
arr.push(`${key}=${el[key]}`)
if (taskType === 'SQL' || taskType === 'PROCEDURE') {
if (key !== 'direct' && key !== 'type') {
arr.push(`${key}=${el[key]}`)
}
} else {
arr.push(`${key}=${el[key]}`)
}
})
return arr.join(' ')
}

5
escheduler-ui/src/js/conf/home/pages/dag/definitionDetails.vue

@ -26,6 +26,7 @@
methods: {
...mapMutations('dag', ['resetParams', 'setIsDetails']),
...mapActions('dag', ['getProcessList', 'getResourcesList', 'getProcessDetails']),
...mapActions('security', ['getWorkerGroupsAll']),
/**
* init
*/
@ -40,7 +41,9 @@
// get process definition
this.getProcessList(),
// get resource
this.getResourcesList()
this.getResourcesList(),
// get worker group list
this.getWorkerGroupsAll()
]).then((data) => {
let item = data[0]
this.setIsDetails(item.releaseState === 'ONLINE')

5
escheduler-ui/src/js/conf/home/pages/dag/index.vue

@ -25,6 +25,7 @@
methods: {
...mapMutations('dag', ['resetParams']),
...mapActions('dag', ['getProcessList', 'getResourcesList']),
...mapActions('security', ['getWorkerGroupsAll']),
/**
* init
*/
@ -37,7 +38,9 @@
// get process definition
this.getProcessList(),
// get resource
this.getResourcesList()
this.getResourcesList(),
// get worker group list
this.getWorkerGroupsAll()
]).then((data) => {
this.isLoading = false
// Whether to pop up the box?

5
escheduler-ui/src/js/conf/home/pages/dag/instanceDetails.vue

@ -26,6 +26,7 @@
methods: {
...mapMutations('dag', ['setIsDetails', 'resetParams']),
...mapActions('dag', ['getProcessList', 'getResourcesList', 'getInstancedetail']),
...mapActions('security', ['getWorkerGroupsAll']),
/**
* init
*/
@ -40,7 +41,9 @@
// get process definition
this.getProcessList(),
// get resources
this.getResourcesList()
this.getResourcesList(),
// get worker group list
this.getWorkerGroupsAll()
]).then((data) => {
let item = data[0]
let flag = false

40
escheduler-ui/src/js/conf/home/pages/monitor/index.vue

@ -1,40 +1,14 @@
<template>
<div class="index-model">
index
<div class="main-layout-box">
<m-secondary-menu :type="'monitor'"></m-secondary-menu>
<router-view></router-view>
</div>
</template>
<script>
import mSecondaryMenu from '@/module/components/secondaryMenu/secondaryMenu'
export default {
name: 'monitor-index',
data () {
return {}
},
props: {},
methods: {},
watch: {},
beforeCreate () {
},
created () {
},
beforeMount () {
},
mounted () {
},
beforeUpdate () {
},
updated () {
},
beforeDestroy () {
},
destroyed () {
},
computed: {},
components: {}
}
</script>
<style lang="scss" rel="stylesheet/scss">
.index-model {
components: { mSecondaryMenu }
}
</style>
</script>

0
escheduler-ui/src/js/conf/home/pages/security/pages/servers/_source/list.vue → escheduler-ui/src/js/conf/home/pages/monitor/pages/servers/_source/list.vue

49
escheduler-ui/src/js/conf/home/pages/monitor/pages/servers/alert.vue

@ -0,0 +1,49 @@
<template>
<m-list-construction title="Alert服务">
<template slot="content">
<template v-if="masterList.length">
<m-list :list="masterList"></m-list>
</template>
<template v-if="!masterList.length">
<m-no-data></m-no-data>
</template>
<m-spin :is-spin="isLoading" ></m-spin>
</template>
</m-list-construction>
</template>
<script>
import { mapActions } from 'vuex'
import mList from './_source/list'
import mSpin from '@/module/components/spin/spin'
import mNoData from '@/module/components/noData/noData'
import mListConstruction from '@/module/components/listConstruction/listConstruction'
export default {
name: 'servers-alert',
data () {
return {
pageSize: 10,
pageNo: 1,
totalPage: null,
searchVal: '',
isLoading: false,
masterList: []
}
},
props: {},
methods: {
...mapActions('security', ['getProcessMasterList'])
},
watch: {},
created () {
this.isLoading = true
this.getProcessMasterList().then(res => {
this.masterList = res.data
this.isLoading = false
})
},
mounted () {
},
components: { mList, mListConstruction, mSpin, mNoData }
}
</script>

40
escheduler-ui/src/js/conf/home/pages/monitor/pages/servers/apiserver.vue

@ -0,0 +1,40 @@
<template>
<div class="apiserver-model">
apiserver
</div>
</template>
<script>
export default {
name: 'apiserver',
data () {
return {}
},
props: {},
methods: {},
watch: {},
beforeCreate () {
},
created () {
},
beforeMount () {
},
mounted () {
},
beforeUpdate () {
},
updated () {
},
beforeDestroy () {
},
destroyed () {
},
computed: {},
components: {}
}
</script>
<style lang="scss" rel="stylesheet/scss">
.apiserver-model {
}
</style>

49
escheduler-ui/src/js/conf/home/pages/monitor/pages/servers/master.vue

@ -0,0 +1,49 @@
<template>
<m-list-construction :title="$t('Service-Master')">
<template slot="content">
<div class="servers-wrapper">
<div class="row">
<div class="col-md-4">.col-md-8</div>
<div class="col-md-4">.col-md-4</div>
<div class="col-md-4">.col-md-4</div>
</div>
</div>
</template>
</m-list-construction>
</template>
<script>
import { mapActions } from 'vuex'
import mList from './_source/list'
import mSpin from '@/module/components/spin/spin'
import mNoData from '@/module/components/noData/noData'
import mListConstruction from '@/module/components/listConstruction/listConstruction'
export default {
name: 'servers-master',
data () {
return {
pageSize: 10,
pageNo: 1,
totalPage: null,
searchVal: '',
isLoading: false,
masterList: []
}
},
props: {},
methods: {
...mapActions('security', ['getProcessMasterList'])
},
watch: {},
created () {
this.isLoading = true
this.getProcessMasterList().then(res => {
this.masterList = res.data
this.isLoading = false
})
},
mounted () {
},
components: { mList, mListConstruction, mSpin, mNoData }
}
</script>

40
escheduler-ui/src/js/conf/home/pages/monitor/pages/servers/mysql.vue

@ -0,0 +1,40 @@
<template>
<div class="mysql-model">
mysql
</div>
</template>
<script>
export default {
name: 'mysql',
data () {
return {}
},
props: {},
methods: {},
watch: {},
beforeCreate () {
},
created () {
},
beforeMount () {
},
mounted () {
},
beforeUpdate () {
},
updated () {
},
beforeDestroy () {
},
destroyed () {
},
computed: {},
components: {}
}
</script>
<style lang="scss" rel="stylesheet/scss">
.mysql-model {
}
</style>

40
escheduler-ui/src/js/conf/home/pages/monitor/pages/servers/rpcserver.vue

@ -0,0 +1,40 @@
<template>
<div class="rpcserver-model">
rpcserver
</div>
</template>
<script>
export default {
name: 'rpcserver',
data () {
return {}
},
props: {},
methods: {},
watch: {},
beforeCreate () {
},
created () {
},
beforeMount () {
},
mounted () {
},
beforeUpdate () {
},
updated () {
},
beforeDestroy () {
},
destroyed () {
},
computed: {},
components: {}
}
</script>
<style lang="scss" rel="stylesheet/scss">
.rpcserver-model {
}
</style>

2
escheduler-ui/src/js/conf/home/pages/security/pages/servers/pages/worker/index.vue → escheduler-ui/src/js/conf/home/pages/monitor/pages/servers/worker.vue

@ -13,7 +13,7 @@
</template>
<script>
import { mapActions } from 'vuex'
import mList from '../../_source/list'
import mList from './_source/list'
import mSpin from '@/module/components/spin/spin'
import mNoData from '@/module/components/noData/noData'
import mListConstruction from '@/module/components/listConstruction/listConstruction'

4
escheduler-ui/src/js/conf/home/pages/security/pages/servers/pages/master/index.vue → escheduler-ui/src/js/conf/home/pages/monitor/pages/servers/zookeeper.vue

@ -13,13 +13,13 @@
</template>
<script>
import { mapActions } from 'vuex'
import mList from '../../_source/list'
import mList from './_source/list'
import mSpin from '@/module/components/spin/spin'
import mNoData from '@/module/components/noData/noData'
import mListConstruction from '@/module/components/listConstruction/listConstruction'
export default {
name: 'servers-master',
name: 'servers-zookeeper',
data () {
return {
pageSize: 10,

21
escheduler-ui/src/js/conf/home/pages/projects/pages/definition/pages/list/_source/start.vue

@ -14,11 +14,11 @@
</x-radio-group>
</div>
</div>
<div class="clearfix list" v-if="sourceType === 'contextmenu'">
<div class="clearfix list" v-if="sourceType === 'contextmenu'" style="margin-top: -8px;">
<div class="text">
{{$t('Node execution')}}
</div>
<div class="cont">
<div class="cont" style="padding-top: 6px;">
<x-radio-group v-model="taskDependType">
<x-radio :label="'TASK_POST'">{{$t('Backward execution')}}</x-radio>
<x-radio :label="'TASK_PRE'">{{$t('Forward execution')}}</x-radio>
@ -49,6 +49,14 @@
<m-priority v-model="processInstancePriority"></m-priority>
</div>
</div>
<div class="clearfix list">
<div class="text">
Worker分组
</div>
<div class="cont">
<m-worker-groups v-model="workerGroupId"></m-worker-groups>
</div>
</div>
<div class="clearfix list">
<div class="text">
{{$t('Notification group')}}
@ -140,6 +148,7 @@
import store from '@/conf/home/store'
import { warningTypeList } from './util'
import mPriority from '@/module/components/priority/priority'
import mWorkerGroups from '@/conf/home/pages/dag/_source/formModel/_source/workerGroups'
export default {
name: 'start-process',
@ -159,7 +168,8 @@
receivers: [],
receiversCc: [],
runMode: 'RUN_MODE_SERIAL',
processInstancePriority: 'MEDIUM'
processInstancePriority: 'MEDIUM',
workerGroupId: -1
}
},
props: {
@ -188,7 +198,8 @@
runMode: this.runMode,
processInstancePriority: this.processInstancePriority,
receivers: this.receivers.join(',') || '',
receiversCc: this.receiversCc.join(',') || ''
receiversCc: this.receiversCc.join(',') || '',
workerGroupId: this.workerGroupId
}
// Executed from the specified node
if (this.sourceType === 'contextmenu') {
@ -251,7 +262,7 @@
})
},
computed: {},
components: { mEmail, mPriority }
components: { mEmail, mPriority, mWorkerGroups }
}
</script>

18
escheduler-ui/src/js/conf/home/pages/projects/pages/definition/pages/list/_source/timing.vue

@ -79,6 +79,14 @@
<m-priority v-model="processInstancePriority"></m-priority>
</div>
</div>
<div class="clearfix list">
<div class="text">
Worker分组
</div>
<div class="cont">
<m-worker-groups v-model="workerGroupId"></m-worker-groups>
</div>
</div>
<div class="clearfix list">
<div class="text">
{{$t('Notification group')}}
@ -133,6 +141,7 @@
import { vCrontab } from '~/@vue/crontab/dist'
import { formatDate } from '@/module/filter/filter'
import mPriority from '@/module/components/priority/priority'
import mWorkerGroups from '@/conf/home/pages/dag/_source/formModel/_source/workerGroups'
export default {
name: 'timing-process',
@ -152,7 +161,8 @@
receivers: [],
receiversCc: [],
i18n: i18n.globalScope.LOCALE,
processInstancePriority: 'MEDIUM'
processInstancePriority: 'MEDIUM',
workerGroupId: -1
}
},
props: {
@ -190,7 +200,8 @@
processInstancePriority: this.processInstancePriority,
warningGroupId: _.isEmpty(this.warningGroupId) ? 0 : this.warningGroupId.id,
receivers: this.receivers.join(',') || '',
receiversCc: this.receiversCc.join(',') || ''
receiversCc: this.receiversCc.join(',') || '',
workerGroupId: this.workerGroupId
}
let msg = ''
@ -255,6 +266,7 @@
this.failureStrategy = item.failureStrategy
this.warningType = item.warningType
this.processInstancePriority = item.processInstancePriority
this.workerGroupId = item.workerGroupId || -1
this._getNotifyGroupList().then(() => {
this.$nextTick(() => {
let list = _.filter(this.notifyGroupList, v => v.id === item.warningGroupId)
@ -269,7 +281,7 @@
}).catch(() => this.warningGroupId = { id: 0 })
}
},
components: { vCrontab, mEmail, mPriority }
components: { vCrontab, mEmail, mPriority, mWorkerGroups }
}
</script>

8
escheduler-ui/src/js/conf/home/pages/security/pages/servers/index.vue

@ -1,8 +0,0 @@
<template>
<router-view></router-view>
</template>
<script>
export default {
name: 'servers-index'
}
</script>

118
escheduler-ui/src/js/conf/home/pages/security/pages/workerGroups/_source/createWorker.vue

@ -0,0 +1,118 @@
<template>
<m-popup
ref="popup"
:ok-text="item ? $t('Edit') : $t('Submit')"
:nameText="item ? '编辑Worker分组' : '创建Worker分组'"
@ok="_ok">
<template slot="content">
<div class="create-worker-model">
<m-list-box-f>
<template slot="name"><b>*</b>{{$t('Group Name')}}</template>
<template slot="content">
<x-input
type="input"
v-model="name"
:placeholder="$t('Please enter group name')">
</x-input>
</template>
</m-list-box-f>
<m-list-box-f>
<template slot="name">IP</template>
<template slot="content">
<x-input
:autosize="{ minRows: 4, maxRows: 6 }"
type="textarea"
v-model="ipList"
:placeholder="'请输入IP地址多个用逗号隔开'">
</x-input>
<div class="ipt-tip">
<span>注意多个IP地址已逗号分割</span>
</div>
</template>
</m-list-box-f>
</div>
</template>
</m-popup>
</template>
<script>
import i18n from '@/module/i18n'
import store from '@/conf/home/store'
import mPopup from '@/module/components/popup/popup'
import mListBoxF from '@/module/components/listBoxF/listBoxF'
export default {
name: 'create-warning',
data () {
return {
store,
id: 0,
name: '',
ipList: ''
}
},
props: {
item: Object
},
methods: {
_ok () {
if (this._verification()) {
// Verify username
this._submit()
}
},
_verification () {
// group name
if (!this.name) {
this.$message.warning(`${i18n.$t('Please enter group name')}`)
return false
}
if (!this.ipList) {
this.$message.warning(`IP地址不能为空`)
return false
}
return true
},
_submit () {
let param = {
id: this.id,
name: this.name,
ipList: this.ipList
}
if (this.item) {
param.id = this.item.id
}
this.$refs['popup'].spinnerLoading = true
this.store.dispatch(`security/saveWorkerGroups`, param).then(res => {
this.$emit('onUpdate')
this.$message.success(res.msg)
setTimeout(() => {
this.$refs['popup'].spinnerLoading = false
}, 800)
}).catch(e => {
this.$message.error(e.msg || '')
this.$refs['popup'].spinnerLoading = false
})
}
},
watch: {},
created () {
if (this.item) {
this.id = this.item.id
this.name = this.item.name
this.ipList = this.item.ipList
}
},
mounted () {
},
components: { mPopup, mListBoxF }
}
</script>
<style lang="scss" rel="stylesheet/scss">
.create-worker-model {
.ipt-tip {
color: #999;
padding-top: 4px;
display: block;
}
}
</style>

119
escheduler-ui/src/js/conf/home/pages/security/pages/workerGroups/_source/list.vue

@ -0,0 +1,119 @@
<template>
<div class="list-model">
<div class="table-box">
<table>
<tr>
<th>
<span>{{$t('#')}}</span>
</th>
<th>
<span>分组名称</span>
</th>
<th>
<span>IPList</span>
</th>
<th>
<span>{{$t('Create Time')}}</span>
</th>
<th>
<span>{{$t('Update Time')}}</span>
</th>
<th width="70">
<span>{{$t('Operation')}}</span>
</th>
</tr>
<tr v-for="(item, $index) in list" :key="$index">
<td>
<span>{{parseInt(pageNo === 1 ? ($index + 1) : (($index + 1) + (pageSize * (pageNo - 1))))}}</span>
</td>
<td>
<span>
<a href="javascript:" class="links">{{item.name}}</a>
</span>
</td>
<td>
<span>{{item.ipList}}</span>
</td>
<td>
<span>{{item.createTime | formatDate}}</span>
</td>
<td><span>{{item.updateTime | formatDate}}</span></td>
<td>
<x-button type="info" shape="circle" size="xsmall" data-toggle="tooltip" icon="iconfont icon-bianjixiugai" :title="$t('Edit')" @click="_edit(item)">
</x-button>
<x-poptip
:ref="'poptip-delete-' + $index"
placement="bottom-end"
width="90">
<p>{{$t('Delete?')}}</p>
<div style="text-align: right; margin: 0;padding-top: 4px;">
<x-button type="text" size="xsmall" shape="circle" @click="_closeDelete($index)">{{$t('Cancel')}}</x-button>
<x-button type="primary" size="xsmall" shape="circle" @click="_delete(item,$index)">{{$t('Confirm')}}</x-button>
</div>
<template slot="reference">
<x-button type="error" shape="circle" size="xsmall" data-toggle="tooltip" icon="iconfont icon-shanchu" :title="$t('delete')">
</x-button>
</template>
</x-poptip>
</td>
</tr>
</table>
</div>
</div>
</template>
<script>
// import _ from 'lodash'
// import i18n from '@/module/i18n'
import { mapActions } from 'vuex'
import '@/module/filter/formatDate'
import { findComponentDownward } from '@/module/util/'
export default {
name: 'user-list',
data () {
return {
list: []
}
},
props: {
workerGroupList: Array,
pageNo: Number,
pageSize: Number
},
methods: {
...mapActions('security', ['deleteWorkerGroups']),
_closeDelete (i) {
this.$refs[`poptip-delete-${i}`][0].doClose()
},
_delete (item, i) {
this.deleteWorkerGroups({
id: item.id
}).then(res => {
this.$refs[`poptip-delete-${i}`][0].doClose()
this.list.splice(i, 1)
this.$message.success(res.msg)
}).catch(e => {
this.$refs[`poptip-delete-${i}`][0].doClose()
this.$message.error(e.msg || '')
})
},
_edit (item) {
findComponentDownward(this.$root, 'worker-groups-index')._create(item)
}
},
watch: {
workerGroupList (a) {
this.list = []
setTimeout(() => {
this.list = a
})
}
},
created () {
this.list = this.workerGroupList
},
mounted () {
},
components: { }
}
</script>

114
escheduler-ui/src/js/conf/home/pages/security/pages/workerGroups/index.vue

@ -0,0 +1,114 @@
<template>
<m-list-construction :title="'worker分组管理'">
<template slot="conditions">
<m-conditions @on-conditions="_onConditions">
<template slot="button-group">
<x-button type="ghost" size="small" @click="_create('')">创建worker分组</x-button>
</template>
</m-conditions>
</template>
<template slot="content">
<template v-if="workerGroupList.length">
<m-list :worker-group-list="workerGroupList" :page-no="searchParams.pageNo" :page-size="searchParams.pageSize"></m-list>
<div class="page-box">
<x-page :current="parseInt(searchParams.pageNo)" :total="total" :page-size="searchParams.pageSize" show-elevator @on-change="_page"></x-page>
</div>
</template>
<template v-if="!workerGroupList.length">
<m-no-data></m-no-data>
</template>
<m-spin :is-spin="isLoading"></m-spin>
</template>
</m-list-construction>
</template>
<script>
import _ from 'lodash'
import { mapActions } from 'vuex'
import mList from './_source/list'
import mSpin from '@/module/components/spin/spin'
import mCreateWorker from './_source/createWorker'
import mNoData from '@/module/components/noData/noData'
import listUrlParamHandle from '@/module/mixin/listUrlParamHandle'
import mConditions from '@/module/components/conditions/conditions'
import mListConstruction from '@/module/components/listConstruction/listConstruction'
export default {
name: 'worker-groups-index',
data () {
return {
total: null,
isLoading: false,
workerGroupList: [],
searchParams: {
pageSize: 10,
pageNo: 1,
searchVal: ''
}
}
},
mixins: [listUrlParamHandle],
props: {},
methods: {
...mapActions('security', ['getWorkerGroups']),
/**
* Inquire
*/
_onConditions (o) {
this.searchParams = _.assign(this.searchParams, o)
this.searchParams.pageNo = 1
},
_page (val) {
this.searchParams.pageNo = val
},
_create (item) {
let self = this
let modal = this.$modal.dialog({
closable: false,
showMask: true,
escClose: true,
className: 'v-modal-custom',
transitionName: 'opacityp',
render (h) {
return h(mCreateWorker, {
on: {
onUpdate () {
self._debounceGET('false')
modal.remove()
},
close () {
modal.remove()
}
},
props: {
item: item
}
})
}
})
},
_getList (flag) {
this.isLoading = !flag
this.getWorkerGroups(this.searchParams).then(res => {
this.workerGroupList = []
this.workerGroupList = res.totalList
this.total = res.total
this.isLoading = false
}).catch(e => {
this.isLoading = false
})
}
},
watch: {
// router
'$route' (a) {
// url no params get instance list
this.searchParams.pageNo = _.isEmpty(a.query) ? 1 : a.query.pageNo
}
},
created () {
},
mounted () {
},
components: { mList, mListConstruction, mConditions, mSpin, mNoData }
}
</script>

2
escheduler-ui/src/js/conf/home/pages/user/pages/token/_source/list.vue

@ -24,7 +24,7 @@
<th>
<span>更新时间</span>
</th>
<th width="120">
<th width="70">
<span>{{$t('Operation')}}</span>
</th>
</tr>

100
escheduler-ui/src/js/conf/home/router/index.js

@ -319,33 +319,12 @@ const router = new Router({
}
},
{
path: '/security/servers',
name: 'servers-manage',
component: resolve => require(['../pages/security/pages/servers/index'], resolve),
path: '/security/worker-groups',
name: 'worker-groups-manage',
component: resolve => require(['../pages/security/pages/workerGroups/index'], resolve),
meta: {
title: `${i18n.$t('Servers manage')}`
},
redirect: {
name: 'servers-master'
},
children: [
{
path: '/security/servers/master',
name: 'servers-master',
component: resolve => require(['../pages/security/pages/servers/pages/master/index'], resolve),
meta: {
title: `${i18n.$t('Service-Master')}`
}
},
{
path: '/security/servers/worker',
name: 'servers-worker',
component: resolve => require(['../pages/security/pages/servers/pages/worker/index'], resolve),
meta: {
title: `${i18n.$t('Service-Worker')}`
}
}
]
title: `workerGroups`
}
}
]
},
@ -385,6 +364,75 @@ const router = new Router({
}
}
]
},
{
path: '/monitor',
name: 'monitor',
component: resolve => require(['../pages/monitor/index'], resolve),
meta: {
title: `monitor`
},
redirect: {
name: 'servers-master'
},
children: [
{
path: '/monitor/servers/master',
name: 'servers-master',
component: resolve => require(['../pages/monitor/pages/servers/master'], resolve),
meta: {
title: `${i18n.$t('Service-Master')}`
}
},
{
path: '/monitor/servers/worker',
name: 'servers-worker',
component: resolve => require(['../pages/monitor/pages/servers/worker'], resolve),
meta: {
title: `${i18n.$t('Service-Worker')}`
}
},
{
path: '/monitor/servers/alert',
name: 'servers-alert',
component: resolve => require(['../pages/monitor/pages/servers/alert'], resolve),
meta: {
title: `alert`
}
},
{
path: '/monitor/servers/rpcserver',
name: 'servers-rpcserver',
component: resolve => require(['../pages/monitor/pages/servers/rpcserver'], resolve),
meta: {
title: `rpcserver`
}
},
{
path: '/monitor/servers/zookeeper',
name: 'servers-zookeeper',
component: resolve => require(['../pages/monitor/pages/servers/zookeeper'], resolve),
meta: {
title: `zookeeper`
}
},
{
path: '/monitor/servers/apiserver',
name: 'servers-apiserver',
component: resolve => require(['../pages/monitor/pages/servers/apiserver'], resolve),
meta: {
title: `apiserver`
}
},
{
path: '/monitor/servers/mysql',
name: 'servers-mysql',
component: resolve => require(['../pages/monitor/pages/servers/mysql'], resolve),
meta: {
title: `mysql`
}
}
]
}
]
})

48
escheduler-ui/src/js/conf/home/store/security/actions.js

@ -413,5 +413,53 @@ export default {
reject(e)
})
})
},
/**
* get worker groups
*/
getWorkerGroups ({ state }, payload) {
return new Promise((resolve, reject) => {
io.get(`worker-group/list-paging`, payload, res => {
resolve(res.data)
}).catch(e => {
reject(e)
})
})
},
/**
* get worker groups all
*/
getWorkerGroupsAll ({ state }, payload) {
return new Promise((resolve, reject) => {
io.get(`worker-group/all-groups`, payload, res => {
let list = res.data
list.unshift({
id: -1,
name: 'All'
})
state.workerGroupsListAll = list
resolve(list)
}).catch(e => {
reject(e)
})
})
},
saveWorkerGroups ({ state }, payload) {
return new Promise((resolve, reject) => {
io.post(`worker-group/save`, payload, res => {
resolve(res)
}).catch(e => {
reject(e)
})
})
},
deleteWorkerGroups ({ state }, payload) {
return new Promise((resolve, reject) => {
io.get(`worker-group/delete-by-id`, payload, res => {
resolve(res)
}).catch(e => {
reject(e)
})
})
}
}

2
escheduler-ui/src/js/conf/home/store/security/state.js

@ -15,5 +15,5 @@
* limitations under the License.
*/
export default {
workerGroupsListAll: []
}

1
escheduler-ui/src/js/module/components/priority/priority.vue

@ -91,6 +91,7 @@
<style lang="scss" rel="stylesheet/scss">
.priority-model {
display: inline-block;
.ans-option-listp {
>span {
font-weight: normal;

103
escheduler-ui/src/js/module/components/secondaryMenu/_source/menu.js

@ -23,7 +23,7 @@ let menu = {
projects: [
{
name: `${i18n.$t('Project Home')}`,
id: 1,
id: 0,
path: 'projects-index',
isOpen: true,
disabled: true,
@ -32,7 +32,7 @@ let menu = {
},
{
name: `${i18n.$t('Process')}`,
id: 2,
id: 1,
path: '',
isOpen: true,
disabled: true,
@ -41,31 +41,31 @@ let menu = {
{
name: `${i18n.$t('Process definition')}`,
path: 'definition',
id: 1,
id: 0,
disabled: true
},
{
name: `${i18n.$t('Process Instance')}`,
path: 'instance',
id: 2,
id: 1,
disabled: true
},
{
name: `${i18n.$t('Task Instance')}`,
path: 'task-instance',
id: 3,
id: 2,
disabled: true
},
{
name: `${i18n.$t('Task record')}`,
path: 'task-record',
id: 4,
id: 3,
disabled: config.recordSwitch
},
{
name: `${i18n.$t('History task record')}`,
path: 'history-task-record',
id: 5,
id: 4,
disabled: config.recordSwitch
}
]
@ -75,7 +75,7 @@ let menu = {
security: [
{
name: `${i18n.$t('Tenant Manage')}`,
id: 1,
id: 0,
path: 'tenement-manage',
isOpen: true,
disabled: true,
@ -93,7 +93,7 @@ let menu = {
},
{
name: `${i18n.$t('Warning group manage')}`,
id: 1,
id: 2,
path: 'warning-groups-manage',
isOpen: true,
disabled: true,
@ -102,7 +102,7 @@ let menu = {
},
{
name: `${i18n.$t('Queue manage')}`,
id: 1,
id: 3,
path: 'queue-manage',
isOpen: true,
disabled: true,
@ -110,32 +110,19 @@ let menu = {
children: []
},
{
name: `${i18n.$t('Servers manage')}`,
id: 1,
path: '',
name: `worker分组管理`,
id: 4,
path: 'worker-groups-manage',
isOpen: true,
disabled: true,
icon: 'fa-server',
children: [
{
name: 'master',
path: 'servers-master',
id: 1,
disabled: true
},
{
name: 'worker',
path: 'servers-worker',
id: 2,
disabled: true
}
]
icon: 'fa-address-book',
children: []
}
],
resource: [
{
name: `${i18n.$t('File Manage')}`,
id: 1,
id: 0,
path: 'file',
isOpen: true,
icon: 'fa-files-o',
@ -153,13 +140,13 @@ let menu = {
{
name: `${i18n.$t('Resource manage')}`,
path: 'resource-udf-resource',
id: 1,
id: 0,
disabled: true
},
{
name: `${i18n.$t('Function manage')}`,
path: 'resource-udf-function',
id: 2,
id: 1,
disabled: true
}
]
@ -193,6 +180,60 @@ let menu = {
children: [],
disabled: !Permissions.getAuth()
}
],
monitor: [
{
name: `${i18n.$t('Servers manage')}`,
id: 0,
path: '',
isOpen: true,
disabled: true,
icon: 'fa-server',
children: [
{
name: 'Master',
path: 'servers-master',
id: 0,
disabled: true
},
{
name: 'Worker',
path: 'servers-worker',
id: 1,
disabled: true
},
// {
// name: 'Alert',
// path: 'servers-alert',
// id: 2,
// disabled: true
// },
// {
// name: 'RpcServer',
// path: 'servers-rpcserver',
// id: 3,
// disabled: true
// },
{
name: 'Zookeeper',
path: 'servers-zookeeper',
id: 4,
disabled: true
},
// {
// name: 'ApiServer',
// path: 'servers-apiserver',
// id: 5,
// disabled: true
// },
{
name: 'Mysql',
path: 'servers-mysql',
id: 6,
disabled: true
}
]
}
]
}

1
escheduler-ui/src/js/module/i18n/locale/zh_CN.js

@ -295,6 +295,7 @@ export default {
'Waiting for dependence': '等待依赖',
'Start': '运行',
'Copy': '复制节点',
'Delete': '删除',
'Please enter keyword': '请输入关键词',
'File Upload': '文件上传',
'Drag the file into the current upload window': '请将文件拖拽到当前上传窗口内',

1
escheduler-ui/src/js/module/permissions/index.js

@ -32,7 +32,6 @@ Permissions.prototype = {
this.isAuth = false
}
this.ps(res)
resolve()
})
})

Loading…
Cancel
Save