From 7666335e436e6b38bcf44a766334069e07bbe421 Mon Sep 17 00:00:00 2001 From: fit2cloud-chenyw Date: Fri, 19 Nov 2021 18:44:58 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E6=96=B0=E5=A2=9E=E5=AE=9A=E6=97=B6?= =?UTF-8?q?=E6=8A=A5=E5=91=8A?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- backend/pom.xml | 8 +- .../job/sechedule/ScheduleManager.java | 4 + .../job/sechedule/strategy/TaskHandler.java | 119 ++++++++++++++++++ .../strategy/TaskStrategyFactory.java | 23 ++++ .../strategy/impl/EmailTaskHandler.java | 74 +++++++++++ .../listener/GlobalTaskStartListener.java | 42 +++++++ .../plugins/server/XEmailTaskServer.java | 71 +++++++++++ .../io/dataease/service/ScheduleService.java | 19 +++ frontend/src/styles/index.scss | 35 ++++++ 9 files changed, 394 insertions(+), 1 deletion(-) create mode 100644 backend/src/main/java/io/dataease/job/sechedule/strategy/TaskHandler.java create mode 100644 backend/src/main/java/io/dataease/job/sechedule/strategy/TaskStrategyFactory.java create mode 100644 backend/src/main/java/io/dataease/job/sechedule/strategy/impl/EmailTaskHandler.java create mode 100644 backend/src/main/java/io/dataease/listener/GlobalTaskStartListener.java create mode 100644 backend/src/main/java/io/dataease/plugins/server/XEmailTaskServer.java diff --git a/backend/pom.xml b/backend/pom.xml index 4a6aaed85c..d7f33a9a94 100644 --- a/backend/pom.xml +++ b/backend/pom.xml @@ -21,6 +21,12 @@ + + + com.google.guava + guava + 30.1.1-jre + org.springframework.boot spring-boot-starter-web @@ -201,7 +207,7 @@ io.dataease dataease-plugin-interface - 1.4 + 1.5 cn.hutool diff --git a/backend/src/main/java/io/dataease/job/sechedule/ScheduleManager.java b/backend/src/main/java/io/dataease/job/sechedule/ScheduleManager.java index c8597498a5..b96488c767 100644 --- a/backend/src/main/java/io/dataease/job/sechedule/ScheduleManager.java +++ b/backend/src/main/java/io/dataease/job/sechedule/ScheduleManager.java @@ -436,4 +436,8 @@ public class ScheduleManager { scheduler.triggerJob(jobKey); } + public void fireNow(JobKey jobKey) throws SchedulerException { + scheduler.triggerJob(jobKey); + } + } diff --git a/backend/src/main/java/io/dataease/job/sechedule/strategy/TaskHandler.java b/backend/src/main/java/io/dataease/job/sechedule/strategy/TaskHandler.java new file mode 100644 index 0000000000..c0ca0295df --- /dev/null +++ b/backend/src/main/java/io/dataease/job/sechedule/strategy/TaskHandler.java @@ -0,0 +1,119 @@ +package io.dataease.job.sechedule.strategy; + +import io.dataease.job.sechedule.ScheduleManager; +import io.dataease.plugins.common.entity.GlobalTaskEntity; +import org.apache.commons.lang3.ObjectUtils; +import org.quartz.*; +import org.springframework.beans.factory.InitializingBean; +import java.text.ParseException; +import java.text.SimpleDateFormat; +import java.util.Calendar; +import java.util.Date; + +public abstract class TaskHandler implements InitializingBean { + + private static final String[] week = {"SUNDAY", "MONDAY", "TUESDAY", "WEDNESDAY", "THURSDAY", "FRIDAY", "SATURDAY"}; + + + public void addTask(ScheduleManager scheduleManager, GlobalTaskEntity taskEntity) throws Exception { + // 1。首先看看是否过期 + Long endTime = taskEntity.getEndTime(); + if (taskExpire(endTime)) { // 过期了就删除任务 + removeTask(scheduleManager, taskEntity); + return; + } + JobKey jobKey = new JobKey(taskEntity.getTaskId().toString()); + TriggerKey triggerKey = new TriggerKey(taskEntity.getTaskId().toString()); + Date start = new Date(taskEntity.getStartTime()); + Date end = null; + if (ObjectUtils.isNotEmpty(taskEntity.getEndTime())) { + new Date(taskEntity.getEndTime()); + } + Class executor = this.getClass(); + String cron = cron(taskEntity); + scheduleManager.addOrUpdateCronJob(jobKey, triggerKey, executor , cron, start, end, jobDataMap(taskEntity)); + } + + + protected abstract JobDataMap jobDataMap( GlobalTaskEntity taskEntity); + + private String cron(GlobalTaskEntity taskEntity) { + if(taskEntity.getRateType() == -1) { + return taskEntity.getRateVal(); + } + SimpleDateFormat sdf = new SimpleDateFormat( "yyyy-MM-dd HH:mm:ss" ); + + Date date = null; + try { + date = sdf.parse(taskEntity.getRateVal()); + } catch (ParseException e) { + e.printStackTrace(); + } + Calendar instance = Calendar.getInstance(); + instance.setTime(date); + + if (taskEntity.getRateType() == 0) { + return + instance.get(Calendar.SECOND) + " " + + instance.get(Calendar.MINUTE) + " " + + instance.get(Calendar.HOUR_OF_DAY) + " * * ?"; + } + if (taskEntity.getRateType() == 1) { + return + instance.get(Calendar.SECOND) + " " + + instance.get(Calendar.MINUTE) + " " + + instance.get(Calendar.HOUR_OF_DAY) + " ? * " + + getDayOfWeek(instance); + } + if (taskEntity.getRateType() == 2) { + return + instance.get(Calendar.SECOND) + " " + + instance.get(Calendar.MINUTE) + " " + + instance.get(Calendar.HOUR_OF_DAY) + " " + + instance.get(Calendar.DATE) + " * ?"; + } + + return null; + } + + private String getDayOfWeek(Calendar instance) { + int index = instance.get(Calendar.DAY_OF_WEEK) - 1; + return week[index]; + } + + + + public void removeTask(ScheduleManager scheduleManager, GlobalTaskEntity taskEntity){ + JobKey jobKey = new JobKey(taskEntity.getTaskId().toString()); + TriggerKey triggerKey = new TriggerKey(taskEntity.getTaskId().toString()); + scheduleManager.removeJob(jobKey, triggerKey); + } + + public void executeTask(ScheduleManager scheduleManager, GlobalTaskEntity taskEntity) throws Exception{ + JobKey jobKey = new JobKey(taskEntity.getTaskId().toString()); + scheduleManager.fireNow(jobKey); + } + + + + //判断任务是否过期 + public Boolean taskExpire(Long endTime) { + if (ObjectUtils.isEmpty(endTime)) return false; + Long now = System.currentTimeMillis(); + return now > endTime; + } + + @Override + public void afterPropertiesSet() throws Exception { + String beanName = null; + String className = this.getClass().getName(); + className = className.substring(className.lastIndexOf(".") + 1); + if(className.length() > 1) { + beanName = className.substring(0, 1).toLowerCase() + className.substring(1); + } else { + beanName = className.toLowerCase(); + } + TaskStrategyFactory.register( beanName, this); + } + +} diff --git a/backend/src/main/java/io/dataease/job/sechedule/strategy/TaskStrategyFactory.java b/backend/src/main/java/io/dataease/job/sechedule/strategy/TaskStrategyFactory.java new file mode 100644 index 0000000000..6323954ecc --- /dev/null +++ b/backend/src/main/java/io/dataease/job/sechedule/strategy/TaskStrategyFactory.java @@ -0,0 +1,23 @@ +package io.dataease.job.sechedule.strategy; + +import org.apache.commons.lang3.StringUtils; +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; + +public class TaskStrategyFactory { + + + + private static Map strategyMap = new ConcurrentHashMap<>(); + + public static TaskHandler getInvokeStrategy(String name) { + return strategyMap.get(name); + } + + public static void register(String name, TaskHandler handler) { + if (StringUtils.isEmpty(name) || null == handler) { + return; + } + strategyMap.put(name, handler); + } +} diff --git a/backend/src/main/java/io/dataease/job/sechedule/strategy/impl/EmailTaskHandler.java b/backend/src/main/java/io/dataease/job/sechedule/strategy/impl/EmailTaskHandler.java new file mode 100644 index 0000000000..18afcb9b75 --- /dev/null +++ b/backend/src/main/java/io/dataease/job/sechedule/strategy/impl/EmailTaskHandler.java @@ -0,0 +1,74 @@ +package io.dataease.job.sechedule.strategy.impl; + + +import io.dataease.auth.service.AuthUserService; +import io.dataease.commons.utils.CommonBeanFactory; +import io.dataease.job.sechedule.strategy.TaskHandler; + +import io.dataease.plugins.common.entity.GlobalTaskEntity; +import io.dataease.plugins.common.entity.GlobalTaskInstance; +import io.dataease.plugins.config.SpringContextUtil; +import io.dataease.plugins.xpack.email.service.EmailXpackService; +import org.quartz.*; +import org.springframework.scheduling.annotation.Async; +import org.springframework.stereotype.Service; + + +@Service +public class EmailTaskHandler extends TaskHandler implements Job { + + + private static final Integer RUNING = 0; + + + + + @Override + protected JobDataMap jobDataMap(GlobalTaskEntity taskEntity) { + JobDataMap jobDataMap = new JobDataMap(); + jobDataMap.put("taskEntity", taskEntity); + return jobDataMap; + } + + @Override + public void execute(JobExecutionContext context) throws JobExecutionException { + // 插件没有加载 空转 + if(!CommonBeanFactory.getBean(AuthUserService.class).pluginLoaded()) return; + + JobDataMap jobDataMap = context.getJobDetail().getJobDataMap(); + GlobalTaskEntity taskEntity = (GlobalTaskEntity)jobDataMap.get("taskEntity"); + + GlobalTaskInstance taskInstance = buildInstance(taskEntity); + Long instanceId = saveInstance(taskInstance); + taskInstance.setInstanceId(instanceId); + proxy().printImage(taskEntity, taskInstance); + } + + + public EmailTaskHandler proxy() { + return CommonBeanFactory.getBean(EmailTaskHandler.class); + } + + public Long saveInstance(GlobalTaskInstance taskInstance){ + EmailXpackService emailXpackService = SpringContextUtil.getBean(EmailXpackService.class); + return emailXpackService.saveInstance(taskInstance); + } + + private GlobalTaskInstance buildInstance(GlobalTaskEntity taskEntity) { + GlobalTaskInstance taskInstance = new GlobalTaskInstance(); + taskInstance.setTaskId(taskEntity.getTaskId()); + taskInstance.setStatus(RUNING); + taskInstance.setExecuteTime(System.currentTimeMillis()); + return taskInstance; + } + + @Async + public void printImage(GlobalTaskEntity taskEntity, GlobalTaskInstance taskInstance) { + EmailXpackService emailXpackService = SpringContextUtil.getBean(EmailXpackService.class); + emailXpackService.executeJob(taskEntity, taskInstance); + + } + + + +} diff --git a/backend/src/main/java/io/dataease/listener/GlobalTaskStartListener.java b/backend/src/main/java/io/dataease/listener/GlobalTaskStartListener.java new file mode 100644 index 0000000000..c7361ee93b --- /dev/null +++ b/backend/src/main/java/io/dataease/listener/GlobalTaskStartListener.java @@ -0,0 +1,42 @@ +package io.dataease.listener; + +import io.dataease.auth.service.AuthUserService; +import io.dataease.job.sechedule.ScheduleManager; +import io.dataease.job.sechedule.strategy.TaskHandler; +import io.dataease.job.sechedule.strategy.TaskStrategyFactory; +import io.dataease.plugins.common.entity.GlobalTaskEntity; +import io.dataease.plugins.config.SpringContextUtil; +import io.dataease.plugins.xpack.email.service.EmailXpackService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.context.event.ApplicationReadyEvent; +import org.springframework.context.ApplicationListener; +import org.springframework.stereotype.Component; + +import java.util.List; + +@Component +public class GlobalTaskStartListener implements ApplicationListener { + + @Autowired + private AuthUserService authUserService; + + @Autowired + private ScheduleManager scheduleManager; + + @Override + public void onApplicationEvent(ApplicationReadyEvent event) { + if (authUserService.pluginLoaded()) { + EmailXpackService emailXpackService = SpringContextUtil.getBean(EmailXpackService.class); + + List tasks = emailXpackService.allTask(); + tasks.stream().forEach(task -> { + TaskHandler taskHandler = TaskStrategyFactory.getInvokeStrategy(task.getTaskType()); + try { + taskHandler.addTask(scheduleManager, task); + } catch (Exception e) { + e.printStackTrace(); + } + }); + } + } +} diff --git a/backend/src/main/java/io/dataease/plugins/server/XEmailTaskServer.java b/backend/src/main/java/io/dataease/plugins/server/XEmailTaskServer.java new file mode 100644 index 0000000000..00e944f01f --- /dev/null +++ b/backend/src/main/java/io/dataease/plugins/server/XEmailTaskServer.java @@ -0,0 +1,71 @@ +package io.dataease.plugins.server; + + +import com.github.pagehelper.Page; +import com.github.pagehelper.PageHelper; +import io.dataease.commons.utils.BeanUtils; +import io.dataease.commons.utils.PageUtils; +import io.dataease.commons.utils.Pager; +import io.dataease.plugins.common.entity.GlobalTaskEntity; +import io.dataease.plugins.common.entity.XpackGridRequest; +import io.dataease.plugins.config.SpringContextUtil; +import io.dataease.plugins.xpack.email.dto.request.XpackEmailCreate; +import io.dataease.plugins.xpack.email.dto.request.XpackEmailTaskRequest; +import io.dataease.plugins.xpack.email.dto.response.XpackTaskGridDTO; +import io.dataease.plugins.xpack.email.service.EmailXpackService; +import io.dataease.service.ScheduleService; +import io.swagger.annotations.Api; +import org.apache.commons.lang3.ObjectUtils; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.*; + +import java.util.List; + +@Api(tags = "xpack:定时报告") +@RequestMapping("/plugin/task") +@RestController +public class XEmailTaskServer { + + @Autowired + private ScheduleService scheduleService; + + @PostMapping("/queryTasks/{goPage}/{pageSize}") + public Pager> queryTask(@PathVariable int goPage, @PathVariable int pageSize, @RequestBody XpackGridRequest request) { + EmailXpackService emailXpackService = SpringContextUtil.getBean(EmailXpackService.class); + Page page = PageHelper.startPage(goPage, pageSize, true); + List tasks = emailXpackService.taskGrid(request); + Pager> listPager = PageUtils.setPageInfo(page, tasks); + return listPager; + } + + @PostMapping("/save") + public void save(@RequestBody XpackEmailCreate param) throws Exception{ + XpackEmailTaskRequest request = param.fillContent(); + EmailXpackService emailXpackService = SpringContextUtil.getBean(EmailXpackService.class); + emailXpackService.save(request); + GlobalTaskEntity globalTask = BeanUtils.copyBean(new GlobalTaskEntity(), request); + scheduleService.addSchedule(globalTask); + } + + @PostMapping("/queryForm/{taskId}") + public XpackEmailCreate queryForm(@PathVariable Long taskId) { + EmailXpackService emailXpackService = SpringContextUtil.getBean(EmailXpackService.class); + + XpackEmailTaskRequest taskForm = emailXpackService.taskForm(taskId); + XpackEmailCreate xpackEmailCreate = new XpackEmailCreate(); + byte[] bytes = taskForm.getContent(); + + if(ObjectUtils.isNotEmpty(bytes)) { + String emailContent; + try { + emailContent = new String(bytes, "UTF-8"); + } catch (Exception e) { + throw new RuntimeException(e); + } + taskForm.setContent(null); + xpackEmailCreate.setEmailContent(emailContent); + } + xpackEmailCreate.setRequest(taskForm); + return xpackEmailCreate; + } +} diff --git a/backend/src/main/java/io/dataease/service/ScheduleService.java b/backend/src/main/java/io/dataease/service/ScheduleService.java index ac52171430..3927d7ad90 100644 --- a/backend/src/main/java/io/dataease/service/ScheduleService.java +++ b/backend/src/main/java/io/dataease/service/ScheduleService.java @@ -4,6 +4,9 @@ import io.dataease.base.domain.DatasetTableTask; import io.dataease.commons.constants.ScheduleType; import io.dataease.job.sechedule.ExtractDataJob; import io.dataease.job.sechedule.ScheduleManager; +import io.dataease.job.sechedule.strategy.TaskHandler; +import io.dataease.job.sechedule.strategy.TaskStrategyFactory; +import io.dataease.plugins.common.entity.GlobalTaskEntity; import org.apache.commons.lang3.StringUtils; import org.quartz.JobKey; import org.quartz.TriggerKey; @@ -59,4 +62,20 @@ public class ScheduleService { public void fireNow(DatasetTableTask datasetTableTask) throws Exception{ scheduleManager.fireNow(datasetTableTask.getId(), datasetTableTask.getTableId()); } + + public void addSchedule(GlobalTaskEntity task) throws Exception{ + TaskHandler taskHandler = TaskStrategyFactory.getInvokeStrategy(task.getTaskType()); + taskHandler.addTask(scheduleManager, task); + } + public void deleteSchedule(GlobalTaskEntity task) { + TaskHandler taskHandler = TaskStrategyFactory.getInvokeStrategy(task.getTaskType()); + taskHandler.removeTask(scheduleManager, task); + } + + public void fireNow(GlobalTaskEntity task) throws Exception{ + TaskHandler taskHandler = TaskStrategyFactory.getInvokeStrategy(task.getTaskType()); + taskHandler.executeTask(scheduleManager, task); + } + + } diff --git a/frontend/src/styles/index.scss b/frontend/src/styles/index.scss index b957141d59..41a1ee2d0e 100644 --- a/frontend/src/styles/index.scss +++ b/frontend/src/styles/index.scss @@ -684,3 +684,38 @@ div:focus { background: linear-gradient(to right, #fff, rgba(255,255,255,0)) !important; } +.rate-date-class > .el-picker-panel__footer > .el-button--text:first-child{ + display: none; + } + .rate-date-class > .el-picker-panel__body-wrapper > .el-picker-panel__body { + >.el-date-picker__header { + display: none; + } + >.el-picker-panel__content{ + >table > tbody { + >tr:first-child { + display: none; + } + >tr >td.prev-month,td.next-month { + display: none; + } + } + } + } + .rate-day-class > .el-picker-panel__footer > .el-button--text:first-child{ + display: none; + } + .rate-day-class > .el-picker-panel__body-wrapper > .el-picker-panel__body { + >.el-date-picker__header { + display: none; + } + >.el-picker-panel__content{ + >table > tbody { + >tr:not(:nth-child(3)) { + display: none; + } + + } + } + } +