diff --git a/backend/src/main/java/io/dataease/auth/service/impl/DynamicMenuServiceImpl.java b/backend/src/main/java/io/dataease/auth/service/impl/DynamicMenuServiceImpl.java index bb33a2cc6c..cafeebae7f 100644 --- a/backend/src/main/java/io/dataease/auth/service/impl/DynamicMenuServiceImpl.java +++ b/backend/src/main/java/io/dataease/auth/service/impl/DynamicMenuServiceImpl.java @@ -36,10 +36,6 @@ public class DynamicMenuServiceImpl implements DynamicMenuService { @Override public List load(String userId) { -// SysMenuExample sysMenuExample = new SysMenuExample(); -// sysMenuExample.createCriteria().andTypeLessThanOrEqualTo(1); -// sysMenuExample.setOrderByClause(" menu_sort "); -// List sysMenus = sysMenuMapper.selectByExample(sysMenuExample); List sysMenus = extSysMenuMapper.querySysMenu(); List dynamicMenuDtos = sysMenus.stream().map(this::convert).collect(Collectors.toList()); //增加插件中的菜单 diff --git a/backend/src/main/java/io/dataease/commons/utils/CronUtils.java b/backend/src/main/java/io/dataease/commons/utils/CronUtils.java index e6a92861eb..c7a6d57327 100644 --- a/backend/src/main/java/io/dataease/commons/utils/CronUtils.java +++ b/backend/src/main/java/io/dataease/commons/utils/CronUtils.java @@ -1,10 +1,15 @@ package io.dataease.commons.utils; +import io.dataease.plugins.common.entity.GlobalTaskEntity; +import org.apache.commons.lang3.ObjectUtils; import org.quartz.CronExpression; import org.quartz.CronScheduleBuilder; import org.quartz.CronTrigger; import org.quartz.TriggerBuilder; +import java.text.ParseException; +import java.text.SimpleDateFormat; +import java.util.Calendar; import java.util.Date; /** @@ -58,5 +63,54 @@ public class CronUtils { return date; } + public static 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 static String getDayOfWeek(Calendar instance) { + int index = instance.get(Calendar.DAY_OF_WEEK); + index = (index + 1) % 7; + return String.valueOf(index); + } + + // 判断任务是否过期 + public static Boolean taskExpire(Long endTime) { + if (ObjectUtils.isEmpty(endTime)) + return false; + Long now = System.currentTimeMillis(); + return now > endTime; + } + } 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 index 87dff10bdf..bb5da23d0a 100644 --- a/backend/src/main/java/io/dataease/job/sechedule/strategy/TaskHandler.java +++ b/backend/src/main/java/io/dataease/job/sechedule/strategy/TaskHandler.java @@ -1,14 +1,13 @@ package io.dataease.job.sechedule.strategy; +import io.dataease.commons.utils.CronUtils; 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 { @@ -17,7 +16,7 @@ public abstract class TaskHandler implements InitializingBean { // 1。首先看看是否过期 Long endTime = taskEntity.getEndTime(); removeTask(scheduleManager, taskEntity); - if (taskExpire(endTime)) { // 过期了就删除任务 + if (CronUtils.taskExpire(endTime)) { // 过期了就删除任务 return; } JobKey jobKey = new JobKey(taskEntity.getTaskId().toString()); @@ -28,55 +27,17 @@ public abstract class TaskHandler implements InitializingBean { new Date(taskEntity.getEndTime()); } Class executor = this.getClass(); - String cron = cron(taskEntity); + String cron = CronUtils.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; - } public abstract void resetRunningInstance(Long taskId); - private String getDayOfWeek(Calendar instance) { - int index = instance.get(Calendar.DAY_OF_WEEK); - index = (index + 1) % 7; - return String.valueOf(index); - } + public void removeTask(ScheduleManager scheduleManager, GlobalTaskEntity taskEntity) { JobKey jobKey = new JobKey(taskEntity.getTaskId().toString()); @@ -89,13 +50,7 @@ public abstract class TaskHandler implements InitializingBean { scheduleManager.fireNow(jobKey); } - // 判断任务是否过期 - public Boolean taskExpire(Long endTime) { - if (ObjectUtils.isEmpty(endTime)) - return false; - Long now = System.currentTimeMillis(); - return now > endTime; - } + protected abstract Boolean taskIsRunning(Long taskId); 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 index 12ba9352a2..f7d14699c4 100644 --- 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 @@ -7,6 +7,7 @@ import io.dataease.auth.service.impl.AuthUserServiceImpl; import io.dataease.auth.util.JWTUtils; import io.dataease.base.mapper.ext.ExtTaskMapper; import io.dataease.commons.utils.CommonBeanFactory; +import io.dataease.commons.utils.CronUtils; import io.dataease.commons.utils.LogUtil; import io.dataease.commons.utils.ServletUtils; import io.dataease.job.sechedule.ScheduleManager; @@ -67,7 +68,7 @@ public class EmailTaskHandler extends TaskHandler implements Job { JobDataMap jobDataMap = context.getJobDetail().getJobDataMap(); GlobalTaskEntity taskEntity = (GlobalTaskEntity) jobDataMap.get("taskEntity"); ScheduleManager scheduleManager = SpringContextUtil.getBean(ScheduleManager.class); - if (taskExpire(taskEntity.getEndTime())) { + if (CronUtils.taskExpire(taskEntity.getEndTime())) { removeTask(scheduleManager, taskEntity); return; } diff --git a/backend/src/main/java/io/dataease/mobile/service/DirService.java b/backend/src/main/java/io/dataease/mobile/service/DirService.java index 8e69473f2a..79abaa2c7b 100644 --- a/backend/src/main/java/io/dataease/mobile/service/DirService.java +++ b/backend/src/main/java/io/dataease/mobile/service/DirService.java @@ -40,7 +40,6 @@ public class DirService { } public List query(DirRequest request) { -// CurrentUserDto user = AuthUtils.getUser(); String userId = String.valueOf(AuthUtils.getUser().getUserId()); List panelEntities = new ArrayList<>(); if (StringUtils.isNotBlank(request.getName())) { @@ -58,17 +57,6 @@ public class DirService { return dirItemDTO; }).collect(Collectors.toList()); return dtos; - -// if (user.getUserId() == 1 && StringUtils.equals("admin", user.getUsername())) { -// return dtos; -// } -// List permissions = proxy().permissions(); -// return dtos.stream().filter( -// dto -> permissions.stream().anyMatch( -// permission -> StringUtils.equals(permission, dto.getId()) -// ) -// ).collect(Collectors.toList()); - } public DirService proxy() { diff --git a/backend/src/main/java/io/dataease/plugins/server/XEmailTaskServer.java b/backend/src/main/java/io/dataease/plugins/server/XEmailTaskServer.java index fd8eb56a74..31595ae413 100644 --- a/backend/src/main/java/io/dataease/plugins/server/XEmailTaskServer.java +++ b/backend/src/main/java/io/dataease/plugins/server/XEmailTaskServer.java @@ -17,7 +17,7 @@ import io.dataease.plugins.xpack.email.dto.response.XpackTaskGridDTO; import io.dataease.plugins.xpack.email.dto.response.XpackTaskInstanceDTO; import io.dataease.plugins.xpack.email.service.EmailXpackService; import io.dataease.service.ScheduleService; -import io.swagger.annotations.Api; +import org.apache.commons.collections.CollectionUtils; import org.apache.commons.lang3.ObjectUtils; import org.apache.commons.lang3.StringUtils; import org.springframework.beans.factory.annotation.Autowired; @@ -28,7 +28,7 @@ import java.util.concurrent.Future; import javax.annotation.Resource; -@Api(tags = "xpack:定时报告") + @RequestMapping("/plugin/task") @RestController public class XEmailTaskServer { @@ -45,6 +45,28 @@ public class XEmailTaskServer { EmailXpackService emailXpackService = SpringContextUtil.getBean(EmailXpackService.class); Page page = PageHelper.startPage(goPage, pageSize, true); List tasks = emailXpackService.taskGrid(request); + if (CollectionUtils.isNotEmpty(tasks)) { + tasks.forEach(item -> { + if (CronUtils.taskExpire(item.getEndTime())) { + item.setNextExecTime(null); + }else { + GlobalTaskEntity globalTaskEntity = new GlobalTaskEntity(); + globalTaskEntity.setRateType(item.getRateType()); + globalTaskEntity.setRateVal(item.getRateVal()); + try{ + String cron = CronUtils.cron(globalTaskEntity); + if (StringUtils.isNotBlank(cron)) { + Long nextTime = CronUtils.getNextTriggerTime(cron).getTime(); + item.setNextExecTime(nextTime); + } + }catch (Exception e) { + item.setNextExecTime(null); + } + } + + }); + } + Pager> listPager = PageUtils.setPageInfo(page, tasks); return listPager; } @@ -133,6 +155,12 @@ public class XEmailTaskServer { } } + @PostMapping("/stop/{taskId}") + public void stop(@PathVariable Long taskId) throws Exception { + EmailXpackService emailXpackService = SpringContextUtil.getBean(EmailXpackService.class); + emailXpackService.stop(taskId); + } + @PostMapping("/queryInstancies/{goPage}/{pageSize}") public Pager> instancesGrid(@PathVariable int goPage, @PathVariable int pageSize, @RequestBody XpackGridRequest request) { diff --git a/backend/src/main/java/io/dataease/service/panel/ShareService.java b/backend/src/main/java/io/dataease/service/panel/ShareService.java index ddc466d4ea..01c7150ff6 100644 --- a/backend/src/main/java/io/dataease/service/panel/ShareService.java +++ b/backend/src/main/java/io/dataease/service/panel/ShareService.java @@ -315,7 +315,9 @@ public class ShareService { } public List queryTargets(String panelId) { - return extPanelShareMapper.queryTargets(panelId); + List targets = extPanelShareMapper.queryTargets(panelId); + if (CollectionUtils.isEmpty(targets)) return new ArrayList<>(); + return targets.stream().filter(item -> StringUtils.isNotEmpty(item.getTargetName())).collect(Collectors.toList()); } public void removeShares(PanelShareRemoveRequest removeRequest) { diff --git a/frontend/src/components/DeDrag/index.vue b/frontend/src/components/DeDrag/index.vue index 8832a2c813..a53416fd9d 100644 --- a/frontend/src/components/DeDrag/index.vue +++ b/frontend/src/components/DeDrag/index.vue @@ -370,7 +370,9 @@ export default { // 鼠标移入事件 mouseOn: false, // 是否移动 (如果没有移动 不需要记录snapshot) - hasMove: false + hasMove: false, + // 上次的鼠标指针纵向位置,用来判断指针是上移还是下移 + latestMoveY: 0 } }, computed: { @@ -543,7 +545,8 @@ export default { 'canvasStyleData', 'linkageSettingStatus', 'mobileLayoutStatus', - 'componentGap' + 'componentGap', + 'scrollAutoMove' ]) }, watch: { @@ -646,12 +649,14 @@ export default { dragging(val) { if (this.enabled) { this.curComponent.optStatus.dragging = val + this.$store.commit('setScrollAutoMove', 0) } }, // private 监控dragging resizing resizing(val) { if (this.enabled) { this.curComponent.optStatus.resizing = val + this.$store.commit('setScrollAutoMove', 0) } } }, @@ -724,6 +729,8 @@ export default { // 此处阻止冒泡 但是外层需要获取pageX pageY this.element.auxiliaryMatrix && this.$emit('elementMouseDown', e) this.$store.commit('setCurComponent', { component: this.element, index: this.index }) + // 移动端组件点击自动置顶 + this.mobileLayoutStatus && this.$store.commit('topComponent') eventsFor = events.mouse this.elementDown(e) }, @@ -763,6 +770,8 @@ export default { this.mouseClickPosition.bottom = this.bottom this.mouseClickPosition.width = this.width this.mouseClickPosition.height = this.height + // 鼠标按下 重置上次鼠标指针位置 + this.latestMoveY = this.mouseClickPosition.mouseY if (this.parent) { this.bounds = this.calcDragLimits() } @@ -997,7 +1006,13 @@ export default { // 水平移动 const tmpDeltaX = axis && axis !== 'y' ? mouseClickPosition.mouseX - (e.touches ? e.touches[0].pageX : e.pageX) : 0 // 垂直移动 - const tmpDeltaY = axis && axis !== 'x' ? mouseClickPosition.mouseY - (e.touches ? e.touches[0].pageY : e.pageY) : 0 + const mY = e.touches ? e.touches[0].pageY : e.pageY + const tmpDeltaY = axis && axis !== 'x' ? mouseClickPosition.mouseY - mY : 0 + // mY 鼠标指针移动的点 mY - this.latestMoveY 是计算向下移动还是向上移动 + const offsetY = mY - this.latestMoveY + // console.log('mY:' + mY + ';latestMoveY=' + this.latestMoveY + ';offsetY=' + offsetY) + this.$emit('canvasDragging', mY, offsetY) + this.latestMoveY = mY const [deltaX, deltaY] = snapToGrid(grid, tmpDeltaX, tmpDeltaY, this.scaleRatio) const left = restrictToBounds(mouseClickPosition.left - deltaX, bounds.minLeft, bounds.maxLeft) const top = restrictToBounds(mouseClickPosition.top - deltaY, bounds.minTop, bounds.maxTop) @@ -1007,7 +1022,7 @@ export default { const right = restrictToBounds(mouseClickPosition.right + deltaX, bounds.minRight, bounds.maxRight) const bottom = restrictToBounds(mouseClickPosition.bottom + deltaY, bounds.minBottom, bounds.maxBottom) this.left = left - this.top = top + this.top = top + this.scrollAutoMove this.right = right this.bottom = bottom await this.snapCheck() @@ -1221,8 +1236,9 @@ export default { // eslint-disable-next-line no-unused-vars const [_, newHeight] = snapToGrid(this.grid, 0, val, this.scale) // const bottom = restrictToBounds(this.parentHeight - newHeight - this.top, this.bounds.minBottom, this.bounds.maxBottom) - // private 将 this.bounds.minBottom 设置为0 - const bottom = restrictToBounds(this.parentHeight - newHeight - this.top, 0, this.bounds.maxBottom) + // private 将 this.bounds.minBottom parentHeight理论不设上限 所以这里不再检验bottom底部距离 + // const bottom = restrictToBounds(this.parentHeight - newHeight - this.top, 0, this.bounds.maxBottom) + const bottom = this.parentHeight - newHeight - this.top let right = this.right if (this.lockAspectRatio) { right = this.right - (this.bottom - bottom) * this.aspectFactor diff --git a/frontend/src/components/canvas/components/Editor/index.vue b/frontend/src/components/canvas/components/Editor/index.vue index 46ebd36679..b5ff7bcd48 100644 --- a/frontend/src/components/canvas/components/Editor/index.vue +++ b/frontend/src/components/canvas/components/Editor/index.vue @@ -55,6 +55,7 @@ @amRemoveItem="removeItem(item._dragId)" @amAddItem="addItemBox(item)" @linkJumpSet="linkJumpSet(item)" + @canvasDragging="canvasDragging" > - + @@ -265,6 +265,7 @@ export default { }, data() { return { + autoMoveOffSet: 15, mobileEditorShow: true, hasStar: false, drawerSize: '300px', @@ -397,7 +398,8 @@ export default { 'mobileLayoutStatus', 'pcMatrixCount', 'mobileMatrixCount', - 'mobileLayoutStyle' + 'mobileLayoutStyle', + 'scrollAutoMove' ]) }, @@ -881,6 +883,33 @@ export default { }, sureStatusChange(status) { this.enableSureButton = status + }, + canvasDragging(mY, offsetY) { + if (this.curComponent && this.curComponent.optStatus.dragging) { + // 触发滚动的区域偏移量 + const touchOffset = 100 + const canvasInfoMobile = document.getElementById('canvasInfoMobile') + // 获取子盒子(高度肯定比父盒子大) + // const editorMobile = document.getElementById('editorMobile') + // 画布区顶部到浏览器顶部距离 + const canvasTop = canvasInfoMobile.offsetTop + 75 + // 画布区有高度 + const canvasHeight = canvasInfoMobile.offsetHeight + // 画布区域底部距离浏览器顶部距离 + const canvasBottom = canvasTop + canvasHeight + if (mY > (canvasBottom - touchOffset) && offsetY > 0) { + // 触发底部滚动 + this.scrollMove(this.autoMoveOffSet) + } else if (mY < (canvasTop + touchOffset) && offsetY < 0) { + // 触发顶部滚动 + this.scrollMove(-this.autoMoveOffSet) + } + } + }, + scrollMove(offset) { + const canvasInfoMobile = document.getElementById('canvasInfoMobile') + canvasInfoMobile.scrollTop = canvasInfoMobile.scrollTop + offset + this.$store.commit('setScrollAutoMove', this.scrollAutoMove + offset) } } } diff --git a/mobile/src/locale/en.json b/mobile/src/locale/en.json index 626104e0b9..36f663af86 100644 --- a/mobile/src/locale/en.json +++ b/mobile/src/locale/en.json @@ -1,15 +1,15 @@ { "app.name": "DataEase", "navigate.menuHome": "Home", - "navigate.menuDir": "Dir", + "navigate.menuDir": "Folder", "navigate.menuMe": "Me", "navigate.search": "Search", - "navigate.personInfo": "Person Info", + "navigate.personInfo": "My Profile", "navigate.language": "Language", "navigate.about": "About", "navigate.login": "Login", - "searchPlaceholder": "Please Code Panel Name", + "searchPlaceholder": "Please Input Panel Name", "commons": { "cancel": "Cancel", @@ -24,11 +24,11 @@ "login": { "title": "User Login", "account": "Account:", - "accountPlaceholder": "Please Code Account", + "accountPlaceholder": "Please Input Account", "password": "Password:", - "passwordPlaceholder": "Please Code Password:", + "passwordPlaceholder": "Please Input Password:", "loginbtn": "Login", - "pwdFmtError": "Password Must More Than 6 Character", + "pwdFmtError": "Password Must More Than 6 Characters", "uOrpwdError": "Invalid Account Or Password" }, "home": { @@ -38,13 +38,13 @@ }, "dir": { "searchHistory": "Search History", - "clearConfirm": "Sure Clean All History ?", + "clearConfirm": "Are You Sure To Clean All History ?", "noHistory": "There Are No Any History", - "contentPrefix": "The Content You Code Are ", + "contentPrefix": "The Content Is ", "contentSuffix": "Will Be Marked As History When You Confirm" }, "me": { - "moreInfo": "More Info", + "moreInfo": "More", "logout": "Logout", "systemInfo": "System Info", @@ -61,4 +61,4 @@ } -} \ No newline at end of file +}