Browse Source

UI以及库中,新增字段 "失败重试次数"

xuxueli 6 years ago
parent
commit
6fd7c943f2

+ 95 - 95
xxl-job-admin/src/main/java/com/xxl/job/admin/controller/JobInfoController.java

@@ -1,95 +1,95 @@
-package com.xxl.job.admin.controller;
-
-import com.xxl.job.admin.core.model.XxlJobGroup;
-import com.xxl.job.admin.core.model.XxlJobInfo;
-import com.xxl.job.admin.core.route.ExecutorRouteStrategyEnum;
-import com.xxl.job.admin.dao.XxlJobGroupDao;
-import com.xxl.job.admin.service.XxlJobService;
-import com.xxl.job.core.biz.model.ReturnT;
-import com.xxl.job.core.enums.ExecutorBlockStrategyEnum;
-import com.xxl.job.core.glue.GlueTypeEnum;
-import org.springframework.stereotype.Controller;
-import org.springframework.ui.Model;
-import org.springframework.web.bind.annotation.RequestMapping;
-import org.springframework.web.bind.annotation.RequestParam;
-import org.springframework.web.bind.annotation.ResponseBody;
-
-import javax.annotation.Resource;
-import java.util.List;
-import java.util.Map;
-
-/**
- * index controller
- * @author xuxueli 2015-12-19 16:13:16
- */
-@Controller
-@RequestMapping("/jobinfo")
-public class JobInfoController {
-
-	@Resource
-	private XxlJobGroupDao xxlJobGroupDao;
-	@Resource
-	private XxlJobService xxlJobService;
-	
-	@RequestMapping
-	public String index(Model model, @RequestParam(required = false, defaultValue = "-1") int jobGroup) {
-
-		// 枚举-字典
-		model.addAttribute("ExecutorRouteStrategyEnum", ExecutorRouteStrategyEnum.values());	// 路由策略-列表
-		model.addAttribute("GlueTypeEnum", GlueTypeEnum.values());								// Glue类型-字典
-		model.addAttribute("ExecutorBlockStrategyEnum", ExecutorBlockStrategyEnum.values());	// 阻塞处理策略-字典
-
-		// 任务组
-		List<XxlJobGroup> jobGroupList =  xxlJobGroupDao.findAll();
-		model.addAttribute("JobGroupList", jobGroupList);
-		model.addAttribute("jobGroup", jobGroup);
-
-		return "jobinfo/jobinfo.index";
-	}
-	
-	@RequestMapping("/pageList")
-	@ResponseBody
-	public Map<String, Object> pageList(@RequestParam(required = false, defaultValue = "0") int start,  
-			@RequestParam(required = false, defaultValue = "10") int length,
-			int jobGroup, String jobDesc, String executorHandler, String filterTime) {
-		
-		return xxlJobService.pageList(start, length, jobGroup, jobDesc, executorHandler, filterTime);
-	}
-	
-	@RequestMapping("/add")
-	@ResponseBody
-	public ReturnT<String> add(XxlJobInfo jobInfo) {
-		return xxlJobService.add(jobInfo);
-	}
-	
-	@RequestMapping("/update")
-	@ResponseBody
-	public ReturnT<String> update(XxlJobInfo jobInfo) {
-		return xxlJobService.update(jobInfo);
-	}
-	
-	@RequestMapping("/remove")
-	@ResponseBody
-	public ReturnT<String> remove(int id) {
-		return xxlJobService.remove(id);
-	}
-	
-	@RequestMapping("/pause")
-	@ResponseBody
-	public ReturnT<String> pause(int id) {
-		return xxlJobService.pause(id);
-	}
-	
-	@RequestMapping("/resume")
-	@ResponseBody
-	public ReturnT<String> resume(int id) {
-		return xxlJobService.resume(id);
-	}
-	
-	@RequestMapping("/trigger")
-	@ResponseBody
-	public ReturnT<String> triggerJob(int id) {
-		return xxlJobService.triggerJob(id);
-	}
-	
-}
+package com.xxl.job.admin.controller;
+
+import com.xxl.job.admin.core.model.XxlJobGroup;
+import com.xxl.job.admin.core.model.XxlJobInfo;
+import com.xxl.job.admin.core.route.ExecutorRouteStrategyEnum;
+import com.xxl.job.admin.dao.XxlJobGroupDao;
+import com.xxl.job.admin.service.XxlJobService;
+import com.xxl.job.core.biz.model.ReturnT;
+import com.xxl.job.core.enums.ExecutorBlockStrategyEnum;
+import com.xxl.job.core.glue.GlueTypeEnum;
+import org.springframework.stereotype.Controller;
+import org.springframework.ui.Model;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestParam;
+import org.springframework.web.bind.annotation.ResponseBody;
+
+import javax.annotation.Resource;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * index controller
+ * @author xuxueli 2015-12-19 16:13:16
+ */
+@Controller
+@RequestMapping("/jobinfo")
+public class JobInfoController {
+
+	@Resource
+	private XxlJobGroupDao xxlJobGroupDao;
+	@Resource
+	private XxlJobService xxlJobService;
+	
+	@RequestMapping
+	public String index(Model model, @RequestParam(required = false, defaultValue = "-1") int jobGroup) {
+
+		// 枚举-字典
+		model.addAttribute("ExecutorRouteStrategyEnum", ExecutorRouteStrategyEnum.values());	// 路由策略-列表
+		model.addAttribute("GlueTypeEnum", GlueTypeEnum.values());								// Glue类型-字典
+		model.addAttribute("ExecutorBlockStrategyEnum", ExecutorBlockStrategyEnum.values());	// 阻塞处理策略-字典
+
+		// 任务组
+		List<XxlJobGroup> jobGroupList =  xxlJobGroupDao.findAll();
+		model.addAttribute("JobGroupList", jobGroupList);
+		model.addAttribute("jobGroup", jobGroup);
+
+		return "jobinfo/jobinfo.index";
+	}
+	
+	@RequestMapping("/pageList")
+	@ResponseBody
+	public Map<String, Object> pageList(@RequestParam(required = false, defaultValue = "0") int start,  
+			@RequestParam(required = false, defaultValue = "10") int length,
+			int jobGroup, String jobDesc, String executorHandler, String filterTime) {
+		
+		return xxlJobService.pageList(start, length, jobGroup, jobDesc, executorHandler, filterTime);
+	}
+	
+	@RequestMapping("/add")
+	@ResponseBody
+	public ReturnT<String> add(XxlJobInfo jobInfo) {
+		return xxlJobService.add(jobInfo);
+	}
+	
+	@RequestMapping("/update")
+	@ResponseBody
+	public ReturnT<String> update(XxlJobInfo jobInfo) {
+		return xxlJobService.update(jobInfo);
+	}
+	
+	@RequestMapping("/remove")
+	@ResponseBody
+	public ReturnT<String> remove(int id) {
+		return xxlJobService.remove(id);
+	}
+	
+	@RequestMapping("/pause")
+	@ResponseBody
+	public ReturnT<String> pause(int id) {
+		return xxlJobService.pause(id);
+	}
+	
+	@RequestMapping("/resume")
+	@ResponseBody
+	public ReturnT<String> resume(int id) {
+		return xxlJobService.resume(id);
+	}
+	
+	@RequestMapping("/trigger")
+	@ResponseBody
+	public ReturnT<String> triggerJob(int id) {
+		return xxlJobService.triggerJob(id);
+	}
+	
+}

+ 211 - 211
xxl-job-admin/src/main/java/com/xxl/job/admin/core/model/XxlJobInfo.java

@@ -1,211 +1,211 @@
-package com.xxl.job.admin.core.model;
-
-import java.util.Date;
-
-/**
- * xxl-job info
- *
- * @author xuxueli  2016-1-12 18:25:49
- */
-public class XxlJobInfo {
-	
-	private int id;				// 主键ID	    (JobKey.name)
-	
-	private int jobGroup;		// 执行器主键ID	(JobKey.group)
-	private String jobCron;		// 任务执行CRON表达式 【base on quartz】
-	private String jobDesc;
-	
-	private Date addTime;
-	private Date updateTime;
-	
-	private String author;		// 负责人
-	private String alarmEmail;	// 报警邮件
-
-	private String executorRouteStrategy;	// 执行器路由策略
-	private String executorHandler;		    // 执行器,任务Handler名称
-	private String executorParam;		    // 执行器,任务参数
-	private String executorBlockStrategy;	// 阻塞处理策略
-	private String executorFailStrategy;	// 失败处理策略
-	private int executorTimeout;     		// 任务执行超时时间,单位秒
-	private int executorFailRetryCount;		// 失败重试次数
-	
-	private String glueType;		// GLUE类型	#com.xxl.job.core.glue.GlueTypeEnum
-	private String glueSource;		// GLUE源代码
-	private String glueRemark;		// GLUE备注
-	private Date glueUpdatetime;	// GLUE更新时间
-
-	private String childJobId;		// 子任务ID,多个逗号分隔
-	
-	// copy from quartz
-	private String jobStatus;		// 任务状态 【base on quartz】
-
-
-	public int getId() {
-		return id;
-	}
-
-	public void setId(int id) {
-		this.id = id;
-	}
-
-	public int getJobGroup() {
-		return jobGroup;
-	}
-
-	public void setJobGroup(int jobGroup) {
-		this.jobGroup = jobGroup;
-	}
-
-	public String getJobCron() {
-		return jobCron;
-	}
-
-	public void setJobCron(String jobCron) {
-		this.jobCron = jobCron;
-	}
-
-	public String getJobDesc() {
-		return jobDesc;
-	}
-
-	public void setJobDesc(String jobDesc) {
-		this.jobDesc = jobDesc;
-	}
-
-	public Date getAddTime() {
-		return addTime;
-	}
-
-	public void setAddTime(Date addTime) {
-		this.addTime = addTime;
-	}
-
-	public Date getUpdateTime() {
-		return updateTime;
-	}
-
-	public void setUpdateTime(Date updateTime) {
-		this.updateTime = updateTime;
-	}
-
-	public String getAuthor() {
-		return author;
-	}
-
-	public void setAuthor(String author) {
-		this.author = author;
-	}
-
-	public String getAlarmEmail() {
-		return alarmEmail;
-	}
-
-	public void setAlarmEmail(String alarmEmail) {
-		this.alarmEmail = alarmEmail;
-	}
-
-	public String getExecutorRouteStrategy() {
-		return executorRouteStrategy;
-	}
-
-	public void setExecutorRouteStrategy(String executorRouteStrategy) {
-		this.executorRouteStrategy = executorRouteStrategy;
-	}
-
-	public String getExecutorHandler() {
-		return executorHandler;
-	}
-
-	public void setExecutorHandler(String executorHandler) {
-		this.executorHandler = executorHandler;
-	}
-
-	public String getExecutorParam() {
-		return executorParam;
-	}
-
-	public void setExecutorParam(String executorParam) {
-		this.executorParam = executorParam;
-	}
-
-	public String getExecutorBlockStrategy() {
-		return executorBlockStrategy;
-	}
-
-	public void setExecutorBlockStrategy(String executorBlockStrategy) {
-		this.executorBlockStrategy = executorBlockStrategy;
-	}
-
-	public String getExecutorFailStrategy() {
-		return executorFailStrategy;
-	}
-
-	public void setExecutorFailStrategy(String executorFailStrategy) {
-		this.executorFailStrategy = executorFailStrategy;
-	}
-
-	public int getExecutorTimeout() {
-		return executorTimeout;
-	}
-
-	public void setExecutorTimeout(int executorTimeout) {
-		this.executorTimeout = executorTimeout;
-	}
-
-	public int getExecutorFailRetryCount() {
-		return executorFailRetryCount;
-	}
-
-	public void setExecutorFailRetryCount(int executorFailRetryCount) {
-		this.executorFailRetryCount = executorFailRetryCount;
-	}
-
-	public String getGlueType() {
-		return glueType;
-	}
-
-	public void setGlueType(String glueType) {
-		this.glueType = glueType;
-	}
-
-	public String getGlueSource() {
-		return glueSource;
-	}
-
-	public void setGlueSource(String glueSource) {
-		this.glueSource = glueSource;
-	}
-
-	public String getGlueRemark() {
-		return glueRemark;
-	}
-
-	public void setGlueRemark(String glueRemark) {
-		this.glueRemark = glueRemark;
-	}
-
-	public Date getGlueUpdatetime() {
-		return glueUpdatetime;
-	}
-
-	public void setGlueUpdatetime(Date glueUpdatetime) {
-		this.glueUpdatetime = glueUpdatetime;
-	}
-
-	public String getChildJobId() {
-		return childJobId;
-	}
-
-	public void setChildJobId(String childJobId) {
-		this.childJobId = childJobId;
-	}
-
-	public String getJobStatus() {
-		return jobStatus;
-	}
-
-	public void setJobStatus(String jobStatus) {
-		this.jobStatus = jobStatus;
-	}
-
-}
+package com.xxl.job.admin.core.model;
+
+import java.util.Date;
+
+/**
+ * xxl-job info
+ *
+ * @author xuxueli  2016-1-12 18:25:49
+ */
+public class XxlJobInfo {
+	
+	private int id;				// 主键ID	    (JobKey.name)
+	
+	private int jobGroup;		// 执行器主键ID	(JobKey.group)
+	private String jobCron;		// 任务执行CRON表达式 【base on quartz】
+	private String jobDesc;
+	
+	private Date addTime;
+	private Date updateTime;
+	
+	private String author;		// 负责人
+	private String alarmEmail;	// 报警邮件
+
+	private String executorRouteStrategy;	// 执行器路由策略
+	private String executorHandler;		    // 执行器,任务Handler名称
+	private String executorParam;		    // 执行器,任务参数
+	private String executorBlockStrategy;	// 阻塞处理策略
+	private String executorFailStrategy;	// 失败处理策略
+	private int executorTimeout;     		// 任务执行超时时间,单位秒
+	private int executorFailRetryCount;		// 失败重试次数
+	
+	private String glueType;		// GLUE类型	#com.xxl.job.core.glue.GlueTypeEnum
+	private String glueSource;		// GLUE源代码
+	private String glueRemark;		// GLUE备注
+	private Date glueUpdatetime;	// GLUE更新时间
+
+	private String childJobId;		// 子任务ID,多个逗号分隔
+	
+	// copy from quartz
+	private String jobStatus;		// 任务状态 【base on quartz】
+
+
+	public int getId() {
+		return id;
+	}
+
+	public void setId(int id) {
+		this.id = id;
+	}
+
+	public int getJobGroup() {
+		return jobGroup;
+	}
+
+	public void setJobGroup(int jobGroup) {
+		this.jobGroup = jobGroup;
+	}
+
+	public String getJobCron() {
+		return jobCron;
+	}
+
+	public void setJobCron(String jobCron) {
+		this.jobCron = jobCron;
+	}
+
+	public String getJobDesc() {
+		return jobDesc;
+	}
+
+	public void setJobDesc(String jobDesc) {
+		this.jobDesc = jobDesc;
+	}
+
+	public Date getAddTime() {
+		return addTime;
+	}
+
+	public void setAddTime(Date addTime) {
+		this.addTime = addTime;
+	}
+
+	public Date getUpdateTime() {
+		return updateTime;
+	}
+
+	public void setUpdateTime(Date updateTime) {
+		this.updateTime = updateTime;
+	}
+
+	public String getAuthor() {
+		return author;
+	}
+
+	public void setAuthor(String author) {
+		this.author = author;
+	}
+
+	public String getAlarmEmail() {
+		return alarmEmail;
+	}
+
+	public void setAlarmEmail(String alarmEmail) {
+		this.alarmEmail = alarmEmail;
+	}
+
+	public String getExecutorRouteStrategy() {
+		return executorRouteStrategy;
+	}
+
+	public void setExecutorRouteStrategy(String executorRouteStrategy) {
+		this.executorRouteStrategy = executorRouteStrategy;
+	}
+
+	public String getExecutorHandler() {
+		return executorHandler;
+	}
+
+	public void setExecutorHandler(String executorHandler) {
+		this.executorHandler = executorHandler;
+	}
+
+	public String getExecutorParam() {
+		return executorParam;
+	}
+
+	public void setExecutorParam(String executorParam) {
+		this.executorParam = executorParam;
+	}
+
+	public String getExecutorBlockStrategy() {
+		return executorBlockStrategy;
+	}
+
+	public void setExecutorBlockStrategy(String executorBlockStrategy) {
+		this.executorBlockStrategy = executorBlockStrategy;
+	}
+
+	public String getExecutorFailStrategy() {
+		return executorFailStrategy;
+	}
+
+	public void setExecutorFailStrategy(String executorFailStrategy) {
+		this.executorFailStrategy = executorFailStrategy;
+	}
+
+	public int getExecutorTimeout() {
+		return executorTimeout;
+	}
+
+	public void setExecutorTimeout(int executorTimeout) {
+		this.executorTimeout = executorTimeout;
+	}
+
+	public int getExecutorFailRetryCount() {
+		return executorFailRetryCount;
+	}
+
+	public void setExecutorFailRetryCount(int executorFailRetryCount) {
+		this.executorFailRetryCount = executorFailRetryCount;
+	}
+
+	public String getGlueType() {
+		return glueType;
+	}
+
+	public void setGlueType(String glueType) {
+		this.glueType = glueType;
+	}
+
+	public String getGlueSource() {
+		return glueSource;
+	}
+
+	public void setGlueSource(String glueSource) {
+		this.glueSource = glueSource;
+	}
+
+	public String getGlueRemark() {
+		return glueRemark;
+	}
+
+	public void setGlueRemark(String glueRemark) {
+		this.glueRemark = glueRemark;
+	}
+
+	public Date getGlueUpdatetime() {
+		return glueUpdatetime;
+	}
+
+	public void setGlueUpdatetime(Date glueUpdatetime) {
+		this.glueUpdatetime = glueUpdatetime;
+	}
+
+	public String getChildJobId() {
+		return childJobId;
+	}
+
+	public void setChildJobId(String childJobId) {
+		this.childJobId = childJobId;
+	}
+
+	public String getJobStatus() {
+		return jobStatus;
+	}
+
+	public void setJobStatus(String jobStatus) {
+		this.jobStatus = jobStatus;
+	}
+
+}

+ 385 - 385
xxl-job-admin/src/main/java/com/xxl/job/admin/service/impl/XxlJobServiceImpl.java

@@ -1,385 +1,385 @@
-package com.xxl.job.admin.service.impl;
-
-import com.xxl.job.admin.core.model.XxlJobGroup;
-import com.xxl.job.admin.core.model.XxlJobInfo;
-import com.xxl.job.admin.core.route.ExecutorRouteStrategyEnum;
-import com.xxl.job.admin.core.schedule.XxlJobDynamicScheduler;
-import com.xxl.job.admin.core.thread.JobTriggerPoolHelper;
-import com.xxl.job.admin.core.util.I18nUtil;
-import com.xxl.job.admin.dao.XxlJobGroupDao;
-import com.xxl.job.admin.dao.XxlJobInfoDao;
-import com.xxl.job.admin.dao.XxlJobLogDao;
-import com.xxl.job.admin.dao.XxlJobLogGlueDao;
-import com.xxl.job.admin.service.XxlJobService;
-import com.xxl.job.core.biz.model.ReturnT;
-import com.xxl.job.core.enums.ExecutorBlockStrategyEnum;
-import com.xxl.job.core.glue.GlueTypeEnum;
-import org.apache.commons.collections4.CollectionUtils;
-import org.apache.commons.lang3.StringUtils;
-import org.apache.commons.lang3.time.DateUtils;
-import org.apache.commons.lang3.time.FastDateFormat;
-import org.quartz.CronExpression;
-import org.quartz.SchedulerException;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-import org.springframework.stereotype.Service;
-
-import javax.annotation.Resource;
-import java.text.MessageFormat;
-import java.util.*;
-
-/**
- * core job action for xxl-job
- * @author xuxueli 2016-5-28 15:30:33
- */
-@Service
-public class XxlJobServiceImpl implements XxlJobService {
-	private static Logger logger = LoggerFactory.getLogger(XxlJobServiceImpl.class);
-
-	@Resource
-	private XxlJobGroupDao xxlJobGroupDao;
-	@Resource
-	private XxlJobInfoDao xxlJobInfoDao;
-	@Resource
-	public XxlJobLogDao xxlJobLogDao;
-	@Resource
-	private XxlJobLogGlueDao xxlJobLogGlueDao;
-	
-	@Override
-	public Map<String, Object> pageList(int start, int length, int jobGroup, String jobDesc, String executorHandler, String filterTime) {
-
-		// page list
-		List<XxlJobInfo> list = xxlJobInfoDao.pageList(start, length, jobGroup, jobDesc, executorHandler);
-		int list_count = xxlJobInfoDao.pageListCount(start, length, jobGroup, jobDesc, executorHandler);
-		
-		// fill job info
-		if (list!=null && list.size()>0) {
-			for (XxlJobInfo jobInfo : list) {
-				XxlJobDynamicScheduler.fillJobInfo(jobInfo);
-			}
-		}
-		
-		// package result
-		Map<String, Object> maps = new HashMap<String, Object>();
-	    maps.put("recordsTotal", list_count);		// 总记录数
-	    maps.put("recordsFiltered", list_count);	// 过滤后的总记录数
-	    maps.put("data", list);  					// 分页列表
-		return maps;
-	}
-
-	@Override
-	public ReturnT<String> add(XxlJobInfo jobInfo) {
-		// valid
-		XxlJobGroup group = xxlJobGroupDao.load(jobInfo.getJobGroup());
-		if (group == null) {
-			return new ReturnT<String>(ReturnT.FAIL_CODE, (I18nUtil.getString("system_please_choose")+I18nUtil.getString("jobinfo_field_jobgroup")) );
-		}
-		if (!CronExpression.isValidExpression(jobInfo.getJobCron())) {
-			return new ReturnT<String>(ReturnT.FAIL_CODE, I18nUtil.getString("jobinfo_field_cron_unvalid") );
-		}
-		if (StringUtils.isBlank(jobInfo.getJobDesc())) {
-			return new ReturnT<String>(ReturnT.FAIL_CODE, (I18nUtil.getString("system_please_input")+I18nUtil.getString("jobinfo_field_jobdesc")) );
-		}
-		if (StringUtils.isBlank(jobInfo.getAuthor())) {
-			return new ReturnT<String>(ReturnT.FAIL_CODE, (I18nUtil.getString("system_please_input")+I18nUtil.getString("jobinfo_field_author")) );
-		}
-		if (ExecutorRouteStrategyEnum.match(jobInfo.getExecutorRouteStrategy(), null) == null) {
-			return new ReturnT<String>(ReturnT.FAIL_CODE, (I18nUtil.getString("jobinfo_field_executorRouteStrategy")+I18nUtil.getString("system_unvalid")) );
-		}
-		if (ExecutorBlockStrategyEnum.match(jobInfo.getExecutorBlockStrategy(), null) == null) {
-			return new ReturnT<String>(ReturnT.FAIL_CODE, (I18nUtil.getString("jobinfo_field_executorBlockStrategy")+I18nUtil.getString("system_unvalid")) );
-		}
-		if (GlueTypeEnum.match(jobInfo.getGlueType()) == null) {
-			return new ReturnT<String>(ReturnT.FAIL_CODE, (I18nUtil.getString("jobinfo_field_gluetype")+I18nUtil.getString("system_unvalid")) );
-		}
-		if (GlueTypeEnum.BEAN==GlueTypeEnum.match(jobInfo.getGlueType()) && StringUtils.isBlank(jobInfo.getExecutorHandler())) {
-			return new ReturnT<String>(ReturnT.FAIL_CODE, (I18nUtil.getString("system_please_input")+"JobHandler") );
-		}
-
-		// fix "\r" in shell
-		if (GlueTypeEnum.GLUE_SHELL==GlueTypeEnum.match(jobInfo.getGlueType()) && jobInfo.getGlueSource()!=null) {
-			jobInfo.setGlueSource(jobInfo.getGlueSource().replaceAll("\r", ""));
-		}
-
-		// ChildJobId valid
-		if (StringUtils.isNotBlank(jobInfo.getChildJobId())) {
-			String[] childJobIds = StringUtils.split(jobInfo.getChildJobId(), ",");
-			for (String childJobIdItem: childJobIds) {
-				if (StringUtils.isNotBlank(childJobIdItem) && StringUtils.isNumeric(childJobIdItem)) {
-					XxlJobInfo childJobInfo = xxlJobInfoDao.loadById(Integer.valueOf(childJobIdItem));
-					if (childJobInfo==null) {
-						return new ReturnT<String>(ReturnT.FAIL_CODE,
-								MessageFormat.format((I18nUtil.getString("jobinfo_field_childJobId")+"({0})"+I18nUtil.getString("system_not_found")), childJobIdItem));
-					}
-				} else {
-					return new ReturnT<String>(ReturnT.FAIL_CODE,
-							MessageFormat.format((I18nUtil.getString("jobinfo_field_childJobId")+"({0})"+I18nUtil.getString("system_unvalid")), childJobIdItem));
-				}
-			}
-			jobInfo.setChildJobId(StringUtils.join(childJobIds, ","));
-		}
-
-		// add in db
-		xxlJobInfoDao.save(jobInfo);
-		if (jobInfo.getId() < 1) {
-			return new ReturnT<String>(ReturnT.FAIL_CODE, (I18nUtil.getString("jobinfo_field_add")+I18nUtil.getString("system_fail")) );
-		}
-
-		// add in quartz
-        String qz_group = String.valueOf(jobInfo.getJobGroup());
-        String qz_name = String.valueOf(jobInfo.getId());
-        try {
-            XxlJobDynamicScheduler.addJob(qz_name, qz_group, jobInfo.getJobCron());
-            //XxlJobDynamicScheduler.pauseJob(qz_name, qz_group);
-            return ReturnT.SUCCESS;
-        } catch (SchedulerException e) {
-            logger.error(e.getMessage(), e);
-            try {
-                xxlJobInfoDao.delete(jobInfo.getId());
-                XxlJobDynamicScheduler.removeJob(qz_name, qz_group);
-            } catch (SchedulerException e1) {
-                logger.error(e.getMessage(), e1);
-            }
-            return new ReturnT<String>(ReturnT.FAIL_CODE, (I18nUtil.getString("jobinfo_field_add")+I18nUtil.getString("system_fail"))+":" + e.getMessage());
-        }
-	}
-
-	@Override
-	public ReturnT<String> update(XxlJobInfo jobInfo) {
-
-		// valid
-		if (!CronExpression.isValidExpression(jobInfo.getJobCron())) {
-			return new ReturnT<String>(ReturnT.FAIL_CODE, I18nUtil.getString("jobinfo_field_cron_unvalid") );
-		}
-		if (StringUtils.isBlank(jobInfo.getJobDesc())) {
-			return new ReturnT<String>(ReturnT.FAIL_CODE, (I18nUtil.getString("system_please_input")+I18nUtil.getString("jobinfo_field_jobdesc")) );
-		}
-		if (StringUtils.isBlank(jobInfo.getAuthor())) {
-			return new ReturnT<String>(ReturnT.FAIL_CODE, (I18nUtil.getString("system_please_input")+I18nUtil.getString("jobinfo_field_author")) );
-		}
-		if (ExecutorRouteStrategyEnum.match(jobInfo.getExecutorRouteStrategy(), null) == null) {
-			return new ReturnT<String>(ReturnT.FAIL_CODE, (I18nUtil.getString("jobinfo_field_executorRouteStrategy")+I18nUtil.getString("system_unvalid")) );
-		}
-		if (ExecutorBlockStrategyEnum.match(jobInfo.getExecutorBlockStrategy(), null) == null) {
-			return new ReturnT<String>(ReturnT.FAIL_CODE, (I18nUtil.getString("jobinfo_field_executorBlockStrategy")+I18nUtil.getString("system_unvalid")) );
-		}
-
-		// ChildJobId valid
-		if (StringUtils.isNotBlank(jobInfo.getChildJobId())) {
-			String[] childJobIds = StringUtils.split(jobInfo.getChildJobId(), ",");
-			for (String childJobIdItem: childJobIds) {
-				if (StringUtils.isNotBlank(childJobIdItem) && StringUtils.isNumeric(childJobIdItem)) {
-					XxlJobInfo childJobInfo = xxlJobInfoDao.loadById(Integer.valueOf(childJobIdItem));
-					if (childJobInfo==null) {
-						return new ReturnT<String>(ReturnT.FAIL_CODE,
-								MessageFormat.format((I18nUtil.getString("jobinfo_field_childJobId")+"({0})"+I18nUtil.getString("system_not_found")), childJobIdItem));
-					}
-					// avoid cycle relate
-					if (childJobInfo.getId() == jobInfo.getId()) {
-						return new ReturnT<String>(ReturnT.FAIL_CODE, MessageFormat.format(I18nUtil.getString("jobinfo_field_childJobId_limit"), childJobIdItem));
-					}
-				} else {
-					return new ReturnT<String>(ReturnT.FAIL_CODE,
-							MessageFormat.format((I18nUtil.getString("jobinfo_field_childJobId")+"({0})"+I18nUtil.getString("system_unvalid")), childJobIdItem));
-				}
-			}
-			jobInfo.setChildJobId(StringUtils.join(childJobIds, ","));
-		}
-
-		// stage job info
-		XxlJobInfo exists_jobInfo = xxlJobInfoDao.loadById(jobInfo.getId());
-		if (exists_jobInfo == null) {
-			return new ReturnT<String>(ReturnT.FAIL_CODE, (I18nUtil.getString("jobinfo_field_id")+I18nUtil.getString("system_not_found")) );
-		}
-		//String old_cron = exists_jobInfo.getJobCron();
-
-		exists_jobInfo.setJobCron(jobInfo.getJobCron());
-		exists_jobInfo.setJobDesc(jobInfo.getJobDesc());
-		exists_jobInfo.setAuthor(jobInfo.getAuthor());
-		exists_jobInfo.setAlarmEmail(jobInfo.getAlarmEmail());
-		exists_jobInfo.setExecutorRouteStrategy(jobInfo.getExecutorRouteStrategy());
-		exists_jobInfo.setExecutorHandler(jobInfo.getExecutorHandler());
-		exists_jobInfo.setExecutorParam(jobInfo.getExecutorParam());
-		exists_jobInfo.setExecutorBlockStrategy(jobInfo.getExecutorBlockStrategy());
-		exists_jobInfo.setExecutorFailStrategy(jobInfo.getExecutorFailStrategy());
-		exists_jobInfo.setExecutorTimeout(jobInfo.getExecutorTimeout());
-		exists_jobInfo.setExecutorFailRetryCount(jobInfo.getExecutorFailRetryCount());
-		exists_jobInfo.setChildJobId(jobInfo.getChildJobId());
-        xxlJobInfoDao.update(exists_jobInfo);
-
-		// fresh quartz
-		String qz_group = String.valueOf(exists_jobInfo.getJobGroup());
-		String qz_name = String.valueOf(exists_jobInfo.getId());
-        try {
-            boolean ret = XxlJobDynamicScheduler.rescheduleJob(qz_group, qz_name, exists_jobInfo.getJobCron());
-            return ret?ReturnT.SUCCESS:ReturnT.FAIL;
-        } catch (SchedulerException e) {
-            logger.error(e.getMessage(), e);
-        }
-
-		return ReturnT.FAIL;
-	}
-
-	@Override
-	public ReturnT<String> remove(int id) {
-		XxlJobInfo xxlJobInfo = xxlJobInfoDao.loadById(id);
-        String group = String.valueOf(xxlJobInfo.getJobGroup());
-        String name = String.valueOf(xxlJobInfo.getId());
-
-		try {
-			XxlJobDynamicScheduler.removeJob(name, group);
-			xxlJobInfoDao.delete(id);
-			xxlJobLogDao.delete(id);
-			xxlJobLogGlueDao.deleteByJobId(id);
-			return ReturnT.SUCCESS;
-		} catch (SchedulerException e) {
-			logger.error(e.getMessage(), e);
-		}
-		return ReturnT.FAIL;
-	}
-
-	@Override
-	public ReturnT<String> pause(int id) {
-        XxlJobInfo xxlJobInfo = xxlJobInfoDao.loadById(id);
-        String group = String.valueOf(xxlJobInfo.getJobGroup());
-        String name = String.valueOf(xxlJobInfo.getId());
-
-		try {
-            boolean ret = XxlJobDynamicScheduler.pauseJob(name, group);	// jobStatus do not store
-            return ret?ReturnT.SUCCESS:ReturnT.FAIL;
-		} catch (SchedulerException e) {
-			logger.error(e.getMessage(), e);
-			return ReturnT.FAIL;
-		}
-	}
-
-	@Override
-	public ReturnT<String> resume(int id) {
-        XxlJobInfo xxlJobInfo = xxlJobInfoDao.loadById(id);
-        String group = String.valueOf(xxlJobInfo.getJobGroup());
-        String name = String.valueOf(xxlJobInfo.getId());
-
-		try {
-			boolean ret = XxlJobDynamicScheduler.resumeJob(name, group);
-			return ret?ReturnT.SUCCESS:ReturnT.FAIL;
-		} catch (SchedulerException e) {
-			logger.error(e.getMessage(), e);
-			return ReturnT.FAIL;
-		}
-	}
-
-	@Override
-	public ReturnT<String> triggerJob(int id) {
-
-		JobTriggerPoolHelper.trigger(id);
-		return ReturnT.SUCCESS;
-
-        /*XxlJobInfo xxlJobInfo = xxlJobInfoDao.loadById(id);
-        if (xxlJobInfo == null) {
-        	return new ReturnT<String>(ReturnT.FAIL_CODE, (I18nUtil.getString("jobinfo_field_id")+I18nUtil.getString("system_unvalid")) );
-		}
-
-        String group = String.valueOf(xxlJobInfo.getJobGroup());
-        String name = String.valueOf(xxlJobInfo.getId());
-
-		try {
-			XxlJobDynamicScheduler.triggerJob(name, group);
-			return ReturnT.SUCCESS;
-		} catch (SchedulerException e) {
-			logger.error(e.getMessage(), e);
-			return new ReturnT<String>(ReturnT.FAIL_CODE, e.getMessage());
-		}*/
-
-	}
-
-	@Override
-	public Map<String, Object> dashboardInfo() {
-
-		int jobInfoCount = xxlJobInfoDao.findAllCount();
-		int jobLogCount = xxlJobLogDao.triggerCountByHandleCode(-1);
-		int jobLogSuccessCount = xxlJobLogDao.triggerCountByHandleCode(ReturnT.SUCCESS_CODE);
-
-		// executor count
-		Set<String> executerAddressSet = new HashSet<String>();
-		List<XxlJobGroup> groupList = xxlJobGroupDao.findAll();
-
-		if (CollectionUtils.isNotEmpty(groupList)) {
-			for (XxlJobGroup group: groupList) {
-				if (CollectionUtils.isNotEmpty(group.getRegistryList())) {
-					executerAddressSet.addAll(group.getRegistryList());
-				}
-			}
-		}
-
-		int executorCount = executerAddressSet.size();
-
-		Map<String, Object> dashboardMap = new HashMap<String, Object>();
-		dashboardMap.put("jobInfoCount", jobInfoCount);
-		dashboardMap.put("jobLogCount", jobLogCount);
-		dashboardMap.put("jobLogSuccessCount", jobLogSuccessCount);
-		dashboardMap.put("executorCount", executorCount);
-		return dashboardMap;
-	}
-
-	private static final String TRIGGER_CHART_DATA_CACHE = "trigger_chart_data_cache";
-	@Override
-	public ReturnT<Map<String, Object>> chartInfo(Date startDate, Date endDate) {
-		/*// get cache
-		String cacheKey = TRIGGER_CHART_DATA_CACHE + "_" + startDate.getTime() + "_" + endDate.getTime();
-		Map<String, Object> chartInfo = (Map<String, Object>) LocalCacheUtil.get(cacheKey);
-		if (chartInfo != null) {
-			return new ReturnT<Map<String, Object>>(chartInfo);
-		}*/
-
-		// process
-		List<String> triggerDayList = new ArrayList<String>();
-		List<Integer> triggerDayCountRunningList = new ArrayList<Integer>();
-		List<Integer> triggerDayCountSucList = new ArrayList<Integer>();
-		List<Integer> triggerDayCountFailList = new ArrayList<Integer>();
-		int triggerCountRunningTotal = 0;
-		int triggerCountSucTotal = 0;
-		int triggerCountFailTotal = 0;
-
-		List<Map<String, Object>> triggerCountMapAll = xxlJobLogDao.triggerCountByDay(startDate, endDate);
-		if (CollectionUtils.isNotEmpty(triggerCountMapAll)) {
-			for (Map<String, Object> item: triggerCountMapAll) {
-				String day = String.valueOf(item.get("triggerDay"));
-				int triggerDayCount = Integer.valueOf(String.valueOf(item.get("triggerDayCount")));
-				int triggerDayCountRunning = Integer.valueOf(String.valueOf(item.get("triggerDayCountRunning")));
-				int triggerDayCountSuc = Integer.valueOf(String.valueOf(item.get("triggerDayCountSuc")));
-				int triggerDayCountFail = triggerDayCount - triggerDayCountRunning - triggerDayCountSuc;
-
-				triggerDayList.add(day);
-				triggerDayCountRunningList.add(triggerDayCountRunning);
-				triggerDayCountSucList.add(triggerDayCountSuc);
-				triggerDayCountFailList.add(triggerDayCountFail);
-
-				triggerCountRunningTotal += triggerDayCountRunning;
-				triggerCountSucTotal += triggerDayCountSuc;
-				triggerCountFailTotal += triggerDayCountFail;
-			}
-		} else {
-            for (int i = 4; i > -1; i--) {
-                triggerDayList.add(FastDateFormat.getInstance("yyyy-MM-dd").format(DateUtils.addDays(new Date(), -i)));
-                triggerDayCountSucList.add(0);
-                triggerDayCountFailList.add(0);
-            }
-		}
-
-		Map<String, Object> result = new HashMap<String, Object>();
-		result.put("triggerDayList", triggerDayList);
-		result.put("triggerDayCountRunningList", triggerDayCountRunningList);
-		result.put("triggerDayCountSucList", triggerDayCountSucList);
-		result.put("triggerDayCountFailList", triggerDayCountFailList);
-
-		result.put("triggerCountRunningTotal", triggerCountRunningTotal);
-		result.put("triggerCountSucTotal", triggerCountSucTotal);
-		result.put("triggerCountFailTotal", triggerCountFailTotal);
-
-		/*// set cache
-		LocalCacheUtil.set(cacheKey, result, 60*1000);     // cache 60s*/
-
-		return new ReturnT<Map<String, Object>>(result);
-	}
-
-}
+package com.xxl.job.admin.service.impl;
+
+import com.xxl.job.admin.core.model.XxlJobGroup;
+import com.xxl.job.admin.core.model.XxlJobInfo;
+import com.xxl.job.admin.core.route.ExecutorRouteStrategyEnum;
+import com.xxl.job.admin.core.schedule.XxlJobDynamicScheduler;
+import com.xxl.job.admin.core.thread.JobTriggerPoolHelper;
+import com.xxl.job.admin.core.util.I18nUtil;
+import com.xxl.job.admin.dao.XxlJobGroupDao;
+import com.xxl.job.admin.dao.XxlJobInfoDao;
+import com.xxl.job.admin.dao.XxlJobLogDao;
+import com.xxl.job.admin.dao.XxlJobLogGlueDao;
+import com.xxl.job.admin.service.XxlJobService;
+import com.xxl.job.core.biz.model.ReturnT;
+import com.xxl.job.core.enums.ExecutorBlockStrategyEnum;
+import com.xxl.job.core.glue.GlueTypeEnum;
+import org.apache.commons.collections4.CollectionUtils;
+import org.apache.commons.lang3.StringUtils;
+import org.apache.commons.lang3.time.DateUtils;
+import org.apache.commons.lang3.time.FastDateFormat;
+import org.quartz.CronExpression;
+import org.quartz.SchedulerException;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.stereotype.Service;
+
+import javax.annotation.Resource;
+import java.text.MessageFormat;
+import java.util.*;
+
+/**
+ * core job action for xxl-job
+ * @author xuxueli 2016-5-28 15:30:33
+ */
+@Service
+public class XxlJobServiceImpl implements XxlJobService {
+	private static Logger logger = LoggerFactory.getLogger(XxlJobServiceImpl.class);
+
+	@Resource
+	private XxlJobGroupDao xxlJobGroupDao;
+	@Resource
+	private XxlJobInfoDao xxlJobInfoDao;
+	@Resource
+	public XxlJobLogDao xxlJobLogDao;
+	@Resource
+	private XxlJobLogGlueDao xxlJobLogGlueDao;
+	
+	@Override
+	public Map<String, Object> pageList(int start, int length, int jobGroup, String jobDesc, String executorHandler, String filterTime) {
+
+		// page list
+		List<XxlJobInfo> list = xxlJobInfoDao.pageList(start, length, jobGroup, jobDesc, executorHandler);
+		int list_count = xxlJobInfoDao.pageListCount(start, length, jobGroup, jobDesc, executorHandler);
+		
+		// fill job info
+		if (list!=null && list.size()>0) {
+			for (XxlJobInfo jobInfo : list) {
+				XxlJobDynamicScheduler.fillJobInfo(jobInfo);
+			}
+		}
+		
+		// package result
+		Map<String, Object> maps = new HashMap<String, Object>();
+	    maps.put("recordsTotal", list_count);		// 总记录数
+	    maps.put("recordsFiltered", list_count);	// 过滤后的总记录数
+	    maps.put("data", list);  					// 分页列表
+		return maps;
+	}
+
+	@Override
+	public ReturnT<String> add(XxlJobInfo jobInfo) {
+		// valid
+		XxlJobGroup group = xxlJobGroupDao.load(jobInfo.getJobGroup());
+		if (group == null) {
+			return new ReturnT<String>(ReturnT.FAIL_CODE, (I18nUtil.getString("system_please_choose")+I18nUtil.getString("jobinfo_field_jobgroup")) );
+		}
+		if (!CronExpression.isValidExpression(jobInfo.getJobCron())) {
+			return new ReturnT<String>(ReturnT.FAIL_CODE, I18nUtil.getString("jobinfo_field_cron_unvalid") );
+		}
+		if (StringUtils.isBlank(jobInfo.getJobDesc())) {
+			return new ReturnT<String>(ReturnT.FAIL_CODE, (I18nUtil.getString("system_please_input")+I18nUtil.getString("jobinfo_field_jobdesc")) );
+		}
+		if (StringUtils.isBlank(jobInfo.getAuthor())) {
+			return new ReturnT<String>(ReturnT.FAIL_CODE, (I18nUtil.getString("system_please_input")+I18nUtil.getString("jobinfo_field_author")) );
+		}
+		if (ExecutorRouteStrategyEnum.match(jobInfo.getExecutorRouteStrategy(), null) == null) {
+			return new ReturnT<String>(ReturnT.FAIL_CODE, (I18nUtil.getString("jobinfo_field_executorRouteStrategy")+I18nUtil.getString("system_unvalid")) );
+		}
+		if (ExecutorBlockStrategyEnum.match(jobInfo.getExecutorBlockStrategy(), null) == null) {
+			return new ReturnT<String>(ReturnT.FAIL_CODE, (I18nUtil.getString("jobinfo_field_executorBlockStrategy")+I18nUtil.getString("system_unvalid")) );
+		}
+		if (GlueTypeEnum.match(jobInfo.getGlueType()) == null) {
+			return new ReturnT<String>(ReturnT.FAIL_CODE, (I18nUtil.getString("jobinfo_field_gluetype")+I18nUtil.getString("system_unvalid")) );
+		}
+		if (GlueTypeEnum.BEAN==GlueTypeEnum.match(jobInfo.getGlueType()) && StringUtils.isBlank(jobInfo.getExecutorHandler())) {
+			return new ReturnT<String>(ReturnT.FAIL_CODE, (I18nUtil.getString("system_please_input")+"JobHandler") );
+		}
+
+		// fix "\r" in shell
+		if (GlueTypeEnum.GLUE_SHELL==GlueTypeEnum.match(jobInfo.getGlueType()) && jobInfo.getGlueSource()!=null) {
+			jobInfo.setGlueSource(jobInfo.getGlueSource().replaceAll("\r", ""));
+		}
+
+		// ChildJobId valid
+		if (StringUtils.isNotBlank(jobInfo.getChildJobId())) {
+			String[] childJobIds = StringUtils.split(jobInfo.getChildJobId(), ",");
+			for (String childJobIdItem: childJobIds) {
+				if (StringUtils.isNotBlank(childJobIdItem) && StringUtils.isNumeric(childJobIdItem)) {
+					XxlJobInfo childJobInfo = xxlJobInfoDao.loadById(Integer.valueOf(childJobIdItem));
+					if (childJobInfo==null) {
+						return new ReturnT<String>(ReturnT.FAIL_CODE,
+								MessageFormat.format((I18nUtil.getString("jobinfo_field_childJobId")+"({0})"+I18nUtil.getString("system_not_found")), childJobIdItem));
+					}
+				} else {
+					return new ReturnT<String>(ReturnT.FAIL_CODE,
+							MessageFormat.format((I18nUtil.getString("jobinfo_field_childJobId")+"({0})"+I18nUtil.getString("system_unvalid")), childJobIdItem));
+				}
+			}
+			jobInfo.setChildJobId(StringUtils.join(childJobIds, ","));
+		}
+
+		// add in db
+		xxlJobInfoDao.save(jobInfo);
+		if (jobInfo.getId() < 1) {
+			return new ReturnT<String>(ReturnT.FAIL_CODE, (I18nUtil.getString("jobinfo_field_add")+I18nUtil.getString("system_fail")) );
+		}
+
+		// add in quartz
+        String qz_group = String.valueOf(jobInfo.getJobGroup());
+        String qz_name = String.valueOf(jobInfo.getId());
+        try {
+            XxlJobDynamicScheduler.addJob(qz_name, qz_group, jobInfo.getJobCron());
+            //XxlJobDynamicScheduler.pauseJob(qz_name, qz_group);
+            return ReturnT.SUCCESS;
+        } catch (SchedulerException e) {
+            logger.error(e.getMessage(), e);
+            try {
+                xxlJobInfoDao.delete(jobInfo.getId());
+                XxlJobDynamicScheduler.removeJob(qz_name, qz_group);
+            } catch (SchedulerException e1) {
+                logger.error(e.getMessage(), e1);
+            }
+            return new ReturnT<String>(ReturnT.FAIL_CODE, (I18nUtil.getString("jobinfo_field_add")+I18nUtil.getString("system_fail"))+":" + e.getMessage());
+        }
+	}
+
+	@Override
+	public ReturnT<String> update(XxlJobInfo jobInfo) {
+
+		// valid
+		if (!CronExpression.isValidExpression(jobInfo.getJobCron())) {
+			return new ReturnT<String>(ReturnT.FAIL_CODE, I18nUtil.getString("jobinfo_field_cron_unvalid") );
+		}
+		if (StringUtils.isBlank(jobInfo.getJobDesc())) {
+			return new ReturnT<String>(ReturnT.FAIL_CODE, (I18nUtil.getString("system_please_input")+I18nUtil.getString("jobinfo_field_jobdesc")) );
+		}
+		if (StringUtils.isBlank(jobInfo.getAuthor())) {
+			return new ReturnT<String>(ReturnT.FAIL_CODE, (I18nUtil.getString("system_please_input")+I18nUtil.getString("jobinfo_field_author")) );
+		}
+		if (ExecutorRouteStrategyEnum.match(jobInfo.getExecutorRouteStrategy(), null) == null) {
+			return new ReturnT<String>(ReturnT.FAIL_CODE, (I18nUtil.getString("jobinfo_field_executorRouteStrategy")+I18nUtil.getString("system_unvalid")) );
+		}
+		if (ExecutorBlockStrategyEnum.match(jobInfo.getExecutorBlockStrategy(), null) == null) {
+			return new ReturnT<String>(ReturnT.FAIL_CODE, (I18nUtil.getString("jobinfo_field_executorBlockStrategy")+I18nUtil.getString("system_unvalid")) );
+		}
+
+		// ChildJobId valid
+		if (StringUtils.isNotBlank(jobInfo.getChildJobId())) {
+			String[] childJobIds = StringUtils.split(jobInfo.getChildJobId(), ",");
+			for (String childJobIdItem: childJobIds) {
+				if (StringUtils.isNotBlank(childJobIdItem) && StringUtils.isNumeric(childJobIdItem)) {
+					XxlJobInfo childJobInfo = xxlJobInfoDao.loadById(Integer.valueOf(childJobIdItem));
+					if (childJobInfo==null) {
+						return new ReturnT<String>(ReturnT.FAIL_CODE,
+								MessageFormat.format((I18nUtil.getString("jobinfo_field_childJobId")+"({0})"+I18nUtil.getString("system_not_found")), childJobIdItem));
+					}
+					// avoid cycle relate
+					if (childJobInfo.getId() == jobInfo.getId()) {
+						return new ReturnT<String>(ReturnT.FAIL_CODE, MessageFormat.format(I18nUtil.getString("jobinfo_field_childJobId_limit"), childJobIdItem));
+					}
+				} else {
+					return new ReturnT<String>(ReturnT.FAIL_CODE,
+							MessageFormat.format((I18nUtil.getString("jobinfo_field_childJobId")+"({0})"+I18nUtil.getString("system_unvalid")), childJobIdItem));
+				}
+			}
+			jobInfo.setChildJobId(StringUtils.join(childJobIds, ","));
+		}
+
+		// stage job info
+		XxlJobInfo exists_jobInfo = xxlJobInfoDao.loadById(jobInfo.getId());
+		if (exists_jobInfo == null) {
+			return new ReturnT<String>(ReturnT.FAIL_CODE, (I18nUtil.getString("jobinfo_field_id")+I18nUtil.getString("system_not_found")) );
+		}
+		//String old_cron = exists_jobInfo.getJobCron();
+
+		exists_jobInfo.setJobCron(jobInfo.getJobCron());
+		exists_jobInfo.setJobDesc(jobInfo.getJobDesc());
+		exists_jobInfo.setAuthor(jobInfo.getAuthor());
+		exists_jobInfo.setAlarmEmail(jobInfo.getAlarmEmail());
+		exists_jobInfo.setExecutorRouteStrategy(jobInfo.getExecutorRouteStrategy());
+		exists_jobInfo.setExecutorHandler(jobInfo.getExecutorHandler());
+		exists_jobInfo.setExecutorParam(jobInfo.getExecutorParam());
+		exists_jobInfo.setExecutorBlockStrategy(jobInfo.getExecutorBlockStrategy());
+		exists_jobInfo.setExecutorFailStrategy(jobInfo.getExecutorFailStrategy());
+		exists_jobInfo.setExecutorTimeout(jobInfo.getExecutorTimeout());
+		exists_jobInfo.setExecutorFailRetryCount(jobInfo.getExecutorFailRetryCount());
+		exists_jobInfo.setChildJobId(jobInfo.getChildJobId());
+        xxlJobInfoDao.update(exists_jobInfo);
+
+		// fresh quartz
+		String qz_group = String.valueOf(exists_jobInfo.getJobGroup());
+		String qz_name = String.valueOf(exists_jobInfo.getId());
+        try {
+            boolean ret = XxlJobDynamicScheduler.rescheduleJob(qz_group, qz_name, exists_jobInfo.getJobCron());
+            return ret?ReturnT.SUCCESS:ReturnT.FAIL;
+        } catch (SchedulerException e) {
+            logger.error(e.getMessage(), e);
+        }
+
+		return ReturnT.FAIL;
+	}
+
+	@Override
+	public ReturnT<String> remove(int id) {
+		XxlJobInfo xxlJobInfo = xxlJobInfoDao.loadById(id);
+        String group = String.valueOf(xxlJobInfo.getJobGroup());
+        String name = String.valueOf(xxlJobInfo.getId());
+
+		try {
+			XxlJobDynamicScheduler.removeJob(name, group);
+			xxlJobInfoDao.delete(id);
+			xxlJobLogDao.delete(id);
+			xxlJobLogGlueDao.deleteByJobId(id);
+			return ReturnT.SUCCESS;
+		} catch (SchedulerException e) {
+			logger.error(e.getMessage(), e);
+		}
+		return ReturnT.FAIL;
+	}
+
+	@Override
+	public ReturnT<String> pause(int id) {
+        XxlJobInfo xxlJobInfo = xxlJobInfoDao.loadById(id);
+        String group = String.valueOf(xxlJobInfo.getJobGroup());
+        String name = String.valueOf(xxlJobInfo.getId());
+
+		try {
+            boolean ret = XxlJobDynamicScheduler.pauseJob(name, group);	// jobStatus do not store
+            return ret?ReturnT.SUCCESS:ReturnT.FAIL;
+		} catch (SchedulerException e) {
+			logger.error(e.getMessage(), e);
+			return ReturnT.FAIL;
+		}
+	}
+
+	@Override
+	public ReturnT<String> resume(int id) {
+        XxlJobInfo xxlJobInfo = xxlJobInfoDao.loadById(id);
+        String group = String.valueOf(xxlJobInfo.getJobGroup());
+        String name = String.valueOf(xxlJobInfo.getId());
+
+		try {
+			boolean ret = XxlJobDynamicScheduler.resumeJob(name, group);
+			return ret?ReturnT.SUCCESS:ReturnT.FAIL;
+		} catch (SchedulerException e) {
+			logger.error(e.getMessage(), e);
+			return ReturnT.FAIL;
+		}
+	}
+
+	@Override
+	public ReturnT<String> triggerJob(int id) {
+
+		JobTriggerPoolHelper.trigger(id);
+		return ReturnT.SUCCESS;
+
+        /*XxlJobInfo xxlJobInfo = xxlJobInfoDao.loadById(id);
+        if (xxlJobInfo == null) {
+        	return new ReturnT<String>(ReturnT.FAIL_CODE, (I18nUtil.getString("jobinfo_field_id")+I18nUtil.getString("system_unvalid")) );
+		}
+
+        String group = String.valueOf(xxlJobInfo.getJobGroup());
+        String name = String.valueOf(xxlJobInfo.getId());
+
+		try {
+			XxlJobDynamicScheduler.triggerJob(name, group);
+			return ReturnT.SUCCESS;
+		} catch (SchedulerException e) {
+			logger.error(e.getMessage(), e);
+			return new ReturnT<String>(ReturnT.FAIL_CODE, e.getMessage());
+		}*/
+
+	}
+
+	@Override
+	public Map<String, Object> dashboardInfo() {
+
+		int jobInfoCount = xxlJobInfoDao.findAllCount();
+		int jobLogCount = xxlJobLogDao.triggerCountByHandleCode(-1);
+		int jobLogSuccessCount = xxlJobLogDao.triggerCountByHandleCode(ReturnT.SUCCESS_CODE);
+
+		// executor count
+		Set<String> executerAddressSet = new HashSet<String>();
+		List<XxlJobGroup> groupList = xxlJobGroupDao.findAll();
+
+		if (CollectionUtils.isNotEmpty(groupList)) {
+			for (XxlJobGroup group: groupList) {
+				if (CollectionUtils.isNotEmpty(group.getRegistryList())) {
+					executerAddressSet.addAll(group.getRegistryList());
+				}
+			}
+		}
+
+		int executorCount = executerAddressSet.size();
+
+		Map<String, Object> dashboardMap = new HashMap<String, Object>();
+		dashboardMap.put("jobInfoCount", jobInfoCount);
+		dashboardMap.put("jobLogCount", jobLogCount);
+		dashboardMap.put("jobLogSuccessCount", jobLogSuccessCount);
+		dashboardMap.put("executorCount", executorCount);
+		return dashboardMap;
+	}
+
+	private static final String TRIGGER_CHART_DATA_CACHE = "trigger_chart_data_cache";
+	@Override
+	public ReturnT<Map<String, Object>> chartInfo(Date startDate, Date endDate) {
+		/*// get cache
+		String cacheKey = TRIGGER_CHART_DATA_CACHE + "_" + startDate.getTime() + "_" + endDate.getTime();
+		Map<String, Object> chartInfo = (Map<String, Object>) LocalCacheUtil.get(cacheKey);
+		if (chartInfo != null) {
+			return new ReturnT<Map<String, Object>>(chartInfo);
+		}*/
+
+		// process
+		List<String> triggerDayList = new ArrayList<String>();
+		List<Integer> triggerDayCountRunningList = new ArrayList<Integer>();
+		List<Integer> triggerDayCountSucList = new ArrayList<Integer>();
+		List<Integer> triggerDayCountFailList = new ArrayList<Integer>();
+		int triggerCountRunningTotal = 0;
+		int triggerCountSucTotal = 0;
+		int triggerCountFailTotal = 0;
+
+		List<Map<String, Object>> triggerCountMapAll = xxlJobLogDao.triggerCountByDay(startDate, endDate);
+		if (CollectionUtils.isNotEmpty(triggerCountMapAll)) {
+			for (Map<String, Object> item: triggerCountMapAll) {
+				String day = String.valueOf(item.get("triggerDay"));
+				int triggerDayCount = Integer.valueOf(String.valueOf(item.get("triggerDayCount")));
+				int triggerDayCountRunning = Integer.valueOf(String.valueOf(item.get("triggerDayCountRunning")));
+				int triggerDayCountSuc = Integer.valueOf(String.valueOf(item.get("triggerDayCountSuc")));
+				int triggerDayCountFail = triggerDayCount - triggerDayCountRunning - triggerDayCountSuc;
+
+				triggerDayList.add(day);
+				triggerDayCountRunningList.add(triggerDayCountRunning);
+				triggerDayCountSucList.add(triggerDayCountSuc);
+				triggerDayCountFailList.add(triggerDayCountFail);
+
+				triggerCountRunningTotal += triggerDayCountRunning;
+				triggerCountSucTotal += triggerDayCountSuc;
+				triggerCountFailTotal += triggerDayCountFail;
+			}
+		} else {
+            for (int i = 4; i > -1; i--) {
+                triggerDayList.add(FastDateFormat.getInstance("yyyy-MM-dd").format(DateUtils.addDays(new Date(), -i)));
+                triggerDayCountSucList.add(0);
+                triggerDayCountFailList.add(0);
+            }
+		}
+
+		Map<String, Object> result = new HashMap<String, Object>();
+		result.put("triggerDayList", triggerDayList);
+		result.put("triggerDayCountRunningList", triggerDayCountRunningList);
+		result.put("triggerDayCountSucList", triggerDayCountSucList);
+		result.put("triggerDayCountFailList", triggerDayCountFailList);
+
+		result.put("triggerCountRunningTotal", triggerCountRunningTotal);
+		result.put("triggerCountSucTotal", triggerCountSucTotal);
+		result.put("triggerCountFailTotal", triggerCountFailTotal);
+
+		/*// set cache
+		LocalCacheUtil.set(cacheKey, result, 60*1000);     // cache 60s*/
+
+		return new ReturnT<Map<String, Object>>(result);
+	}
+
+}

+ 185 - 185
xxl-job-admin/src/main/resources/mybatis-mapper/XxlJobInfoMapper.xml

@@ -1,186 +1,186 @@
-<?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="com.xxl.job.admin.dao.XxlJobInfoDao">
-
-	<resultMap id="XxlJobInfo" type="com.xxl.job.admin.core.model.XxlJobInfo" >
-		<result column="id" property="id" />
-
-		<result column="job_group" property="jobGroup" />
-	    <result column="job_cron" property="jobCron" />
-	    <result column="job_desc" property="jobDesc" />
-
-	    <result column="add_time" property="addTime" />
-	    <result column="update_time" property="updateTime" />
-
-	    <result column="author" property="author" />
-	    <result column="alarm_email" property="alarmEmail" />
-
-		<result column="executor_route_strategy" property="executorRouteStrategy" />
-		<result column="executor_handler" property="executorHandler" />
-	    <result column="executor_param" property="executorParam" />
-		<result column="executor_block_strategy" property="executorBlockStrategy" />
-		<result column="executor_fail_strategy" property="executorFailStrategy" />
-		<result column="executor_timeout" property="executorTimeout" />
-		<result column="executor_fail_retry_count" property="executorFailRetryCount" />
-
-	    <result column="glue_type" property="glueType" />
-	    <result column="glue_source" property="glueSource" />
-	    <result column="glue_remark" property="glueRemark" />
-		<result column="glue_updatetime" property="glueUpdatetime" />
-
-		<result column="child_jobid" property="childJobId" />
-	</resultMap>
-
-	<sql id="Base_Column_List">
-		t.id,
-		t.job_group,
-		t.job_cron,
-		t.job_desc,
-		t.add_time,
-		t.update_time,
-		t.author,
-		t.alarm_email,
-		t.executor_route_strategy,
-		t.executor_handler,
-		t.executor_param,
-		t.executor_block_strategy,
-		t.executor_fail_strategy,
-		t.executor_timeout,
-		t.executor_fail_retry_count,
-		t.glue_type,
-		t.glue_source,
-		t.glue_remark,
-		t.glue_updatetime,
-		t.child_jobid
-	</sql>
-
-	<select id="pageList" parameterType="java.util.HashMap" resultMap="XxlJobInfo">
-		SELECT <include refid="Base_Column_List" />
-		FROM XXL_JOB_QRTZ_TRIGGER_INFO AS t
-		<trim prefix="WHERE" prefixOverrides="AND | OR" >
-			<if test="jobGroup gt 0">
-				AND t.job_group = #{jobGroup}
-			</if>
-			<if test="jobDesc != null and jobDesc != ''">
-				AND t.job_desc like CONCAT(CONCAT('%', #{jobDesc}), '%')
-			</if>
-			<if test="executorHandler != null and executorHandler != ''">
-				AND t.executor_handler like CONCAT(CONCAT('%', #{executorHandler}), '%')
-			</if>
-		</trim>
-		ORDER BY id DESC
-		LIMIT #{offset}, #{pagesize}
-	</select>
-
-	<select id="pageListCount" parameterType="java.util.HashMap" resultType="int">
-		SELECT count(1)
-		FROM XXL_JOB_QRTZ_TRIGGER_INFO AS t
-		<trim prefix="WHERE" prefixOverrides="AND | OR" >
-			<if test="jobGroup gt 0">
-				AND t.job_group = #{jobGroup}
-			</if>
-			<if test="jobDesc != null and jobDesc != ''">
-				AND t.job_desc like CONCAT(CONCAT('%', #{jobDesc}), '%')
-			</if>
-			<if test="executorHandler != null and executorHandler != ''">
-				AND t.executor_handler like CONCAT(CONCAT('%', #{executorHandler}), '%')
-			</if>
-		</trim>
-	</select>
-
-	<insert id="save" parameterType="com.xxl.job.admin.core.model.XxlJobInfo" useGeneratedKeys="true" keyProperty="id" >
-		INSERT INTO XXL_JOB_QRTZ_TRIGGER_INFO (
-			job_group,
-			job_cron,
-			job_desc,
-			add_time,
-			update_time,
-			author,
-			alarm_email,
-            executor_route_strategy,
-			executor_handler,
-			executor_param,
-			executor_block_strategy,
-			executor_fail_strategy,
-			executor_timeout,
-			executor_fail_retry_count,
-			glue_type,
-			glue_source,
-			glue_remark,
-			glue_updatetime,
-			child_jobid
-		) VALUES (
-			#{jobGroup},
-			#{jobCron},
-			#{jobDesc},
-			NOW(),
-			NOW(),
-			#{author},
-			#{alarmEmail},
-			#{executorRouteStrategy},
-			#{executorHandler},
-			#{executorParam},
-			#{executorBlockStrategy},
-			#{executorFailStrategy},
-			#{executorTimeout},
-			#{executorFailRetryCount},
-			#{glueType},
-			#{glueSource},
-			#{glueRemark},
-			NOW(),
-			#{childJobId}
-		);
-		<!--<selectKey resultType="java.lang.Integer" order="AFTER" keyProperty="id">
-			SELECT LAST_INSERT_ID()
-			/*SELECT @@IDENTITY AS id*/
-		</selectKey>-->
-	</insert>
-
-	<select id="loadById" parameterType="java.util.HashMap" resultMap="XxlJobInfo">
-		SELECT <include refid="Base_Column_List" />
-		FROM XXL_JOB_QRTZ_TRIGGER_INFO AS t
-		WHERE t.id = #{id}
-	</select>
-
-	<update id="update" parameterType="com.xxl.job.admin.core.model.XxlJobInfo" >
-		UPDATE XXL_JOB_QRTZ_TRIGGER_INFO
-		SET
-			job_cron = #{jobCron},
-			job_desc = #{jobDesc},
-			update_time = NOW(),
-			author = #{author},
-			alarm_email = #{alarmEmail},
-			executor_route_strategy = #{executorRouteStrategy},
-			executor_handler = #{executorHandler},
-			executor_param = #{executorParam},
-			executor_block_strategy = #{executorBlockStrategy},
-			executor_fail_strategy = #{executorFailStrategy},
-			executor_timeout = ${executorTimeout},
-			executor_fail_retry_count = ${executorFailRetryCount},
-			glue_type = #{glueType},
-			glue_source = #{glueSource},
-			glue_remark = #{glueRemark},
-			glue_updatetime = #{glueUpdatetime},
-			child_jobid = #{childJobId}
-		WHERE id = #{id}
-	</update>
-
-	<delete id="delete" parameterType="java.util.HashMap">
-		DELETE
-		FROM XXL_JOB_QRTZ_TRIGGER_INFO
-		WHERE id = #{id}
-	</delete>
-
-	<select id="getJobsByGroup" parameterType="java.util.HashMap" resultMap="XxlJobInfo">
-		SELECT <include refid="Base_Column_List" />
-		FROM XXL_JOB_QRTZ_TRIGGER_INFO AS t
-		WHERE t.job_group = #{jobGroup}
-	</select>
-
-	<select id="findAllCount" resultType="int">
-		SELECT count(1)
-		FROM XXL_JOB_QRTZ_TRIGGER_INFO
-	</select>
-
+<?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="com.xxl.job.admin.dao.XxlJobInfoDao">
+
+	<resultMap id="XxlJobInfo" type="com.xxl.job.admin.core.model.XxlJobInfo" >
+		<result column="id" property="id" />
+
+		<result column="job_group" property="jobGroup" />
+	    <result column="job_cron" property="jobCron" />
+	    <result column="job_desc" property="jobDesc" />
+
+	    <result column="add_time" property="addTime" />
+	    <result column="update_time" property="updateTime" />
+
+	    <result column="author" property="author" />
+	    <result column="alarm_email" property="alarmEmail" />
+
+		<result column="executor_route_strategy" property="executorRouteStrategy" />
+		<result column="executor_handler" property="executorHandler" />
+	    <result column="executor_param" property="executorParam" />
+		<result column="executor_block_strategy" property="executorBlockStrategy" />
+		<result column="executor_fail_strategy" property="executorFailStrategy" />
+		<result column="executor_timeout" property="executorTimeout" />
+		<result column="executor_fail_retry_count" property="executorFailRetryCount" />
+
+	    <result column="glue_type" property="glueType" />
+	    <result column="glue_source" property="glueSource" />
+	    <result column="glue_remark" property="glueRemark" />
+		<result column="glue_updatetime" property="glueUpdatetime" />
+
+		<result column="child_jobid" property="childJobId" />
+	</resultMap>
+
+	<sql id="Base_Column_List">
+		t.id,
+		t.job_group,
+		t.job_cron,
+		t.job_desc,
+		t.add_time,
+		t.update_time,
+		t.author,
+		t.alarm_email,
+		t.executor_route_strategy,
+		t.executor_handler,
+		t.executor_param,
+		t.executor_block_strategy,
+		t.executor_fail_strategy,
+		t.executor_timeout,
+		t.executor_fail_retry_count,
+		t.glue_type,
+		t.glue_source,
+		t.glue_remark,
+		t.glue_updatetime,
+		t.child_jobid
+	</sql>
+
+	<select id="pageList" parameterType="java.util.HashMap" resultMap="XxlJobInfo">
+		SELECT <include refid="Base_Column_List" />
+		FROM XXL_JOB_QRTZ_TRIGGER_INFO AS t
+		<trim prefix="WHERE" prefixOverrides="AND | OR" >
+			<if test="jobGroup gt 0">
+				AND t.job_group = #{jobGroup}
+			</if>
+			<if test="jobDesc != null and jobDesc != ''">
+				AND t.job_desc like CONCAT(CONCAT('%', #{jobDesc}), '%')
+			</if>
+			<if test="executorHandler != null and executorHandler != ''">
+				AND t.executor_handler like CONCAT(CONCAT('%', #{executorHandler}), '%')
+			</if>
+		</trim>
+		ORDER BY id DESC
+		LIMIT #{offset}, #{pagesize}
+	</select>
+
+	<select id="pageListCount" parameterType="java.util.HashMap" resultType="int">
+		SELECT count(1)
+		FROM XXL_JOB_QRTZ_TRIGGER_INFO AS t
+		<trim prefix="WHERE" prefixOverrides="AND | OR" >
+			<if test="jobGroup gt 0">
+				AND t.job_group = #{jobGroup}
+			</if>
+			<if test="jobDesc != null and jobDesc != ''">
+				AND t.job_desc like CONCAT(CONCAT('%', #{jobDesc}), '%')
+			</if>
+			<if test="executorHandler != null and executorHandler != ''">
+				AND t.executor_handler like CONCAT(CONCAT('%', #{executorHandler}), '%')
+			</if>
+		</trim>
+	</select>
+
+	<insert id="save" parameterType="com.xxl.job.admin.core.model.XxlJobInfo" useGeneratedKeys="true" keyProperty="id" >
+		INSERT INTO XXL_JOB_QRTZ_TRIGGER_INFO (
+			job_group,
+			job_cron,
+			job_desc,
+			add_time,
+			update_time,
+			author,
+			alarm_email,
+            executor_route_strategy,
+			executor_handler,
+			executor_param,
+			executor_block_strategy,
+			executor_fail_strategy,
+			executor_timeout,
+			executor_fail_retry_count,
+			glue_type,
+			glue_source,
+			glue_remark,
+			glue_updatetime,
+			child_jobid
+		) VALUES (
+			#{jobGroup},
+			#{jobCron},
+			#{jobDesc},
+			NOW(),
+			NOW(),
+			#{author},
+			#{alarmEmail},
+			#{executorRouteStrategy},
+			#{executorHandler},
+			#{executorParam},
+			#{executorBlockStrategy},
+			#{executorFailStrategy},
+			#{executorTimeout},
+			#{executorFailRetryCount},
+			#{glueType},
+			#{glueSource},
+			#{glueRemark},
+			NOW(),
+			#{childJobId}
+		);
+		<!--<selectKey resultType="java.lang.Integer" order="AFTER" keyProperty="id">
+			SELECT LAST_INSERT_ID()
+			/*SELECT @@IDENTITY AS id*/
+		</selectKey>-->
+	</insert>
+
+	<select id="loadById" parameterType="java.util.HashMap" resultMap="XxlJobInfo">
+		SELECT <include refid="Base_Column_List" />
+		FROM XXL_JOB_QRTZ_TRIGGER_INFO AS t
+		WHERE t.id = #{id}
+	</select>
+
+	<update id="update" parameterType="com.xxl.job.admin.core.model.XxlJobInfo" >
+		UPDATE XXL_JOB_QRTZ_TRIGGER_INFO
+		SET
+			job_cron = #{jobCron},
+			job_desc = #{jobDesc},
+			update_time = NOW(),
+			author = #{author},
+			alarm_email = #{alarmEmail},
+			executor_route_strategy = #{executorRouteStrategy},
+			executor_handler = #{executorHandler},
+			executor_param = #{executorParam},
+			executor_block_strategy = #{executorBlockStrategy},
+			executor_fail_strategy = #{executorFailStrategy},
+			executor_timeout = ${executorTimeout},
+			executor_fail_retry_count = ${executorFailRetryCount},
+			glue_type = #{glueType},
+			glue_source = #{glueSource},
+			glue_remark = #{glueRemark},
+			glue_updatetime = #{glueUpdatetime},
+			child_jobid = #{childJobId}
+		WHERE id = #{id}
+	</update>
+
+	<delete id="delete" parameterType="java.util.HashMap">
+		DELETE
+		FROM XXL_JOB_QRTZ_TRIGGER_INFO
+		WHERE id = #{id}
+	</delete>
+
+	<select id="getJobsByGroup" parameterType="java.util.HashMap" resultMap="XxlJobInfo">
+		SELECT <include refid="Base_Column_List" />
+		FROM XXL_JOB_QRTZ_TRIGGER_INFO AS t
+		WHERE t.job_group = #{jobGroup}
+	</select>
+
+	<select id="findAllCount" resultType="int">
+		SELECT count(1)
+		FROM XXL_JOB_QRTZ_TRIGGER_INFO
+	</select>
+
 </mapper>
 </mapper>

+ 377 - 377
xxl-job-admin/src/main/webapp/WEB-INF/template/jobinfo/jobinfo.index.ftl

@@ -1,377 +1,377 @@
-<!DOCTYPE html>
-<html>
-<head>
-  	<#import "/common/common.macro.ftl" as netCommon>
-	<@netCommon.commonStyle />
-	<!-- DataTables -->
-  	<link rel="stylesheet" href="${request.contextPath}/static/adminlte/plugins/datatables/dataTables.bootstrap.css">
-    <title>${I18n.admin_name}</title>
-</head>
-<body class="hold-transition skin-blue sidebar-mini <#if cookieMap?exists && "off" == cookieMap["xxljob_adminlte_settings"].value >sidebar-collapse</#if>">
-<div class="wrapper">
-	<!-- header -->
-	<@netCommon.commonHeader />
-	<!-- left -->
-	<@netCommon.commonLeft "jobinfo" />
-	
-	<!-- Content Wrapper. Contains page content -->
-	<div class="content-wrapper">
-		<!-- Content Header (Page header) -->
-		<section class="content-header">
-			<h1>${I18n.jobinfo_name}</h1>
-		</section>
-		
-		<!-- Main content -->
-	    <section class="content">
-	    
-	    	<div class="row">
-	    		<div class="col-xs-3">
-	              	<div class="input-group">
-	                	<span class="input-group-addon">${I18n.jobinfo_field_jobgroup}</span>
-                		<select class="form-control" id="jobGroup" >
-                			<#list JobGroupList as group>
-                				<option value="${group.id}" <#if jobGroup==group.id>selected</#if> >${group.title}</option>
-                			</#list>
-	                  	</select>
-	              	</div>
-	            </div>
-                <div class="col-xs-3">
-                    <div class="input-group">
-                        <span class="input-group-addon">${I18n.jobinfo_field_jobdesc}</span>
-                        <input type="text" class="form-control" id="jobDesc" autocomplete="on" >
-                    </div>
-                </div>
-                <div class="col-xs-3">
-                    <div class="input-group">
-                        <span class="input-group-addon">JobHandler</span>
-                        <input type="text" class="form-control" id="executorHandler" autocomplete="on" >
-                    </div>
-                </div>
-	            <div class="col-xs-1">
-	            	<button class="btn btn-block btn-info" id="searchBtn">${I18n.system_search}</button>
-	            </div>
-	            <div class="col-xs-2">
-	            	<button class="btn btn-block btn-success add" type="button">${I18n.jobinfo_field_add}</button>
-	            </div>
-          	</div>
-	    	
-			<div class="row">
-				<div class="col-xs-12">
-					<div class="box">
-			            <#--<div class="box-header hide">
-			            	<h3 class="box-title">调度列表</h3>
-			            </div>-->
-			            <div class="box-body" >
-			              	<table id="job_list" class="table table-bordered table-striped" width="100%" >
-				                <thead>
-					            	<tr>
-					            		<th name="id" >${I18n.jobinfo_field_id}</th>
-					                	<th name="jobGroup" >${I18n.jobinfo_field_jobgroup}</th>
-					                  	<th name="jobDesc" >${I18n.jobinfo_field_jobdesc}</th>
-                                        <th name="glueType" >${I18n.jobinfo_field_gluetype}</th>
-					                  	<th name="executorParam" >${I18n.jobinfo_field_executorparam}</th>
-                                        <th name="jobCron" >Cron</th>
-					                  	<th name="addTime" >addTime</th>
-					                  	<th name="updateTime" >updateTime</th>
-					                  	<th name="author" >${I18n.jobinfo_field_author}</th>
-					                  	<th name="alarmEmail" >${I18n.jobinfo_field_alarmemail}</th>
-					                  	<th name="jobStatus" >${I18n.system_status}</th>
-					                  	<th>${I18n.system_opt}</th>
-					                </tr>
-				                </thead>
-				                <tbody></tbody>
-				                <tfoot></tfoot>
-							</table>
-						</div>
-					</div>
-				</div>
-			</div>
-	    </section>
-	</div>
-	
-	<!-- footer -->
-	<@netCommon.commonFooter />
-</div>
-
-<!-- job新增.模态框 -->
-<div class="modal fade" id="addModal" tabindex="-1" role="dialog"  aria-hidden="true">
-	<div class="modal-dialog modal-lg">
-		<div class="modal-content">
-			<div class="modal-header">
-            	<h4 class="modal-title" >${I18n.jobinfo_field_add}</h4>
-         	</div>
-         	<div class="modal-body">
-				<form class="form-horizontal form" role="form" >
-					<div class="form-group">
-						<label for="firstname" class="col-sm-2 control-label">${I18n.jobinfo_field_jobgroup}<font color="red">*</font></label>
-						<div class="col-sm-4">
-							<select class="form-control" name="jobGroup" >
-		            			<#list JobGroupList as group>
-		            				<option value="${group.id}" <#if jobGroup==group.id>selected</#if> >${group.title}</option>
-		            			</#list>
-		                  	</select>
-						</div>
-                        <label for="lastname" class="col-sm-2 control-label">${I18n.jobinfo_field_jobdesc}<font color="red">*</font></label>
-                        <div class="col-sm-4"><input type="text" class="form-control" name="jobDesc" placeholder="${I18n.system_please_input}${I18n.jobinfo_field_jobdesc}" maxlength="50" ></div>
-					</div>
-                    <div class="form-group">
-                        <label for="firstname" class="col-sm-2 control-label">${I18n.jobinfo_field_executorRouteStrategy}<font color="red">*</font></label>
-                        <div class="col-sm-4">
-                            <select class="form-control" name="executorRouteStrategy" >
-							<#list ExecutorRouteStrategyEnum as item>
-                                <option value="${item}" >${item.title}</option>
-							</#list>
-                            </select>
-                        </div>
-                        <label for="lastname" class="col-sm-2 control-label">Cron<font color="red">*</font></label>
-                        <div class="col-sm-4"><input type="text" class="form-control" name="jobCron" placeholder="${I18n.system_please_input}Cron" maxlength="128" ></div>
-                    </div>
-                    <div class="form-group">
-                        <label for="firstname" class="col-sm-2 control-label">${I18n.jobinfo_field_gluetype}<font color="red">*</font></label>
-                        <div class="col-sm-4">
-                            <select class="form-control glueType" name="glueType" >
-								<#list GlueTypeEnum as item>
-									<option value="${item}" >${item.desc}</option>
-								</#list>
-                            </select>
-                        </div>
-                        <label for="firstname" class="col-sm-2 control-label">JobHandler<font color="red">*</font></label>
-                        <div class="col-sm-4"><input type="text" class="form-control" name="executorHandler" placeholder="${I18n.system_please_input}JobHandler" maxlength="100" ></div>
-                    </div>
-                    <div class="form-group">
-                        <label for="firstname" class="col-sm-2 control-label">${I18n.jobinfo_field_executorparam}<font color="black">*</font></label>
-                        <div class="col-sm-4"><input type="text" class="form-control" name="executorParam" placeholder="${I18n.system_please_input}${I18n.jobinfo_field_executorparam}" maxlength="512" ></div>
-                        <label for="lastname" class="col-sm-2 control-label">${I18n.jobinfo_field_childJobId}<font color="black">*</font></label>
-                        <div class="col-sm-4"><input type="text" class="form-control" name="childJobId" placeholder="${I18n.jobinfo_field_childJobId_placeholder}" maxlength="100" ></div>
-                    </div>
-                    <div class="form-group">
-                        <label for="lastname" class="col-sm-2 control-label">${I18n.jobinfo_field_timeout}<font color="black">*</font></label>
-                        <div class="col-sm-4"><input type="text" class="form-control" name="executorTimeout" placeholder="${I18n.jobinfo_field_executorTimeout_placeholder}" maxlength="6" ></div>
-                        <label for="firstname" class="col-sm-2 control-label">${I18n.jobinfo_field_executorBlockStrategy}<font color="red">*</font></label>
-                        <div class="col-sm-4">
-                            <select class="form-control" name="executorBlockStrategy" >
-								<#list ExecutorBlockStrategyEnum as item>
-                                    <option value="${item}" >${item.title}</option>
-                                </#list>
-                            </select>
-                        </div>
-                    </div>
-                    <div class="form-group">
-                        <label for="lastname" class="col-sm-2 control-label">${I18n.jobinfo_field_executorFailRetryCount}<font color="black">*</font></label>
-                        <div class="col-sm-4"><input type="text" class="form-control" name="executorFailRetryCount" placeholder="${I18n.jobinfo_field_executorFailRetryCount_placeholder}" maxlength="4" ></div>
-                        <label for="lastname" class="col-sm-2 control-label">${I18n.jobinfo_field_alarmemail}<font color="black">*</font></label>
-                        <div class="col-sm-4"><input type="text" class="form-control" name="alarmEmail" placeholder="${I18n.jobinfo_field_alarmemail_placeholder}" maxlength="100" ></div>
-                    </div>
-					<div class="form-group">
-                        <label for="lastname" class="col-sm-2 control-label">${I18n.jobinfo_field_author}<font color="red">*</font></label>
-                        <div class="col-sm-4"><input type="text" class="form-control" name="author" placeholder="${I18n.system_please_input}${I18n.jobinfo_field_author}" maxlength="50" ></div>
-					</div>
-
-                    <hr>
-					<div class="form-group">
-						<div class="col-sm-offset-3 col-sm-6">
-							<button type="submit" class="btn btn-primary"  >${I18n.system_save}</button>
-							<button type="button" class="btn btn-default" data-dismiss="modal">${I18n.system_cancel}</button>
-						</div>
-					</div>
-
-<input type="hidden" name="glueRemark" value="GLUE代码初始化" >
-<textarea name="glueSource" style="display:none;" ></textarea>
-<textarea class="glueSource_java" style="display:none;" >
-package com.xxl.job.service.handler;
-
-import com.xxl.job.core.log.XxlJobLogger;
-import com.xxl.job.core.biz.model.ReturnT;
-import com.xxl.job.core.handler.IJobHandler;
-
-public class DemoGlueJobHandler extends IJobHandler {
-
-	@Override
-	public ReturnT<String> execute(String param) throws Exception {
-		XxlJobLogger.log("XXL-JOB, Hello World.");
-		return ReturnT.SUCCESS;
-	}
-
-}
-</textarea>
-<textarea class="glueSource_shell" style="display:none;" >
-#!/bin/bash
-echo "xxl-job: hello shell"
-
-echo "${I18n.jobinfo_script_location}:$0"
-echo "${I18n.jobinfo_field_executorparam}:$1"
-echo "${I18n.jobinfo_shard_index} = $2"
-echo "${I18n.jobinfo_shard_total} = $3"
-<#--echo "参数数量:$#"
-for param in $*
-do
-    echo "参数 : $param"
-    sleep 1s
-done-->
-
-echo "Good bye!"
-exit 0
-</textarea>
-<textarea class="glueSource_python" style="display:none;" >
-#!/usr/bin/python
-# -*- coding: UTF-8 -*-
-import time
-import sys
-
-print "xxl-job: hello python"
-
-print "${I18n.jobinfo_script_location}:", sys.argv[0]
-print "${I18n.jobinfo_field_executorparam}:", sys.argv[1]
-print "${I18n.jobinfo_shard_index}:", sys.argv[2]
-print "${I18n.jobinfo_shard_total}:", sys.argv[3]
-<#--for i in range(1, len(sys.argv)):
-	time.sleep(1)
-	print "参数", i, sys.argv[i]-->
-
-print "Good bye!"
-exit(0)
-<#--
-import logging
-logging.basicConfig(level=logging.DEBUG)
-logging.info("脚本文件:" + sys.argv[0])
--->
-</textarea>
-<#--这里有问题,新建一个运行模式为 php 的任务后,GLUE 中没有下边的 php 代码-->
-<textarea class="glueSource_php" style="display:none;" >
-<?php
-
-    echo "xxl-job: hello php  \n";
-
-    echo "${I18n.jobinfo_script_location}:$argv[0]  \n";
-    echo "${I18n.jobinfo_field_executorparam}:$argv[1]  \n";
-    echo "${I18n.jobinfo_shard_index} = $argv[2]  \n";
-    echo "${I18n.jobinfo_shard_total} = $argv[3]  \n";
-
-    echo "Good bye!  \n";
-    exit(0);
-
-?>
-</textarea>
-<textarea class="glueSource_nodejs" style="display:none;" >
-#!/usr/bin/env node
-console.log("xxl-job: hello nodejs")
-
-var arguments = process.argv
-
-console.log("${I18n.jobinfo_script_location}: " + arguments[1])
-console.log("${I18n.jobinfo_field_executorparam}: " + arguments[2])
-console.log("${I18n.jobinfo_shard_index}: " + arguments[3])
-console.log("${I18n.jobinfo_shard_total}: " + arguments[4])
-<#--for (var i = 2; i < arguments.length; i++){
-	console.log("参数 %s = %s", (i-1), arguments[i]);
-}-->
-
-console.log("Good bye!")
-process.exit(0)
-</textarea>		
-				</form>
-         	</div>
-		</div>
-	</div>
-</div>
-
-<!-- 更新.模态框 -->
-<div class="modal fade" id="updateModal" tabindex="-1" role="dialog"  aria-hidden="true">
-	<div class="modal-dialog modal-lg">
-		<div class="modal-content">
-			<div class="modal-header">
-            	<h4 class="modal-title" >${I18n.jobinfo_field_update}</h4>
-         	</div>
-         	<div class="modal-body">
-				<form class="form-horizontal form" role="form" >
-					<div class="form-group">
-                        <label for="firstname" class="col-sm-2 control-label">${I18n.jobinfo_field_jobgroup}<font color="red">*</font></label>
-                        <div class="col-sm-4">
-                            <select class="form-control" name="jobGroup" disabled >
-							<#list JobGroupList as group>
-                                <option value="${group.id}" >${group.title}</option>
-							</#list>
-                            </select>
-                        </div>
-                        <label for="lastname" class="col-sm-2 control-label">${I18n.jobinfo_field_jobdesc}<font color="red">*</font></label>
-                        <div class="col-sm-4"><input type="text" class="form-control" name="jobDesc" placeholder="${I18n.system_please_input}${I18n.jobinfo_field_jobdesc}" maxlength="50" ></div>
-                    </div>
-                    <div class="form-group">
-                        <label for="firstname" class="col-sm-2 control-label">${I18n.jobinfo_field_executorRouteStrategy}<font color="red">*</font></label>
-                        <div class="col-sm-4">
-                            <select class="form-control" name="executorRouteStrategy" >
-							<#list ExecutorRouteStrategyEnum as item>
-                                <option value="${item}" >${item.title}</option>
-							</#list>
-                            </select>
-                        </div>
-                        <label for="lastname" class="col-sm-2 control-label">Cron<font color="red">*</font></label>
-                        <div class="col-sm-4"><input type="text" class="form-control" name="jobCron" placeholder="${I18n.system_please_input}Cron" maxlength="128" ></div>
-                    </div>
-                    <div class="form-group">
-                        <label for="firstname" class="col-sm-2 control-label">${I18n.jobinfo_field_gluetype}<font color="red">*</font></label>
-                        <div class="col-sm-4">
-                            <select class="form-control glueType" name="glueType" disabled >
-							<#list GlueTypeEnum as item>
-                                <option value="${item}" >${item.desc}</option>
-							</#list>
-                            </select>
-                        </div>
-                        <label for="firstname" class="col-sm-2 control-label">JobHandler<font color="red">*</font></label>
-                        <div class="col-sm-4"><input type="text" class="form-control" name="executorHandler" placeholder="${I18n.system_please_input}JobHandler" maxlength="100" ></div>
-                    </div>
-                    <div class="form-group">
-                        <label for="firstname" class="col-sm-2 control-label">${I18n.jobinfo_field_executorparam}<font color="black">*</font></label>
-                        <div class="col-sm-4"><input type="text" class="form-control" name="executorParam" placeholder="${I18n.system_please_input}${I18n.jobinfo_field_executorparam}" maxlength="512" ></div>
-                        <label for="lastname" class="col-sm-2 control-label">${I18n.jobinfo_field_childJobId}<font color="black">*</font></label>
-                        <div class="col-sm-4"><input type="text" class="form-control" name="childJobId" placeholder="${I18n.jobinfo_field_childJobId_placeholder}" maxlength="100" ></div>
-                    </div>
-                    <div class="form-group">
-                        <label for="lastname" class="col-sm-2 control-label">${I18n.jobinfo_field_timeout}<font color="black">*</font></label>
-                        <div class="col-sm-4"><input type="text" class="form-control" name="executorTimeout" placeholder="${I18n.jobinfo_field_executorTimeout_placeholder}" maxlength="6" ></div>
-                        <label for="firstname" class="col-sm-2 control-label">${I18n.jobinfo_field_executorBlockStrategy}<font color="red">*</font></label>
-                        <div class="col-sm-4">
-                            <select class="form-control" name="executorBlockStrategy" >
-							<#list ExecutorBlockStrategyEnum as item>
-                                <option value="${item}" >${item.title}</option>
-                            </#list>
-                            </select>
-                        </div>
-                    </div>
-                    <div class="form-group">
-                        <label for="lastname" class="col-sm-2 control-label">${I18n.jobinfo_field_executorFailRetryCount}<font color="black">*</font></label>
-                        <div class="col-sm-4"><input type="text" class="form-control" name="executorFailRetryCount" placeholder="${I18n.jobinfo_field_executorFailRetryCount_placeholder}" maxlength="4" ></div>
-                        <label for="lastname" class="col-sm-2 control-label">${I18n.jobinfo_field_alarmemail}<font color="black">*</font></label>
-                        <div class="col-sm-4"><input type="text" class="form-control" name="alarmEmail" placeholder="${I18n.jobinfo_field_alarmemail_placeholder}" maxlength="100" ></div>
-
-                    </div>
-                    <div class="form-group">
-                        <label for="lastname" class="col-sm-2 control-label">${I18n.jobinfo_field_author}<font color="red">*</font></label>
-                        <div class="col-sm-4"><input type="text" class="form-control" name="author" placeholder="${I18n.system_please_input}${I18n.jobinfo_field_author}" maxlength="50" ></div>
-                    </div>
-
-					<hr>
-					<div class="form-group">
-                        <div class="col-sm-offset-3 col-sm-6">
-							<button type="submit" class="btn btn-primary"  >${I18n.system_save}</button>
-							<button type="button" class="btn btn-default" data-dismiss="modal">${I18n.system_cancel}</button>
-                            <input type="hidden" name="id" >
-						</div>
-					</div>
-
-				</form>
-         	</div>
-		</div>
-	</div>
-</div>
-
-<@netCommon.commonScript />
-<!-- DataTables -->
-<script src="${request.contextPath}/static/adminlte/plugins/datatables/jquery.dataTables.min.js"></script>
-<script src="${request.contextPath}/static/adminlte/plugins/datatables/dataTables.bootstrap.min.js"></script>
-<script src="${request.contextPath}/static/plugins/jquery/jquery.validate.min.js"></script>
-<!-- moment -->
-<script src="${request.contextPath}/static/adminlte/plugins/daterangepicker/moment.min.js"></script>
-<script src="${request.contextPath}/static/js/jobinfo.index.1.js"></script>
-</body>
-</html>
+<!DOCTYPE html>
+<html>
+<head>
+  	<#import "/common/common.macro.ftl" as netCommon>
+	<@netCommon.commonStyle />
+	<!-- DataTables -->
+  	<link rel="stylesheet" href="${request.contextPath}/static/adminlte/plugins/datatables/dataTables.bootstrap.css">
+    <title>${I18n.admin_name}</title>
+</head>
+<body class="hold-transition skin-blue sidebar-mini <#if cookieMap?exists && "off" == cookieMap["xxljob_adminlte_settings"].value >sidebar-collapse</#if>">
+<div class="wrapper">
+	<!-- header -->
+	<@netCommon.commonHeader />
+	<!-- left -->
+	<@netCommon.commonLeft "jobinfo" />
+	
+	<!-- Content Wrapper. Contains page content -->
+	<div class="content-wrapper">
+		<!-- Content Header (Page header) -->
+		<section class="content-header">
+			<h1>${I18n.jobinfo_name}</h1>
+		</section>
+		
+		<!-- Main content -->
+	    <section class="content">
+	    
+	    	<div class="row">
+	    		<div class="col-xs-3">
+	              	<div class="input-group">
+	                	<span class="input-group-addon">${I18n.jobinfo_field_jobgroup}</span>
+                		<select class="form-control" id="jobGroup" >
+                			<#list JobGroupList as group>
+                				<option value="${group.id}" <#if jobGroup==group.id>selected</#if> >${group.title}</option>
+                			</#list>
+	                  	</select>
+	              	</div>
+	            </div>
+                <div class="col-xs-3">
+                    <div class="input-group">
+                        <span class="input-group-addon">${I18n.jobinfo_field_jobdesc}</span>
+                        <input type="text" class="form-control" id="jobDesc" autocomplete="on" >
+                    </div>
+                </div>
+                <div class="col-xs-3">
+                    <div class="input-group">
+                        <span class="input-group-addon">JobHandler</span>
+                        <input type="text" class="form-control" id="executorHandler" autocomplete="on" >
+                    </div>
+                </div>
+	            <div class="col-xs-1">
+	            	<button class="btn btn-block btn-info" id="searchBtn">${I18n.system_search}</button>
+	            </div>
+	            <div class="col-xs-2">
+	            	<button class="btn btn-block btn-success add" type="button">${I18n.jobinfo_field_add}</button>
+	            </div>
+          	</div>
+	    	
+			<div class="row">
+				<div class="col-xs-12">
+					<div class="box">
+			            <#--<div class="box-header hide">
+			            	<h3 class="box-title">调度列表</h3>
+			            </div>-->
+			            <div class="box-body" >
+			              	<table id="job_list" class="table table-bordered table-striped" width="100%" >
+				                <thead>
+					            	<tr>
+					            		<th name="id" >${I18n.jobinfo_field_id}</th>
+					                	<th name="jobGroup" >${I18n.jobinfo_field_jobgroup}</th>
+					                  	<th name="jobDesc" >${I18n.jobinfo_field_jobdesc}</th>
+                                        <th name="glueType" >${I18n.jobinfo_field_gluetype}</th>
+					                  	<th name="executorParam" >${I18n.jobinfo_field_executorparam}</th>
+                                        <th name="jobCron" >Cron</th>
+					                  	<th name="addTime" >addTime</th>
+					                  	<th name="updateTime" >updateTime</th>
+					                  	<th name="author" >${I18n.jobinfo_field_author}</th>
+					                  	<th name="alarmEmail" >${I18n.jobinfo_field_alarmemail}</th>
+					                  	<th name="jobStatus" >${I18n.system_status}</th>
+					                  	<th>${I18n.system_opt}</th>
+					                </tr>
+				                </thead>
+				                <tbody></tbody>
+				                <tfoot></tfoot>
+							</table>
+						</div>
+					</div>
+				</div>
+			</div>
+	    </section>
+	</div>
+	
+	<!-- footer -->
+	<@netCommon.commonFooter />
+</div>
+
+<!-- job新增.模态框 -->
+<div class="modal fade" id="addModal" tabindex="-1" role="dialog"  aria-hidden="true">
+	<div class="modal-dialog modal-lg">
+		<div class="modal-content">
+			<div class="modal-header">
+            	<h4 class="modal-title" >${I18n.jobinfo_field_add}</h4>
+         	</div>
+         	<div class="modal-body">
+				<form class="form-horizontal form" role="form" >
+					<div class="form-group">
+						<label for="firstname" class="col-sm-2 control-label">${I18n.jobinfo_field_jobgroup}<font color="red">*</font></label>
+						<div class="col-sm-4">
+							<select class="form-control" name="jobGroup" >
+		            			<#list JobGroupList as group>
+		            				<option value="${group.id}" <#if jobGroup==group.id>selected</#if> >${group.title}</option>
+		            			</#list>
+		                  	</select>
+						</div>
+                        <label for="lastname" class="col-sm-2 control-label">${I18n.jobinfo_field_jobdesc}<font color="red">*</font></label>
+                        <div class="col-sm-4"><input type="text" class="form-control" name="jobDesc" placeholder="${I18n.system_please_input}${I18n.jobinfo_field_jobdesc}" maxlength="50" ></div>
+					</div>
+                    <div class="form-group">
+                        <label for="firstname" class="col-sm-2 control-label">${I18n.jobinfo_field_executorRouteStrategy}<font color="red">*</font></label>
+                        <div class="col-sm-4">
+                            <select class="form-control" name="executorRouteStrategy" >
+							<#list ExecutorRouteStrategyEnum as item>
+                                <option value="${item}" >${item.title}</option>
+							</#list>
+                            </select>
+                        </div>
+                        <label for="lastname" class="col-sm-2 control-label">Cron<font color="red">*</font></label>
+                        <div class="col-sm-4"><input type="text" class="form-control" name="jobCron" placeholder="${I18n.system_please_input}Cron" maxlength="128" ></div>
+                    </div>
+                    <div class="form-group">
+                        <label for="firstname" class="col-sm-2 control-label">${I18n.jobinfo_field_gluetype}<font color="red">*</font></label>
+                        <div class="col-sm-4">
+                            <select class="form-control glueType" name="glueType" >
+								<#list GlueTypeEnum as item>
+									<option value="${item}" >${item.desc}</option>
+								</#list>
+                            </select>
+                        </div>
+                        <label for="firstname" class="col-sm-2 control-label">JobHandler<font color="red">*</font></label>
+                        <div class="col-sm-4"><input type="text" class="form-control" name="executorHandler" placeholder="${I18n.system_please_input}JobHandler" maxlength="100" ></div>
+                    </div>
+                    <div class="form-group">
+                        <label for="firstname" class="col-sm-2 control-label">${I18n.jobinfo_field_executorparam}<font color="black">*</font></label>
+                        <div class="col-sm-4"><input type="text" class="form-control" name="executorParam" placeholder="${I18n.system_please_input}${I18n.jobinfo_field_executorparam}" maxlength="512" ></div>
+                        <label for="lastname" class="col-sm-2 control-label">${I18n.jobinfo_field_childJobId}<font color="black">*</font></label>
+                        <div class="col-sm-4"><input type="text" class="form-control" name="childJobId" placeholder="${I18n.jobinfo_field_childJobId_placeholder}" maxlength="100" ></div>
+                    </div>
+                    <div class="form-group">
+                        <label for="lastname" class="col-sm-2 control-label">${I18n.jobinfo_field_timeout}<font color="black">*</font></label>
+                        <div class="col-sm-4"><input type="text" class="form-control" name="executorTimeout" placeholder="${I18n.jobinfo_field_executorTimeout_placeholder}" maxlength="6" ></div>
+                        <label for="firstname" class="col-sm-2 control-label">${I18n.jobinfo_field_executorBlockStrategy}<font color="red">*</font></label>
+                        <div class="col-sm-4">
+                            <select class="form-control" name="executorBlockStrategy" >
+								<#list ExecutorBlockStrategyEnum as item>
+                                    <option value="${item}" >${item.title}</option>
+                                </#list>
+                            </select>
+                        </div>
+                    </div>
+                    <div class="form-group">
+                        <label for="lastname" class="col-sm-2 control-label">${I18n.jobinfo_field_executorFailRetryCount}<font color="black">*</font></label>
+                        <div class="col-sm-4"><input type="text" class="form-control" name="executorFailRetryCount" placeholder="${I18n.jobinfo_field_executorFailRetryCount_placeholder}" maxlength="4" ></div>
+                        <label for="lastname" class="col-sm-2 control-label">${I18n.jobinfo_field_alarmemail}<font color="black">*</font></label>
+                        <div class="col-sm-4"><input type="text" class="form-control" name="alarmEmail" placeholder="${I18n.jobinfo_field_alarmemail_placeholder}" maxlength="100" ></div>
+                    </div>
+					<div class="form-group">
+                        <label for="lastname" class="col-sm-2 control-label">${I18n.jobinfo_field_author}<font color="red">*</font></label>
+                        <div class="col-sm-4"><input type="text" class="form-control" name="author" placeholder="${I18n.system_please_input}${I18n.jobinfo_field_author}" maxlength="50" ></div>
+					</div>
+
+                    <hr>
+					<div class="form-group">
+						<div class="col-sm-offset-3 col-sm-6">
+							<button type="submit" class="btn btn-primary"  >${I18n.system_save}</button>
+							<button type="button" class="btn btn-default" data-dismiss="modal">${I18n.system_cancel}</button>
+						</div>
+					</div>
+
+<input type="hidden" name="glueRemark" value="GLUE代码初始化" >
+<textarea name="glueSource" style="display:none;" ></textarea>
+<textarea class="glueSource_java" style="display:none;" >
+package com.xxl.job.service.handler;
+
+import com.xxl.job.core.log.XxlJobLogger;
+import com.xxl.job.core.biz.model.ReturnT;
+import com.xxl.job.core.handler.IJobHandler;
+
+public class DemoGlueJobHandler extends IJobHandler {
+
+	@Override
+	public ReturnT<String> execute(String param) throws Exception {
+		XxlJobLogger.log("XXL-JOB, Hello World.");
+		return ReturnT.SUCCESS;
+	}
+
+}
+</textarea>
+<textarea class="glueSource_shell" style="display:none;" >
+#!/bin/bash
+echo "xxl-job: hello shell"
+
+echo "${I18n.jobinfo_script_location}:$0"
+echo "${I18n.jobinfo_field_executorparam}:$1"
+echo "${I18n.jobinfo_shard_index} = $2"
+echo "${I18n.jobinfo_shard_total} = $3"
+<#--echo "参数数量:$#"
+for param in $*
+do
+    echo "参数 : $param"
+    sleep 1s
+done-->
+
+echo "Good bye!"
+exit 0
+</textarea>
+<textarea class="glueSource_python" style="display:none;" >
+#!/usr/bin/python
+# -*- coding: UTF-8 -*-
+import time
+import sys
+
+print "xxl-job: hello python"
+
+print "${I18n.jobinfo_script_location}:", sys.argv[0]
+print "${I18n.jobinfo_field_executorparam}:", sys.argv[1]
+print "${I18n.jobinfo_shard_index}:", sys.argv[2]
+print "${I18n.jobinfo_shard_total}:", sys.argv[3]
+<#--for i in range(1, len(sys.argv)):
+	time.sleep(1)
+	print "参数", i, sys.argv[i]-->
+
+print "Good bye!"
+exit(0)
+<#--
+import logging
+logging.basicConfig(level=logging.DEBUG)
+logging.info("脚本文件:" + sys.argv[0])
+-->
+</textarea>
+<#--这里有问题,新建一个运行模式为 php 的任务后,GLUE 中没有下边的 php 代码-->
+<textarea class="glueSource_php" style="display:none;" >
+<?php
+
+    echo "xxl-job: hello php  \n";
+
+    echo "${I18n.jobinfo_script_location}:$argv[0]  \n";
+    echo "${I18n.jobinfo_field_executorparam}:$argv[1]  \n";
+    echo "${I18n.jobinfo_shard_index} = $argv[2]  \n";
+    echo "${I18n.jobinfo_shard_total} = $argv[3]  \n";
+
+    echo "Good bye!  \n";
+    exit(0);
+
+?>
+</textarea>
+<textarea class="glueSource_nodejs" style="display:none;" >
+#!/usr/bin/env node
+console.log("xxl-job: hello nodejs")
+
+var arguments = process.argv
+
+console.log("${I18n.jobinfo_script_location}: " + arguments[1])
+console.log("${I18n.jobinfo_field_executorparam}: " + arguments[2])
+console.log("${I18n.jobinfo_shard_index}: " + arguments[3])
+console.log("${I18n.jobinfo_shard_total}: " + arguments[4])
+<#--for (var i = 2; i < arguments.length; i++){
+	console.log("参数 %s = %s", (i-1), arguments[i]);
+}-->
+
+console.log("Good bye!")
+process.exit(0)
+</textarea>		
+				</form>
+         	</div>
+		</div>
+	</div>
+</div>
+
+<!-- 更新.模态框 -->
+<div class="modal fade" id="updateModal" tabindex="-1" role="dialog"  aria-hidden="true">
+	<div class="modal-dialog modal-lg">
+		<div class="modal-content">
+			<div class="modal-header">
+            	<h4 class="modal-title" >${I18n.jobinfo_field_update}</h4>
+         	</div>
+         	<div class="modal-body">
+				<form class="form-horizontal form" role="form" >
+					<div class="form-group">
+                        <label for="firstname" class="col-sm-2 control-label">${I18n.jobinfo_field_jobgroup}<font color="red">*</font></label>
+                        <div class="col-sm-4">
+                            <select class="form-control" name="jobGroup" disabled >
+							<#list JobGroupList as group>
+                                <option value="${group.id}" >${group.title}</option>
+							</#list>
+                            </select>
+                        </div>
+                        <label for="lastname" class="col-sm-2 control-label">${I18n.jobinfo_field_jobdesc}<font color="red">*</font></label>
+                        <div class="col-sm-4"><input type="text" class="form-control" name="jobDesc" placeholder="${I18n.system_please_input}${I18n.jobinfo_field_jobdesc}" maxlength="50" ></div>
+                    </div>
+                    <div class="form-group">
+                        <label for="firstname" class="col-sm-2 control-label">${I18n.jobinfo_field_executorRouteStrategy}<font color="red">*</font></label>
+                        <div class="col-sm-4">
+                            <select class="form-control" name="executorRouteStrategy" >
+							<#list ExecutorRouteStrategyEnum as item>
+                                <option value="${item}" >${item.title}</option>
+							</#list>
+                            </select>
+                        </div>
+                        <label for="lastname" class="col-sm-2 control-label">Cron<font color="red">*</font></label>
+                        <div class="col-sm-4"><input type="text" class="form-control" name="jobCron" placeholder="${I18n.system_please_input}Cron" maxlength="128" ></div>
+                    </div>
+                    <div class="form-group">
+                        <label for="firstname" class="col-sm-2 control-label">${I18n.jobinfo_field_gluetype}<font color="red">*</font></label>
+                        <div class="col-sm-4">
+                            <select class="form-control glueType" name="glueType" disabled >
+							<#list GlueTypeEnum as item>
+                                <option value="${item}" >${item.desc}</option>
+							</#list>
+                            </select>
+                        </div>
+                        <label for="firstname" class="col-sm-2 control-label">JobHandler<font color="red">*</font></label>
+                        <div class="col-sm-4"><input type="text" class="form-control" name="executorHandler" placeholder="${I18n.system_please_input}JobHandler" maxlength="100" ></div>
+                    </div>
+                    <div class="form-group">
+                        <label for="firstname" class="col-sm-2 control-label">${I18n.jobinfo_field_executorparam}<font color="black">*</font></label>
+                        <div class="col-sm-4"><input type="text" class="form-control" name="executorParam" placeholder="${I18n.system_please_input}${I18n.jobinfo_field_executorparam}" maxlength="512" ></div>
+                        <label for="lastname" class="col-sm-2 control-label">${I18n.jobinfo_field_childJobId}<font color="black">*</font></label>
+                        <div class="col-sm-4"><input type="text" class="form-control" name="childJobId" placeholder="${I18n.jobinfo_field_childJobId_placeholder}" maxlength="100" ></div>
+                    </div>
+                    <div class="form-group">
+                        <label for="lastname" class="col-sm-2 control-label">${I18n.jobinfo_field_timeout}<font color="black">*</font></label>
+                        <div class="col-sm-4"><input type="text" class="form-control" name="executorTimeout" placeholder="${I18n.jobinfo_field_executorTimeout_placeholder}" maxlength="6" ></div>
+                        <label for="firstname" class="col-sm-2 control-label">${I18n.jobinfo_field_executorBlockStrategy}<font color="red">*</font></label>
+                        <div class="col-sm-4">
+                            <select class="form-control" name="executorBlockStrategy" >
+							<#list ExecutorBlockStrategyEnum as item>
+                                <option value="${item}" >${item.title}</option>
+                            </#list>
+                            </select>
+                        </div>
+                    </div>
+                    <div class="form-group">
+                        <label for="lastname" class="col-sm-2 control-label">${I18n.jobinfo_field_executorFailRetryCount}<font color="black">*</font></label>
+                        <div class="col-sm-4"><input type="text" class="form-control" name="executorFailRetryCount" placeholder="${I18n.jobinfo_field_executorFailRetryCount_placeholder}" maxlength="4" ></div>
+                        <label for="lastname" class="col-sm-2 control-label">${I18n.jobinfo_field_alarmemail}<font color="black">*</font></label>
+                        <div class="col-sm-4"><input type="text" class="form-control" name="alarmEmail" placeholder="${I18n.jobinfo_field_alarmemail_placeholder}" maxlength="100" ></div>
+
+                    </div>
+                    <div class="form-group">
+                        <label for="lastname" class="col-sm-2 control-label">${I18n.jobinfo_field_author}<font color="red">*</font></label>
+                        <div class="col-sm-4"><input type="text" class="form-control" name="author" placeholder="${I18n.system_please_input}${I18n.jobinfo_field_author}" maxlength="50" ></div>
+                    </div>
+
+					<hr>
+					<div class="form-group">
+                        <div class="col-sm-offset-3 col-sm-6">
+							<button type="submit" class="btn btn-primary"  >${I18n.system_save}</button>
+							<button type="button" class="btn btn-default" data-dismiss="modal">${I18n.system_cancel}</button>
+                            <input type="hidden" name="id" >
+						</div>
+					</div>
+
+				</form>
+         	</div>
+		</div>
+	</div>
+</div>
+
+<@netCommon.commonScript />
+<!-- DataTables -->
+<script src="${request.contextPath}/static/adminlte/plugins/datatables/jquery.dataTables.min.js"></script>
+<script src="${request.contextPath}/static/adminlte/plugins/datatables/dataTables.bootstrap.min.js"></script>
+<script src="${request.contextPath}/static/plugins/jquery/jquery.validate.min.js"></script>
+<!-- moment -->
+<script src="${request.contextPath}/static/adminlte/plugins/daterangepicker/moment.min.js"></script>
+<script src="${request.contextPath}/static/js/jobinfo.index.1.js"></script>
+</body>
+</html>

File diff suppressed because it is too large
+ 505 - 505
xxl-job-admin/src/main/webapp/static/js/jobinfo.index.1.js