提交 02dc2a4c authored 作者: xuxueli's avatar xuxueli

迁移 springboot

上级 3568340c
......@@ -29,9 +29,8 @@
<javax.servlet-api.version>3.1.0</javax.servlet-api.version>
<javax.servlet.jsp-api.version>2.3.3</javax.servlet.jsp-api.version>
<spring.version>4.3.19.RELEASE</spring.version>
<jackson.version>2.9.6</jackson.version>
<aspectjweaver.version>1.8.13</aspectjweaver.version>
<spring.version>4.3.20.RELEASE</spring.version>
<jackson.version>2.9.7</jackson.version>
<slf4j-api.version>1.7.25</slf4j-api.version>
<freemarker.version>2.3.28</freemarker.version>
<junit.version>4.12</junit.version>
......@@ -53,7 +52,10 @@
<groovy-all.version>2.4.15</groovy-all.version>
<quartz.version>2.3.0</quartz.version>
<spring-boot.version>1.5.16.RELEASE</spring-boot.version>
<spring-boot.version>1.5.17.RELEASE</spring-boot.version>
<mybatis-spring-boot-starter.version>1.3.2</mybatis-spring-boot-starter.version>
</properties>
<build>
......
FROM tomcat:8.0-jre8-slim
FROM openjdk:7-jre-slim
MAINTAINER xuxueli
ADD target/xxl-job-admin*.war /usr/local/tomcat/webapps/xxl-job-admin.war
ENV PARAMS=""
CMD ["catalina.sh", "run"]
\ No newline at end of file
ADD target/xxl-conf-admin-*.jar /app.jar
ENTRYPOINT ["sh","-c","java -jar /app.jar $PARAMS"]
\ No newline at end of file
......@@ -7,77 +7,56 @@
<version>2.0.0-SNAPSHOT</version>
</parent>
<artifactId>xxl-job-admin</artifactId>
<packaging>war</packaging>
<packaging>jar</packaging>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>${spring-boot.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<dependencies>
<!-- springframe start -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context-support</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-orm</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId>
<version>${spring.version}</version>
</dependency>
<!-- springframe end -->
<!-- aspectjweaver (support spring aop) -->
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>${aspectjweaver.version}</version>
</dependency>
<!-- jackson (support spring json) -->
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>${jackson.version}</version>
</dependency>
<!-- servlet -->
<!-- starter-web:spring-webmvc + autoconfigure + logback + yaml + tomcat -->
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>${javax.servlet-api.version}</version>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- starter-test:junit + spring-test + mockito -->
<dependency>
<groupId>javax.servlet.jsp</groupId>
<artifactId>javax.servlet.jsp-api</artifactId>
<version>${javax.servlet.jsp-api.version}</version>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<!-- freemarker -->
<!-- freemarker-starter -->
<dependency>
<groupId>org.freemarker</groupId>
<artifactId>freemarker</artifactId>
<version>${freemarker.version}</version>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-freemarker</artifactId>
</dependency>
<!-- slf4j -->
<!-- mybatis-starter:mybatis + mybatis-spring + tomcat-jdbc(default) -->
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
<version>${slf4j-api.version}</version>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>${mybatis-spring-boot-starter.version}</version>
</dependency>
<!-- junit -->
<!-- mysql -->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>${junit.version}</version>
<scope>test</scope>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>${mysql-connector-java.version}</version>
</dependency>
<!-- commons-collections4 -->
<dependency>
<groupId>org.apache.commons</groupId>
......@@ -97,36 +76,6 @@
<version>${commons-email.version}</version>
</dependency>
<!-- c3p0 -->
<dependency>
<groupId>com.mchange</groupId>
<artifactId>c3p0</artifactId>
<version>${c3p0.version}</version>
</dependency>
<!-- mysql-connector -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>${mysql-connector-java.version}</version>
</dependency>
<!-- mybatis-spring -->
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis-spring</artifactId>
<version>${mybatis-spring.version}</version>
</dependency>
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>${mybatis.version}</version>
</dependency>
<!-- httpclient -->
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpclient</artifactId>
<version>${httpclient.version}</version>
</dependency>
<!-- quartz :quartz-2.2.3/c3p0-0.9.1.1/slf4j-api-1.6.6 -->
<dependency>
......@@ -135,6 +84,7 @@
<version>${quartz.version}</version>
</dependency>
<!-- xxl-job-core -->
<dependency>
<groupId>com.xuxueli</groupId>
......
package com.xxl.job.admin;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
/**
* @author xuxueli 2018-10-28 00:38:13
*/
@SpringBootApplication
public class XxlJobAdminApplication {
public static void main(String[] args) {
SpringApplication.run(XxlJobAdminApplication.class, args);
}
}
\ No newline at end of file
package com.xxl.job.admin.controller;
import com.xxl.job.admin.core.conf.XxlJobAdminConfig;
import com.xxl.job.admin.core.model.XxlJobGroup;
import com.xxl.job.admin.core.model.XxlJobRegistry;
import com.xxl.job.admin.core.schedule.XxlJobDynamicScheduler;
......@@ -115,7 +116,7 @@ public class JobGroupController {
private List<String> findRegistryByAppName(String appNameParam){
HashMap<String, List<String>> appAddressMap = new HashMap<String, List<String>>();
List<XxlJobRegistry> list = XxlJobDynamicScheduler.xxlJobRegistryDao.findAll(RegistryConfig.DEAD_TIMEOUT);
List<XxlJobRegistry> list = XxlJobAdminConfig.getAdminConfig().getXxlJobRegistryDao().findAll(RegistryConfig.DEAD_TIMEOUT);
if (list != null) {
for (XxlJobRegistry item: list) {
if (RegistryConfig.RegistType.EXECUTOR.name().equals(item.getRegistryGroup())) {
......
......@@ -3,6 +3,7 @@ package com.xxl.job.admin.controller.interceptor;
import com.xxl.job.admin.core.util.FtlUtil;
import com.xxl.job.admin.core.util.I18nUtil;
import org.apache.commons.lang3.ArrayUtils;
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.handler.HandlerInterceptorAdapter;
......@@ -16,6 +17,7 @@ import java.util.HashMap;
*
* @author xuxueli 2015-12-12 18:09:04
*/
@Component
public class CookieInterceptor extends HandlerInterceptorAdapter {
@Override
......
......@@ -4,6 +4,7 @@ import com.xxl.job.admin.controller.annotation.PermessionLimit;
import com.xxl.job.admin.core.conf.XxlJobAdminConfig;
import com.xxl.job.admin.core.util.CookieUtil;
import org.apache.commons.codec.digest.DigestUtils;
import org.springframework.stereotype.Component;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.handler.HandlerInterceptorAdapter;
......@@ -16,23 +17,25 @@ import java.math.BigInteger;
*
* @author xuxueli 2015-12-12 18:09:04
*/
@Component
public class PermissionInterceptor extends HandlerInterceptorAdapter {
public static final String LOGIN_IDENTITY_KEY = "XXL_JOB_LOGIN_IDENTITY";
public static final String LOGIN_IDENTITY_TOKEN;
static {
String username = XxlJobAdminConfig.getAdminConfig().getLoginUsername();
String password = XxlJobAdminConfig.getAdminConfig().getLoginPassword();
// login token
String tokenTmp = DigestUtils.md5Hex(username + "_" + password);
tokenTmp = new BigInteger(1, tokenTmp.getBytes()).toString(16);
LOGIN_IDENTITY_TOKEN = tokenTmp;
}
private static String LOGIN_IDENTITY_TOKEN;
public static String getLoginIdentityToken() {
if (LOGIN_IDENTITY_TOKEN == null) {
String username = XxlJobAdminConfig.getAdminConfig().getLoginUsername();
String password = XxlJobAdminConfig.getAdminConfig().getLoginPassword();
// login token
String tokenTmp = DigestUtils.md5Hex(username + "_" + password);
tokenTmp = new BigInteger(1, tokenTmp.getBytes()).toString(16);
LOGIN_IDENTITY_TOKEN = tokenTmp;
}
return LOGIN_IDENTITY_TOKEN;
}
public static boolean login(HttpServletResponse response, String username, String password, boolean ifRemember){
......@@ -40,12 +43,12 @@ public class PermissionInterceptor extends HandlerInterceptorAdapter {
String tokenTmp = DigestUtils.md5Hex(username + "_" + password);
tokenTmp = new BigInteger(1, tokenTmp.getBytes()).toString(16);
if (!LOGIN_IDENTITY_TOKEN.equals(tokenTmp)){
if (!getLoginIdentityToken().equals(tokenTmp)){
return false;
}
// do login
CookieUtil.set(response, LOGIN_IDENTITY_KEY, LOGIN_IDENTITY_TOKEN, ifRemember);
CookieUtil.set(response, LOGIN_IDENTITY_KEY, getLoginIdentityToken(), ifRemember);
return true;
}
public static void logout(HttpServletRequest request, HttpServletResponse response){
......@@ -53,7 +56,7 @@ public class PermissionInterceptor extends HandlerInterceptorAdapter {
}
public static boolean ifLogin(HttpServletRequest request){
String indentityInfo = CookieUtil.getValue(request, LOGIN_IDENTITY_KEY);
if (indentityInfo==null || !LOGIN_IDENTITY_TOKEN.equals(indentityInfo.trim())) {
if (indentityInfo==null || !getLoginIdentityToken().equals(indentityInfo.trim())) {
return false;
}
return true;
......
package com.xxl.job.admin.controller.interceptor;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;
import javax.annotation.Resource;
/**
* web mvc config
*
* @author xuxueli 2018-04-02 20:48:20
*/
@Configuration
public class WebMvcConfig extends WebMvcConfigurerAdapter {
@Resource
private PermissionInterceptor permissionInterceptor;
@Resource
private CookieInterceptor cookieInterceptor;
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(permissionInterceptor).addPathPatterns("/**");
registry.addInterceptor(cookieInterceptor).addPathPatterns("/**");
super.addInterceptors(registry);
}
}
\ No newline at end of file
......@@ -4,6 +4,7 @@ import com.xxl.job.core.biz.model.ReturnT;
import com.xxl.job.core.util.JacksonUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.HandlerExceptionResolver;
......@@ -15,8 +16,10 @@ import java.io.IOException;
/**
* common exception resolver
*
* @author xuxueli 2016-1-6 19:22:18
*/
@Component
public class WebExceptionResolver implements HandlerExceptionResolver {
private static transient Logger logger = LoggerFactory.getLogger(WebExceptionResolver.class);
......
package com.xxl.job.admin.core.conf;
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.XxlJobRegistryDao;
import com.xxl.job.core.biz.AdminBiz;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Configuration;
import javax.annotation.Resource;
/**
* xxl-job config
*
......@@ -21,6 +28,8 @@ public class XxlJobAdminConfig implements InitializingBean{
adminConfig = this;
}
// conf
@Value("${xxl.job.mail.host}")
private String mailHost;
......@@ -48,6 +57,22 @@ public class XxlJobAdminConfig implements InitializingBean{
@Value("${xxl.job.i18n}")
private String i18n;
@Value("${xxl.job.accessToken}")
private String accessToken;
// dao, service
@Resource
public XxlJobLogDao xxlJobLogDao;
@Resource
public XxlJobInfoDao xxlJobInfoDao;
@Resource
public XxlJobRegistryDao xxlJobRegistryDao;
@Resource
public XxlJobGroupDao xxlJobGroupDao;
@Resource
public AdminBiz adminBiz;
public String getMailHost() {
return mailHost;
......@@ -85,4 +110,28 @@ public class XxlJobAdminConfig implements InitializingBean{
return i18n;
}
public String getAccessToken() {
return accessToken;
}
public XxlJobLogDao getXxlJobLogDao() {
return xxlJobLogDao;
}
public XxlJobInfoDao getXxlJobInfoDao() {
return xxlJobInfoDao;
}
public XxlJobRegistryDao getXxlJobRegistryDao() {
return xxlJobRegistryDao;
}
public XxlJobGroupDao getXxlJobGroupDao() {
return xxlJobGroupDao;
}
public AdminBiz getAdminBiz() {
return adminBiz;
}
}
package com.xxl.job.admin.core.conf;
import com.xxl.job.admin.core.schedule.XxlJobDynamicScheduler;
import org.quartz.Scheduler;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.io.ClassPathResource;
import org.springframework.scheduling.quartz.SchedulerFactoryBean;
import javax.sql.DataSource;
/**
* @author xuxueli 2018-10-28 00:18:17
*/
@Configuration
public class XxlJobDynamicSchedulerConfig {
@Bean
public SchedulerFactoryBean getSchedulerFactoryBean(DataSource dataSource){
SchedulerFactoryBean schedulerFactory = new SchedulerFactoryBean();
schedulerFactory.setDataSource(dataSource);
schedulerFactory.setAutoStartup(true); // 自动启动
schedulerFactory.setStartupDelay(20); // 延时启动,应用启动成功后在启动
schedulerFactory.setOverwriteExistingJobs(true); // 覆盖DB中JOB:true、以数据库中已经存在的为准:false
schedulerFactory.setApplicationContextSchedulerContextKey("applicationContext");
schedulerFactory.setConfigLocation(new ClassPathResource("quartz.properties"));
return schedulerFactory;
}
@Bean(initMethod = "start", destroyMethod = "destroy")
public XxlJobDynamicScheduler getXxlJobDynamicScheduler(SchedulerFactoryBean schedulerFactory){
Scheduler scheduler = schedulerFactory.getScheduler();
XxlJobDynamicScheduler xxlJobDynamicScheduler = new XxlJobDynamicScheduler();
xxlJobDynamicScheduler.setScheduler(scheduler);
return xxlJobDynamicScheduler;
}
}
package com.xxl.job.admin.core.schedule;
import com.xxl.job.admin.core.conf.XxlJobAdminConfig;
import com.xxl.job.admin.core.jobbean.RemoteHttpJobBean;
import com.xxl.job.admin.core.model.XxlJobInfo;
import com.xxl.job.admin.core.thread.JobFailMonitorHelper;
......@@ -21,6 +22,8 @@ import org.quartz.impl.triggers.CronTriggerImpl;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.DisposableBean;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.util.Assert;
......@@ -33,7 +36,7 @@ import java.util.concurrent.ConcurrentHashMap;
* base quartz scheduler util
* @author xuxueli 2015-12-19 16:13:53
*/
public final class XxlJobDynamicScheduler implements ApplicationContextAware {
public final class XxlJobDynamicScheduler {
private static final Logger logger = LoggerFactory.getLogger(XxlJobDynamicScheduler.class);
// ---------------------- param ----------------------
......@@ -44,31 +47,9 @@ public final class XxlJobDynamicScheduler implements ApplicationContextAware {
XxlJobDynamicScheduler.scheduler = scheduler;
}
// accessToken
private static String accessToken;
public void setAccessToken(String accessToken) {
this.accessToken = accessToken;
}
// dao
public static XxlJobLogDao xxlJobLogDao;
public static XxlJobInfoDao xxlJobInfoDao;
public static XxlJobRegistryDao xxlJobRegistryDao;
public static XxlJobGroupDao xxlJobGroupDao;
public static AdminBiz adminBiz;
// ---------------------- applicationContext ----------------------
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
XxlJobDynamicScheduler.xxlJobLogDao = applicationContext.getBean(XxlJobLogDao.class);
XxlJobDynamicScheduler.xxlJobInfoDao = applicationContext.getBean(XxlJobInfoDao.class);
XxlJobDynamicScheduler.xxlJobRegistryDao = applicationContext.getBean(XxlJobRegistryDao.class);
XxlJobDynamicScheduler.xxlJobGroupDao = applicationContext.getBean(XxlJobGroupDao.class);
XxlJobDynamicScheduler.adminBiz = applicationContext.getBean(AdminBiz.class);
}
// ---------------------- init + destroy ----------------------
public void init() throws Exception {
public void start() throws Exception {
// admin registry monitor run
JobRegistryMonitorHelper.getInstance().start();
......@@ -76,8 +57,8 @@ public final class XxlJobDynamicScheduler implements ApplicationContextAware {
JobFailMonitorHelper.getInstance().start();
// admin-server(spring-mvc)
NetComServerFactory.putService(AdminBiz.class, XxlJobDynamicScheduler.adminBiz);
NetComServerFactory.setAccessToken(accessToken);
NetComServerFactory.putService(AdminBiz.class, XxlJobAdminConfig.getAdminConfig().getAdminBiz());
NetComServerFactory.setAccessToken(XxlJobAdminConfig.getAdminConfig().getAccessToken());
// init i18n
initI18n();
......@@ -105,6 +86,7 @@ public final class XxlJobDynamicScheduler implements ApplicationContextAware {
JobFailMonitorHelper.getInstance().toStop();
}
// ---------------------- executor-client ----------------------
private static ConcurrentHashMap<String, ExecutorBiz> executorBizRepository = new ConcurrentHashMap<String, ExecutorBiz>();
public static ExecutorBiz getExecutorBiz(String address) throws Exception {
......@@ -121,7 +103,7 @@ public final class XxlJobDynamicScheduler implements ApplicationContextAware {
}
// set-cache
executorBiz = (ExecutorBiz) new NetComClientProxy(ExecutorBiz.class, address, accessToken).getObject();
executorBiz = (ExecutorBiz) new NetComClientProxy(ExecutorBiz.class, address, XxlJobAdminConfig.getAdminConfig().getAccessToken()).getObject();
executorBizRepository.put(address, executorBiz);
return executorBiz;
}
......@@ -362,6 +344,7 @@ public final class XxlJobDynamicScheduler implements ApplicationContextAware {
return result;
}
/**
* finaAllJobList
*
......
package com.xxl.job.admin.core.thread;
import com.xxl.job.admin.core.conf.XxlJobAdminConfig;
import com.xxl.job.admin.core.model.XxlJobGroup;
import com.xxl.job.admin.core.model.XxlJobInfo;
import com.xxl.job.admin.core.model.XxlJobLog;
......@@ -52,7 +53,7 @@ public class JobFailMonitorHelper {
if (jobLogId==null || jobLogId==0) {
continue;
}
XxlJobLog log = XxlJobDynamicScheduler.xxlJobLogDao.load(jobLogId);
XxlJobLog log = XxlJobAdminConfig.getAdminConfig().getXxlJobLogDao().load(jobLogId);
if (log == null) {
continue;
}
......@@ -70,13 +71,13 @@ public class JobFailMonitorHelper {
// job fail,
// 1、fail retry
XxlJobInfo info = XxlJobDynamicScheduler.xxlJobInfoDao.loadById(log.getJobId());
XxlJobInfo info = XxlJobAdminConfig.getAdminConfig().getXxlJobInfoDao().loadById(log.getJobId());
if (log.getExecutorFailRetryCount() > 0) {
JobTriggerPoolHelper.trigger(log.getJobId(), TriggerTypeEnum.RETRY, (log.getExecutorFailRetryCount()-1), log.getExecutorShardingParam(), null);
String retryMsg = "<br><br><span style=\"color:#F39C12;\" > >>>>>>>>>>>"+ I18nUtil.getString("jobconf_trigger_type_retry") +"<<<<<<<<<<< </span><br>";
log.setTriggerMsg(log.getTriggerMsg() + retryMsg);
XxlJobDynamicScheduler.xxlJobLogDao.updateTriggerInfo(log);
XxlJobAdminConfig.getAdminConfig().getXxlJobLogDao().updateTriggerInfo(log);
}
// 2、fail alarm
......@@ -101,10 +102,10 @@ public class JobFailMonitorHelper {
int drainToNum = getInstance().queue.drainTo(jobLogIdList);
if (jobLogIdList!=null && jobLogIdList.size()>0) {
for (Integer jobLogId: jobLogIdList) {
XxlJobLog log = XxlJobDynamicScheduler.xxlJobLogDao.load(jobLogId);
XxlJobLog log = XxlJobAdminConfig.getAdminConfig().getXxlJobLogDao().load(jobLogId);
if (ReturnT.FAIL_CODE == log.getTriggerCode()|| ReturnT.FAIL_CODE==log.getHandleCode()) {
// job fail,
XxlJobInfo info = XxlJobDynamicScheduler.xxlJobInfoDao.loadById(log.getJobId());
XxlJobInfo info = XxlJobAdminConfig.getAdminConfig().getXxlJobInfoDao().loadById(log.getJobId());
failAlarm(info, log);
logger.info(">>>>>>>>>>> job monitor last, job fail, JobLogId:{}", jobLogId);
......@@ -180,7 +181,7 @@ public class JobFailMonitorHelper {
Set<String> emailSet = new HashSet<String>(Arrays.asList(info.getAlarmEmail().split(",")));
for (String email: emailSet) {
XxlJobGroup group = XxlJobDynamicScheduler.xxlJobGroupDao.load(Integer.valueOf(info.getJobGroup()));
XxlJobGroup group = XxlJobAdminConfig.getAdminConfig().getXxlJobGroupDao().load(Integer.valueOf(info.getJobGroup()));
String title = I18nUtil.getString("jobconf_monitor");
String content = MessageFormat.format(mailBodyTemplate,
......
package com.xxl.job.admin.core.thread;
import com.xxl.job.admin.core.conf.XxlJobAdminConfig;
import com.xxl.job.admin.core.model.XxlJobGroup;
import com.xxl.job.admin.core.model.XxlJobRegistry;
import com.xxl.job.admin.core.schedule.XxlJobDynamicScheduler;
......@@ -36,15 +37,15 @@ public class JobRegistryMonitorHelper {
while (!toStop) {
try {
// auto registry group
List<XxlJobGroup> groupList = XxlJobDynamicScheduler.xxlJobGroupDao.findByAddressType(0);
List<XxlJobGroup> groupList = XxlJobAdminConfig.getAdminConfig().getXxlJobGroupDao().findByAddressType(0);
if (CollectionUtils.isNotEmpty(groupList)) {
// remove dead address (admin/executor)
XxlJobDynamicScheduler.xxlJobRegistryDao.removeDead(RegistryConfig.DEAD_TIMEOUT);
XxlJobAdminConfig.getAdminConfig().getXxlJobRegistryDao().removeDead(RegistryConfig.DEAD_TIMEOUT);
// fresh online address (admin/executor)
HashMap<String, List<String>> appAddressMap = new HashMap<String, List<String>>();
List<XxlJobRegistry> list = XxlJobDynamicScheduler.xxlJobRegistryDao.findAll(RegistryConfig.DEAD_TIMEOUT);
List<XxlJobRegistry> list = XxlJobAdminConfig.getAdminConfig().getXxlJobRegistryDao().findAll(RegistryConfig.DEAD_TIMEOUT);
if (list != null) {
for (XxlJobRegistry item: list) {
if (RegistryConfig.RegistType.EXECUTOR.name().equals(item.getRegistryGroup())) {
......@@ -71,7 +72,7 @@ public class JobRegistryMonitorHelper {
addressListStr = StringUtils.join(registryList, ",");
}
group.setAddressList(addressListStr);
XxlJobDynamicScheduler.xxlJobGroupDao.update(group);
XxlJobAdminConfig.getAdminConfig().getXxlJobGroupDao().update(group);
}
}
} catch (Exception e) {
......
package com.xxl.job.admin.core.trigger;
import com.xxl.job.admin.core.conf.XxlJobAdminConfig;
import com.xxl.job.admin.core.model.XxlJobGroup;
import com.xxl.job.admin.core.model.XxlJobInfo;
import com.xxl.job.admin.core.model.XxlJobLog;
......@@ -41,7 +42,7 @@ public class XxlJobTrigger {
*/
public static void trigger(int jobId, TriggerTypeEnum triggerType, int failRetryCount, String executorShardingParam, String executorParam) {
// load data
XxlJobInfo jobInfo = XxlJobDynamicScheduler.xxlJobInfoDao.loadById(jobId);
XxlJobInfo jobInfo = XxlJobAdminConfig.getAdminConfig().getXxlJobInfoDao().loadById(jobId);
if (jobInfo == null) {
logger.warn(">>>>>>>>>>>> trigger fail, jobId invalid,jobId={}", jobId);
return;
......@@ -50,7 +51,7 @@ public class XxlJobTrigger {
jobInfo.setExecutorParam(executorParam);
}
int finalFailRetryCount = failRetryCount>=0?failRetryCount:jobInfo.getExecutorFailRetryCount();
XxlJobGroup group = XxlJobDynamicScheduler.xxlJobGroupDao.load(jobInfo.getJobGroup());
XxlJobGroup group = XxlJobAdminConfig.getAdminConfig().getXxlJobGroupDao().load(jobInfo.getJobGroup());
// sharding param
int[] shardingParam = null;
......@@ -96,7 +97,7 @@ public class XxlJobTrigger {
jobLog.setJobGroup(jobInfo.getJobGroup());
jobLog.setJobId(jobInfo.getId());
jobLog.setTriggerTime(new Date());
XxlJobDynamicScheduler.xxlJobLogDao.save(jobLog);
XxlJobAdminConfig.getAdminConfig().getXxlJobLogDao().save(jobLog);
logger.debug(">>>>>>>>>>> xxl-job trigger start, jobId:{}", jobLog.getId());
// 2、init trigger-param
......@@ -169,7 +170,7 @@ public class XxlJobTrigger {
//jobLog.setTriggerTime();
jobLog.setTriggerCode(triggerResult.getCode());
jobLog.setTriggerMsg(triggerMsgSb.toString());
XxlJobDynamicScheduler.xxlJobLogDao.updateTriggerInfo(jobLog);
XxlJobAdminConfig.getAdminConfig().getXxlJobLogDao().updateTriggerInfo(jobLog);
// 7、monitor trigger
JobFailMonitorHelper.monitor(jobLog.getId());
......
package com.xxl.job.admin.dao;
import com.xxl.job.admin.core.model.XxlJobGroup;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
import java.util.List;
......@@ -8,6 +9,7 @@ import java.util.List;
/**
* Created by xuxueli on 16/9/30.
*/
@Mapper
public interface XxlJobGroupDao {
public List<XxlJobGroup> findAll();
......
package com.xxl.job.admin.dao;
import com.xxl.job.admin.core.model.XxlJobInfo;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
import java.util.List;
......@@ -10,6 +11,7 @@ import java.util.List;
* job info
* @author xuxueli 2016-1-12 18:03:45
*/
@Mapper
public interface XxlJobInfoDao {
public List<XxlJobInfo> pageList(@Param("offset") int offset,
......
package com.xxl.job.admin.dao;
import com.xxl.job.admin.core.model.XxlJobLog;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
import java.util.Date;
......@@ -11,6 +12,7 @@ import java.util.Map;
* job log
* @author xuxueli 2016-1-12 18:03:06
*/
@Mapper
public interface XxlJobLogDao {
public List<XxlJobLog> pageList(@Param("offset") int offset,
......
package com.xxl.job.admin.dao;
import com.xxl.job.admin.core.model.XxlJobLogGlue;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
import java.util.List;
......@@ -9,6 +10,7 @@ import java.util.List;
* job log for glue
* @author xuxueli 2016-5-19 18:04:56
*/
@Mapper
public interface XxlJobLogGlueDao {
public int save(XxlJobLogGlue xxlJobLogGlue);
......
package com.xxl.job.admin.dao;
import com.xxl.job.admin.core.model.XxlJobRegistry;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
import java.util.List;
......@@ -8,6 +9,7 @@ import java.util.List;
/**
* Created by xuxueli on 16/9/30.
*/
@Mapper
public interface XxlJobRegistryDao {
public int removeDead(@Param("timeout") int timeout);
......
### xxl-job db (use &amp; replace & in xml)
xxl.job.db.driverClass=com.mysql.jdbc.Driver
xxl.job.db.url=jdbc:mysql://localhost:3306/xxl-job?useUnicode=true&characterEncoding=UTF-8
xxl.job.db.user=root
xxl.job.db.password=root_pwd
### web
server.port=8080
server.context-path=/xxl-job-admin
### resources
spring.mvc.static-path-pattern=/static/**
spring.resources.static-locations=classpath:/static/
### freemarker
spring.freemarker.templateLoaderPath=classpath:/templates/
spring.freemarker.suffix=.ftl
spring.freemarker.charset=UTF-8
spring.freemarker.request-context-attribute=request
### mybatis
mybatis.mapper-locations=classpath:/mybatis-mapper/*Mapper.xml
### xxl-job, datasource
spring.datasource.url=jdbc:mysql://127.0.0.1:3306/xxl-job?Unicode=true&characterEncoding=UTF-8
spring.datasource.username=root
spring.datasource.password=root_pwd
spring.datasource.driver-class-name=com.mysql.jdbc.Driver
spring.datasource.type=org.apache.tomcat.jdbc.pool.DataSource
spring.datasource.tomcat.max-wait=10000
spring.datasource.tomcat.max-active=30
spring.datasource.tomcat.test-on-borrow=true
### xxl-job email
xxl.job.mail.host=smtp.163.com
......@@ -20,4 +42,4 @@ xxl.job.login.password=123456
xxl.job.accessToken=
### xxl-job, i18n (default empty as chinese, "en" as english)
xxl.job.i18n=
\ No newline at end of file
xxl.job.i18n=
template_update_delay=0
default_encoding=UTF-8
output_encoding=UTF-8
locale=zh_CN
number_format=0.##########
date_format=yyyy-MM-dd
time_format=HH:mm:ss
datetime_format=yyyy-MM-dd HH:mm:s
classic_compatible=true
template_exception_handler=ignore
\ No newline at end of file
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE log4j:configuration PUBLIC "-//log4j/log4j Configuration//EN" "log4j.dtd">
<log4j:configuration xmlns:log4j="http://jakarta.apache.org/log4j/" threshold="null" debug="null">
<appender name="CONSOLE" class="org.apache.log4j.ConsoleAppender">
<param name="Target" value="System.out" />
<layout class="org.apache.log4j.PatternLayout">
<param name="ConversionPattern" value="%-d{yyyy-MM-dd HH:mm:ss} xxl-job-admin [%c]-[%t]-[%M]-[%L]-[%p] %m%n"/>
</layout>
</appender>
<appender name="FILE" class="org.apache.log4j.DailyRollingFileAppender">
<param name="file" value="/data/applogs/xxl-job/xxl-job-admin.log"/>
<param name="append" value="true"/>
<param name="encoding" value="UTF-8"/>
<layout class="org.apache.log4j.PatternLayout">
<param name="ConversionPattern" value="%-d{yyyy-MM-dd HH:mm:ss} xxl-job-admin [%c]-[%t]-[%M]-[%L]-[%p] %m%n"/>
</layout>
</appender>
<root>
<level value="INFO" />
<appender-ref ref="CONSOLE" />
<appender-ref ref="FILE" />
</root>
</log4j:configuration>
\ No newline at end of file
<?xml version="1.0" encoding="UTF-8"?>
<configuration debug="false" scan="true" scanPeriod="1 seconds">
<contextName>logback</contextName>
<property name="log.path" value="/data/applogs/xxl-job/xxl-job-admin.log"/>
<appender name="console" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<pattern>%d{HH:mm:ss.SSS} %contextName [%thread] %-5level %logger{36} - %msg%n</pattern>
</encoder>
</appender>
<appender name="file" class="ch.qos.logback.core.rolling.RollingFileAppender">
<file>${log.path}</file>
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<fileNamePattern>${log.path}.%d{yyyy-MM-dd}.zip</fileNamePattern>
</rollingPolicy>
<encoder>
<pattern>%date %level [%thread] %logger{36} [%file : %line] %msg%n
</pattern>
</encoder>
</appender>
<root level="info">
<appender-ref ref="console"/>
<appender-ref ref="file"/>
</root>
</configuration>
\ No newline at end of file
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd">
<context:component-scan base-package="com.xxl.job.admin.core.conf, com.xxl.job.admin.service, com.xxl.job.admin.dao" />
<bean id="freemarkerConfig" class="org.springframework.web.servlet.view.freemarker.FreeMarkerConfigurer">
<property name="templateLoaderPath" value="/WEB-INF/template/" />
<property name="freemarkerSettings">
<bean class="org.springframework.beans.factory.config.PropertiesFactoryBean">
<property name="location" value="classpath:freemarker.properties" />
</bean>
</property>
</bean>
</beans>
\ No newline at end of file
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx.xsd">
<bean id="propertyConfigurer" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="fileEncoding" value="utf-8" />
<property name="locations">
<list>
<value>classpath*:xxl-job-admin.properties</value>
</list>
</property>
</bean>
<!-- ********************************* part 1 :for datasource ********************************* -->
<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource" destroy-method="close">
<property name="driverClass" value="${xxl.job.db.driverClass}" />
<property name="jdbcUrl" value="${xxl.job.db.url}" />
<property name="user" value="${xxl.job.db.user}" />
<property name="password" value="${xxl.job.db.password}" />
<property name="initialPoolSize" value="3" />
<property name="minPoolSize" value="2" />
<property name="maxPoolSize" value="10" />
<property name="maxIdleTime" value="60" />
<property name="acquireRetryDelay" value="1000" />
<property name="acquireRetryAttempts" value="10" />
<property name="preferredTestQuery" value="SELECT 1" />
</bean>
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
<property name="dataSource" ref="dataSource" />
<property name="mapperLocations" value="classpath:mybatis-mapper/*.xml"/>
</bean>
<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
<property name="sqlSessionFactoryBeanName" value="sqlSessionFactory"/>
<property name="basePackage" value="com.xxl.job.admin.dao" />
</bean>
<!-- ********************************* part 2 :for tx ********************************* -->
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource" />
</bean>
<tx:annotation-driven transaction-manager="transactionManager" proxy-target-class="true"/>
<!-- ********************************* part 3 :for xxl-job scheduler ********************************* -->
<bean id="quartzScheduler" lazy-init="false" class="org.springframework.scheduling.quartz.SchedulerFactoryBean">
<property name="dataSource" ref="dataSource" />
<property name="autoStartup" value="true" /> <!--自动启动 -->
<property name="startupDelay" value="20" /> <!--延时启动,应用启动成功后在启动 -->
<property name="overwriteExistingJobs" value="true" /> <!--覆盖DB中JOB:true、以数据库中已经存在的为准:false -->
<property name="applicationContextSchedulerContextKey" value="applicationContextKey" />
<property name="configLocation" value="classpath:quartz.properties"/>
</bean>
<bean id="xxlJobDynamicScheduler" class="com.xxl.job.admin.core.schedule.XxlJobDynamicScheduler" init-method="init" destroy-method="destroy" >
<!-- (轻易不要变更“调度器名称”, 任务创建时会绑定该“调度器名称”) -->
<property name="scheduler" ref="quartzScheduler"/>
<property name="accessToken" value="${xxl.job.accessToken}" />
</bean>
</beans>
\ No newline at end of file
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/mvc
http://www.springframework.org/schema/mvc/spring-mvc.xsd">
<mvc:annotation-driven />
<context:component-scan base-package="com.xxl.job.admin.controller" />
<mvc:resources mapping="/favicon.ico" location="/favicon.ico" />
<mvc:resources mapping="/static/**" location="/static/" />
<mvc:resources mapping="/**/*.html" location="/" />
<bean id="viewResolver" class="org.springframework.web.servlet.view.freemarker.FreeMarkerViewResolver">
<property name="viewClass" value="org.springframework.web.servlet.view.freemarker.FreeMarkerView" />
<property name="prefix" value="" />
<property name="suffix" value=".ftl" />
<property name="contentType" value="text/html;charset=UTF-8" />
<property name="exposeSpringMacroHelpers" value="true" />
<property name="exposeRequestAttributes" value="true" />
<property name="exposeSessionAttributes" value="true" />
<property name="requestContextAttribute" value="request" />
<property name="cache" value="true" />
<property name="order" value="0" />
</bean>
<mvc:interceptors>
<mvc:interceptor>
<mvc:mapping path="/**"/>
<bean class="com.xxl.job.admin.controller.interceptor.PermissionInterceptor"/>
</mvc:interceptor>
<mvc:interceptor>
<mvc:mapping path="/**"/>
<bean class="com.xxl.job.admin.controller.interceptor.CookieInterceptor"/>
</mvc:interceptor>
</mvc:interceptors>
<bean id="exceptionResolver" class="com.xxl.job.admin.controller.resolver.WebExceptionResolver" />
</beans>
\ No newline at end of file
$(function(){
// logout
$("#logoutBtn").click(function(){
layer.confirm( I18n.logout_confirm , {
icon: 3,
title: I18n.system_tips ,
btn: [ I18n.system_ok, I18n.system_cancel ]
}, function(index){
layer.close(index);
$.post(base_url + "/logout", function(data, status) {
if (data.code == "200") {
layer.msg( I18n.logout_success );
setTimeout(function(){
window.location.href = base_url + "/";
}, 500);
} else {
layer.open({
title: I18n.system_tips ,
btn: [ I18n.system_ok ],
content: (data.msg || I18n.logout_fail),
icon: '2'
});
}
});
});
});
// slideToTop
var slideToTop = $("<div />");
slideToTop.html('<i class="fa fa-chevron-up"></i>');
slideToTop.css({
position: 'fixed',
bottom: '20px',
right: '25px',
width: '40px',
height: '40px',
color: '#eee',
'font-size': '',
'line-height': '40px',
'text-align': 'center',
'background-color': '#222d32',
cursor: 'pointer',
'border-radius': '5px',
'z-index': '99999',
opacity: '.7',
'display': 'none'
});
slideToTop.on('mouseenter', function () {
$(this).css('opacity', '1');
});
slideToTop.on('mouseout', function () {
$(this).css('opacity', '.7');
});
$('.wrapper').append(slideToTop);
$(window).scroll(function () {
if ($(window).scrollTop() >= 150) {
if (!$(slideToTop).is(':visible')) {
$(slideToTop).fadeIn(500);
}
} else {
$(slideToTop).fadeOut(500);
}
});
$(slideToTop).click(function () {
$("html,body").animate({ // firefox ie not support body, chrome support body. but found that new version chrome not support body too.
scrollTop: 0
}, 100);
});
// left menu status v: js + server + cookie
$('.sidebar-toggle').click(function(){
var xxljob_adminlte_settings = $.cookie('xxljob_adminlte_settings'); // on=open,off=close
if ('off' == xxljob_adminlte_settings) {
xxljob_adminlte_settings = 'on';
} else {
xxljob_adminlte_settings = 'off';
}
$.cookie('xxljob_adminlte_settings', xxljob_adminlte_settings, { expires: 7 }); //$.cookie('the_cookie', '', { expires: -1 });
});
// left menu status v1: js + cookie
/*
var xxljob_adminlte_settings = $.cookie('xxljob_adminlte_settings');
if (xxljob_adminlte_settings == 'off') {
$('body').addClass('sidebar-collapse');
}
*/
});
$(function(){
// logout
$("#logoutBtn").click(function(){
layer.confirm( I18n.logout_confirm , {
icon: 3,
title: I18n.system_tips ,
btn: [ I18n.system_ok, I18n.system_cancel ]
}, function(index){
layer.close(index);
$.post(base_url + "/logout", function(data, status) {
if (data.code == "200") {
layer.msg( I18n.logout_success );
setTimeout(function(){
window.location.href = base_url + "/";
}, 500);
} else {
layer.open({
title: I18n.system_tips ,
btn: [ I18n.system_ok ],
content: (data.msg || I18n.logout_fail),
icon: '2'
});
}
});
});
});
// slideToTop
var slideToTop = $("<div />");
slideToTop.html('<i class="fa fa-chevron-up"></i>');
slideToTop.css({
position: 'fixed',
bottom: '20px',
right: '25px',
width: '40px',
height: '40px',
color: '#eee',
'font-size': '',
'line-height': '40px',
'text-align': 'center',
'background-color': '#222d32',
cursor: 'pointer',
'border-radius': '5px',
'z-index': '99999',
opacity: '.7',
'display': 'none'
});
slideToTop.on('mouseenter', function () {
$(this).css('opacity', '1');
});
slideToTop.on('mouseout', function () {
$(this).css('opacity', '.7');
});
$('.wrapper').append(slideToTop);
$(window).scroll(function () {
if ($(window).scrollTop() >= 150) {
if (!$(slideToTop).is(':visible')) {
$(slideToTop).fadeIn(500);
}
} else {
$(slideToTop).fadeOut(500);
}
});
$(slideToTop).click(function () {
$("html,body").animate({ // firefox ie not support body, chrome support body. but found that new version chrome not support body too.
scrollTop: 0
}, 100);
});
// left menu status v: js + server + cookie
$('.sidebar-toggle').click(function(){
var xxljob_adminlte_settings = $.cookie('xxljob_adminlte_settings'); // on=open,off=close
if ('off' == xxljob_adminlte_settings) {
xxljob_adminlte_settings = 'on';
} else {
xxljob_adminlte_settings = 'off';
}
$.cookie('xxljob_adminlte_settings', xxljob_adminlte_settings, { expires: 7 }); //$.cookie('the_cookie', '', { expires: -1 });
});
// left menu status v1: js + cookie
/*
var xxljob_adminlte_settings = $.cookie('xxljob_adminlte_settings');
if (xxljob_adminlte_settings == 'off') {
$('body').addClass('sidebar-collapse');
}
*/
});
$(function() {
// init code editor
var codeEditor;
function initIde(glueSource) {
if (codeEditor == null) {
codeEditor = CodeMirror(document.getElementById("ideWindow"), {
mode : ideMode,
lineNumbers : true,
matchBrackets : true,
value: glueSource
});
} else {
codeEditor.setValue(glueSource);
}
}
initIde($("#version_now").val());
// code change
$(".source_version").click(function(){
var sourceId = $(this).attr('version');
var temp = $( "#" + sourceId ).val();
//codeEditor.setValue('');
initIde(temp);
});
// code source save
$("#save").click(function() {
$('#saveModal').modal({backdrop: false, keyboard: false}).modal('show');
});
$("#saveModal .ok").click(function() {
var glueSource = codeEditor.getValue();
var glueRemark = $("#glueRemark").val();
if (!glueRemark) {
layer.open({
title: I18n.system_tips,
btn: [ I18n.system_ok],
content: I18n.system_please_input + I18n.jobinfo_glue_remark ,
icon: '2'
});
return;
}
if (glueRemark.length <4 || glueRemark.length > 100) {
layer.open({
title: I18n.system_tips ,
btn: [ I18n.system_ok ],
content: I18n.jobinfo_glue_remark_limit ,
icon: '2'
});
return;
}
$.ajax({
type : 'POST',
url : base_url + '/jobcode/save',
data : {
'id' : id,
'glueSource' : glueSource,
'glueRemark' : glueRemark
},
dataType : "json",
success : function(data){
if (data.code == 200) {
layer.open({
title: I18n.system_tips,
btn: [ I18n.system_ok ],
content: (I18n.system_save + I18n.system_success) ,
icon: '1',
end: function(layero, index){
//$(window).unbind('beforeunload');
window.location.reload();
}
});
} else {
layer.open({
title: I18n.system_tips,
btn: [ I18n.system_ok ],
content: (data.msg || (I18n.system_save + I18n.system_fail) ),
icon: '2'
});
}
}
});
});
// before upload
/*$(window).bind('beforeunload',function(){
return 'Glue尚未保存,确定离开Glue编辑器?';
});*/
});
$(function() {
// init code editor
var codeEditor;
function initIde(glueSource) {
if (codeEditor == null) {
codeEditor = CodeMirror(document.getElementById("ideWindow"), {
mode : ideMode,
lineNumbers : true,
matchBrackets : true,
value: glueSource
});
} else {
codeEditor.setValue(glueSource);
}
}
initIde($("#version_now").val());
// code change
$(".source_version").click(function(){
var sourceId = $(this).attr('version');
var temp = $( "#" + sourceId ).val();
//codeEditor.setValue('');
initIde(temp);
});
// code source save
$("#save").click(function() {
$('#saveModal').modal({backdrop: false, keyboard: false}).modal('show');
});
$("#saveModal .ok").click(function() {
var glueSource = codeEditor.getValue();
var glueRemark = $("#glueRemark").val();
if (!glueRemark) {
layer.open({
title: I18n.system_tips,
btn: [ I18n.system_ok],
content: I18n.system_please_input + I18n.jobinfo_glue_remark ,
icon: '2'
});
return;
}
if (glueRemark.length <4 || glueRemark.length > 100) {
layer.open({
title: I18n.system_tips ,
btn: [ I18n.system_ok ],
content: I18n.jobinfo_glue_remark_limit ,
icon: '2'
});
return;
}
$.ajax({
type : 'POST',
url : base_url + '/jobcode/save',
data : {
'id' : id,
'glueSource' : glueSource,
'glueRemark' : glueRemark
},
dataType : "json",
success : function(data){
if (data.code == 200) {
layer.open({
title: I18n.system_tips,
btn: [ I18n.system_ok ],
content: (I18n.system_save + I18n.system_success) ,
icon: '1',
end: function(layero, index){
//$(window).unbind('beforeunload');
window.location.reload();
}
});
} else {
layer.open({
title: I18n.system_tips,
btn: [ I18n.system_ok ],
content: (data.msg || (I18n.system_save + I18n.system_fail) ),
icon: '2'
});
}
}
});
});
// before upload
/*$(window).bind('beforeunload',function(){
return 'Glue尚未保存,确定离开Glue编辑器?';
});*/
});
$(function(){
// input iCheck
$('input').iCheck({
checkboxClass: 'icheckbox_square-blue',
radioClass: 'iradio_square-blue',
increaseArea: '20%' // optional
});
// login Form Valid
var loginFormValid = $("#loginForm").validate({
errorElement : 'span',
errorClass : 'help-block',
focusInvalid : true,
rules : {
userName : {
required : true ,
minlength: 5,
maxlength: 18
},
password : {
required : true ,
minlength: 5,
maxlength: 18
}
},
messages : {
userName : {
required : I18n.login_username_empty,
minlength : I18n.login_username_lt_5
},
password : {
required : I18n.login_password_empty ,
minlength : I18n.login_password_lt_5
/*,maxlength:"登录密码不应超过18位"*/
}
},
highlight : function(element) {
$(element).closest('.form-group').addClass('has-error');
},
success : function(label) {
label.closest('.form-group').removeClass('has-error');
label.remove();
},
errorPlacement : function(error, element) {
element.parent('div').append(error);
},
submitHandler : function(form) {
$.post(base_url + "/login", $("#loginForm").serialize(), function(data, status) {
if (data.code == "200") {
layer.msg( I18n.login_success );
setTimeout(function(){
window.location.href = base_url;
}, 500);
} else {
layer.open({
title: I18n.system_tips,
btn: [ I18n.system_ok ],
content: (data.msg || I18n.login_fail ),
icon: '2'
});
}
});
}
});
$(function(){
// input iCheck
$('input').iCheck({
checkboxClass: 'icheckbox_square-blue',
radioClass: 'iradio_square-blue',
increaseArea: '20%' // optional
});
// login Form Valid
var loginFormValid = $("#loginForm").validate({
errorElement : 'span',
errorClass : 'help-block',
focusInvalid : true,
rules : {
userName : {
required : true ,
minlength: 5,
maxlength: 18
},
password : {
required : true ,
minlength: 5,
maxlength: 18
}
},
messages : {
userName : {
required : I18n.login_username_empty,
minlength : I18n.login_username_lt_5
},
password : {
required : I18n.login_password_empty ,
minlength : I18n.login_password_lt_5
/*,maxlength:"登录密码不应超过18位"*/
}
},
highlight : function(element) {
$(element).closest('.form-group').addClass('has-error');
},
success : function(label) {
label.closest('.form-group').removeClass('has-error');
label.remove();
},
errorPlacement : function(error, element) {
element.parent('div').append(error);
},
submitHandler : function(form) {
$.post(base_url + "/login", $("#loginForm").serialize(), function(data, status) {
if (data.code == "200") {
layer.msg( I18n.login_success );
setTimeout(function(){
window.location.href = base_url;
}, 500);
} else {
layer.open({
title: I18n.system_tips,
btn: [ I18n.system_ok ],
content: (data.msg || I18n.login_fail ),
icon: '2'
});
}
});
}
});
});
\ No newline at end of file
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Error</title>
<style type="text/css">
body { background-color: #fff; color: #666; text-align: center; font-family: arial, sans-serif; }
div.dialog {
width: 80%;
padding: 1em 4em;
margin: 4em auto 0 auto;
border: 1px solid #ccc;
border-right-color: #999;
border-bottom-color: #999;
}
h1 { font-size: 100%; color: #f00; line-height: 1.5em; }
</style>
</head>
</head>
<body>
<div class="dialog">
<h1>System Error</h1>
<p>${exceptionMsg}</p>
<a href="javascript:window.location.href='${request.contextPath}/'">Back</a>
</p>
</div>
</body>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Error</title>
<style type="text/css">
body { background-color: #fff; color: #666; text-align: center; font-family: arial, sans-serif; }
div.dialog {
width: 80%;
padding: 1em 4em;
margin: 4em auto 0 auto;
border: 1px solid #ccc;
border-right-color: #999;
border-bottom-color: #999;
}
h1 { font-size: 100%; color: #f00; line-height: 1.5em; }
</style>
</head>
</head>
<body>
<div class="dialog">
<h1>System Error</h1>
<p>${exceptionMsg}</p>
<a href="javascript:window.location.href='${request.contextPath}/'">Back</a>
</p>
</div>
</body>
</html>
\ No newline at end of file
<#macro commonStyle>
<#-- favicon -->
<link rel="icon" href="favicon.ico" />
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<!-- Tell the browser to be responsive to screen width -->
<meta content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no" name="viewport">
<!-- Bootstrap 3.3.5 -->
<link rel="stylesheet" href="${request.contextPath}/static/adminlte/bootstrap/css/bootstrap.min.css">
<!-- Font Awesome -->
<!-- <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.5.0/css/font-awesome.min.css"> -->
<link rel="stylesheet" href="${request.contextPath}/static/plugins/font-awesome-4.5.0/css/font-awesome.min.css">
<!-- Ionicons -->
<!-- <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/ionicons/2.0.1/css/ionicons.min.css"> -->
<link rel="stylesheet" href="${request.contextPath}/static/plugins/ionicons-2.0.1/css/ionicons.min.css">
<!-- Theme style -->
<link rel="stylesheet" href="${request.contextPath}/static/adminlte/dist/css/AdminLTE-local.min.css">
<!-- AdminLTE Skins. Choose a skin from the css/skins folder instead of downloading all of them to reduce the load. -->
<link rel="stylesheet" href="${request.contextPath}/static/adminlte/dist/css/skins/_all-skins.min.css">
<!-- HTML5 Shim and Respond.js IE8 support of HTML5 elements and media queries -->
<!-- WARNING: Respond.js doesn't work if you view the page via file:// -->
<!--[if lt IE 9]>
<script src="https://oss.maxcdn.com/html5shiv/3.7.3/html5shiv.min.js"></script>
<script src="https://oss.maxcdn.com/respond/1.4.2/respond.min.js"></script>
<![endif]-->
<!-- pace -->
<link rel="stylesheet" href="${request.contextPath}/static/plugins/pace/themes/pace-theme-flash.css">
<#-- i18n -->
<#global I18n = I18nUtil.getMultString()?eval />
</#macro>
<#macro commonScript>
<!-- jQuery 2.1.4 -->
<script src="${request.contextPath}/static/adminlte/plugins/jQuery/jquery-2.2.3.min.js"></script>
<!-- Bootstrap 3.3.5 -->
<script src="${request.contextPath}/static/adminlte/bootstrap/js/bootstrap.min.js"></script>
<!-- FastClick -->
<script src="${request.contextPath}/static/adminlte/plugins/fastclick/fastclick.min.js"></script>
<!-- AdminLTE App -->
<script src="${request.contextPath}/static/adminlte/dist/js/app.min.js"></script>
<#-- jquery.slimscroll -->
<script src="${request.contextPath}/static/adminlte/plugins/slimScroll/jquery.slimscroll.min.js"></script>
<!-- pace -->
<script src="${request.contextPath}/static/plugins/pace/pace.min.js"></script>
<#-- jquery cookie -->
<script src="${request.contextPath}/static/plugins/jquery/jquery.cookie.js"></script>
<#-- layer -->
<script src="${request.contextPath}/static/plugins/layer/layer.js"></script>
<#-- common -->
<script src="${request.contextPath}/static/js/common.1.js"></script>
<script>
var base_url = '${request.contextPath}';
var I18n = ${I18nUtil.getMultString()};
</script>
</#macro>
<#macro commonHeader>
<header class="main-header">
<a href="${request.contextPath}/" class="logo">
<span class="logo-mini"><b>XXL</b></span>
<span class="logo-lg"><b>${I18n.admin_name}</b></span>
</a>
<nav class="navbar navbar-static-top" role="navigation">
<a href="#" class="sidebar-toggle" data-toggle="offcanvas" role="button"><span class="sr-only">切换导航</span></a>
<div class="navbar-custom-menu">
<ul class="nav navbar-nav">
<li class="dropdown user user-menu">
<a href=";" id="logoutBtn" class="dropdown-toggle" data-toggle="dropdown" aria-expanded="false">
<span class="hidden-xs">${I18n.logout_btn}</span>
</a>
</li>
</ul>
</div>
</nav>
</header>
</#macro>
<#macro commonLeft pageName >
<!-- Left side column. contains the logo and sidebar -->
<aside class="main-sidebar">
<!-- sidebar: style can be found in sidebar.less -->
<section class="sidebar">
<!-- sidebar menu: : style can be found in sidebar.less -->
<ul class="sidebar-menu">
<li class="header">${I18n.system_nav}</li>
<li class="nav-click <#if pageName == "index">active</#if>" ><a href="${request.contextPath}/"><i class="fa fa-circle-o text-aqua"></i><span>${I18n.job_dashboard_name}</span></a></li>
<li class="nav-click <#if pageName == "jobinfo">active</#if>" ><a href="${request.contextPath}/jobinfo"><i class="fa fa-circle-o text-yellow"></i><span>${I18n.jobinfo_name}</span></a></li>
<li class="nav-click <#if pageName == "joblog">active</#if>" ><a href="${request.contextPath}/joblog"><i class="fa fa-circle-o text-green"></i><span>${I18n.joblog_name}</span></a></li>
<li class="nav-click <#if pageName == "jobgroup">active</#if>" ><a href="${request.contextPath}/jobgroup"><i class="fa fa-circle-o text-red"></i><span>${I18n.jobgroup_name}</span></a></li>
<li class="nav-click <#if pageName == "help">active</#if>" ><a href="${request.contextPath}/help"><i class="fa fa-circle-o text-gray"></i><span>${I18n.job_help}</span></a></li>
</ul>
</section>
<!-- /.sidebar -->
</aside>
</#macro>
<#macro commonControl >
<!-- Control Sidebar -->
<aside class="control-sidebar control-sidebar-dark">
<!-- Create the tabs -->
<ul class="nav nav-tabs nav-justified control-sidebar-tabs">
<li class="active"><a href="#control-sidebar-home-tab" data-toggle="tab"><i class="fa fa-home"></i></a></li>
<li><a href="#control-sidebar-settings-tab" data-toggle="tab"><i class="fa fa-gears"></i></a></li>
</ul>
<!-- Tab panes -->
<div class="tab-content">
<!-- Home tab content -->
<div class="tab-pane active" id="control-sidebar-home-tab">
<h3 class="control-sidebar-heading">近期活动</h3>
<ul class="control-sidebar-menu">
<li>
<a href="javascript::;">
<i class="menu-icon fa fa-birthday-cake bg-red"></i>
<div class="menu-info">
<h4 class="control-sidebar-subheading">张三今天过生日</h4>
<p>2015-09-10</p>
</div>
</a>
</li>
<li>
<a href="javascript::;">
<i class="menu-icon fa fa-user bg-yellow"></i>
<div class="menu-info">
<h4 class="control-sidebar-subheading">Frodo 更新了资料</h4>
<p>更新手机号码 +1(800)555-1234</p>
</div>
</a>
</li>
<li>
<a href="javascript::;">
<i class="menu-icon fa fa-envelope-o bg-light-blue"></i>
<div class="menu-info">
<h4 class="control-sidebar-subheading">Nora 加入邮件列表</h4>
<p>nora@example.com</p>
</div>
</a>
</li>
<li>
<a href="javascript::;">
<i class="menu-icon fa fa-file-code-o bg-green"></i>
<div class="menu-info">
<h4 class="control-sidebar-subheading">001号定时作业调度</h4>
<p>5秒前执行</p>
</div>
</a>
</li>
</ul>
<!-- /.control-sidebar-menu -->
</div>
<!-- /.tab-pane -->
<!-- Settings tab content -->
<div class="tab-pane" id="control-sidebar-settings-tab">
<form method="post">
<h3 class="control-sidebar-heading">个人设置</h3>
<div class="form-group">
<label class="control-sidebar-subheading"> 左侧菜单自适应
<input type="checkbox" class="pull-right" checked>
</label>
<p>左侧菜单栏样式自适应</p>
</div>
<!-- /.form-group -->
</form>
</div>
<!-- /.tab-pane -->
</div>
</aside>
<!-- /.control-sidebar -->
<!-- Add the sidebar's background. This div must be placed immediately after the control sidebar -->
<div class="control-sidebar-bg"></div>
</#macro>
<#macro commonFooter >
<footer class="main-footer">
Powered by <b>XXL-JOB</b> ${I18n.admin_version}
<div class="pull-right hidden-xs">
<strong>Copyright &copy; 2015-${.now?string('yyyy')} &nbsp;
<a href="http://www.xuxueli.com/" target="_blank" >xuxueli</a>
&nbsp;
<a href="https://github.com/xuxueli/xxl-job" target="_blank" >github</a>
</strong><!-- All rights reserved. -->
</div>
</footer>
<#macro commonStyle>
<#-- favicon -->
<link rel="icon" href="${request.contextPath}/static/favicon.ico" />
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<!-- Tell the browser to be responsive to screen width -->
<meta content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no" name="viewport">
<!-- Bootstrap 3.3.5 -->
<link rel="stylesheet" href="${request.contextPath}/static/adminlte/bootstrap/css/bootstrap.min.css">
<!-- Font Awesome -->
<!-- <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.5.0/css/font-awesome.min.css"> -->
<link rel="stylesheet" href="${request.contextPath}/static/plugins/font-awesome-4.5.0/css/font-awesome.min.css">
<!-- Ionicons -->
<!-- <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/ionicons/2.0.1/css/ionicons.min.css"> -->
<link rel="stylesheet" href="${request.contextPath}/static/plugins/ionicons-2.0.1/css/ionicons.min.css">
<!-- Theme style -->
<link rel="stylesheet" href="${request.contextPath}/static/adminlte/dist/css/AdminLTE-local.min.css">
<!-- AdminLTE Skins. Choose a skin from the css/skins folder instead of downloading all of them to reduce the load. -->
<link rel="stylesheet" href="${request.contextPath}/static/adminlte/dist/css/skins/_all-skins.min.css">
<!-- HTML5 Shim and Respond.js IE8 support of HTML5 elements and media queries -->
<!-- WARNING: Respond.js doesn't work if you view the page via file:// -->
<!--[if lt IE 9]>
<script src="https://oss.maxcdn.com/html5shiv/3.7.3/html5shiv.min.js"></script>
<script src="https://oss.maxcdn.com/respond/1.4.2/respond.min.js"></script>
<![endif]-->
<!-- pace -->
<link rel="stylesheet" href="${request.contextPath}/static/plugins/pace/themes/pace-theme-flash.css">
<#-- i18n -->
<#global I18n = I18nUtil.getMultString()?eval />
</#macro>
<#macro commonScript>
<!-- jQuery 2.1.4 -->
<script src="${request.contextPath}/static/adminlte/plugins/jQuery/jquery-2.2.3.min.js"></script>
<!-- Bootstrap 3.3.5 -->
<script src="${request.contextPath}/static/adminlte/bootstrap/js/bootstrap.min.js"></script>
<!-- FastClick -->
<script src="${request.contextPath}/static/adminlte/plugins/fastclick/fastclick.min.js"></script>
<!-- AdminLTE App -->
<script src="${request.contextPath}/static/adminlte/dist/js/app.min.js"></script>
<#-- jquery.slimscroll -->
<script src="${request.contextPath}/static/adminlte/plugins/slimScroll/jquery.slimscroll.min.js"></script>
<!-- pace -->
<script src="${request.contextPath}/static/plugins/pace/pace.min.js"></script>
<#-- jquery cookie -->
<script src="${request.contextPath}/static/plugins/jquery/jquery.cookie.js"></script>
<#-- layer -->
<script src="${request.contextPath}/static/plugins/layer/layer.js"></script>
<#-- common -->
<script src="${request.contextPath}/static/js/common.1.js"></script>
<script>
var base_url = '${request.contextPath}';
var I18n = ${I18nUtil.getMultString()};
</script>
</#macro>
<#macro commonHeader>
<header class="main-header">
<a href="${request.contextPath}/" class="logo">
<span class="logo-mini"><b>XXL</b></span>
<span class="logo-lg"><b>${I18n.admin_name}</b></span>
</a>
<nav class="navbar navbar-static-top" role="navigation">
<a href="#" class="sidebar-toggle" data-toggle="offcanvas" role="button"><span class="sr-only">切换导航</span></a>
<div class="navbar-custom-menu">
<ul class="nav navbar-nav">
<li class="dropdown user user-menu">
<a href=";" id="logoutBtn" class="dropdown-toggle" data-toggle="dropdown" aria-expanded="false">
<span class="hidden-xs">${I18n.logout_btn}</span>
</a>
</li>
</ul>
</div>
</nav>
</header>
</#macro>
<#macro commonLeft pageName >
<!-- Left side column. contains the logo and sidebar -->
<aside class="main-sidebar">
<!-- sidebar: style can be found in sidebar.less -->
<section class="sidebar">
<!-- sidebar menu: : style can be found in sidebar.less -->
<ul class="sidebar-menu">
<li class="header">${I18n.system_nav}</li>
<li class="nav-click <#if pageName == "index">active</#if>" ><a href="${request.contextPath}/"><i class="fa fa-circle-o text-aqua"></i><span>${I18n.job_dashboard_name}</span></a></li>
<li class="nav-click <#if pageName == "jobinfo">active</#if>" ><a href="${request.contextPath}/jobinfo"><i class="fa fa-circle-o text-yellow"></i><span>${I18n.jobinfo_name}</span></a></li>
<li class="nav-click <#if pageName == "joblog">active</#if>" ><a href="${request.contextPath}/joblog"><i class="fa fa-circle-o text-green"></i><span>${I18n.joblog_name}</span></a></li>
<li class="nav-click <#if pageName == "jobgroup">active</#if>" ><a href="${request.contextPath}/jobgroup"><i class="fa fa-circle-o text-red"></i><span>${I18n.jobgroup_name}</span></a></li>
<li class="nav-click <#if pageName == "help">active</#if>" ><a href="${request.contextPath}/help"><i class="fa fa-circle-o text-gray"></i><span>${I18n.job_help}</span></a></li>
</ul>
</section>
<!-- /.sidebar -->
</aside>
</#macro>
<#macro commonControl >
<!-- Control Sidebar -->
<aside class="control-sidebar control-sidebar-dark">
<!-- Create the tabs -->
<ul class="nav nav-tabs nav-justified control-sidebar-tabs">
<li class="active"><a href="#control-sidebar-home-tab" data-toggle="tab"><i class="fa fa-home"></i></a></li>
<li><a href="#control-sidebar-settings-tab" data-toggle="tab"><i class="fa fa-gears"></i></a></li>
</ul>
<!-- Tab panes -->
<div class="tab-content">
<!-- Home tab content -->
<div class="tab-pane active" id="control-sidebar-home-tab">
<h3 class="control-sidebar-heading">近期活动</h3>
<ul class="control-sidebar-menu">
<li>
<a href="javascript::;">
<i class="menu-icon fa fa-birthday-cake bg-red"></i>
<div class="menu-info">
<h4 class="control-sidebar-subheading">张三今天过生日</h4>
<p>2015-09-10</p>
</div>
</a>
</li>
<li>
<a href="javascript::;">
<i class="menu-icon fa fa-user bg-yellow"></i>
<div class="menu-info">
<h4 class="control-sidebar-subheading">Frodo 更新了资料</h4>
<p>更新手机号码 +1(800)555-1234</p>
</div>
</a>
</li>
<li>
<a href="javascript::;">
<i class="menu-icon fa fa-envelope-o bg-light-blue"></i>
<div class="menu-info">
<h4 class="control-sidebar-subheading">Nora 加入邮件列表</h4>
<p>nora@example.com</p>
</div>
</a>
</li>
<li>
<a href="javascript::;">
<i class="menu-icon fa fa-file-code-o bg-green"></i>
<div class="menu-info">
<h4 class="control-sidebar-subheading">001号定时作业调度</h4>
<p>5秒前执行</p>
</div>
</a>
</li>
</ul>
<!-- /.control-sidebar-menu -->
</div>
<!-- /.tab-pane -->
<!-- Settings tab content -->
<div class="tab-pane" id="control-sidebar-settings-tab">
<form method="post">
<h3 class="control-sidebar-heading">个人设置</h3>
<div class="form-group">
<label class="control-sidebar-subheading"> 左侧菜单自适应
<input type="checkbox" class="pull-right" checked>
</label>
<p>左侧菜单栏样式自适应</p>
</div>
<!-- /.form-group -->
</form>
</div>
<!-- /.tab-pane -->
</div>
</aside>
<!-- /.control-sidebar -->
<!-- Add the sidebar's background. This div must be placed immediately after the control sidebar -->
<div class="control-sidebar-bg"></div>
</#macro>
<#macro commonFooter >
<footer class="main-footer">
Powered by <b>XXL-JOB</b> ${I18n.admin_version}
<div class="pull-right hidden-xs">
<strong>Copyright &copy; 2015-${.now?string('yyyy')} &nbsp;
<a href="http://www.xuxueli.com/" target="_blank" >xuxueli</a>
&nbsp;
<a href="https://github.com/xuxueli/xxl-job" target="_blank" >github</a>
</strong><!-- All rights reserved. -->
</div>
</footer>
</#macro>
\ No newline at end of file
<!DOCTYPE html>
<html>
<head>
<#import "/common/common.macro.ftl" as netCommon>
<@netCommon.commonStyle />
<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 "help" />
<!-- Content Wrapper. Contains page content -->
<div class="content-wrapper">
<!-- Content Header (Page header) -->
<section class="content-header">
<h1>${I18n.job_help}</h1>
</section>
<!-- Main content -->
<section class="content">
<div class="callout callout-info">
<h4>${I18n.admin_name_full}</h4>
<br>
<p>
<a target="_blank" href="https://github.com/xuxueli/xxl-job">Github</a>&nbsp;&nbsp;&nbsp;&nbsp;
<iframe src="https://ghbtns.com/github-btn.html?user=xuxueli&repo=xxl-job&type=star&count=true" frameborder="0" scrolling="0" width="170px" height="20px" style="margin-bottom:-5px;"></iframe>
<br><br>
<a target="_blank" href="http://www.xuxueli.com/xxl-job/">${I18n.job_help_document}</a>
<br><br>
</p>
<p></p>
</div>
</section>
<!-- /.content -->
</div>
<!-- /.content-wrapper -->
<!-- footer -->
<@netCommon.commonFooter />
</div>
<@netCommon.commonScript />
</body>
</html>
<!DOCTYPE html>
<html>
<head>
<#import "./common/common.macro.ftl" as netCommon>
<@netCommon.commonStyle />
<title>${I18n.admin_name}</title>
</head>
<body class="hold-transition skin-blue sidebar-mini <#if cookieMap?exists && cookieMap["xxljob_adminlte_settings"]?exists && "off" == cookieMap["xxljob_adminlte_settings"].value >sidebar-collapse</#if> ">
<div class="wrapper">
<!-- header -->
<@netCommon.commonHeader />
<!-- left -->
<@netCommon.commonLeft "help" />
<!-- Content Wrapper. Contains page content -->
<div class="content-wrapper">
<!-- Content Header (Page header) -->
<section class="content-header">
<h1>${I18n.job_help}</h1>
</section>
<!-- Main content -->
<section class="content">
<div class="callout callout-info">
<h4>${I18n.admin_name_full}</h4>
<br>
<p>
<a target="_blank" href="https://github.com/xuxueli/xxl-job">Github</a>&nbsp;&nbsp;&nbsp;&nbsp;
<iframe src="https://ghbtns.com/github-btn.html?user=xuxueli&repo=xxl-job&type=star&count=true" frameborder="0" scrolling="0" width="170px" height="20px" style="margin-bottom:-5px;"></iframe>
<br><br>
<a target="_blank" href="http://www.xuxueli.com/xxl-job/">${I18n.job_help_document}</a>
<br><br>
</p>
<p></p>
</div>
</section>
<!-- /.content -->
</div>
<!-- /.content-wrapper -->
<!-- footer -->
<@netCommon.commonFooter />
</div>
<@netCommon.commonScript />
</body>
</html>
<!DOCTYPE html>
<html>
<head>
<#import "/common/common.macro.ftl" as netCommon>
<#import "./common/common.macro.ftl" as netCommon>
<@netCommon.commonStyle />
<!-- daterangepicker -->
<link rel="stylesheet" href="${request.contextPath}/static/adminlte/plugins/daterangepicker/daterangepicker.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> ">
<body class="hold-transition skin-blue sidebar-mini <#if cookieMap?exists && cookieMap["xxljob_adminlte_settings"]?exists && "off" == cookieMap["xxljob_adminlte_settings"].value >sidebar-collapse</#if> ">
<div class="wrapper">
<!-- header -->
<@netCommon.commonHeader />
......
<!DOCTYPE html>
<html>
<head>
<#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">
<title>${I18n.admin_name}</title>
<style type="text/css">
.CodeMirror {
font-size:16px;
width: 100%;
height: 100%;
/*bottom: 0;
top: 0px;*/
position: absolute;
}
</style>
</head>
<body class="skin-blue fixed layout-top-nav">
<div class="wrapper">
<header class="main-header">
<nav class="navbar navbar-static-top">
<div class="container">
<#-- icon -->
<div class="navbar-header">
<a class="navbar-brand"><b>Web</b>IDE</a>
<button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target="#navbar-collapse">
<i class="fa fa-bars"></i>
</button>
</div>
<#-- left nav -->
<div class="collapse navbar-collapse pull-left" id="navbar-collapse">
<ul class="nav navbar-nav">
<li class="active" ><a href="javascript:;">
<span class="sr-only">(current)</span>
<#list GlueTypeEnum as item><#if item == jobInfo.glueType>${item.desc}</#if></#list>
${jobInfo.jobDesc}
</a></li>
</ul>
</div>
<#-- right nav -->
<div class="navbar-custom-menu">
<ul class="nav navbar-nav">
<li class="dropdown">
<a href="#" class="dropdown-toggle" data-toggle="dropdown" aria-expanded="false">${I18n.jobinfo_glue_rollback} <span class="caret"></span></a>
<ul class="dropdown-menu" role="menu">
<li <#if jobLogGlues?exists && jobLogGlues?size gt 0 >style="display: none;"</#if> >
<a href="javascript:;" class="source_version" version="version_now" glueType="${jobInfo.glueType}" >
<#list GlueTypeEnum as item><#if item == jobInfo.glueType>${item.desc}</#if></#list>: ${jobInfo.glueRemark}
</a>
</li>
<textarea id="version_now" style="display:none;" >${jobInfo.glueSource}</textarea>
<#if jobLogGlues?exists && jobLogGlues?size gt 0 >
<#list jobLogGlues as glue>
<li>
<a href="javascript:;" class="source_version" version="version_${glue.id}" glueType="${glue.glueType}" >
<#list GlueTypeEnum as item><#if item == glue.glueType>${item.desc}</#if></#list>: ${glue.glueRemark}
</a>
</li>
<textarea id="version_${glue.id}" style="display:none;" >${glue.glueSource}</textarea>
</#list>
</#if>
</ul>
</li>
<li id="save" >
<a href="javascript:;" >
<i class="fa fa-fw fa-save" ></i>
${I18n.system_save}
</a>
</li>
</ul>
</div>
</div>
</nav>
</header>
<div class="content-wrapper" id="ideWindow" ></div>
<!-- footer -->
<#--<@netCommon.commonFooter />-->
</div>
<!-- 保存.模态框 -->
<div class="modal fade" id="saveModal" tabindex="-1" role="dialog" aria-hidden="true">
<div class="modal-dialog ">
<div class="modal-content">
<div class="modal-header">
<h4 class="modal-title" ><i class="fa fa-fw fa-save"></i>${I18n.system_save}</h4>
</div>
<div class="modal-body">
<form class="form-horizontal form" role="form" >
<div class="form-group">
<label for="lastname" class="col-sm-2 control-label">${I18n.jobinfo_glue_remark}<font color="red">*</font></label>
<div class="col-sm-10"><input type="text" class="form-control" id="glueRemark" placeholder="${I18n.system_please_input}${I18n.jobinfo_glue_remark}" maxlength="64" ></div>
</div>
<hr>
<div class="form-group">
<div class="col-sm-offset-3 col-sm-6">
<button type="button" class="btn btn-primary ok" >${I18n.system_save}</button>
<button type="button" class="btn btn-default" data-dismiss="modal">${I18n.system_cancel}</button>
</div>
</div>
</form>
</div>
</div>
</div>
</div>
<@netCommon.commonScript />
<#assign glueTypeModeSrc = "${request.contextPath}/static/plugins/codemirror/mode/clike/clike.js" />
<#assign glueTypeIdeMode = "text/x-java" />
<#if jobInfo.glueType == "GLUE_GROOVY" >
<#assign glueTypeModeSrc = "${request.contextPath}/static/plugins/codemirror/mode/clike/clike.js" />
<#assign glueTypeIdeMode = "text/x-java" />
<#elseif jobInfo.glueType == "GLUE_SHELL" >
<#assign glueTypeModeSrc = "${request.contextPath}/static/plugins/codemirror/mode/shell/shell.js" />
<#assign glueTypeIdeMode = "text/x-sh" />
<#elseif jobInfo.glueType == "GLUE_PYTHON" >
<#assign glueTypeModeSrc = "${request.contextPath}/static/plugins/codemirror/mode/python/python.js" />
<#assign glueTypeIdeMode = "text/x-python" />
<#elseif jobInfo.glueType == "GLUE_PHP" >
<#assign glueTypeModeSrc = "${request.contextPath}/static/plugins/codemirror/mode/php/php.js" />
<#assign glueTypeIdeMode = "text/x-php" />
<#assign glueTypeModeSrc02 = "${request.contextPath}/static/plugins/codemirror/mode/clike/clike.js" />
<#elseif jobInfo.glueType == "GLUE_NODEJS" >
<#assign glueTypeModeSrc = "${request.contextPath}/static/plugins/codemirror/mode/javascript/javascript.js" />
<#assign glueTypeIdeMode = "text/javascript" />
<#elseif jobInfo.glueType == "GLUE_POWERSHELL" >
<#assign glueTypeModeSrc = "${request.contextPath}/static/plugins/codemirror/mode/powershell/powershell.js" />
<#assign glueTypeIdeMode = "powershell" />
</#if>
<script src="${request.contextPath}/static/plugins/codemirror/lib/codemirror.js"></script>
<script src="${glueTypeModeSrc}"></script>
<#if glueTypeModeSrc02?exists>
<script src="${glueTypeModeSrc02}"></script>
</#if>
<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>
var id = '${jobInfo.id}';
var ideMode = '${glueTypeIdeMode}';
</script>
<script src="${request.contextPath}/static/js/jobcode.index.1.js"></script>
</body>
</html>
<!DOCTYPE html>
<html>
<head>
<#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">
<title>${I18n.admin_name}</title>
<style type="text/css">
.CodeMirror {
font-size:16px;
width: 100%;
height: 100%;
/*bottom: 0;
top: 0px;*/
position: absolute;
}
</style>
</head>
<body class="skin-blue fixed layout-top-nav">
<div class="wrapper">
<header class="main-header">
<nav class="navbar navbar-static-top">
<div class="container">
<#-- icon -->
<div class="navbar-header">
<a class="navbar-brand"><b>Web</b>IDE</a>
<button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target="#navbar-collapse">
<i class="fa fa-bars"></i>
</button>
</div>
<#-- left nav -->
<div class="collapse navbar-collapse pull-left" id="navbar-collapse">
<ul class="nav navbar-nav">
<li class="active" ><a href="javascript:;">
<span class="sr-only">(current)</span>
<#list GlueTypeEnum as item><#if item == jobInfo.glueType>${item.desc}</#if></#list>
${jobInfo.jobDesc}
</a></li>
</ul>
</div>
<#-- right nav -->
<div class="navbar-custom-menu">
<ul class="nav navbar-nav">
<li class="dropdown">
<a href="#" class="dropdown-toggle" data-toggle="dropdown" aria-expanded="false">${I18n.jobinfo_glue_rollback} <span class="caret"></span></a>
<ul class="dropdown-menu" role="menu">
<li <#if jobLogGlues?exists && jobLogGlues?size gt 0 >style="display: none;"</#if> >
<a href="javascript:;" class="source_version" version="version_now" glueType="${jobInfo.glueType}" >
<#list GlueTypeEnum as item><#if item == jobInfo.glueType>${item.desc}</#if></#list>: ${jobInfo.glueRemark}
</a>
</li>
<textarea id="version_now" style="display:none;" >${jobInfo.glueSource}</textarea>
<#if jobLogGlues?exists && jobLogGlues?size gt 0 >
<#list jobLogGlues as glue>
<li>
<a href="javascript:;" class="source_version" version="version_${glue.id}" glueType="${glue.glueType}" >
<#list GlueTypeEnum as item><#if item == glue.glueType>${item.desc}</#if></#list>: ${glue.glueRemark}
</a>
</li>
<textarea id="version_${glue.id}" style="display:none;" >${glue.glueSource}</textarea>
</#list>
</#if>
</ul>
</li>
<li id="save" >
<a href="javascript:;" >
<i class="fa fa-fw fa-save" ></i>
${I18n.system_save}
</a>
</li>
</ul>
</div>
</div>
</nav>
</header>
<div class="content-wrapper" id="ideWindow" ></div>
<!-- footer -->
<#--<@netCommon.commonFooter />-->
</div>
<!-- 保存.模态框 -->
<div class="modal fade" id="saveModal" tabindex="-1" role="dialog" aria-hidden="true">
<div class="modal-dialog ">
<div class="modal-content">
<div class="modal-header">
<h4 class="modal-title" ><i class="fa fa-fw fa-save"></i>${I18n.system_save}</h4>
</div>
<div class="modal-body">
<form class="form-horizontal form" role="form" >
<div class="form-group">
<label for="lastname" class="col-sm-2 control-label">${I18n.jobinfo_glue_remark}<font color="red">*</font></label>
<div class="col-sm-10"><input type="text" class="form-control" id="glueRemark" placeholder="${I18n.system_please_input}${I18n.jobinfo_glue_remark}" maxlength="64" ></div>
</div>
<hr>
<div class="form-group">
<div class="col-sm-offset-3 col-sm-6">
<button type="button" class="btn btn-primary ok" >${I18n.system_save}</button>
<button type="button" class="btn btn-default" data-dismiss="modal">${I18n.system_cancel}</button>
</div>
</div>
</form>
</div>
</div>
</div>
</div>
<@netCommon.commonScript />
<#assign glueTypeModeSrc = "${request.contextPath}/static/plugins/codemirror/mode/clike/clike.js" />
<#assign glueTypeIdeMode = "text/x-java" />
<#if jobInfo.glueType == "GLUE_GROOVY" >
<#assign glueTypeModeSrc = "${request.contextPath}/static/plugins/codemirror/mode/clike/clike.js" />
<#assign glueTypeIdeMode = "text/x-java" />
<#elseif jobInfo.glueType == "GLUE_SHELL" >
<#assign glueTypeModeSrc = "${request.contextPath}/static/plugins/codemirror/mode/shell/shell.js" />
<#assign glueTypeIdeMode = "text/x-sh" />
<#elseif jobInfo.glueType == "GLUE_PYTHON" >
<#assign glueTypeModeSrc = "${request.contextPath}/static/plugins/codemirror/mode/python/python.js" />
<#assign glueTypeIdeMode = "text/x-python" />
<#elseif jobInfo.glueType == "GLUE_PHP" >
<#assign glueTypeModeSrc = "${request.contextPath}/static/plugins/codemirror/mode/php/php.js" />
<#assign glueTypeIdeMode = "text/x-php" />
<#assign glueTypeModeSrc02 = "${request.contextPath}/static/plugins/codemirror/mode/clike/clike.js" />
<#elseif jobInfo.glueType == "GLUE_NODEJS" >
<#assign glueTypeModeSrc = "${request.contextPath}/static/plugins/codemirror/mode/javascript/javascript.js" />
<#assign glueTypeIdeMode = "text/javascript" />
<#elseif jobInfo.glueType == "GLUE_POWERSHELL" >
<#assign glueTypeModeSrc = "${request.contextPath}/static/plugins/codemirror/mode/powershell/powershell.js" />
<#assign glueTypeIdeMode = "powershell" />
</#if>
<script src="${request.contextPath}/static/plugins/codemirror/lib/codemirror.js"></script>
<script src="${glueTypeModeSrc}"></script>
<#if glueTypeModeSrc02?exists>
<script src="${glueTypeModeSrc02}"></script>
</#if>
<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>
var id = '${jobInfo.id}';
var ideMode = '${glueTypeIdeMode}';
</script>
<script src="${request.contextPath}/static/js/jobcode.index.1.js"></script>
</body>
</html>
<!DOCTYPE html>
<html>
<head>
<#import "/common/common.macro.ftl" as netCommon>
<#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> ">
<body class="hold-transition skin-blue sidebar-mini <#if cookieMap?exists && cookieMap["xxljob_adminlte_settings"]?exists && "off" == cookieMap["xxljob_adminlte_settings"].value >sidebar-collapse</#if> ">
<div class="wrapper">
<!-- header -->
<@netCommon.commonHeader />
......@@ -74,7 +74,7 @@
title="${group.title}"
order="${group.order}"
addressType="${group.addressType}"
addressList="${group.addressList}" >${I18n.system_opt_edit}</button>
addressList="${group.addressList!}" >${I18n.system_opt_edit}</button>
<button class="btn btn-danger btn-xs remove" id="${group.id}" >${I18n.system_opt_del}</button>
</td>
</tr>
......
<!DOCTYPE html>
<html>
<head>
<#import "/common/common.macro.ftl" as netCommon>
<#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>">
<body class="hold-transition skin-blue sidebar-mini <#if cookieMap?exists && cookieMap["xxljob_adminlte_settings"]?exists && "off" == cookieMap["xxljob_adminlte_settings"].value >sidebar-collapse</#if>">
<div class="wrapper">
<!-- header -->
<@netCommon.commonHeader />
......
<!DOCTYPE html>
<html>
<head>
<#import "/common/common.macro.ftl" as netCommon>
<#import "../common/common.macro.ftl" as netCommon>
<@netCommon.commonStyle />
<title>${I18n.admin_name}</title>
</head>
......@@ -64,7 +64,7 @@
var triggerCode = '${triggerCode}';
var handleCode = '${handleCode}';
var executorAddress = '${executorAddress}';
var triggerTime = '${triggerTime}';
var triggerTime = '${triggerTime?c}';
var logId = '${logId}';
</script>
<script src="${request.contextPath}/static/js/joblog.detail.1.js"></script>
......
<!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">
<!-- daterangepicker -->
<link rel="stylesheet" href="${request.contextPath}/static/adminlte/plugins/daterangepicker/daterangepicker.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 "joblog" />
<!-- Content Wrapper. Contains page content -->
<div class="content-wrapper">
<!-- Content Header (Page header) -->
<section class="content-header">
<h1>${I18n.joblog_name}</h1>
</section>
<!-- Main content -->
<section class="content">
<div class="row">
<div class="col-xs-2">
<div class="input-group">
<span class="input-group-addon">${I18n.jobinfo_field_jobgroup}</span>
<select class="form-control" id="jobGroup" paramVal="<#if jobInfo?exists>${jobInfo.jobGroup}</#if>" >
<option value="0" >${I18n.system_all}</option>
<#list JobGroupList as group>
<option value="${group.id}" >${group.title}</option>
</#list>
</select>
</div>
</div>
<div class="col-xs-2">
<div class="input-group">
<span class="input-group-addon">${I18n.jobinfo_job}</span>
<select class="form-control" id="jobId" paramVal="<#if jobInfo?exists>${jobInfo.id}</#if>" >
<option value="0" >${I18n.system_all}</option>
</select>
</div>
</div>
<div class="col-xs-2">
<div class="input-group">
<span class="input-group-addon">${I18n.joblog_status}</span>
<select class="form-control" id="logStatus" >
<option value="-1" >${I18n.joblog_status_all}</option>
<option value="1" >${I18n.joblog_status_suc}</option>
<option value="2" >${I18n.joblog_status_fail}</option>
<option value="3" >${I18n.joblog_status_running}</option>
</select>
</div>
</div>
<div class="col-xs-4">
<div class="input-group">
<span class="input-group-addon">
${I18n.joblog_field_triggerTime}
</span>
<input type="text" class="form-control" id="filterTime" readonly >
</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-1">
<button class="btn btn-block btn-nomal" id="clearLog">${I18n.joblog_clean}</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="joblog_list" class="table table-bordered table-striped display" width="100%" >
<thead>
<tr>
<th name="jobId" >${I18n.jobinfo_field_id}</th>
<th name="jobGroup" >jobGroup</th>
<#--<th name="executorAddress" >执行器地址</th>
<th name="glueType" >运行模式</th>
<th name="executorParam" >任务参数</th>-->
<th name="triggerTime" >${I18n.joblog_field_triggerTime}</th>
<th name="triggerCode" >${I18n.joblog_field_triggerCode}</th>
<th name="triggerMsg" >${I18n.joblog_field_triggerMsg}</th>
<th name="handleTime" >${I18n.joblog_field_handleTime}</th>
<th name="handleCode" >${I18n.joblog_field_handleCode}</th>
<th name="handleMsg" >${I18n.joblog_field_handleMsg}</th>
<th name="handleMsg" >${I18n.system_opt}</th>
</tr>
</thead>
<tbody></tbody>
</table>
</div>
</div>
</div>
</div>
</section>
</div>
<!-- footer -->
<@netCommon.commonFooter />
</div>
<!-- 日志清理.模态框 -->
<div class="modal fade" id="clearLogModal" tabindex="-1" role="dialog" aria-hidden="true">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<h4 class="modal-title" >${I18n.joblog_clean_log}</h4>
</div>
<div class="modal-body">
<form class="form-horizontal form" role="form" >
<div class="form-group">
<label class="col-sm-3 control-label"">${I18n.jobinfo_field_jobgroup}:</label>
<div class="col-sm-9">
<input type="text" class="form-control jobGroupText" readonly >
<input type="hidden" name="jobGroup" >
</div>
</div>
<div class="form-group">
<label class="col-sm-3 control-label"">${I18n.jobinfo_job}:</label>
<div class="col-sm-9">
<input type="text" class="form-control jobIdText" readonly >
<input type="hidden" name="jobId" >
</div>
</div>
<div class="form-group">
<label class="col-sm-3 control-label"">${I18n.joblog_clean_type}:</label>
<div class="col-sm-9">
<select class="form-control" name="type" >
<option value="1" >${I18n.joblog_clean_type_1}</option>
<option value="2" >${I18n.joblog_clean_type_2}</option>
<option value="3" >${I18n.joblog_clean_type_3}</option>
<option value="4" >${I18n.joblog_clean_type_4}</option>
<option value="5" >${I18n.joblog_clean_type_5}</option>
<option value="6" >${I18n.joblog_clean_type_6}</option>
<option value="7" >${I18n.joblog_clean_type_7}</option>
<option value="8" >${I18n.joblog_clean_type_8}</option>
<option value="9" >${I18n.joblog_clean_type_9}</option>
</select>
</div>
</div>
<hr>
<div class="form-group">
<div class="col-sm-offset-3 col-sm-6">
<button type="button" class="btn btn-primary ok" >${I18n.system_ok}</button>
<button type="button" class="btn btn-default" data-dismiss="modal">${I18n.system_cancel}</button>
</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>
<!-- daterangepicker -->
<script src="${request.contextPath}/static/adminlte/plugins/daterangepicker/moment.min.js"></script>
<script src="${request.contextPath}/static/adminlte/plugins/daterangepicker/daterangepicker.js"></script>
<script src="${request.contextPath}/static/js/joblog.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">
<!-- daterangepicker -->
<link rel="stylesheet" href="${request.contextPath}/static/adminlte/plugins/daterangepicker/daterangepicker.css">
<title>${I18n.admin_name}</title>
</head>
<body class="hold-transition skin-blue sidebar-mini <#if cookieMap?exists && cookieMap["xxljob_adminlte_settings"]?exists && "off" == cookieMap["xxljob_adminlte_settings"].value >sidebar-collapse</#if> ">
<div class="wrapper">
<!-- header -->
<@netCommon.commonHeader />
<!-- left -->
<@netCommon.commonLeft "joblog" />
<!-- Content Wrapper. Contains page content -->
<div class="content-wrapper">
<!-- Content Header (Page header) -->
<section class="content-header">
<h1>${I18n.joblog_name}</h1>
</section>
<!-- Main content -->
<section class="content">
<div class="row">
<div class="col-xs-2">
<div class="input-group">
<span class="input-group-addon">${I18n.jobinfo_field_jobgroup}</span>
<select class="form-control" id="jobGroup" paramVal="<#if jobInfo?exists>${jobInfo.jobGroup}</#if>" >
<option value="0" >${I18n.system_all}</option>
<#list JobGroupList as group>
<option value="${group.id}" >${group.title}</option>
</#list>
</select>
</div>
</div>
<div class="col-xs-2">
<div class="input-group">
<span class="input-group-addon">${I18n.jobinfo_job}</span>
<select class="form-control" id="jobId" paramVal="<#if jobInfo?exists>${jobInfo.id}</#if>" >
<option value="0" >${I18n.system_all}</option>
</select>
</div>
</div>
<div class="col-xs-2">
<div class="input-group">
<span class="input-group-addon">${I18n.joblog_status}</span>
<select class="form-control" id="logStatus" >
<option value="-1" >${I18n.joblog_status_all}</option>
<option value="1" >${I18n.joblog_status_suc}</option>
<option value="2" >${I18n.joblog_status_fail}</option>
<option value="3" >${I18n.joblog_status_running}</option>
</select>
</div>
</div>
<div class="col-xs-4">
<div class="input-group">
<span class="input-group-addon">
${I18n.joblog_field_triggerTime}
</span>
<input type="text" class="form-control" id="filterTime" readonly >
</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-1">
<button class="btn btn-block btn-nomal" id="clearLog">${I18n.joblog_clean}</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="joblog_list" class="table table-bordered table-striped display" width="100%" >
<thead>
<tr>
<th name="jobId" >${I18n.jobinfo_field_id}</th>
<th name="jobGroup" >jobGroup</th>
<#--<th name="executorAddress" >执行器地址</th>
<th name="glueType" >运行模式</th>
<th name="executorParam" >任务参数</th>-->
<th name="triggerTime" >${I18n.joblog_field_triggerTime}</th>
<th name="triggerCode" >${I18n.joblog_field_triggerCode}</th>
<th name="triggerMsg" >${I18n.joblog_field_triggerMsg}</th>
<th name="handleTime" >${I18n.joblog_field_handleTime}</th>
<th name="handleCode" >${I18n.joblog_field_handleCode}</th>
<th name="handleMsg" >${I18n.joblog_field_handleMsg}</th>
<th name="handleMsg" >${I18n.system_opt}</th>
</tr>
</thead>
<tbody></tbody>
</table>
</div>
</div>
</div>
</div>
</section>
</div>
<!-- footer -->
<@netCommon.commonFooter />
</div>
<!-- 日志清理.模态框 -->
<div class="modal fade" id="clearLogModal" tabindex="-1" role="dialog" aria-hidden="true">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<h4 class="modal-title" >${I18n.joblog_clean_log}</h4>
</div>
<div class="modal-body">
<form class="form-horizontal form" role="form" >
<div class="form-group">
<label class="col-sm-3 control-label"">${I18n.jobinfo_field_jobgroup}:</label>
<div class="col-sm-9">
<input type="text" class="form-control jobGroupText" readonly >
<input type="hidden" name="jobGroup" >
</div>
</div>
<div class="form-group">
<label class="col-sm-3 control-label"">${I18n.jobinfo_job}:</label>
<div class="col-sm-9">
<input type="text" class="form-control jobIdText" readonly >
<input type="hidden" name="jobId" >
</div>
</div>
<div class="form-group">
<label class="col-sm-3 control-label"">${I18n.joblog_clean_type}:</label>
<div class="col-sm-9">
<select class="form-control" name="type" >
<option value="1" >${I18n.joblog_clean_type_1}</option>
<option value="2" >${I18n.joblog_clean_type_2}</option>
<option value="3" >${I18n.joblog_clean_type_3}</option>
<option value="4" >${I18n.joblog_clean_type_4}</option>
<option value="5" >${I18n.joblog_clean_type_5}</option>
<option value="6" >${I18n.joblog_clean_type_6}</option>
<option value="7" >${I18n.joblog_clean_type_7}</option>
<option value="8" >${I18n.joblog_clean_type_8}</option>
<option value="9" >${I18n.joblog_clean_type_9}</option>
</select>
</div>
</div>
<hr>
<div class="form-group">
<div class="col-sm-offset-3 col-sm-6">
<button type="button" class="btn btn-primary ok" >${I18n.system_ok}</button>
<button type="button" class="btn btn-default" data-dismiss="modal">${I18n.system_cancel}</button>
</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>
<!-- daterangepicker -->
<script src="${request.contextPath}/static/adminlte/plugins/daterangepicker/moment.min.js"></script>
<script src="${request.contextPath}/static/adminlte/plugins/daterangepicker/daterangepicker.js"></script>
<script src="${request.contextPath}/static/js/joblog.index.1.js"></script>
</body>
</html>
<!DOCTYPE html>
<html>
<head>
<#import "/common/common.macro.ftl" as netCommon>
<#import "./common/common.macro.ftl" as netCommon>
<@netCommon.commonStyle />
<link rel="stylesheet" href="${request.contextPath}/static/adminlte/plugins/iCheck/square/blue.css">
<title>${I18n.admin_name}</title>
......
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Error</title>
<style type="text/css">
body { background-color: #fff; color: #666; text-align: center; font-family: arial, sans-serif; }
div.dialog {
width: 80%;
padding: 1em 4em;
margin: 4em auto 0 auto;
border: 1px solid #ccc;
border-right-color: #999;
border-bottom-color: #999;
}
h1 { font-size: 100%; color: #f00; line-height: 1.5em; }
</style>
</head>
</head>
<body>
<div class="dialog">
<h1>System Error</h1>
<p>Oops! Page not found.</p>
<a href="javascript:window.location.href='${request.contextPath}/'">Back</a>
</div>
</body>
</html>
\ No newline at end of file
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://java.sun.com/xml/ns/javaee" xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
id="WebApp_ID" version="2.5">
<display-name>xxl-job-admin</display-name>
<context-param>
<param-name>webAppRootKey</param-name>
<param-value>xxl-job-admin</param-value>
</context-param>
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath*:spring/applicationcontext-*.xml</param-value>
</context-param>
<listener>
<listener-class>org.springframework.web.util.Log4jConfigListener</listener-class>
</listener>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<filter>
<filter-name>encodingFilter</filter-name>
<filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
<init-param>
<param-name>encoding</param-name>
<param-value>UTF-8</param-value>
</init-param>
<init-param>
<param-name>forceEncoding</param-name>
<param-value>true</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>encodingFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<servlet>
<servlet-name>springmvc</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath*:spring/springmvc-context.xml</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>springmvc</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
<welcome-file-list>
<welcome-file>index.html</welcome-file>
</welcome-file-list>
<error-page>
<error-code>404</error-code>
<location>/500.html</location>
</error-page>
<error-page>
<error-code>500</error-code>
<location>/500.html</location>
</error-page>
</web-app>
\ No newline at end of file
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论