提交 0e805413 编写于 作者: X xueli.xue

交互重构

上级 0f4c412f
package com.xxl.job.controller;
import javax.servlet.http.HttpServletRequest;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
/**
* job code controller
* @author xuxueli 2015-12-19 16:13:16
*/
@Controller
@RequestMapping("/jobcode")
public class JobCodeController {
@RequestMapping
public String index(Model model, HttpServletRequest request) {
return "jobcode/index";
}
}
package com.xxl.job.controller; package com.xxl.job.controller;
import java.util.ArrayList;
import java.util.HashMap; import java.util.HashMap;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
...@@ -9,7 +8,6 @@ import javax.annotation.Resource; ...@@ -9,7 +8,6 @@ import javax.annotation.Resource;
import org.apache.commons.lang.StringUtils; import org.apache.commons.lang.StringUtils;
import org.quartz.CronExpression; import org.quartz.CronExpression;
import org.quartz.Job;
import org.quartz.SchedulerException; import org.quartz.SchedulerException;
import org.springframework.stereotype.Controller; import org.springframework.stereotype.Controller;
import org.springframework.ui.Model; import org.springframework.ui.Model;
...@@ -25,14 +23,11 @@ import com.xxl.job.core.model.XxlJobInfo; ...@@ -25,14 +23,11 @@ import com.xxl.job.core.model.XxlJobInfo;
import com.xxl.job.core.util.DynamicSchedulerUtil; import com.xxl.job.core.util.DynamicSchedulerUtil;
import com.xxl.job.dao.IXxlJobInfoDao; import com.xxl.job.dao.IXxlJobInfoDao;
import com.xxl.job.service.job.RemoteHttpJobBean; import com.xxl.job.service.job.RemoteHttpJobBean;
import com.xxl.job.service.job.impl.DemoConcurrentJobBean;
import com.xxl.job.service.job.impl.DemoNomalJobBean;
/** /**
* index controller * index controller
* @author xuxueli 2015-12-19 16:13:16 * @author xuxueli 2015-12-19 16:13:16
*/ */
@SuppressWarnings("unchecked")
@Controller @Controller
@RequestMapping("/jobinfo") @RequestMapping("/jobinfo")
public class JobInfoController { public class JobInfoController {
...@@ -40,19 +35,8 @@ public class JobInfoController { ...@@ -40,19 +35,8 @@ public class JobInfoController {
@Resource @Resource
private IXxlJobInfoDao xxlJobInfoDao; private IXxlJobInfoDao xxlJobInfoDao;
// remote job bean
public static Class <? extends Job> remoteJobBean = RemoteHttpJobBean.class;
// loacal job bean
public static List<Class <? extends Job>> localJobBeanList = new ArrayList<Class<? extends Job>>();
static{
localJobBeanList.add((Class<? extends Job>) DemoNomalJobBean.class);
localJobBeanList.add((Class<? extends Job>) DemoConcurrentJobBean.class);
}
@RequestMapping @RequestMapping
public String index(Model model) { public String index(Model model) {
model.addAttribute("localJobBeanList", localJobBeanList); // 本地任务-列表
model.addAttribute("remoteJobBean", remoteJobBean); // 远程任务-jobBean
model.addAttribute("JobGroupList", JobGroupEnum.values()); // 任务组列表 model.addAttribute("JobGroupList", JobGroupEnum.values()); // 任务组列表
return "jobinfo/index"; return "jobinfo/index";
} }
...@@ -84,8 +68,8 @@ public class JobInfoController { ...@@ -84,8 +68,8 @@ public class JobInfoController {
@RequestMapping("/add") @RequestMapping("/add")
@ResponseBody @ResponseBody
public ReturnT<String> add(String jobGroup, String jobName, String jobCron, String jobDesc, String jobClass, public ReturnT<String> add(String jobGroup, String jobName, String jobCron, String jobDesc,
String handler_params, String handler_address, String handler_name, String handler_address, String handler_name, String handler_params,
String author, String alarmEmail, int alarmThreshold) { String author, String alarmEmail, int alarmThreshold) {
// valid // valid
...@@ -101,25 +85,11 @@ public class JobInfoController { ...@@ -101,25 +85,11 @@ public class JobInfoController {
if (StringUtils.isBlank(jobDesc)) { if (StringUtils.isBlank(jobDesc)) {
return new ReturnT<String>(500, "请输入“任务描述”"); return new ReturnT<String>(500, "请输入“任务描述”");
} }
Class<? extends Job> jobClass_ = null; if (StringUtils.isBlank(handler_address)) {
try { return new ReturnT<String>(500, "请输入“机器地址”");
Class<?> clazz = Class.forName(jobClass);
if (clazz!=null) {
jobClass_ = (Class<? extends Job>) clazz;
}
} catch (ClassNotFoundException e1) {
e1.printStackTrace();
} }
if (jobClass_ == null) { if (StringUtils.isBlank(handler_name)) {
return new ReturnT<String>(500, "请选择“JobBean”"); return new ReturnT<String>(500, "请输入“执行器”");
}
if (jobClass_.getClass().getName().equals(remoteJobBean.getName())) {
if (StringUtils.isBlank(handler_address)) {
return new ReturnT<String>(500, "请输入“远程-机器地址”");
}
if (StringUtils.isBlank(handler_name)) {
return new ReturnT<String>(500, "请输入“远程-执行器”");
}
} }
if (StringUtils.isBlank(author)) { if (StringUtils.isBlank(author)) {
return new ReturnT<String>(500, "请输入“负责人”"); return new ReturnT<String>(500, "请输入“负责人”");
...@@ -127,6 +97,9 @@ public class JobInfoController { ...@@ -127,6 +97,9 @@ public class JobInfoController {
if (StringUtils.isBlank(alarmEmail)) { if (StringUtils.isBlank(alarmEmail)) {
return new ReturnT<String>(500, "请输入“报警邮件”"); return new ReturnT<String>(500, "请输入“报警邮件”");
} }
if (alarmThreshold < 0) {
alarmThreshold = 0;
}
try { try {
if (DynamicSchedulerUtil.checkExists(jobName, jobGroup)) { if (DynamicSchedulerUtil.checkExists(jobName, jobGroup)) {
...@@ -139,9 +112,9 @@ public class JobInfoController { ...@@ -139,9 +112,9 @@ public class JobInfoController {
// parse jobDataMap // parse jobDataMap
HashMap<String, String> jobDataMap = new HashMap<String, String>(); HashMap<String, String> jobDataMap = new HashMap<String, String>();
jobDataMap.put(HandlerRepository.HANDLER_PARAMS, handler_params);
jobDataMap.put(HandlerRepository.HANDLER_ADDRESS, handler_address); jobDataMap.put(HandlerRepository.HANDLER_ADDRESS, handler_address);
jobDataMap.put(HandlerRepository.HANDLER_NAME, handler_name); jobDataMap.put(HandlerRepository.HANDLER_NAME, handler_name);
jobDataMap.put(HandlerRepository.HANDLER_PARAMS, handler_params);
// Backup to the database // Backup to the database
XxlJobInfo jobInfo = new XxlJobInfo(); XxlJobInfo jobInfo = new XxlJobInfo();
...@@ -149,7 +122,7 @@ public class JobInfoController { ...@@ -149,7 +122,7 @@ public class JobInfoController {
jobInfo.setJobName(jobName); jobInfo.setJobName(jobName);
jobInfo.setJobCron(jobCron); jobInfo.setJobCron(jobCron);
jobInfo.setJobDesc(jobDesc); jobInfo.setJobDesc(jobDesc);
jobInfo.setJobClass(jobClass); jobInfo.setJobClass(RemoteHttpJobBean.class.getName());
jobInfo.setJobData(JacksonUtil.writeValueAsString(jobDataMap)); jobInfo.setJobData(JacksonUtil.writeValueAsString(jobDataMap));
jobInfo.setAuthor(author); jobInfo.setAuthor(author);
jobInfo.setAlarmEmail(alarmEmail); jobInfo.setAlarmEmail(alarmEmail);
...@@ -173,8 +146,8 @@ public class JobInfoController { ...@@ -173,8 +146,8 @@ public class JobInfoController {
@RequestMapping("/reschedule") @RequestMapping("/reschedule")
@ResponseBody @ResponseBody
public ReturnT<String> reschedule(String jobGroup, String jobName, String jobCron, String jobDesc, String jobClass, public ReturnT<String> reschedule(String jobGroup, String jobName, String jobCron, String jobDesc,
String handler_params, String handler_address, String handler_name, String handler_address, String handler_name, String handler_params,
String author, String alarmEmail, int alarmThreshold) { String author, String alarmEmail, int alarmThreshold) {
// valid // valid
...@@ -187,12 +160,30 @@ public class JobInfoController { ...@@ -187,12 +160,30 @@ public class JobInfoController {
if (!CronExpression.isValidExpression(jobCron)) { if (!CronExpression.isValidExpression(jobCron)) {
return new ReturnT<String>(500, "“corn”不合法"); return new ReturnT<String>(500, "“corn”不合法");
} }
if (StringUtils.isBlank(jobDesc)) {
return new ReturnT<String>(500, "请输入“任务描述”");
}
if (StringUtils.isBlank(handler_address)) {
return new ReturnT<String>(500, "请输入“机器地址”");
}
if (StringUtils.isBlank(handler_name)) {
return new ReturnT<String>(500, "请输入“执行器”");
}
if (StringUtils.isBlank(author)) {
return new ReturnT<String>(500, "请输入“负责人”");
}
if (StringUtils.isBlank(alarmEmail)) {
return new ReturnT<String>(500, "请输入“报警邮件”");
}
if (alarmThreshold < 0) {
alarmThreshold = 0;
}
// parse jobDataMap // parse jobDataMap
HashMap<String, String> jobDataMap = new HashMap<String, String>(); HashMap<String, String> jobDataMap = new HashMap<String, String>();
jobDataMap.put(HandlerRepository.HANDLER_PARAMS, handler_params);
jobDataMap.put(HandlerRepository.HANDLER_ADDRESS, handler_address); jobDataMap.put(HandlerRepository.HANDLER_ADDRESS, handler_address);
jobDataMap.put(HandlerRepository.HANDLER_NAME, handler_name); jobDataMap.put(HandlerRepository.HANDLER_NAME, handler_name);
jobDataMap.put(HandlerRepository.HANDLER_PARAMS, handler_params);
XxlJobInfo jobInfo = xxlJobInfoDao.load(jobGroup, jobName); XxlJobInfo jobInfo = xxlJobInfoDao.load(jobGroup, jobName);
jobInfo.setJobCron(jobCron); jobInfo.setJobCron(jobCron);
......
package com.xxl.job.service.job; //package com.xxl.job.service.job;
//
import java.io.PrintWriter; //import java.io.PrintWriter;
import java.io.StringWriter; //import java.io.StringWriter;
import java.util.Date; //import java.util.Date;
import java.util.HashMap; //import java.util.HashMap;
import java.util.Map; //import java.util.Map;
//
import org.apache.commons.lang.StringUtils; //import org.apache.commons.lang.StringUtils;
import org.quartz.JobExecutionContext; //import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException; //import org.quartz.JobExecutionException;
import org.quartz.JobKey; //import org.quartz.JobKey;
import org.slf4j.Logger; //import org.slf4j.Logger;
import org.slf4j.LoggerFactory; //import org.slf4j.LoggerFactory;
import org.springframework.scheduling.quartz.QuartzJobBean; //import org.springframework.scheduling.quartz.QuartzJobBean;
//
import com.xxl.job.client.handler.HandlerRepository; //import com.xxl.job.client.handler.HandlerRepository;
import com.xxl.job.client.util.HttpUtil.RemoteCallBack; //import com.xxl.job.client.util.HttpUtil.RemoteCallBack;
import com.xxl.job.client.util.JacksonUtil; //import com.xxl.job.client.util.JacksonUtil;
import com.xxl.job.core.model.XxlJobInfo; //import com.xxl.job.core.model.XxlJobInfo;
import com.xxl.job.core.model.XxlJobLog; //import com.xxl.job.core.model.XxlJobLog;
import com.xxl.job.core.thread.JobMonitorHelper; //import com.xxl.job.core.thread.JobMonitorHelper;
import com.xxl.job.core.util.DynamicSchedulerUtil; //import com.xxl.job.core.util.DynamicSchedulerUtil;
//
/** ///**
* http job bean // * http job bean
* @author xuxueli 2015-12-17 18:20:34 // * @author xuxueli 2015-12-17 18:20:34
*/ // */
public abstract class LocalNomalJobBean extends QuartzJobBean { //@Deprecated
private static Logger logger = LoggerFactory.getLogger(LocalNomalJobBean.class); //public abstract class LocalNomalJobBean extends QuartzJobBean {
// private static Logger logger = LoggerFactory.getLogger(LocalNomalJobBean.class);
@Override //
protected void executeInternal(JobExecutionContext context) // @Override
throws JobExecutionException { // protected void executeInternal(JobExecutionContext context)
JobKey jobKey = context.getTrigger().getJobKey(); // throws JobExecutionException {
// JobKey jobKey = context.getTrigger().getJobKey();
XxlJobInfo jobInfo = DynamicSchedulerUtil.xxlJobInfoDao.load(jobKey.getGroup(), jobKey.getName()); //
@SuppressWarnings("unchecked") // XxlJobInfo jobInfo = DynamicSchedulerUtil.xxlJobInfoDao.load(jobKey.getGroup(), jobKey.getName());
HashMap<String, String> jobDataMap = (HashMap<String, String>) JacksonUtil.readValueRefer(jobInfo.getJobData(), Map.class); // @SuppressWarnings("unchecked")
// HashMap<String, String> jobDataMap = (HashMap<String, String>) JacksonUtil.readValueRefer(jobInfo.getJobData(), Map.class);
// save log //
XxlJobLog jobLog = new XxlJobLog(); // // save log
jobLog.setJobGroup(jobInfo.getJobGroup()); // XxlJobLog jobLog = new XxlJobLog();
jobLog.setJobName(jobInfo.getJobName()); // jobLog.setJobGroup(jobInfo.getJobGroup());
jobLog.setJobCron(jobInfo.getJobCron()); // jobLog.setJobName(jobInfo.getJobName());
jobLog.setJobDesc(jobInfo.getJobDesc()); // jobLog.setJobCron(jobInfo.getJobCron());
jobLog.setJobClass(jobInfo.getJobClass()); // jobLog.setJobDesc(jobInfo.getJobDesc());
jobLog.setJobData(jobInfo.getJobData()); // jobLog.setJobClass(jobInfo.getJobClass());
// jobLog.setJobData(jobInfo.getJobData());
jobLog.setJobClass(RemoteHttpJobBean.class.getName()); //
jobLog.setJobData(jobInfo.getJobData()); // jobLog.setJobClass(RemoteHttpJobBean.class.getName());
DynamicSchedulerUtil.xxlJobLogDao.save(jobLog); // jobLog.setJobData(jobInfo.getJobData());
logger.info(">>>>>>>>>>> xxl-job trigger start, jobLog:{}", jobLog); // DynamicSchedulerUtil.xxlJobLogDao.save(jobLog);
// logger.info(">>>>>>>>>>> xxl-job trigger start, jobLog:{}", jobLog);
// trigger request //
String handler_params = jobDataMap.get(HandlerRepository.HANDLER_PARAMS); // // trigger request
String[] handlerParams = null; // String handler_params = jobDataMap.get(HandlerRepository.HANDLER_PARAMS);
if (StringUtils.isNotBlank(handler_params)) { // String[] handlerParams = null;
handlerParams = handler_params.split(","); // if (StringUtils.isNotBlank(handler_params)) {
} // handlerParams = handler_params.split(",");
// }
jobLog.setTriggerTime(new Date()); //
jobLog.setTriggerStatus(RemoteCallBack.SUCCESS); // jobLog.setTriggerTime(new Date());
jobLog.setTriggerMsg(null); // jobLog.setTriggerStatus(RemoteCallBack.SUCCESS);
// jobLog.setTriggerMsg(null);
try { //
Object responseMsg = this.handle(handlerParams); // try {
// Object responseMsg = this.handle(handlerParams);
jobLog.setHandleTime(new Date()); //
jobLog.setHandleStatus(RemoteCallBack.SUCCESS); // jobLog.setHandleTime(new Date());
jobLog.setHandleMsg(JacksonUtil.writeValueAsString(responseMsg)); // jobLog.setHandleStatus(RemoteCallBack.SUCCESS);
} catch (Exception e) { // jobLog.setHandleMsg(JacksonUtil.writeValueAsString(responseMsg));
logger.info("HandlerThread Exception:", e); // } catch (Exception e) {
StringWriter out = new StringWriter(); // logger.info("HandlerThread Exception:", e);
e.printStackTrace(new PrintWriter(out)); // StringWriter out = new StringWriter();
// e.printStackTrace(new PrintWriter(out));
jobLog.setHandleTime(new Date()); //
jobLog.setHandleStatus(RemoteCallBack.FAIL); // jobLog.setHandleTime(new Date());
jobLog.setHandleMsg(out.toString()); // jobLog.setHandleStatus(RemoteCallBack.FAIL);
} // jobLog.setHandleMsg(out.toString());
// }
// update trigger info //
DynamicSchedulerUtil.xxlJobLogDao.updateTriggerInfo(jobLog); // // update trigger info
DynamicSchedulerUtil.xxlJobLogDao.updateHandleInfo(jobLog); // DynamicSchedulerUtil.xxlJobLogDao.updateTriggerInfo(jobLog);
JobMonitorHelper.monitor(jobLog.getId()); // DynamicSchedulerUtil.xxlJobLogDao.updateHandleInfo(jobLog);
logger.info(">>>>>>>>>>> xxl-job trigger end, jobLog.id:{}, jobLog:{}", jobLog.getId(), jobLog); // JobMonitorHelper.monitor(jobLog.getId());
// logger.info(">>>>>>>>>>> xxl-job trigger end, jobLog.id:{}, jobLog:{}", jobLog.getId(), jobLog);
} //
// }
public abstract Object handle(String... param); //
// public abstract Object handle(String... param);
} //
\ No newline at end of file //}
\ No newline at end of file
package com.xxl.job.service.job.impl; //package com.xxl.job.service.job.impl;
//
import java.util.concurrent.TimeUnit; //import java.util.concurrent.TimeUnit;
//
import org.quartz.DisallowConcurrentExecution; //import org.quartz.DisallowConcurrentExecution;
//
import com.xxl.job.service.job.LocalNomalJobBean; //import com.xxl.job.service.job.LocalNomalJobBean;
//
/** ///**
* demo job bean for no-concurrent // * demo job bean for no-concurrent
* @author xuxueli 2016-3-12 14:25:14 // * @author xuxueli 2016-3-12 14:25:14
*/ // */
@DisallowConcurrentExecution // 串行;线程数要多配置几个,否则不生效; //@Deprecated
public class DemoConcurrentJobBean extends LocalNomalJobBean { //@DisallowConcurrentExecution // 串行;线程数要多配置几个,否则不生效;
//public class DemoConcurrentJobBean extends LocalNomalJobBean {
@Override //
public Object handle(String... param) { // @Override
// public Object handle(String... param) {
try { //
TimeUnit.SECONDS.sleep(10); // try {
} catch (InterruptedException e) { // TimeUnit.SECONDS.sleep(10);
e.printStackTrace(); // } catch (InterruptedException e) {
} // e.printStackTrace();
// }
return false; //
} // return false;
// }
} //
//}
package com.xxl.job.service.job.impl; //package com.xxl.job.service.job.impl;
//
import java.util.concurrent.TimeUnit; //import java.util.concurrent.TimeUnit;
//
import org.slf4j.Logger; //import org.slf4j.Logger;
import org.slf4j.LoggerFactory; //import org.slf4j.LoggerFactory;
//
import com.xxl.job.service.job.LocalNomalJobBean; //import com.xxl.job.service.job.LocalNomalJobBean;
//
/** ///**
* demo job bean for concurrent // * demo job bean for concurrent
* @author xuxueli 2016-3-12 14:25:57 // * @author xuxueli 2016-3-12 14:25:57
*/ // */
public class DemoNomalJobBean extends LocalNomalJobBean { //@Deprecated
private static Logger Logger = LoggerFactory.getLogger(DemoNomalJobBean.class); //public class DemoNomalJobBean extends LocalNomalJobBean {
// private static Logger Logger = LoggerFactory.getLogger(DemoNomalJobBean.class);
@Override //
public Object handle(String... param) { // @Override
Logger.info("DemoNomalJobBean run :" + param); // public Object handle(String... param) {
// Logger.info("DemoNomalJobBean run :" + param);
try { //
TimeUnit.SECONDS.sleep(10); // try {
} catch (InterruptedException e) { // TimeUnit.SECONDS.sleep(10);
e.printStackTrace(); // } catch (InterruptedException e) {
} // e.printStackTrace();
// }
return false; //
} // return false;
// }
} //
//}
c3p0.driverClass=com.mysql.jdbc.Driver c3p0.driverClass=com.mysql.jdbc.Driver
c3p0.url=jdbc:mysql://localhost:3306/test?Unicode=true&amp;characterEncoding=UTF-8 c3p0.url=jdbc:mysql://localhost:3306/xxl-job?Unicode=true&amp;characterEncoding=UTF-8
c3p0.user=root c3p0.user=root
c3p0.password=root_pwd c3p0.password=root_pwd
\ No newline at end of file
...@@ -24,7 +24,7 @@ ...@@ -24,7 +24,7 @@
<h1>应用程序异常</h1> <h1>应用程序异常</h1>
<p>抱歉!您访问的页面出现异常,请稍后重试或联系管理员。</p> <p>抱歉!您访问的页面出现异常,请稍后重试或联系管理员。</p>
<p><a href="javascript:showErr();">详 情</a> <p><a href="javascript:showErr();">详 情</a>
<a href="javascript:window.location.href='${request.contextPath}'">返 回</a> <a href="javascript:window.location.href='${request.contextPath}/'">返 回</a>
</p> </p>
<div style="display:none;text-align: left;" id="err">${exceptionMsg}</div> <div style="display:none;text-align: left;" id="err">${exceptionMsg}</div>
</div> </div>
......
<!DOCTYPE html> <!DOCTYPE html>
<html> <html>
<head> <head>
<title>调度中心</title> <title>任务调度中心</title>
<#import "/common/common.macro.ftl" as netCommon> <#import "/common/common.macro.ftl" as netCommon>
<@netCommon.commonStyle /> <@netCommon.commonStyle />
</head> </head>
...@@ -16,11 +16,13 @@ ...@@ -16,11 +16,13 @@
<div class="content-wrapper"> <div class="content-wrapper">
<!-- Content Header (Page header) --> <!-- Content Header (Page header) -->
<section class="content-header"> <section class="content-header">
<h1>使用教程<small>调度管理平台</small></h1> <h1>任务调度中心<small>使用教程</small></h1>
<!--
<ol class="breadcrumb"> <ol class="breadcrumb">
<li><a><i class="fa fa-dashboard"></i>调度中心</a></li> <li><a><i class="fa fa-dashboard"></i>调度中心</a></li>
<li class="active">使用教程</li> <li class="active">使用教程</li>
</ol> </ol>
-->
</section> </section>
<!-- Main content --> <!-- Main content -->
......
<!DOCTYPE html>
<html>
<head>
<title>任务调度中心</title>
<#import "/common/common.macro.ftl" as netCommon>
<@netCommon.commonStyle />
<link rel="stylesheet" href="${request.contextPath}/static/plugins/codemirror/lib/codemirror.css">
<link rel="stylesheet" href="${request.contextPath}/static/plugins/codemirror/addon/hint/show-hint.css">
<style type="text/css">
.CodeMirror {
border: 0px solid black;
font-size:16px;
height: 95%;
row:200;
}
</style>
</head>
<body>
<div class="wrapper">
<div class="content-wrapper">
<!-- Content Header (Page header) -->
<section class="content-header">
<h1>任务调度中心<small>任务CODE管理</small></h1>
</section>
<!-- Main content -->
<section class="content">
<div class="row">
<div class="col-xs-4">
<div class="input-group margin">
<div class="input-group-btn">
<button type="button" class="btn btn-default">版本回溯</button>
</div>
<select class="form-control" id="jobGroup" >
<option value="999" >逻辑调整版本C</option>
<option value="999" >逻辑调整版本B</option>
<option value="999" >逻辑调整版本A</option>
<option value="999" >代码初始化</option>
</select>
</div>
</div>
<div class="col-xs-4">
<div class="input-group margin">
<div class="input-group-btn">
<button type="button" class="btn btn-default">Action</button>
</div>
<input type="text" class="form-control" id="jobName" value="${jobName}" autocomplete="on" >
</div>
</div>
<div class="col-xs-2">
<div class="input-group margin">
<div class="input-group-btn">
<button type="button" class="btn btn-info">保存</button>
</div>
</div>
</div>
</div>
<div class="row">
<div class="col-xs-12">
<div class="box">
<textarea id="editor" >
package com.xxl.job.service.handler;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.xxl.job.client.handler.IJobHandler;
public class DemoJobHandler extends IJobHandler {
private static transient Logger logger = LoggerFactory.getLogger(DemoJobHandler.class);
@Override
public JobHandleStatus handle(String... params) throws Exception {
logger.info(" ... params:" + params);
for (int i = 0; i < 5; i++) {
TimeUnit.SECONDS.sleep(1);
logger.info("handler run:{}", i);
}
return JobHandleStatus.SUCCESS;
}
}
</textarea>
</div>
</div>
</div>
</section>
</div>
<!-- footer -->
<@netCommon.commonFooter />
</div>
<@netCommon.comAlert />
<@netCommon.commonScript />
<script src="${request.contextPath}/static/plugins/codemirror/lib/codemirror.js"></script>
<script src="${request.contextPath}/static/plugins/codemirror/mode/clike/clike.js"></script>
<script src="${request.contextPath}/static/plugins/codemirror/addon/hint/show-hint.js"></script>
<script src="${request.contextPath}/static/plugins/codemirror/addon/hint/anyword-hint.js"></script>
<script src="${request.contextPath}/static/js/jobcode.index.1.js"></script>
</body>
</html>
<!DOCTYPE html> <!DOCTYPE html>
<html> <html>
<head> <head>
<title>调度中心</title> <title>任务调度中心</title>
<#import "/common/common.macro.ftl" as netCommon> <#import "/common/common.macro.ftl" as netCommon>
<@netCommon.commonStyle /> <@netCommon.commonStyle />
<!-- DataTables --> <!-- DataTables -->
...@@ -19,11 +19,13 @@ ...@@ -19,11 +19,13 @@
<div class="content-wrapper"> <div class="content-wrapper">
<!-- Content Header (Page header) --> <!-- Content Header (Page header) -->
<section class="content-header"> <section class="content-header">
<h1>调度管理<small>调度中心</small></h1> <h1>任务调度中心<small>调度管理</small></h1>
<!--
<ol class="breadcrumb"> <ol class="breadcrumb">
<li><a><i class="fa fa-dashboard"></i>调度管理</a></li> <li><a><i class="fa fa-dashboard"></i>调度管理</a></li>
<li class="active">调度中心</li> <li class="active">调度中心</li>
</ol> </ol>
-->
</section> </section>
<!-- Main content --> <!-- Main content -->
...@@ -104,7 +106,7 @@ ...@@ -104,7 +106,7 @@
<div class="modal-body"> <div class="modal-body">
<form class="form-horizontal form" role="form" > <form class="form-horizontal form" role="form" >
<div class="form-group"> <div class="form-group">
<label for="firstname" class="col-sm-2 control-label">任务组</label> <label for="firstname" class="col-sm-2 control-label">任务组<font color="red">*</font></label>
<div class="col-sm-4"> <div class="col-sm-4">
<select class="form-control" name="jobGroup" > <select class="form-control" name="jobGroup" >
<#list JobGroupList as group> <#list JobGroupList as group>
...@@ -112,46 +114,31 @@ ...@@ -112,46 +114,31 @@
</#list> </#list>
</select> </select>
</div> </div>
<label for="firstname" class="col-sm-2 control-label">任务名</label> <label for="firstname" class="col-sm-2 control-label">任务名<font color="red">*</font></label>
<div class="col-sm-4"><input type="text" class="form-control" name="jobName" placeholder="请输入“任务名”" minlength="4" maxlength="100" ></div> <div class="col-sm-4"><input type="text" class="form-control" name="jobName" placeholder="请输入“任务名”" minlength="4" maxlength="100" ></div>
</div> </div>
<div class="form-group"> <div class="form-group">
<label for="lastname" class="col-sm-2 control-label">Corn</label> <label for="lastname" class="col-sm-2 control-label">Corn<font color="red">*</font></label>
<div class="col-sm-4"><input type="text" class="form-control" name="jobCron" placeholder="请输入“Corn”" maxlength="100" ></div> <div class="col-sm-4"><input type="text" class="form-control" name="jobCron" placeholder="请输入“Corn”" maxlength="100" ></div>
<label for="lastname" class="col-sm-2 control-label">描述</label> <label for="lastname" class="col-sm-2 control-label">描述<font color="red">*</font></label>
<div class="col-sm-4"><input type="text" class="form-control" name="jobDesc" placeholder="请输入“描述”" maxlength="200" ></div> <div class="col-sm-4"><input type="text" class="form-control" name="jobDesc" placeholder="请输入“描述”" maxlength="200" ></div>
</div> </div>
<div class="form-group"> <div class="form-group">
<label for="firstname" class="col-sm-2 control-label">JobBean</label> <label for="lastname" class="col-sm-2 control-label">机器地址<font color="red">*</font></label>
<div class="col-sm-4">
<select class="form-control" name="jobClass" >
<#if remoteJobBean?exists >
<option value="${remoteJobBean.name}" jobClassType="remote" >【远程任务】</option>
</#if>
<#if localJobBeanList?exists && localJobBeanList?size gt 0 >
<#list localJobBeanList as localJobBean>
<option value="${localJobBean.name}" jobClassType="local" >${localJobBean.name}</option>
</#list>
</#if>
</select>
</div>
<label for="firstname" class="col-sm-2 control-label">执行参数</label>
<div class="col-sm-4"><input type="text" class="form-control" name="handler_params" placeholder="请输入“执行参数”" maxlength="100" ></div>
</div>
<div class="form-group remote_panel">
<label for="lastname" class="col-sm-2 control-label">远程-机器地址</label>
<div class="col-sm-4"><input type="text" class="form-control" name="handler_address" placeholder="请输入“远程-机器地址”" maxlength="200" ></div> <div class="col-sm-4"><input type="text" class="form-control" name="handler_address" placeholder="请输入“远程-机器地址”" maxlength="200" ></div>
<label for="lastname" class="col-sm-2 control-label">远程-执行器</label> <label for="lastname" class="col-sm-2 control-label">执行器<font color="red">*</font></label>
<div class="col-sm-4"><input type="text" class="form-control" name="handler_name" placeholder="请输入“远程-执行器”" maxlength="200" ></div> <div class="col-sm-4"><input type="text" class="form-control" name="handler_name" placeholder="请输入“远程-执行器”" maxlength="200" ></div>
</div> </div>
<div class="form-group"> <div class="form-group">
<label for="lastname" class="col-sm-2 control-label">负责人</label> <label for="firstname" class="col-sm-2 control-label">执行参数<font color="black">*</font></label>
<div class="col-sm-4"><input type="text" class="form-control" name="handler_params" placeholder="请输入“执行参数”" maxlength="100" ></div>
<label for="lastname" class="col-sm-2 control-label">负责人<font color="red">*</font></label>
<div class="col-sm-4"><input type="text" class="form-control" name="author" placeholder="请输入“负责人”" maxlength="200" ></div> <div class="col-sm-4"><input type="text" class="form-control" name="author" placeholder="请输入“负责人”" maxlength="200" ></div>
<label for="lastname" class="col-sm-2 control-label">报警邮件</label>
<div class="col-sm-4"><input type="text" class="form-control" name="alarmEmail" placeholder="请输入“报警邮件”,多个邮件地址逗号分隔" maxlength="200" ></div>
</div> </div>
<div class="form-group"> <div class="form-group">
<label for="lastname" class="col-sm-2 control-label">报警阈值</label> <label for="lastname" class="col-sm-2 control-label">报警邮件<font color="red">*</font></label>
<div class="col-sm-4"><input type="text" class="form-control" name="alarmEmail" placeholder="请输入“报警邮件”,多个邮件地址逗号分隔" maxlength="200" ></div>
<label for="lastname" class="col-sm-2 control-label">报警阈值<font color="red">*</font></label>
<div class="col-sm-4"><input type="text" class="form-control" name="alarmThreshold" placeholder="请输入“报警阈值”" maxlength="200" ></div> <div class="col-sm-4"><input type="text" class="form-control" name="alarmThreshold" placeholder="请输入“报警阈值”" maxlength="200" ></div>
</div> </div>
<div class="form-group"> <div class="form-group">
...@@ -176,37 +163,34 @@ ...@@ -176,37 +163,34 @@
<div class="modal-body"> <div class="modal-body">
<form class="form-horizontal form" role="form" > <form class="form-horizontal form" role="form" >
<div class="form-group"> <div class="form-group">
<label for="firstname" class="col-sm-2 control-label">任务组</label> <label for="firstname" class="col-sm-2 control-label">任务组<font color="red">*</font></label>
<div class="col-sm-4"><input type="text" class="form-control" name="jobGroup" placeholder="请输入“任务组”" minlength="4" maxlength="100" readonly ></div> <div class="col-sm-4"><input type="text" class="form-control" name="jobGroup" placeholder="请输入“任务组”" minlength="4" maxlength="100" readonly ></div>
<label for="firstname" class="col-sm-2 control-label">任务名</label> <label for="firstname" class="col-sm-2 control-label">任务名<font color="red">*</font></label>
<div class="col-sm-4"><input type="text" class="form-control" name="jobName" placeholder="请输入“任务名”" minlength="4" maxlength="100" readonly ></div> <div class="col-sm-4"><input type="text" class="form-control" name="jobName" placeholder="请输入“任务名”" minlength="4" maxlength="100" readonly ></div>
</div> </div>
<div class="form-group"> <div class="form-group">
<label for="lastname" class="col-sm-2 control-label">Corn</label> <label for="lastname" class="col-sm-2 control-label">Corn<font color="red">*</font></label>
<div class="col-sm-4"><input type="text" class="form-control" name="jobCron" placeholder="请输入“Corn”" maxlength="100" ></div> <div class="col-sm-4"><input type="text" class="form-control" name="jobCron" placeholder="请输入“Corn”" maxlength="100" ></div>
<label for="lastname" class="col-sm-2 control-label">描述</label> <label for="lastname" class="col-sm-2 control-label">描述<font color="red">*</font></label>
<div class="col-sm-4"><input type="text" class="form-control" name="jobDesc" placeholder="请输入“描述”" maxlength="200" ></div> <div class="col-sm-4"><input type="text" class="form-control" name="jobDesc" placeholder="请输入“描述”" maxlength="200" ></div>
</div> </div>
<div class="form-group"> <div class="form-group">
<label for="firstname" class="col-sm-2 control-label">JobBean</label> <label for="lastname" class="col-sm-2 control-label">机器地址<font color="red">*</font></label>
<div class="col-sm-4"><input type="text" class="form-control" name="jobClass" placeholder="请输入“执行参数”" maxlength="100" readonly ></div>
<label for="firstname" class="col-sm-2 control-label">执行参数</label>
<div class="col-sm-4"><input type="text" class="form-control" name="handler_params" placeholder="请输入“执行参数”" maxlength="100" ></div>
</div>
<div class="form-group remote_panel">
<label for="lastname" class="col-sm-2 control-label">远程-机器地址</label>
<div class="col-sm-4"><input type="text" class="form-control" name="handler_address" placeholder="请输入“远程-机器地址”" maxlength="200" ></div> <div class="col-sm-4"><input type="text" class="form-control" name="handler_address" placeholder="请输入“远程-机器地址”" maxlength="200" ></div>
<label for="lastname" class="col-sm-2 control-label">远程-执行器</label> <label for="lastname" class="col-sm-2 control-label">执行器<font color="red">*</font></label>
<div class="col-sm-4"><input type="text" class="form-control" name="handler_name" placeholder="请输入“远程-执行器”" maxlength="200" ></div> <div class="col-sm-4"><input type="text" class="form-control" name="handler_name" placeholder="请输入“远程-执行器”" maxlength="200" ></div>
</div> </div>
<div class="form-group"> <div class="form-group">
<label for="lastname" class="col-sm-2 control-label">负责人</label> <label for="firstname" class="col-sm-2 control-label">执行参数<font color="black">*</font></label>
<div class="col-sm-4"><input type="text" class="form-control" name="handler_params" placeholder="请输入“执行参数”" maxlength="100" ></div>
<label for="lastname" class="col-sm-2 control-label">负责人<font color="red">*</font></label>
<div class="col-sm-4"><input type="text" class="form-control" name="author" placeholder="请输入“负责人”" maxlength="200" ></div> <div class="col-sm-4"><input type="text" class="form-control" name="author" placeholder="请输入“负责人”" maxlength="200" ></div>
<label for="lastname" class="col-sm-2 control-label">报警邮件</label>
<div class="col-sm-4"><input type="text" class="form-control" name="alarmEmail" placeholder="请输入“报警邮件”,多个邮件地址逗号分隔" maxlength="200" ></div>
</div> </div>
<div class="form-group"> <div class="form-group">
<label for="lastname" class="col-sm-2 control-label">报警阈值</label> <label for="lastname" class="col-sm-2 control-label">报警邮件<font color="red">*</font></label>
<div class="col-sm-4"><input type="text" class="form-control" name="alarmEmail" placeholder="请输入“报警邮件”,多个邮件地址逗号分隔" maxlength="200" ></div>
<label for="lastname" class="col-sm-2 control-label">报警阈值<font color="red">*</font></label>
<div class="col-sm-4"><input type="text" class="form-control" name="alarmThreshold" placeholder="请输入“报警阈值”" maxlength="200" ></div> <div class="col-sm-4"><input type="text" class="form-control" name="alarmThreshold" placeholder="请输入“报警阈值”" maxlength="200" ></div>
</div> </div>
<div class="form-group"> <div class="form-group">
......
<!DOCTYPE html> <!DOCTYPE html>
<html> <html>
<head> <head>
<title>调度日志</title> <title>任务调度中心</title>
<#import "/common/common.macro.ftl" as netCommon> <#import "/common/common.macro.ftl" as netCommon>
<@netCommon.commonStyle /> <@netCommon.commonStyle />
<!-- DataTables --> <!-- DataTables -->
...@@ -20,11 +20,13 @@ ...@@ -20,11 +20,13 @@
<div class="content-wrapper"> <div class="content-wrapper">
<!-- Content Header (Page header) --> <!-- Content Header (Page header) -->
<section class="content-header"> <section class="content-header">
<h1>调度日志<small>调度中心</small></h1> <h1>任务调度中心<small>调度日志</small></h1>
<!--
<ol class="breadcrumb"> <ol class="breadcrumb">
<li><a><i class="fa fa-dashboard"></i>调度日志</a></li> <li><a><i class="fa fa-dashboard"></i>调度日志</a></li>
<li class="active">调度管理</li> <li class="active">调度管理</li>
</ol> </ol>
-->
</section> </section>
<!-- Main content --> <!-- Main content -->
......
...@@ -21,7 +21,7 @@ $(function(){ ...@@ -21,7 +21,7 @@ $(function(){
$.post(base_url + "/logout", function(data, status) { $.post(base_url + "/logout", function(data, status) {
if (data.code == "200") { if (data.code == "200") {
ComAlert.show(1, "注销成功", function(){ ComAlert.show(1, "注销成功", function(){
window.location.href = base_url; window.location.href = base_url + "/";
}); });
} else { } else {
ComAlert.show(1, data.msg); ComAlert.show(1, data.msg);
......
$(function() {
var javaEditor = CodeMirror.fromTextArea(document.getElementById("editor"), {
mode : "text/x-java",
lineNumbers : true,
matchBrackets : true,
extraKeys: {
"F11": function(cm) {
cm.setOption("fullScreen", !cm.getOption("fullScreen"));
},
"Esc": function(cm) {
if (cm.getOption("fullScreen")) cm.setOption("fullScreen", false);
}
}
});
});
...@@ -81,12 +81,14 @@ $(function() { ...@@ -81,12 +81,14 @@ $(function() {
// status // status
var pause_resume = ""; var pause_resume = "";
if ('NORMAL' == row.jobStatus) { if ('NORMAL' == row.jobStatus) {
pause_resume = '<button class="btn btn-info btn-xs job_operate" type="job_pause" type="button">暂停</button> '; pause_resume = '<button class="btn btn-primary btn-xs job_operate" type="job_pause" type="button">暂停</button> ';
} else if ('PAUSED' == row.jobStatus){ } else if ('PAUSED' == row.jobStatus){
pause_resume = '<button class="btn btn-info btn-xs job_operate" type="job_resume" type="button">恢复</button> '; pause_resume = '<button class="btn btn-primary btn-xs job_operate" type="job_resume" type="button">恢复</button> ';
} }
// log url // log url
var logUrl = base_url +'/joblog?jobGroup='+ row.jobGroup +'&jobName='+ row.jobName; var logUrl = base_url +'/joblog?jobGroup='+ row.jobGroup +'&jobName='+ row.jobName;
// log url
var codeUrl = base_url +'/jobcode?id='+ row.id;
// job data // job data
var jobDataMap = eval('(' + row.jobData + ')'); var jobDataMap = eval('(' + row.jobData + ')');
...@@ -105,11 +107,11 @@ $(function() { ...@@ -105,11 +107,11 @@ $(function() {
' handler_address="'+ jobDataMap.handler_address +'" '+ ' handler_address="'+ jobDataMap.handler_address +'" '+
' handler_name="'+ jobDataMap.handler_name +'" '+ ' handler_name="'+ jobDataMap.handler_name +'" '+
'>'+ '>'+
pause_resume + '<button class="btn btn-primary btn-xs job_operate" type="job_trigger" type="button">执行</button> '+
'<button class="btn btn-info btn-xs job_operate" type="job_trigger" type="button">执行</button>'+ pause_resume +
'<button class="btn btn-warning btn-xs update" type="button">编辑</button><br>'+ '<button class="btn btn-primary btn-xs" type="job_del" type="button" onclick="javascript:window.open(\'' + logUrl + '\')" >日志</button><br> '+
'<button class="btn btn-warning btn-xs" type="job_del" type="button" '+ '<button class="btn btn-warning btn-xs update" type="button">编辑</button> '+
'onclick="javascript:window.open(\'' + logUrl + '\')" >查看日志</button> '+ '<button class="btn btn-warning btn-xs" type="button" onclick="javascript:window.open(\'' + codeUrl + '\')" >CODE</button> '+
'<button class="btn btn-danger btn-xs job_operate" type="job_del" type="button">删除</button> '+ '<button class="btn btn-danger btn-xs job_operate" type="job_del" type="button">删除</button> '+
'</p>'; '</p>';
...@@ -263,12 +265,12 @@ $(function() { ...@@ -263,12 +265,12 @@ $(function() {
maxlength:"“任务描述”长度不应超过200位" maxlength:"“任务描述”长度不应超过200位"
}, },
handler_address : { handler_address : {
required :"请输入“远程-机器地址”." , required :"请输入“机器地址”." ,
maxlength:"远程-机器地址”长度不应超过200位" maxlength:"“机器地址”长度不应超过200位"
}, },
handler_name : { handler_name : {
required : "请输入“远程-执行器”." , required : "请输入“执行器”." ,
maxlength: "远程-执行器”长度不应超过200位" maxlength: "“执行器”长度不应超过200位"
}, },
author : { author : {
required : "请输入“负责人”." , required : "请输入“负责人”." ,
...@@ -316,38 +318,19 @@ $(function() { ...@@ -316,38 +318,19 @@ $(function() {
$(".remote_panel").show(); // remote $(".remote_panel").show(); // remote
}); });
// 远程任务/本地任务,切换
$("#addModal select[name='jobClass']").change(function() {
//console.log( $(this).val().indexOf('RemoteHttpJobBean') );
if($(this).val().indexOf('RemoteHttpJobBean') > -1){
$(".remote_panel").show(); // remote
} else if($(this).val().indexOf('RemoteHttpJobBean') == -1){
$(".remote_panel").hide(); // local
}
});
// 更新 // 更新
$("#job_list").on('click', '.update',function() { $("#job_list").on('click', '.update',function() {
$("#updateModal .form input[name='jobGroup']").val($(this).parent('p').attr("jobGroup")); $("#updateModal .form input[name='jobGroup']").val($(this).parent('p').attr("jobGroup"));
$("#updateModal .form input[name='jobName']").val($(this).parent('p').attr("jobName")); $("#updateModal .form input[name='jobName']").val($(this).parent('p').attr("jobName"));
$("#updateModal .form input[name='jobCron']").val($(this).parent('p').attr("jobCron")); $("#updateModal .form input[name='jobCron']").val($(this).parent('p').attr("jobCron"));
$("#updateModal .form input[name='jobDesc']").val($(this).parent('p').attr("jobDesc")); $("#updateModal .form input[name='jobDesc']").val($(this).parent('p').attr("jobDesc"));
$("#updateModal .form input[name='jobClass']").val($(this).parent('p').attr("jobClass"));
$("#updateModal .form input[name='handler_params']").val($(this).parent('p').attr("handler_params"));
$("#updateModal .form input[name='handler_address']").val($(this).parent('p').attr("handler_address")); $("#updateModal .form input[name='handler_address']").val($(this).parent('p').attr("handler_address"));
$("#updateModal .form input[name='handler_name']").val($(this).parent('p').attr("handler_name")); $("#updateModal .form input[name='handler_name']").val($(this).parent('p').attr("handler_name"));
$("#updateModal .form input[name='handler_params']").val($(this).parent('p').attr("handler_params"));
$("#updateModal .form input[name='author']").val($(this).parent('p').attr("author")); $("#updateModal .form input[name='author']").val($(this).parent('p').attr("author"));
$("#updateModal .form input[name='alarmEmail']").val($(this).parent('p').attr("alarmEmail")); $("#updateModal .form input[name='alarmEmail']").val($(this).parent('p').attr("alarmEmail"));
$("#updateModal .form input[name='alarmThreshold']").val($(this).parent('p').attr("alarmThreshold")); $("#updateModal .form input[name='alarmThreshold']").val($(this).parent('p').attr("alarmThreshold"));
var _jobClass = $(this).parent('p').attr("jobClass");
if(_jobClass.indexOf('RemoteHttpJobBean') > -1){
$(".remote_panel").show(); // remote
} else if($(this).val().indexOf('RemoteHttpJobBean') == -1){
$(".remote_panel").hide(); // local
}
$('#updateModal').modal({backdrop: false, keyboard: false}).modal('show'); $('#updateModal').modal({backdrop: false, keyboard: false}).modal('show');
}); });
var updateModalValidate = $("#updateModal .form").validate({ var updateModalValidate = $("#updateModal .form").validate({
...@@ -394,12 +377,12 @@ $(function() { ...@@ -394,12 +377,12 @@ $(function() {
maxlength:"“任务描述”长度不应超过200位" maxlength:"“任务描述”长度不应超过200位"
}, },
handler_address : { handler_address : {
required :"请输入“远程-机器地址”." , required :"请输入“机器地址”." ,
maxlength:"远程-机器地址”长度不应超过200位" maxlength:"“机器地址”长度不应超过200位"
}, },
handler_name : { handler_name : {
required : "请输入“远程-执行器”." , required : "请输入“执行器”." ,
maxlength: "远程-执行器”长度不应超过200位" maxlength: "“执行器”长度不应超过200位"
}, },
author : { author : {
required : "请输入“负责人”." , required : "请输入“负责人”." ,
......
// CodeMirror, copyright (c) by Marijn Haverbeke and others
// Distributed under an MIT license: http://codemirror.net/LICENSE
(function(mod) {
if (typeof exports == "object" && typeof module == "object") // CommonJS
mod(require("../../lib/codemirror"));
else if (typeof define == "function" && define.amd) // AMD
define(["../../lib/codemirror"], mod);
else // Plain browser env
mod(CodeMirror);
})(function(CodeMirror) {
"use strict";
var WORD = /[\w$]+/, RANGE = 500;
CodeMirror.registerHelper("hint", "anyword", function(editor, options) {
var word = options && options.word || WORD;
var range = options && options.range || RANGE;
var cur = editor.getCursor(), curLine = editor.getLine(cur.line);
var end = cur.ch, start = end;
while (start && word.test(curLine.charAt(start - 1))) --start;
var curWord = start != end && curLine.slice(start, end);
var list = options && options.list || [], seen = {};
var re = new RegExp(word.source, "g");
for (var dir = -1; dir <= 1; dir += 2) {
var line = cur.line, endLine = Math.min(Math.max(line + dir * range, editor.firstLine()), editor.lastLine()) + dir;
for (; line != endLine; line += dir) {
var text = editor.getLine(line), m;
while (m = re.exec(text)) {
if (line == cur.line && m[0] === curWord) continue;
if ((!curWord || m[0].lastIndexOf(curWord, 0) == 0) && !Object.prototype.hasOwnProperty.call(seen, m[0])) {
seen[m[0]] = true;
list.push(m[0]);
}
}
}
}
return {list: list, from: CodeMirror.Pos(cur.line, start), to: CodeMirror.Pos(cur.line, end)};
});
});
.CodeMirror-hints {
position: absolute;
z-index: 10;
overflow: hidden;
list-style: none;
margin: 0;
padding: 2px;
-webkit-box-shadow: 2px 3px 5px rgba(0,0,0,.2);
-moz-box-shadow: 2px 3px 5px rgba(0,0,0,.2);
box-shadow: 2px 3px 5px rgba(0,0,0,.2);
border-radius: 3px;
border: 1px solid silver;
background: white;
font-size: 90%;
font-family: monospace;
max-height: 20em;
overflow-y: auto;
}
.CodeMirror-hint {
margin: 0;
padding: 0 4px;
border-radius: 2px;
max-width: 19em;
overflow: hidden;
white-space: pre;
color: black;
cursor: pointer;
}
li.CodeMirror-hint-active {
background: #08f;
color: white;
}
// CodeMirror, copyright (c) by Marijn Haverbeke and others
// Distributed under an MIT license: http://codemirror.net/LICENSE
(function(mod) {
if (typeof exports == "object" && typeof module == "object") // CommonJS
mod(require("../../lib/codemirror"));
else if (typeof define == "function" && define.amd) // AMD
define(["../../lib/codemirror"], mod);
else // Plain browser env
mod(CodeMirror);
})(function(CodeMirror) {
"use strict";
var HINT_ELEMENT_CLASS = "CodeMirror-hint";
var ACTIVE_HINT_ELEMENT_CLASS = "CodeMirror-hint-active";
// This is the old interface, kept around for now to stay
// backwards-compatible.
CodeMirror.showHint = function(cm, getHints, options) {
if (!getHints) return cm.showHint(options);
if (options && options.async) getHints.async = true;
var newOpts = {hint: getHints};
if (options) for (var prop in options) newOpts[prop] = options[prop];
return cm.showHint(newOpts);
};
CodeMirror.defineExtension("showHint", function(options) {
options = parseOptions(this, this.getCursor("start"), options);
var selections = this.listSelections()
if (selections.length > 1) return;
// By default, don't allow completion when something is selected.
// A hint function can have a `supportsSelection` property to
// indicate that it can handle selections.
if (this.somethingSelected()) {
if (!options.hint.supportsSelection) return;
// Don't try with cross-line selections
for (var i = 0; i < selections.length; i++)
if (selections[i].head.line != selections[i].anchor.line) return;
}
if (this.state.completionActive) this.state.completionActive.close();
var completion = this.state.completionActive = new Completion(this, options);
if (!completion.options.hint) return;
CodeMirror.signal(this, "startCompletion", this);
completion.update(true);
});
function Completion(cm, options) {
this.cm = cm;
this.options = options;
this.widget = null;
this.debounce = 0;
this.tick = 0;
this.startPos = this.cm.getCursor("start");
this.startLen = this.cm.getLine(this.startPos.line).length - this.cm.getSelection().length;
var self = this;
cm.on("cursorActivity", this.activityFunc = function() { self.cursorActivity(); });
}
var requestAnimationFrame = window.requestAnimationFrame || function(fn) {
return setTimeout(fn, 1000/60);
};
var cancelAnimationFrame = window.cancelAnimationFrame || clearTimeout;
Completion.prototype = {
close: function() {
if (!this.active()) return;
this.cm.state.completionActive = null;
this.tick = null;
this.cm.off("cursorActivity", this.activityFunc);
if (this.widget && this.data) CodeMirror.signal(this.data, "close");
if (this.widget) this.widget.close();
CodeMirror.signal(this.cm, "endCompletion", this.cm);
},
active: function() {
return this.cm.state.completionActive == this;
},
pick: function(data, i) {
var completion = data.list[i];
if (completion.hint) completion.hint(this.cm, data, completion);
else this.cm.replaceRange(getText(completion), completion.from || data.from,
completion.to || data.to, "complete");
CodeMirror.signal(data, "pick", completion);
this.close();
},
cursorActivity: function() {
if (this.debounce) {
cancelAnimationFrame(this.debounce);
this.debounce = 0;
}
var pos = this.cm.getCursor(), line = this.cm.getLine(pos.line);
if (pos.line != this.startPos.line || line.length - pos.ch != this.startLen - this.startPos.ch ||
pos.ch < this.startPos.ch || this.cm.somethingSelected() ||
(pos.ch && this.options.closeCharacters.test(line.charAt(pos.ch - 1)))) {
this.close();
} else {
var self = this;
this.debounce = requestAnimationFrame(function() {self.update();});
if (this.widget) this.widget.disable();
}
},
update: function(first) {
if (this.tick == null) return;
if (!this.options.hint.async) {
this.finishUpdate(this.options.hint(this.cm, this.options), first);
} else {
var myTick = ++this.tick, self = this;
this.options.hint(this.cm, function(data) {
if (self.tick == myTick) self.finishUpdate(data, first);
}, this.options);
}
},
finishUpdate: function(data, first) {
if (this.data) CodeMirror.signal(this.data, "update");
var picked = (this.widget && this.widget.picked) || (first && this.options.completeSingle);
if (this.widget) this.widget.close();
if (data && this.data && isNewCompletion(this.data, data)) return;
this.data = data;
if (data && data.list.length) {
if (picked && data.list.length == 1) {
this.pick(data, 0);
} else {
this.widget = new Widget(this, data);
CodeMirror.signal(data, "shown");
}
}
}
};
function isNewCompletion(old, nw) {
var moved = CodeMirror.cmpPos(nw.from, old.from)
return moved > 0 && old.to.ch - old.from.ch != nw.to.ch - nw.from.ch
}
function parseOptions(cm, pos, options) {
var editor = cm.options.hintOptions;
var out = {};
for (var prop in defaultOptions) out[prop] = defaultOptions[prop];
if (editor) for (var prop in editor)
if (editor[prop] !== undefined) out[prop] = editor[prop];
if (options) for (var prop in options)
if (options[prop] !== undefined) out[prop] = options[prop];
if (out.hint.resolve) out.hint = out.hint.resolve(cm, pos)
return out;
}
function getText(completion) {
if (typeof completion == "string") return completion;
else return completion.text;
}
function buildKeyMap(completion, handle) {
var baseMap = {
Up: function() {handle.moveFocus(-1);},
Down: function() {handle.moveFocus(1);},
PageUp: function() {handle.moveFocus(-handle.menuSize() + 1, true);},
PageDown: function() {handle.moveFocus(handle.menuSize() - 1, true);},
Home: function() {handle.setFocus(0);},
End: function() {handle.setFocus(handle.length - 1);},
Enter: handle.pick,
Tab: handle.pick,
Esc: handle.close
};
var custom = completion.options.customKeys;
var ourMap = custom ? {} : baseMap;
function addBinding(key, val) {
var bound;
if (typeof val != "string")
bound = function(cm) { return val(cm, handle); };
// This mechanism is deprecated
else if (baseMap.hasOwnProperty(val))
bound = baseMap[val];
else
bound = val;
ourMap[key] = bound;
}
if (custom)
for (var key in custom) if (custom.hasOwnProperty(key))
addBinding(key, custom[key]);
var extra = completion.options.extraKeys;
if (extra)
for (var key in extra) if (extra.hasOwnProperty(key))
addBinding(key, extra[key]);
return ourMap;
}
function getHintElement(hintsElement, el) {
while (el && el != hintsElement) {
if (el.nodeName.toUpperCase() === "LI" && el.parentNode == hintsElement) return el;
el = el.parentNode;
}
}
function Widget(completion, data) {
this.completion = completion;
this.data = data;
this.picked = false;
var widget = this, cm = completion.cm;
var hints = this.hints = document.createElement("ul");
hints.className = "CodeMirror-hints";
this.selectedHint = data.selectedHint || 0;
var completions = data.list;
for (var i = 0; i < completions.length; ++i) {
var elt = hints.appendChild(document.createElement("li")), cur = completions[i];
var className = HINT_ELEMENT_CLASS + (i != this.selectedHint ? "" : " " + ACTIVE_HINT_ELEMENT_CLASS);
if (cur.className != null) className = cur.className + " " + className;
elt.className = className;
if (cur.render) cur.render(elt, data, cur);
else elt.appendChild(document.createTextNode(cur.displayText || getText(cur)));
elt.hintId = i;
}
var pos = cm.cursorCoords(completion.options.alignWithWord ? data.from : null);
var left = pos.left, top = pos.bottom, below = true;
hints.style.left = left + "px";
hints.style.top = top + "px";
// If we're at the edge of the screen, then we want the menu to appear on the left of the cursor.
var winW = window.innerWidth || Math.max(document.body.offsetWidth, document.documentElement.offsetWidth);
var winH = window.innerHeight || Math.max(document.body.offsetHeight, document.documentElement.offsetHeight);
(completion.options.container || document.body).appendChild(hints);
var box = hints.getBoundingClientRect(), overlapY = box.bottom - winH;
if (overlapY > 0) {
var height = box.bottom - box.top, curTop = pos.top - (pos.bottom - box.top);
if (curTop - height > 0) { // Fits above cursor
hints.style.top = (top = pos.top - height) + "px";
below = false;
} else if (height > winH) {
hints.style.height = (winH - 5) + "px";
hints.style.top = (top = pos.bottom - box.top) + "px";
var cursor = cm.getCursor();
if (data.from.ch != cursor.ch) {
pos = cm.cursorCoords(cursor);
hints.style.left = (left = pos.left) + "px";
box = hints.getBoundingClientRect();
}
}
}
var overlapX = box.right - winW;
if (overlapX > 0) {
if (box.right - box.left > winW) {
hints.style.width = (winW - 5) + "px";
overlapX -= (box.right - box.left) - winW;
}
hints.style.left = (left = pos.left - overlapX) + "px";
}
cm.addKeyMap(this.keyMap = buildKeyMap(completion, {
moveFocus: function(n, avoidWrap) { widget.changeActive(widget.selectedHint + n, avoidWrap); },
setFocus: function(n) { widget.changeActive(n); },
menuSize: function() { return widget.screenAmount(); },
length: completions.length,
close: function() { completion.close(); },
pick: function() { widget.pick(); },
data: data
}));
if (completion.options.closeOnUnfocus) {
var closingOnBlur;
cm.on("blur", this.onBlur = function() { closingOnBlur = setTimeout(function() { completion.close(); }, 100); });
cm.on("focus", this.onFocus = function() { clearTimeout(closingOnBlur); });
}
var startScroll = cm.getScrollInfo();
cm.on("scroll", this.onScroll = function() {
var curScroll = cm.getScrollInfo(), editor = cm.getWrapperElement().getBoundingClientRect();
var newTop = top + startScroll.top - curScroll.top;
var point = newTop - (window.pageYOffset || (document.documentElement || document.body).scrollTop);
if (!below) point += hints.offsetHeight;
if (point <= editor.top || point >= editor.bottom) return completion.close();
hints.style.top = newTop + "px";
hints.style.left = (left + startScroll.left - curScroll.left) + "px";
});
CodeMirror.on(hints, "dblclick", function(e) {
var t = getHintElement(hints, e.target || e.srcElement);
if (t && t.hintId != null) {widget.changeActive(t.hintId); widget.pick();}
});
CodeMirror.on(hints, "click", function(e) {
var t = getHintElement(hints, e.target || e.srcElement);
if (t && t.hintId != null) {
widget.changeActive(t.hintId);
if (completion.options.completeOnSingleClick) widget.pick();
}
});
CodeMirror.on(hints, "mousedown", function() {
setTimeout(function(){cm.focus();}, 20);
});
CodeMirror.signal(data, "select", completions[0], hints.firstChild);
return true;
}
Widget.prototype = {
close: function() {
if (this.completion.widget != this) return;
this.completion.widget = null;
this.hints.parentNode.removeChild(this.hints);
this.completion.cm.removeKeyMap(this.keyMap);
var cm = this.completion.cm;
if (this.completion.options.closeOnUnfocus) {
cm.off("blur", this.onBlur);
cm.off("focus", this.onFocus);
}
cm.off("scroll", this.onScroll);
},
disable: function() {
this.completion.cm.removeKeyMap(this.keyMap);
var widget = this;
this.keyMap = {Enter: function() { widget.picked = true; }};
this.completion.cm.addKeyMap(this.keyMap);
},
pick: function() {
this.completion.pick(this.data, this.selectedHint);
},
changeActive: function(i, avoidWrap) {
if (i >= this.data.list.length)
i = avoidWrap ? this.data.list.length - 1 : 0;
else if (i < 0)
i = avoidWrap ? 0 : this.data.list.length - 1;
if (this.selectedHint == i) return;
var node = this.hints.childNodes[this.selectedHint];
node.className = node.className.replace(" " + ACTIVE_HINT_ELEMENT_CLASS, "");
node = this.hints.childNodes[this.selectedHint = i];
node.className += " " + ACTIVE_HINT_ELEMENT_CLASS;
if (node.offsetTop < this.hints.scrollTop)
this.hints.scrollTop = node.offsetTop - 3;
else if (node.offsetTop + node.offsetHeight > this.hints.scrollTop + this.hints.clientHeight)
this.hints.scrollTop = node.offsetTop + node.offsetHeight - this.hints.clientHeight + 3;
CodeMirror.signal(this.data, "select", this.data.list[this.selectedHint], node);
},
screenAmount: function() {
return Math.floor(this.hints.clientHeight / this.hints.firstChild.offsetHeight) || 1;
}
};
function applicableHelpers(cm, helpers) {
if (!cm.somethingSelected()) return helpers
var result = []
for (var i = 0; i < helpers.length; i++)
if (helpers[i].supportsSelection) result.push(helpers[i])
return result
}
function resolveAutoHints(cm, pos) {
var helpers = cm.getHelpers(pos, "hint"), words
if (helpers.length) {
var async = false, resolved
for (var i = 0; i < helpers.length; i++) if (helpers[i].async) async = true
if (async) {
resolved = function(cm, callback, options) {
var app = applicableHelpers(cm, helpers)
function run(i, result) {
if (i == app.length) return callback(null)
var helper = app[i]
if (helper.async) {
helper(cm, function(result) {
if (result) callback(result)
else run(i + 1)
}, options)
} else {
var result = helper(cm, options)
if (result) callback(result)
else run(i + 1)
}
}
run(0)
}
resolved.async = true
} else {
resolved = function(cm, options) {
var app = applicableHelpers(cm, helpers)
for (var i = 0; i < app.length; i++) {
var cur = app[i](cm, options)
if (cur && cur.list.length) return cur
}
}
}
resolved.supportsSelection = true
return resolved
} else if (words = cm.getHelper(cm.getCursor(), "hintWords")) {
return function(cm) { return CodeMirror.hint.fromList(cm, {words: words}) }
} else if (CodeMirror.hint.anyword) {
return function(cm, options) { return CodeMirror.hint.anyword(cm, options) }
} else {
return function() {}
}
}
CodeMirror.registerHelper("hint", "auto", {
resolve: resolveAutoHints
});
CodeMirror.registerHelper("hint", "fromList", function(cm, options) {
var cur = cm.getCursor(), token = cm.getTokenAt(cur);
var to = CodeMirror.Pos(cur.line, token.end);
if (token.string && /\w/.test(token.string[token.string.length - 1])) {
var term = token.string, from = CodeMirror.Pos(cur.line, token.start);
} else {
var term = "", from = to;
}
var found = [];
for (var i = 0; i < options.words.length; i++) {
var word = options.words[i];
if (word.slice(0, term.length) == term)
found.push(word);
}
if (found.length) return {list: found, from: from, to: to};
});
CodeMirror.commands.autocomplete = CodeMirror.showHint;
var defaultOptions = {
hint: CodeMirror.hint.auto,
completeSingle: true,
alignWithWord: true,
closeCharacters: /[\s()\[\]{};:>,]/,
closeOnUnfocus: true,
completeOnSingleClick: true,
container: null,
customKeys: null,
extraKeys: null
};
CodeMirror.defineOption("hintOptions", null);
});
/* BASICS */
.CodeMirror {
/* Set height, width, borders, and global font properties here */
font-family: monospace;
height: 300px;
color: black;
}
/* PADDING */
.CodeMirror-lines {
padding: 4px 0; /* Vertical padding around content */
}
.CodeMirror pre {
padding: 0 4px; /* Horizontal padding of content */
}
.CodeMirror-scrollbar-filler, .CodeMirror-gutter-filler {
background-color: white; /* The little square between H and V scrollbars */
}
/* GUTTER */
.CodeMirror-gutters {
border-right: 1px solid #ddd;
background-color: #f7f7f7;
white-space: nowrap;
}
.CodeMirror-linenumbers {}
.CodeMirror-linenumber {
padding: 0 3px 0 5px;
min-width: 20px;
text-align: right;
color: #999;
white-space: nowrap;
}
.CodeMirror-guttermarker { color: black; }
.CodeMirror-guttermarker-subtle { color: #999; }
/* CURSOR */
.CodeMirror-cursor {
border-left: 1px solid black;
border-right: none;
width: 0;
}
/* Shown when moving in bi-directional text */
.CodeMirror div.CodeMirror-secondarycursor {
border-left: 1px solid silver;
}
.cm-fat-cursor .CodeMirror-cursor {
width: auto;
border: 0;
background: #7e7;
}
.cm-fat-cursor div.CodeMirror-cursors {
z-index: 1;
}
.cm-animate-fat-cursor {
width: auto;
border: 0;
-webkit-animation: blink 1.06s steps(1) infinite;
-moz-animation: blink 1.06s steps(1) infinite;
animation: blink 1.06s steps(1) infinite;
background-color: #7e7;
}
@-moz-keyframes blink {
0% {}
50% { background-color: transparent; }
100% {}
}
@-webkit-keyframes blink {
0% {}
50% { background-color: transparent; }
100% {}
}
@keyframes blink {
0% {}
50% { background-color: transparent; }
100% {}
}
/* Can style cursor different in overwrite (non-insert) mode */
.CodeMirror-overwrite .CodeMirror-cursor {}
.cm-tab { display: inline-block; text-decoration: inherit; }
.CodeMirror-ruler {
border-left: 1px solid #ccc;
position: absolute;
}
/* DEFAULT THEME */
.cm-s-default .cm-header {color: blue;}
.cm-s-default .cm-quote {color: #090;}
.cm-negative {color: #d44;}
.cm-positive {color: #292;}
.cm-header, .cm-strong {font-weight: bold;}
.cm-em {font-style: italic;}
.cm-link {text-decoration: underline;}
.cm-strikethrough {text-decoration: line-through;}
.cm-s-default .cm-keyword {color: #708;}
.cm-s-default .cm-atom {color: #219;}
.cm-s-default .cm-number {color: #164;}
.cm-s-default .cm-def {color: #00f;}
.cm-s-default .cm-variable,
.cm-s-default .cm-punctuation,
.cm-s-default .cm-property,
.cm-s-default .cm-operator {}
.cm-s-default .cm-variable-2 {color: #05a;}
.cm-s-default .cm-variable-3 {color: #085;}
.cm-s-default .cm-comment {color: #a50;}
.cm-s-default .cm-string {color: #a11;}
.cm-s-default .cm-string-2 {color: #f50;}
.cm-s-default .cm-meta {color: #555;}
.cm-s-default .cm-qualifier {color: #555;}
.cm-s-default .cm-builtin {color: #30a;}
.cm-s-default .cm-bracket {color: #997;}
.cm-s-default .cm-tag {color: #170;}
.cm-s-default .cm-attribute {color: #00c;}
.cm-s-default .cm-hr {color: #999;}
.cm-s-default .cm-link {color: #00c;}
.cm-s-default .cm-error {color: #f00;}
.cm-invalidchar {color: #f00;}
.CodeMirror-composing { border-bottom: 2px solid; }
/* Default styles for common addons */
div.CodeMirror span.CodeMirror-matchingbracket {color: #0f0;}
div.CodeMirror span.CodeMirror-nonmatchingbracket {color: #f22;}
.CodeMirror-matchingtag { background: rgba(255, 150, 0, .3); }
.CodeMirror-activeline-background {background: #e8f2ff;}
/* STOP */
/* The rest of this file contains styles related to the mechanics of
the editor. You probably shouldn't touch them. */
.CodeMirror {
position: relative;
overflow: hidden;
background: white;
}
.CodeMirror-scroll {
overflow: scroll !important; /* Things will break if this is overridden */
/* 30px is the magic margin used to hide the element's real scrollbars */
/* See overflow: hidden in .CodeMirror */
margin-bottom: -30px; margin-right: -30px;
padding-bottom: 30px;
height: 100%;
outline: none; /* Prevent dragging from highlighting the element */
position: relative;
}
.CodeMirror-sizer {
position: relative;
border-right: 30px solid transparent;
}
/* The fake, visible scrollbars. Used to force redraw during scrolling
before actual scrolling happens, thus preventing shaking and
flickering artifacts. */
.CodeMirror-vscrollbar, .CodeMirror-hscrollbar, .CodeMirror-scrollbar-filler, .CodeMirror-gutter-filler {
position: absolute;
z-index: 6;
display: none;
}
.CodeMirror-vscrollbar {
right: 0; top: 0;
overflow-x: hidden;
overflow-y: scroll;
}
.CodeMirror-hscrollbar {
bottom: 0; left: 0;
overflow-y: hidden;
overflow-x: scroll;
}
.CodeMirror-scrollbar-filler {
right: 0; bottom: 0;
}
.CodeMirror-gutter-filler {
left: 0; bottom: 0;
}
.CodeMirror-gutters {
position: absolute; left: 0; top: 0;
min-height: 100%;
z-index: 3;
}
.CodeMirror-gutter {
white-space: normal;
height: 100%;
display: inline-block;
vertical-align: top;
margin-bottom: -30px;
/* Hack to make IE7 behave */
*zoom:1;
*display:inline;
}
.CodeMirror-gutter-wrapper {
position: absolute;
z-index: 4;
background: none !important;
border: none !important;
}
.CodeMirror-gutter-background {
position: absolute;
top: 0; bottom: 0;
z-index: 4;
}
.CodeMirror-gutter-elt {
position: absolute;
cursor: default;
z-index: 4;
}
.CodeMirror-gutter-wrapper {
-webkit-user-select: none;
-moz-user-select: none;
user-select: none;
}
.CodeMirror-lines {
cursor: text;
min-height: 1px; /* prevents collapsing before first draw */
}
.CodeMirror pre {
/* Reset some styles that the rest of the page might have set */
-moz-border-radius: 0; -webkit-border-radius: 0; border-radius: 0;
border-width: 0;
background: transparent;
font-family: inherit;
font-size: inherit;
margin: 0;
white-space: pre;
word-wrap: normal;
line-height: inherit;
color: inherit;
z-index: 2;
position: relative;
overflow: visible;
-webkit-tap-highlight-color: transparent;
-webkit-font-variant-ligatures: none;
font-variant-ligatures: none;
}
.CodeMirror-wrap pre {
word-wrap: break-word;
white-space: pre-wrap;
word-break: normal;
}
.CodeMirror-linebackground {
position: absolute;
left: 0; right: 0; top: 0; bottom: 0;
z-index: 0;
}
.CodeMirror-linewidget {
position: relative;
z-index: 2;
overflow: auto;
}
.CodeMirror-widget {}
.CodeMirror-code {
outline: none;
}
/* Force content-box sizing for the elements where we expect it */
.CodeMirror-scroll,
.CodeMirror-sizer,
.CodeMirror-gutter,
.CodeMirror-gutters,
.CodeMirror-linenumber {
-moz-box-sizing: content-box;
box-sizing: content-box;
}
.CodeMirror-measure {
position: absolute;
width: 100%;
height: 0;
overflow: hidden;
visibility: hidden;
}
.CodeMirror-cursor { position: absolute; }
.CodeMirror-measure pre { position: static; }
div.CodeMirror-cursors {
visibility: hidden;
position: relative;
z-index: 3;
}
div.CodeMirror-dragcursors {
visibility: visible;
}
.CodeMirror-focused div.CodeMirror-cursors {
visibility: visible;
}
.CodeMirror-selected { background: #d9d9d9; }
.CodeMirror-focused .CodeMirror-selected { background: #d7d4f0; }
.CodeMirror-crosshair { cursor: crosshair; }
.CodeMirror-line::selection, .CodeMirror-line > span::selection, .CodeMirror-line > span > span::selection { background: #d7d4f0; }
.CodeMirror-line::-moz-selection, .CodeMirror-line > span::-moz-selection, .CodeMirror-line > span > span::-moz-selection { background: #d7d4f0; }
.cm-searching {
background: #ffa;
background: rgba(255, 255, 0, .4);
}
/* IE7 hack to prevent it from returning funny offsetTops on the spans */
.CodeMirror span { *vertical-align: text-bottom; }
/* Used to force a border model for a node */
.cm-force-border { padding-right: .1px; }
@media print {
/* Hide the cursor when printing */
.CodeMirror div.CodeMirror-cursors {
visibility: hidden;
}
}
/* See issue #2901 */
.cm-tab-wrap-hack:after { content: ''; }
/* Help users use markselection to safely style text background */
span.CodeMirror-selectedtext { background: none; }
// CodeMirror, copyright (c) by Marijn Haverbeke and others
// Distributed under an MIT license: http://codemirror.net/LICENSE
(function() {
var mode = CodeMirror.getMode({indentUnit: 2}, "text/x-c");
function MT(name) { test.mode(name, mode, Array.prototype.slice.call(arguments, 1)); }
MT("indent",
"[variable-3 void] [def foo]([variable-3 void*] [variable a], [variable-3 int] [variable b]) {",
" [variable-3 int] [variable c] [operator =] [variable b] [operator +]",
" [number 1];",
" [keyword return] [operator *][variable a];",
"}");
MT("indent_switch",
"[keyword switch] ([variable x]) {",
" [keyword case] [number 10]:",
" [keyword return] [number 20];",
" [keyword default]:",
" [variable printf]([string \"foo %c\"], [variable x]);",
"}");
MT("def",
"[variable-3 void] [def foo]() {}",
"[keyword struct] [def bar]{}",
"[variable-3 int] [variable-3 *][def baz]() {}");
MT("double_block",
"[keyword for] (;;)",
" [keyword for] (;;)",
" [variable x][operator ++];",
"[keyword return];");
MT("preprocessor",
"[meta #define FOO 3]",
"[variable-3 int] [variable foo];",
"[meta #define BAR\\]",
"[meta 4]",
"[variable-3 unsigned] [variable-3 int] [variable bar] [operator =] [number 8];",
"[meta #include <baz> ][comment // comment]")
var mode_cpp = CodeMirror.getMode({indentUnit: 2}, "text/x-c++src");
function MTCPP(name) { test.mode(name, mode_cpp, Array.prototype.slice.call(arguments, 1)); }
MTCPP("cpp14_literal",
"[number 10'000];",
"[number 0b10'000];",
"[number 0x10'000];",
"[string '100000'];");
})();
// CodeMirror, copyright (c) by Marijn Haverbeke and others
// Distributed under an MIT license: http://codemirror.net/LICENSE
(function(mod) {
if (typeof exports == "object" && typeof module == "object") // CommonJS
mod(require("../../lib/codemirror"));
else if (typeof define == "function" && define.amd) // AMD
define(["../../lib/codemirror"], mod);
else // Plain browser env
mod(CodeMirror);
})(function(CodeMirror) {
"use strict";
CodeMirror.defineMode("groovy", function(config) {
function words(str) {
var obj = {}, words = str.split(" ");
for (var i = 0; i < words.length; ++i) obj[words[i]] = true;
return obj;
}
var keywords = words(
"abstract as assert boolean break byte case catch char class const continue def default " +
"do double else enum extends final finally float for goto if implements import in " +
"instanceof int interface long native new package private protected public return " +
"short static strictfp super switch synchronized threadsafe throw throws transient " +
"try void volatile while");
var blockKeywords = words("catch class do else finally for if switch try while enum interface def");
var standaloneKeywords = words("return break continue");
var atoms = words("null true false this");
var curPunc;
function tokenBase(stream, state) {
var ch = stream.next();
if (ch == '"' || ch == "'") {
return startString(ch, stream, state);
}
if (/[\[\]{}\(\),;\:\.]/.test(ch)) {
curPunc = ch;
return null;
}
if (/\d/.test(ch)) {
stream.eatWhile(/[\w\.]/);
if (stream.eat(/eE/)) { stream.eat(/\+\-/); stream.eatWhile(/\d/); }
return "number";
}
if (ch == "/") {
if (stream.eat("*")) {
state.tokenize.push(tokenComment);
return tokenComment(stream, state);
}
if (stream.eat("/")) {
stream.skipToEnd();
return "comment";
}
if (expectExpression(state.lastToken, false)) {
return startString(ch, stream, state);
}
}
if (ch == "-" && stream.eat(">")) {
curPunc = "->";
return null;
}
if (/[+\-*&%=<>!?|\/~]/.test(ch)) {
stream.eatWhile(/[+\-*&%=<>|~]/);
return "operator";
}
stream.eatWhile(/[\w\$_]/);
if (ch == "@") { stream.eatWhile(/[\w\$_\.]/); return "meta"; }
if (state.lastToken == ".") return "property";
if (stream.eat(":")) { curPunc = "proplabel"; return "property"; }
var cur = stream.current();
if (atoms.propertyIsEnumerable(cur)) { return "atom"; }
if (keywords.propertyIsEnumerable(cur)) {
if (blockKeywords.propertyIsEnumerable(cur)) curPunc = "newstatement";
else if (standaloneKeywords.propertyIsEnumerable(cur)) curPunc = "standalone";
return "keyword";
}
return "variable";
}
tokenBase.isBase = true;
function startString(quote, stream, state) {
var tripleQuoted = false;
if (quote != "/" && stream.eat(quote)) {
if (stream.eat(quote)) tripleQuoted = true;
else return "string";
}
function t(stream, state) {
var escaped = false, next, end = !tripleQuoted;
while ((next = stream.next()) != null) {
if (next == quote && !escaped) {
if (!tripleQuoted) { break; }
if (stream.match(quote + quote)) { end = true; break; }
}
if (quote == '"' && next == "$" && !escaped && stream.eat("{")) {
state.tokenize.push(tokenBaseUntilBrace());
return "string";
}
escaped = !escaped && next == "\\";
}
if (end) state.tokenize.pop();
return "string";
}
state.tokenize.push(t);
return t(stream, state);
}
function tokenBaseUntilBrace() {
var depth = 1;
function t(stream, state) {
if (stream.peek() == "}") {
depth--;
if (depth == 0) {
state.tokenize.pop();
return state.tokenize[state.tokenize.length-1](stream, state);
}
} else if (stream.peek() == "{") {
depth++;
}
return tokenBase(stream, state);
}
t.isBase = true;
return t;
}
function tokenComment(stream, state) {
var maybeEnd = false, ch;
while (ch = stream.next()) {
if (ch == "/" && maybeEnd) {
state.tokenize.pop();
break;
}
maybeEnd = (ch == "*");
}
return "comment";
}
function expectExpression(last, newline) {
return !last || last == "operator" || last == "->" || /[\.\[\{\(,;:]/.test(last) ||
last == "newstatement" || last == "keyword" || last == "proplabel" ||
(last == "standalone" && !newline);
}
function Context(indented, column, type, align, prev) {
this.indented = indented;
this.column = column;
this.type = type;
this.align = align;
this.prev = prev;
}
function pushContext(state, col, type) {
return state.context = new Context(state.indented, col, type, null, state.context);
}
function popContext(state) {
var t = state.context.type;
if (t == ")" || t == "]" || t == "}")
state.indented = state.context.indented;
return state.context = state.context.prev;
}
// Interface
return {
startState: function(basecolumn) {
return {
tokenize: [tokenBase],
context: new Context((basecolumn || 0) - config.indentUnit, 0, "top", false),
indented: 0,
startOfLine: true,
lastToken: null
};
},
token: function(stream, state) {
var ctx = state.context;
if (stream.sol()) {
if (ctx.align == null) ctx.align = false;
state.indented = stream.indentation();
state.startOfLine = true;
// Automatic semicolon insertion
if (ctx.type == "statement" && !expectExpression(state.lastToken, true)) {
popContext(state); ctx = state.context;
}
}
if (stream.eatSpace()) return null;
curPunc = null;
var style = state.tokenize[state.tokenize.length-1](stream, state);
if (style == "comment") return style;
if (ctx.align == null) ctx.align = true;
if ((curPunc == ";" || curPunc == ":") && ctx.type == "statement") popContext(state);
// Handle indentation for {x -> \n ... }
else if (curPunc == "->" && ctx.type == "statement" && ctx.prev.type == "}") {
popContext(state);
state.context.align = false;
}
else if (curPunc == "{") pushContext(state, stream.column(), "}");
else if (curPunc == "[") pushContext(state, stream.column(), "]");
else if (curPunc == "(") pushContext(state, stream.column(), ")");
else if (curPunc == "}") {
while (ctx.type == "statement") ctx = popContext(state);
if (ctx.type == "}") ctx = popContext(state);
while (ctx.type == "statement") ctx = popContext(state);
}
else if (curPunc == ctx.type) popContext(state);
else if (ctx.type == "}" || ctx.type == "top" || (ctx.type == "statement" && curPunc == "newstatement"))
pushContext(state, stream.column(), "statement");
state.startOfLine = false;
state.lastToken = curPunc || style;
return style;
},
indent: function(state, textAfter) {
if (!state.tokenize[state.tokenize.length-1].isBase) return 0;
var firstChar = textAfter && textAfter.charAt(0), ctx = state.context;
if (ctx.type == "statement" && !expectExpression(state.lastToken, true)) ctx = ctx.prev;
var closing = firstChar == ctx.type;
if (ctx.type == "statement") return ctx.indented + (firstChar == "{" ? 0 : config.indentUnit);
else if (ctx.align) return ctx.column + (closing ? 0 : 1);
else return ctx.indented + (closing ? 0 : config.indentUnit);
},
electricChars: "{}",
closeBrackets: {triples: "'\""},
fold: "brace"
};
});
CodeMirror.defineMIME("text/x-groovy", "groovy");
});
...@@ -78,6 +78,7 @@ public class HandlerThread extends Thread{ ...@@ -78,6 +78,7 @@ public class HandlerThread extends Thread{
String _msg = null; String _msg = null;
try { try {
XxlJobFileAppender.contextHolder.set(trigger_log_id); XxlJobFileAppender.contextHolder.set(trigger_log_id);
logger.info(">>>>>>>>>>> xxl-job handle start.");
_status = handler.handle(handlerParams); _status = handler.handle(handlerParams);
} catch (Exception e) { } catch (Exception e) {
logger.info("HandlerThread Exception:", e); logger.info("HandlerThread Exception:", e);
...@@ -85,20 +86,23 @@ public class HandlerThread extends Thread{ ...@@ -85,20 +86,23 @@ public class HandlerThread extends Thread{
e.printStackTrace(new PrintWriter(out)); e.printStackTrace(new PrintWriter(out));
_msg = out.toString(); _msg = out.toString();
} }
logger.info(">>>>>>>>>>> xxl-job handle end, handlerParams:{}, _status:{}, _msg:{}",
new Object[]{handlerParams, _status, _msg});
// callback handler info // callback handler info
HashMap<String, String> params = new HashMap<String, String>();
params.put("trigger_log_id", trigger_log_id);
params.put("status", _status.name());
params.put("msg", _msg);
RemoteCallBack callback = null; RemoteCallBack callback = null;
logger.info(">>>>>>>>>>> xxl-job callback start.");
try { try {
HashMap<String, String> params = new HashMap<String, String>();
params.put("trigger_log_id", trigger_log_id);
params.put("status", _status.name());
params.put("msg", _msg);
callback = HttpUtil.post(trigger_log_url, params); callback = HttpUtil.post(trigger_log_url, params);
} catch (Exception e) { } catch (Exception e) {
logger.info("HandlerThread Exception:", e); logger.info("HandlerThread Exception:", e);
} }
logger.info(">>>>>>>>>>> xxl-job thread handle, handlerData:{}, callback_status:{}, callback_msg:{}, callback:{}, thread:{}", logger.info(">>>>>>>>>>> xxl-job callback end, params:{}, result:{}", new Object[]{params, callback.toString()});
new Object[]{handlerData, _status, _msg, callback, this});
} else { } else {
i++; i++;
logIdSet.clear(); logIdSet.clear();
......
...@@ -46,6 +46,12 @@ public class HttpUtil { ...@@ -46,6 +46,12 @@ public class HttpUtil {
public String getMsg() { public String getMsg() {
return msg; return msg;
} }
@Override
public String toString() {
return "RemoteCallBack [status=" + status + ", msg=" + msg + "]";
}
} }
/** /**
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册