提交 6a9a84ea 编写于 作者: lakernote's avatar lakernote

(新增)[整体](增加定时任务管理)

上级 9972ba47
......@@ -26,7 +26,7 @@
| **自定义注解+AOP用户行为分析**🐾 | ✅ | [SpringBoot自定义注解+AOP实现用户行为监控](https://blog.csdn.net/abu935009066/article/details/119755927) |
| **基于Freemrker的前后端代码一键生成**🐾 | ✅ | |
| **基于mybatis插件的数据权限控制**🐾 | ❌ | [基于Mybatis-Plus的数据权限实现](https://blog.csdn.net/abu935009066/article/details/115481149) |
| **基于SpringTask定时任务(支持动态CRUD任务)**🐾 | | [基于Spring Task实现动态管理任务](https://blog.csdn.net/abu935009066/article/details/116142630) |
| **基于SpringTask定时任务(支持动态CRUD任务)**🐾 | | [基于Spring Task实现动态管理任务](https://blog.csdn.net/abu935009066/article/details/116142630) |
| **在线WebLog、动态修改日志级别**🐾 | ✅ | [在线WebLog、动态修改日志级别](https://blog.csdn.net/abu935009066/article/details/114121941) |
#### 在线演示
......
package com.laker.admin.framework;
import cn.hutool.core.lang.TypeReference;
import cn.hutool.core.util.ArrayUtil;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.core.ResolvableType;
import org.springframework.stereotype.Component;
import java.lang.reflect.ParameterizedType;
import java.util.Arrays;
import java.util.Map;
@Component
public class SpringUtils implements ApplicationContextAware {
private static ApplicationContext applicationContext;
@Override
public void setApplicationContext(ApplicationContext applicationContext) {
SpringUtils.applicationContext = applicationContext;
}
/**
* 获取applicationContext
*
* @return ApplicationContext
*/
public static ApplicationContext getApplicationContext() {
return applicationContext;
}
//通过name获取 Bean.
/**
* 通过name获取 Bean
*
* @param <T> Bean类型
* @param name Bean名称
* @return Bean
*/
@SuppressWarnings("unchecked")
public static <T> T getBean(String name) {
return (T) applicationContext.getBean(name);
}
/**
* 通过class获取Bean
*
* @param <T> Bean类型
* @param clazz Bean类
* @return Bean对象
*/
public static <T> T getBean(Class<T> clazz) {
return applicationContext.getBean(clazz);
}
/**
* 通过name,以及Clazz返回指定的Bean
*
* @param <T> bean类型
* @param name Bean名称
* @param clazz bean类型
* @return Bean对象
*/
public static <T> T getBean(String name, Class<T> clazz) {
return applicationContext.getBean(name, clazz);
}
/**
* 通过类型参考返回带泛型参数的Bean
*
* @param reference 类型参考,用于持有转换后的泛型类型
* @param <T> Bean类型
* @return 带泛型参数的Bean
* @since 5.4.0
*/
@SuppressWarnings("unchecked")
public static <T> T getBean(TypeReference<T> reference) {
final ParameterizedType parameterizedType = (ParameterizedType) reference.getType();
final Class<T> rawType = (Class<T>) parameterizedType.getRawType();
final Class<?>[] genericTypes = Arrays.stream(parameterizedType.getActualTypeArguments()).map(type -> (Class<?>) type).toArray(Class[]::new);
final String[] beanNames = applicationContext.getBeanNamesForType(ResolvableType.forClassWithGenerics(rawType, genericTypes));
return getBean(beanNames[0], rawType);
}
/**
* 获取指定类型对应的所有Bean,包括子类
*
* @param <T> Bean类型
* @param type 类、接口,null表示获取所有bean
* @return 类型对应的bean,key是bean注册的name,value是Bean
* @since 5.3.3
*/
public static <T> Map<String, T> getBeansOfType(Class<T> type) {
return applicationContext.getBeansOfType(type);
}
/**
* 获取指定类型对应的Bean名称,包括子类
*
* @param type 类、接口,null表示获取所有bean名称
* @return bean名称
* @since 5.3.3
*/
public static String[] getBeanNamesForType(Class<?> type) {
return applicationContext.getBeanNamesForType(type);
}
/**
* 获取配置文件配置项的值
*
* @param key 配置项key
* @return 属性值
* @since 5.3.3
*/
public static String getProperty(String key) {
return applicationContext.getEnvironment().getProperty(key);
}
/**
* 获取当前的环境配置,无配置返回null
*
* @return 当前的环境配置
* @since 5.3.3
*/
public static String[] getActiveProfiles() {
return applicationContext.getEnvironment().getActiveProfiles();
}
/**
* 获取当前的环境配置,当有多个环境配置时,只获取第一个
*
* @return 当前的环境配置
* @since 5.3.3
*/
public static String getActiveProfile() {
final String[] activeProfiles = getActiveProfiles();
return ArrayUtil.isNotEmpty(activeProfiles) ? activeProfiles[0] : null;
}
/**
* 动态向Spring注册Bean
* <p>
* 由{@link org.springframework.beans.factory.BeanFactory} 实现,通过工具开放API
*
* @param <T> Bean类型
* @param beanName 名称
* @param bean bean
* @author shadow
* @since 5.4.2
*/
public static <T> void registerBean(String beanName, T bean) {
ConfigurableApplicationContext context = (ConfigurableApplicationContext) applicationContext;
context.getBeanFactory().registerSingleton(beanName, bean);
}
}
package com.laker.admin.module.enums;
import com.baomidou.mybatisplus.annotation.EnumValue;
import lombok.Getter;
@Getter
public enum TaskStateEnum {
START(1, "开始"), STOP(0, "暂停");
TaskStateEnum(int code, String descp) {
this.code = code;
this.descp = descp;
}
@EnumValue//标记数据库存的值是code
private final int code;
private final String descp;
}
package com.laker.admin.module.task;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.github.xiaoymin.knife4j.annotations.ApiSupport;
import com.laker.admin.framework.PageResponse;
import com.laker.admin.framework.Response;
import com.laker.admin.module.task.core.CoreProcessor;
import com.laker.admin.module.task.entity.SysTask;
import com.laker.admin.module.task.service.ISysTaskService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
......@@ -12,36 +18,48 @@ import org.springframework.web.bind.annotation.*;
@Api(tags = "定时任务管理")
@ApiSupport(order = 1)
@RestController
@RequestMapping("/task-manager")
@RequestMapping("/sys/task")
@Slf4j
public class TaskManagerController {
@Autowired
private CoreProcessor coreProcessor;
@GetMapping("/list")
@ApiOperation("列表")
public Response startCron() {
return Response.ok(coreProcessor.listJob());
@Autowired
ISysTaskService sysTaskService;
@GetMapping
@ApiOperation(value = "分页查询")
public PageResponse pageAll(@RequestParam(required = false, defaultValue = "1") long page,
@RequestParam(required = false, defaultValue = "10") long limit) {
Page roadPage = new Page<>(page, limit);
LambdaQueryWrapper<SysTask> queryWrapper = new QueryWrapper().lambda();
Page pageList = sysTaskService.page(roadPage, queryWrapper);
return PageResponse.ok(pageList.getRecords(), pageList.getTotal());
}
@GetMapping("/start")
@ApiOperation("开始任务")
public Response start(String taskCode) {
coreProcessor.startJob(taskCode);
@PostMapping
@ApiOperation("更新任务")
public Response update(@RequestBody SysTask sysTask) {
sysTaskService.saveOrUpdate(sysTask);
return Response.ok();
}
@GetMapping("/{id}")
public Response get(@PathVariable Long id) {
return Response.ok(sysTaskService.getById(id));
}
@PutMapping("/update")
@ApiOperation("更新任务")
public Response update(String taskCode, String taskCron, String taskName) {
coreProcessor.updateJob( taskCode, taskCron, taskName);
@GetMapping("/start")
@ApiOperation("开始任务")
public Response start(String taskCode) {
coreProcessor.startJob(taskCode);
return Response.ok();
}
@DeleteMapping("/stop")
@ApiOperation("取消任务")
@GetMapping("/stop")
@ApiOperation("暂停任务")
public Response stopCron(String taskCode) {
coreProcessor.stopJob(taskCode);
return Response.ok();
......
......@@ -5,6 +5,11 @@ import cn.hutool.cache.impl.CacheObj;
import cn.hutool.cache.impl.LFUCache;
import cn.hutool.core.map.MapUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.laker.admin.framework.SpringUtils;
import com.laker.admin.module.enums.TaskStateEnum;
import com.laker.admin.module.task.entity.SysTask;
import com.laker.admin.module.task.service.ISysTaskService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.CommandLineRunner;
......@@ -37,6 +42,9 @@ public class CoreProcessor implements CommandLineRunner {
@Autowired
private List<ICallBack> callBacks;
@Autowired
private ISysTaskService sysTaskService;
/**
* 启动后存储任务列表
*/
......@@ -62,7 +70,6 @@ public class CoreProcessor implements CommandLineRunner {
.taskCode(taskCode)
.taskName(taskName)
.taskCron(cron)
.job(job)
.taskClassName(job.getClass().getName()).build();
TaskDto res = this.startJVMJob(taskDto, null);
taskStore.saveTask(res);
......@@ -85,10 +92,13 @@ public class CoreProcessor implements CommandLineRunner {
iCallBack.start(task);
});
try {
if (task.getJob() != null) {
task.getJob().execute(param);
} else {
log.error("未获取到job实例,task:{}", task);
String taskClassName = task.getTaskClassName();
Map<String, IJob> beansOfType = SpringUtils.getBeansOfType(IJob.class);
for (IJob iJob : beansOfType.values()) {
if (StrUtil.equals(taskClassName, iJob.getClass().getName())) {
iJob.execute(param);
break;
}
}
} catch (Exception e) {
......@@ -102,7 +112,6 @@ public class CoreProcessor implements CommandLineRunner {
}
},
new CronTrigger(taskCron));
task.setScheduledFuture(future);
JVM_RUNNING_TASK.put(task.getTaskCode(), future);
} else {
log.warn("cron表达式为:{},Job信息:{},不予启动任务。", taskCron, task);
......@@ -135,28 +144,14 @@ public class CoreProcessor implements CommandLineRunner {
removeJvmTask(taskCode);
TaskDto taskDto = taskStore.findByTaskCode(taskCode);
startJVMJob(taskDto, null);
taskDto.setTaskState(TaskStateEnum.START);
taskStore.saveTask(taskDto);
sysTaskService.update(Wrappers.<SysTask>lambdaUpdate().set(SysTask::getTaskState, TaskStateEnum.START).eq(SysTask::getTaskCode, taskCode));
}
public synchronized void stopJob(String taskCode) {
removeJvmTask(taskCode);
taskStore.updateTaskStateByTaskCode(TaskStateEnum.STOP, taskCode);
}
public synchronized void updateJob(String taskCode, String taskCron, String taskName) {
removeJvmTask(taskCode);
taskStore.updateTaskByTaskCode(taskCron, taskName, taskCode);
TaskDto taskDto = taskStore.findByTaskCode(taskCode);
startJVMJob(taskDto, null);
taskStore.updateTaskStateByTaskCode(TaskStateEnum.START, taskCode);
sysTaskService.update(Wrappers.<SysTask>lambdaUpdate().set(SysTask::getTaskState, TaskStateEnum.STOP).eq(SysTask::getTaskCode, taskCode));
}
public List<TaskDto> listJob() {
return taskStore.list();
}
}
package com.laker.admin.module.task.core;
import java.util.List;
public interface ITaskStore {
void saveTask(TaskDto taskDto);
List<TaskDto> list();
TaskDto updateTaskByTaskCode(String taskCron, String taskName, String taskCode);
TaskDto updateTaskStateByTaskCode(TaskStateEnum taskState, String taskCode);
void deleteTaskByTaskCode(String taskCode);
TaskDto findByTaskCode(String taskCode);
......
package com.laker.admin.module.task.core;
import com.fasterxml.jackson.annotation.JsonIgnore;
import com.laker.admin.module.enums.TaskStateEnum;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import java.util.concurrent.ScheduledFuture;
@Data
@Builder
@AllArgsConstructor
public class TaskDto {
/**
* 任务的编码 必须全局唯一
......@@ -26,19 +26,12 @@ public class TaskDto {
*/
private String taskCron;
@JsonIgnore
private ScheduledFuture scheduledFuture;
@JsonIgnore
private IJob job;
/**
* 是否执行完成
*/
private Boolean done;
private TaskStateEnum taskState;
public Boolean getDone() {
return scheduledFuture == null ? null : scheduledFuture.isDone();
public TaskDto() {
}
}
package com.laker.admin.module.task.core;
public enum TaskStateEnum {
START, STOP
}
package com.laker.admin.module.task.core.impl;
import cn.hutool.cache.CacheUtil;
import cn.hutool.cache.impl.LFUCache;
import com.laker.admin.module.task.core.ITaskStore;
import com.laker.admin.module.task.core.TaskDto;
import com.laker.admin.module.task.core.TaskStateEnum;
import org.springframework.stereotype.Component;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.TimeUnit;
@Component
public class MemoryTaskStore implements ITaskStore {
private final static LFUCache<String, TaskDto> TASK_CACHE = CacheUtil.newLFUCache(1000, TimeUnit.DAYS.toMillis(3));
@Override
public void saveTask(TaskDto taskDto) {
TASK_CACHE.put(taskDto.getTaskCode(), taskDto);
}
@Override
public List<TaskDto> list() {
List list = new ArrayList();
TASK_CACHE.forEach(taskDto -> {
list.add(taskDto);
});
return list;
}
@Override
public TaskDto updateTaskByTaskCode(String taskCron, String taskName, String taskCode) {
TaskDto taskDtoSave = this.findByTaskCode(taskCode);
taskDtoSave.setTaskCron(taskCron);
taskDtoSave.setTaskName(taskName);
TASK_CACHE.put(taskCode, taskDtoSave);
return taskDtoSave;
}
@Override
public TaskDto updateTaskStateByTaskCode(TaskStateEnum taskState, String taskCode) {
TaskDto taskDtoSave = this.findByTaskCode(taskCode);
taskDtoSave.setTaskState(taskState);
TASK_CACHE.put(taskCode, taskDtoSave);
return taskDtoSave;
}
@Override
public void deleteTaskByTaskCode(String taskCode) {
TaskDto taskDtoSave = this.findByTaskCode(taskCode);
TASK_CACHE.put(taskCode, taskDtoSave);
}
@Override
public TaskDto findByTaskCode(String taskCode) {
return TASK_CACHE.get(taskCode, false);
}
}
package com.laker.admin.module.task.core.impl;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.laker.admin.module.enums.TaskStateEnum;
import com.laker.admin.module.task.core.ITaskStore;
import com.laker.admin.module.task.core.TaskDto;
import com.laker.admin.module.task.entity.SysTask;
import com.laker.admin.module.task.service.ISysTaskService;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import java.util.List;
import java.util.stream.Collectors;
@Component
public class MysqlTaskStore implements ITaskStore {
@Autowired
ISysTaskService taskService;
@Override
public void saveTask(TaskDto taskDto) {
SysTask task = new SysTask();
task.setEnable(true);
BeanUtils.copyProperties(taskDto, task);
try {
int count = taskService.count(Wrappers.<SysTask>lambdaQuery().eq(SysTask::getTaskCode, taskDto.getTaskCode()));
if (count == 0) {
task.setTaskState(TaskStateEnum.START);
taskService.save(task);
}
} finally {
}
}
@Override
public TaskDto findByTaskCode(String taskCode) {
SysTask task = taskService.getOne(Wrappers.<SysTask>lambdaQuery().eq(SysTask::getTaskCode, taskCode));
TaskDto taskDto = new TaskDto();
BeanUtils.copyProperties(task, taskDto);
return taskDto;
}
}
package com.laker.admin.module.task.entity;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import com.laker.admin.module.enums.TaskStateEnum;
import lombok.Data;
import lombok.EqualsAndHashCode;
import java.io.Serializable;
import java.time.LocalDateTime;
/**
* <p>
*
* </p>
*
* @author laker
* @since 2021-08-17
*/
@Data
@EqualsAndHashCode(callSuper = false)
public class SysTask implements Serializable {
private static final long serialVersionUID = 1L;
/**
* 主键
*/
@TableId(value = "task_id", type = IdType.AUTO)
private Long taskId;
/**
* 任务的编码 必须全局唯一
*/
private String taskCode;
/**
* 任务的名称
*/
private String taskName;
/**
* 任务的类名称
*/
private String taskClassName;
/**
* 任务的cron表达式
*/
private String taskCron;
/**
* 任务创建时间
*/
private LocalDateTime createTime;
/**
* 是否启用
*/
private Boolean enable;
private TaskStateEnum taskState;
}
package com.laker.admin.module.task.mapper;
import com.laker.admin.module.task.entity.SysTask;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
/**
* <p>
* Mapper 接口
* </p>
*
* @author laker
* @since 2021-08-17
*/
public interface SysTaskMapper extends BaseMapper<SysTask> {
}
package com.laker.admin.module.task.service;
import com.laker.admin.module.task.entity.SysTask;
import com.baomidou.mybatisplus.extension.service.IService;
/**
* <p>
* 服务类
* </p>
*
* @author laker
* @since 2021-08-17
*/
public interface ISysTaskService extends IService<SysTask> {
}
package com.laker.admin.module.task.service.impl;
import com.laker.admin.module.task.entity.SysTask;
import com.laker.admin.module.task.mapper.SysTaskMapper;
import com.laker.admin.module.task.service.ISysTaskService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.stereotype.Service;
/**
* <p>
* 服务实现类
* </p>
*
* @author laker
* @since 2021-08-17
*/
@Service
public class SysTaskServiceImpl extends ServiceImpl<SysTaskMapper, SysTask> implements ISysTaskService {
}
......@@ -24,6 +24,9 @@ spring:
suffix: .ftl
mybatis-plus:
type-aliases-package: org.snaker.engine.entity
# 支持统配符 * 或者 ; 分割
typeEnumsPackage: com.laker.admin.module.enums
knife4j:
# 开启增强
enable: true
......
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.laker.admin.module.task.mapper.SysTaskMapper">
<!-- 通用查询映射结果 -->
<resultMap id="BaseResultMap" type="com.laker.admin.module.task.entity.SysTask">
<id column="task_id" property="taskId" />
<result column="task_code" property="taskCode" />
<result column="task_name" property="taskName" />
<result column="task_class_name" property="taskClassName" />
<result column="task_cron" property="taskCron" />
<result column="create_time" property="createTime" />
<result column="enable" property="enable" />
</resultMap>
<!-- 通用查询结果列 -->
<sql id="Base_Column_List">
task_id, task_code, task_name, task_class_name, task_cron, create_time, enable
</sql>
</mapper>
......@@ -182,7 +182,7 @@ layui.define(['jquery', 'element', 'form', 'table', 'yaml', 'common'], function
layer.msg(result.msg, {
icon: 1,
time: 1000,
area: ['100px', '80px'],
area: ['100px', '65px'],
content: "删除成功"
}, function () {
obj.del();
......@@ -191,7 +191,7 @@ layui.define(['jquery', 'element', 'form', 'table', 'yaml', 'common'], function
layer.msg(result.msg, {
icon: 2,
time: 1000,
area: ['100px', '80px'],
area: ['100px', '65px'],
content: "删除失败"
});
}
......@@ -259,7 +259,7 @@ layui.define(['jquery', 'element', 'form', 'table', 'yaml', 'common'], function
if (result.success) {
layer.msg(result.msg, {
icon: 1,
area: ['100px', '80px'],
area: ['100px', '65px'],
time: 1000
}, function () {
table.reload('table');
......@@ -267,7 +267,7 @@ layui.define(['jquery', 'element', 'form', 'table', 'yaml', 'common'], function
} else {
layer.msg(result.msg, {
icon: 2,
area: ['100px', '80px'],
area: ['100px', '65px'],
time: 1000
});
}
......@@ -340,7 +340,7 @@ layui.define(['jquery', 'element', 'form', 'table', 'yaml', 'common'], function
{
icon: 1,
time: 1000,
area: ['100px', '80px'],
area: ['100px', '65px'],
content: "新增成功"
}
, function () {
......@@ -349,7 +349,7 @@ layui.define(['jquery', 'element', 'form', 'table', 'yaml', 'common'], function
});
} else {
layer.msg(result.msg,
{icon: 2, time: 1000, area: ['100px', '80px']}
{icon: 2, time: 1000, area: ['100px', '65px']}
);
}
}
......
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>数据字典</title>
<link href="../../component/pear/css/pear.css" rel="stylesheet"/>
</head>
<body class="pear-container">
<div class="layui-card">
<div class="layui-card-body">
<form class="layui-form" action="">
<div class="layui-form-item">
<label class="layui-form-label">字典名称</label>
<div class="layui-input-inline">
<input type="text" name="typeName" placeholder="" class="layui-input">
</div>
<button class="pear-btn pear-btn-md pear-btn-primary" lay-submit lay-filter="dict-type-query">
<i class="layui-icon layui-icon-search"></i>
查询
</button>
<button type="reset" class="pear-btn pear-btn-md">
<i class="layui-icon layui-icon-refresh"></i>
重置
</button>
</div>
</form>
</div>
</div>
<div class="layui-card">
<div class="layui-card-body">
<table id="dict-type-table" lay-filter="dict-type-table"></table>
</div>
</div>
</body>
<script type="text/html" id="dict-type-toolbar">
<button class="pear-btn pear-btn-primary pear-btn-md" lay-event="add">
<i class="layui-icon layui-icon-add-1"></i>
新增
</button>
<button class="pear-btn pear-btn-danger pear-btn-md" lay-event="batchRemove">
<i class="layui-icon layui-icon-delete"></i>
删除
</button>
</script>
<script type="text/html" id="dict-type-bar">
<button class="pear-btn pear-btn-primary pear-btn-sm" lay-event="edit">
<i class="layui-icon layui-icon-edit"></i>
</button>
<button class="pear-btn pear-btn-warming pear-btn-sm" lay-event="details">
<i class="layui-icon layui-icon-transfer"></i>
</button>
<button class="pear-btn pear-btn-danger pear-btn-sm" lay-event="remove">
<i class="layui-icon layui-icon-delete"></i>
</button>
</script>
<script type="text/html" id="dict-type-enable">
<input type="checkbox" value="{{d.id}}" lay-skin="switch" lay-text="启用|禁用" lay-filter="dict-type-enable"
{{d.enable== '0' ? 'checked' : '' }}>
</script>
<script type="text/html" id="dict-data-toolbar">
<button class="pear-btn pear-btn-primary pear-btn-md" lay-event="add">
<i class="layui-icon layui-icon-add-1"></i>
新增
</button>
<button class="pear-btn pear-btn-danger pear-btn-md" lay-event="batchRemove">
<i class="layui-icon layui-icon-delete"></i>
删除
</button>
</script>
<script type="text/html" id="dict-data-bar">
<button class="pear-btn pear-btn-primary pear-btn-sm" lay-event="edit"><i class="layui-icon layui-icon-edit"></i>
</button>
<button class="pear-btn pear-btn-danger pear-btn-sm" lay-event="remove"><i class="layui-icon layui-icon-delete"></i>
</button>
</script>
<script type="text/html" id="dict-data-enable">
<input type="checkbox" value="{{d.dataId}}" lay-skin="switch" lay-text="启用|禁用" lay-filter="dict-data-enable"
{{d.enable== '0' ? 'checked' : '' }}>
</script>
<script src="../../component/layui/layui.js"></script>
<script src="../../component/pear/pear.js"></script>
<script>
layui.use(['table', 'form', 'jquery', 'easyAdmin'], function () {
let table = layui.table;
let form = layui.form;
let $ = layui.jquery;
let easyAdmin = layui.easyAdmin;
let MODULE_PATH = "dict/";
let typeCode;
let cols = [
[{
type: 'checkbox'
},
{
title: '字典名称',
field: 'typeName',
align: 'center',
width: 120
},
{
title: '描述',
field: 'description',
align: 'center'
},
{
title: '字典状态',
field: 'enable',
align: 'center',
templet: '#dict-type-enable'
},
{
title: '操作',
toolbar: '#dict-type-bar',
align: 'center',
width: 180
}
]
];
let dataCols = [
[{
type: 'checkbox'
},
{
title: '标签',
field: 'dataLabel',
align: 'center',
width: 120
},
{
title: '对应值',
field: 'dataValue',
align: 'center'
},
{
title: '状态',
field: 'enable',
align: 'center',
templet: '#dict-data-enable'
},
{
title: '操作',
toolbar: '#dict-data-bar',
align: 'center',
width: 180
}
]
];
table.render({
elem: '#dict-type-table',
url: "../../admin/data/dictType.json",
page: true,
cols: cols,
skin: 'line',
height: 'full-148',
toolbar: '#dict-type-toolbar',
defaultToolbar: [{
title: '刷新',
layEvent: 'refresh',
icon: 'layui-icon-refresh',
}, 'filter', 'print', 'exports']
});
window.renderData = function (code) {
typeCode = code;
$(".empty").hide();
table.render({
elem: '#dict-data-table',
url: "../../admin/data/dictData.json",
page: true,
height: 'full-148',
cols: dataCols,
skin: 'line',
toolbar: '#dict-data-toolbar'
});
}
table.on('tool(dict-type-table)', function (obj) {
if (obj.event === 'remove') {
window.removeType(obj);
} else if (obj.event === 'edit') {
window.editType(obj);
} else if (obj.event === 'details') {
window.renderData(obj.data['typeCode'])
}
});
table.on('toolbar(dict-type-table)', function (obj) {
if (obj.event === 'add') {
window.addType();
} else if (obj.event === 'refresh') {
window.refreshType();
} else if (obj.event === 'batchRemove') {
layer.msg("批量删除")
}
});
form.on('submit(dict-type-query)', function (data) {
table.reload('dict-type-table', {
where: data.field
})
return false;
});
form.on('switch(dict-type-enable)', function (obj) {
layer.msg("切换");
});
window.addType = function () {
layer.open({
type: 2,
title: '新增',
shade: 0.1,
area: ['500px', '400px'],
content: MODULE_PATH + 'add.html'
});
}
window.editType = function (obj) {
layer.open({
type: 2,
title: '修改',
shade: 0.1,
area: ['500px', '400px'],
content: MODULE_PATH + 'edit.html'
});
}
window.removeType = function (obj) {
layer.msg("删除");
}
window.refreshType = function () {
table.reload('dict-type-table');
}
window.addData = function () {
layer.open({
type: 2,
title: '新增',
shade: 0.1,
area: ['500px', '450px'],
content: MODULE_PATH + 'add.html'
});
}
window.editData = function (obj) {
layer.open({
type: 2,
title: '修改',
shade: 0.1,
area: ['500px', '450px'],
content: MODULE_PATH + 'edit.html'
});
}
window.removeData = function (obj) {
layer.msg("删除");
}
table.on('tool(dict-data-table)', function (obj) {
if (obj.event === 'remove') {
window.removeData(obj);
} else if (obj.event === 'edit') {
window.editData(obj);
} else if (obj.event === 'details') {
window.details(obj);
}
});
table.on('toolbar(dict-data-table)', function (obj) {
if (obj.event === 'add') {
window.addData();
} else if (obj.event === 'refresh') {
window.refreshData();
} else if (obj.event === 'batchRemove') {
layer.msg("批量删除")
}
});
form.on('submit(dict-data-query)', function (data) {
data.field.typeCode = typeCode;
table.reload('dict-data-table', {
where: data.field
})
return false;
});
form.on('switch(dict-data-enable)', function (obj) {
layer.msg("切换状态");
});
window.refreshData = function () {
table.reload('dict-data-table');
}
})
</script>
</html>
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
<link href="../../component/pear/css/pear.css" rel="stylesheet"/>
</head>
<body class="pear-container">
<div class="layui-card">
<div class="layui-card-body">
<form class="layui-form" action="">
<div class="layui-form-item">
<label class="layui-form-label">关键字</label>
<div class="layui-input-inline">
<input type="text" name="keyWord" placeholder="" class="layui-input">
</div>
<button class="pear-btn pear-btn-md pear-btn-primary" lay-submit lay-filter="dict-type-query">
<i class="layui-icon layui-icon-search"></i>
查询
</button>
<button type="reset" class="pear-btn pear-btn-md">
<i class="layui-icon layui-icon-refresh"></i>
重置
</button>
</div>
</form>
</div>
</div>
<div class="layui-card">
<div class="layui-card-body">
<table id="table" lay-filter="table-filter"></table>
</div>
</div>
</body>
<script type="text/html" id="record-toolbar">
<button class="pear-btn pear-btn-primary pear-btn-sm" lay-event="edit">
编辑
</button>
<button class="pear-btn pear-btn-success pear-btn-sm" lay-event="start">
开启
</button>
<button class="pear-btn pear-btn-sm" lay-event="stop">
暂停
</button>
</script>
<script src="../../component/layui/layui.js"></script>
<script src="../../component/pear/pear.js"></script>
<script>
layui.use(['easyAdmin', 'table'], function () {
let easyAdmin = layui.easyAdmin;
let table = layui.table;
let cols = [
[{
type: 'checkbox'
},
{
title: '任务的编码',
field: 'taskCode',
align: 'center',
width: 120
},
{
title: '任务的名称',
field: 'taskName',
align: 'center',
width: 120
},
{
title: '任务的类名称',
field: 'taskClassName',
align: 'center'
},
{
title: '任务的cron表达式',
field: 'taskCron',
align: 'center',
width: 120
},
{
title: '任务状态',
field: 'taskState',
align: 'center',
width: 120,
templet: function (d) {
if (d.taskState === 'START') {
return '<button type="button" class="tag-item layui-btn layui-btn-primary layui-btn-sm">启用</button>';
}
return '<button type="button" class="tag-item tag-item-warm layui-btn layui-btn-primary layui-btn-sm">暂停</button>';
}
},
{
title: '启用状态',
field: 'enable',
align: 'center',
width: 120,
templet: function (d) {
if (d.enable) {
return '<button type="button" class="tag-item layui-btn layui-btn-primary layui-btn-sm">启用</button>';
}
return '<button type="button" class="tag-item tag-item-warm layui-btn layui-btn-primary layui-btn-sm">暂停</button>';
}
},
{
title: '操作',
toolbar: '#record-toolbar',
align: 'center',
width: 220
}
]
]
;
let module = "task";
let uri = "/sys/" + module;
easyAdmin.tableRender({
url: uri,
cols: cols,
toolbar: null,
defaultToolbar: null
});
table.on('tool(table-filter)', function (obj) {
if (obj.event === 'stop') {
easyAdmin.httpGet(uri + "/stop?taskCode=" + obj.data.taskCode, function (result) {
layer.msg(result.msg,
{
icon: 1,
time: 1000,
area: ['100px', '65px'],
content: "操作成功"
}
, function () {
table.reload('table');
});
});
} else if (obj.event === 'start') {
easyAdmin.httpGet(uri + "/start?taskCode=" + obj.data.taskCode, function (result) {
layer.msg(result.msg,
{
icon: 1,
time: 1000,
area: ['100px', '65px'],
content: "操作成功"
}
, function () {
table.reload('table');
});
});
} else if (obj.event === 'edit') {
easyAdmin.JumpEdit(module, obj.data[module + 'Id']);
}
});
easyAdmin.FormQuery();
})
</script>
</html>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<link rel="stylesheet" href="../../../component/pear/css/pear.css"/>
</head>
<body>
<form class="layui-form" action="" lay-filter="edit">
<div class="mainBox">
<div class="main-container">
<!-- id隐藏列 -->
<div class="layui-form-item layui-hide">
<label class="layui-form-label">id</label>
<div class="layui-input-block">
<input type="text" name="taskId">
</div>
</div>
<div class="layui-form-item">
<label class="layui-form-label">任务编码</label>
<div class="layui-input-block">
<input type="text" name="taskCode" lay-verify="title" autocomplete="off"
placeholder="请输入"
class="layui-input layui-disabled" disabled>
</div>
</div>
<div class="layui-form-item">
<label class="layui-form-label">任务名称</label>
<div class="layui-input-block">
<input type="text" name="taskName" lay-verify="title" autocomplete="off"
placeholder="请输入"
class="layui-input">
</div>
</div>
<div class="layui-form-item">
<label class="layui-form-label">任务类名称</label>
<div class="layui-input-block">
<input type="text" name="taskClassName" lay-verify="title" autocomplete="off"
placeholder="请输入"
class="layui-input layui-disabled" disabled>
</div>
</div>
<div class="layui-form-item">
<label class="layui-form-label">cron表达式</label>
<div class="layui-input-block">
<input type="text" name="taskCron" lay-verify="title" autocomplete="off"
placeholder="请输入"
class="layui-input">
</div>
</div>
<div class="layui-form-item">
<label class="layui-form-label">启用状态</label>
<div class="layui-input-block">
<input type="radio" name="enable" value="1" title="开启">
<input type="radio" name="enable" value="0" title="关闭">
</div>
</div>
</div>
</div>
<div class="bottom">
<div class="button-container">
<button type="submit" class="pear-btn pear-btn-primary pear-btn-sm" lay-submit lay-filter="save">
<i class="layui-icon layui-icon-ok"></i>
提交
</button>
<button type="reset" class="pear-btn pear-btn-sm">
<i class="layui-icon layui-icon-refresh"></i>
重置
</button>
</div>
</div>
</form>
<script src="../../../component/layui/layui.js"></script>
<script src="../../../component/pear/pear.js"></script>
<script>
layui.use(['easyAdmin'], function () {
let module = "task";
let uri = "/sys/" + module;
let easyAdmin = layui.easyAdmin;
easyAdmin.FormVal(uri);
easyAdmin.FormSave(uri);
})
</script>
<script>
</script>
</body>
</html>
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册