From 1a0c1ac2b577aeb0b73f2aa63209332a8270bf8b Mon Sep 17 00:00:00 2001 From: junjun Date: Wed, 7 Aug 2024 10:35:54 +0800 Subject: [PATCH] =?UTF-8?q?feat(=E5=9B=BE=E8=A1=A8):=20=E8=BF=87=E6=BB=A4?= =?UTF-8?q?=E5=99=A8=E6=94=AF=E6=8C=81=E5=8A=A8=E6=80=81=E6=97=B6=E9=97=B4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../manage/ChartViewOldDataMergeService.java | 59 ++++++++- .../engine/trans/CustomWhere2Str.java | 119 ++++++++++++++++-- .../listener/ChartFilterDynamicListener.java | 45 +++++++ .../main/resources/db/desktop/V2.10__ddl.sql | 3 + .../resources/db/migration/V2.10__ddl.sql | 3 + .../view/filter/DynamicTimeSetting.java | 18 +++ .../view/filter/FilterTreeItem.java | 2 + 7 files changed, 240 insertions(+), 9 deletions(-) create mode 100644 core/core-backend/src/main/java/io/dataease/listener/ChartFilterDynamicListener.java create mode 100644 core/core-backend/src/main/resources/db/desktop/V2.10__ddl.sql create mode 100644 core/core-backend/src/main/resources/db/migration/V2.10__ddl.sql create mode 100644 sdk/extensions/extensions-view/src/main/java/io/dataease/extensions/view/filter/DynamicTimeSetting.java diff --git a/core/core-backend/src/main/java/io/dataease/chart/manage/ChartViewOldDataMergeService.java b/core/core-backend/src/main/java/io/dataease/chart/manage/ChartViewOldDataMergeService.java index 3d026c39d5..16592f0799 100644 --- a/core/core-backend/src/main/java/io/dataease/chart/manage/ChartViewOldDataMergeService.java +++ b/core/core-backend/src/main/java/io/dataease/chart/manage/ChartViewOldDataMergeService.java @@ -2,15 +2,16 @@ package io.dataease.chart.manage; import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; import com.fasterxml.jackson.core.type.TypeReference; +import io.dataease.chart.dao.auto.entity.CoreChartView; +import io.dataease.chart.dao.auto.mapper.CoreChartViewMapper; import io.dataease.extensions.view.dto.ChartCustomFilterItemDTO; import io.dataease.extensions.view.dto.ChartFieldCustomFilterDTO; import io.dataease.extensions.view.filter.FilterTreeItem; import io.dataease.extensions.view.filter.FilterTreeObj; -import io.dataease.chart.dao.auto.entity.CoreChartView; -import io.dataease.chart.dao.auto.mapper.CoreChartViewMapper; import io.dataease.utils.JsonUtil; import jakarta.annotation.Resource; import org.apache.commons.collections4.CollectionUtils; +import org.apache.commons.lang3.ObjectUtils; import org.apache.commons.lang3.StringUtils; import org.springframework.stereotype.Service; @@ -147,4 +148,58 @@ public class ChartViewOldDataMergeService { } return tree; } + + /** + * 视图过滤器动态时间兼容老数据 + */ + public void refreshFilter() { + // 获取所有视图数据 + // 在filter中增加filterTypeTime = dateValue + List chartViewWithBLOBs = coreChartViewMapper.selectList(new QueryWrapper<>()); + if (CollectionUtils.isEmpty(chartViewWithBLOBs)) { + return; + } + + for (CoreChartView view : chartViewWithBLOBs) { + FilterTreeObj filterTreeObj; + try { + filterTreeObj = JsonUtil.parseObject(view.getCustomFilter(), FilterTreeObj.class); + } catch (Exception e) { + continue; + } + + if (ObjectUtils.isNotEmpty(filterTreeObj)) { + if (ObjectUtils.isEmpty(filterTreeObj.getItems())) { + continue; + } + FilterTreeObj tree = fixFilter(filterTreeObj); + view.setCustomFilter((String) JsonUtil.toJSONString(tree)); + } + + try { + coreChartViewMapper.updateById(view); + } catch (Exception e) { + // do nothing,to continue + e.printStackTrace(); + } + } + } + + public FilterTreeObj fixFilter(FilterTreeObj filterTreeObj) { + doFix(filterTreeObj.getItems()); + return filterTreeObj; + } + + public void doFix(List items) { + if (ObjectUtils.isEmpty(items)) { + return; + } + for (FilterTreeItem item : items) { + if (StringUtils.equalsIgnoreCase(item.getType(), "item")) { + item.setFilterTypeTime("dateValue"); + } else { + doFix(item.getSubTree().getItems()); + } + } + } } diff --git a/core/core-backend/src/main/java/io/dataease/engine/trans/CustomWhere2Str.java b/core/core-backend/src/main/java/io/dataease/engine/trans/CustomWhere2Str.java index 67c825e8c6..778f11fc2f 100644 --- a/core/core-backend/src/main/java/io/dataease/engine/trans/CustomWhere2Str.java +++ b/core/core-backend/src/main/java/io/dataease/engine/trans/CustomWhere2Str.java @@ -1,22 +1,20 @@ package io.dataease.engine.trans; +import io.dataease.engine.constant.SQLConstants; +import io.dataease.engine.utils.Utils; import io.dataease.extensions.datasource.constant.SqlPlaceholderConstants; +import io.dataease.extensions.datasource.dto.DatasetTableFieldDTO; import io.dataease.extensions.datasource.dto.DatasourceSchemaDTO; import io.dataease.extensions.datasource.model.SQLMeta; import io.dataease.extensions.datasource.model.SQLObj; +import io.dataease.extensions.view.filter.DynamicTimeSetting; import io.dataease.extensions.view.filter.FilterTreeItem; import io.dataease.extensions.view.filter.FilterTreeObj; -import io.dataease.extensions.datasource.dto.DatasetTableFieldDTO; -import io.dataease.engine.constant.SQLConstants; -import io.dataease.engine.utils.Utils; import org.apache.commons.collections4.CollectionUtils; import org.apache.commons.lang3.ObjectUtils; import org.apache.commons.lang3.StringUtils; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; +import java.util.*; /** * @Author Junjun @@ -153,6 +151,8 @@ public class CustomWhere2Str { } else { // 如果是时间字段过滤,当条件是等于和不等于的时候转换成between和not between if (field.getDeType() == 1) { + // 如果是动态时间,计算具体值 + value = fixValue(item); if (StringUtils.equalsIgnoreCase(whereTerm, " = ")) { whereTerm = " BETWEEN "; // 把value类似过滤组件处理,获得start time和end time @@ -178,4 +178,109 @@ public class CustomWhere2Str { } return res; } + + private static String fixValue(FilterTreeItem item) { + if (StringUtils.isNotEmpty(item.getFilterTypeTime()) && StringUtils.equalsIgnoreCase(item.getFilterTypeTime(), "dynamicDate")) { + DynamicTimeSetting dynamicTimeSetting = item.getDynamicTimeSetting(); + Calendar instance = Calendar.getInstance(); + if (StringUtils.equalsIgnoreCase(dynamicTimeSetting.getTimeGranularity(), "year")) { + if (StringUtils.equalsIgnoreCase(dynamicTimeSetting.getRelativeToCurrent(), "thisYear")) { + } else if (StringUtils.equalsIgnoreCase(dynamicTimeSetting.getRelativeToCurrent(), "lastYear")) { + instance.add(Calendar.YEAR, -1); + } else if (StringUtils.equalsIgnoreCase(dynamicTimeSetting.getRelativeToCurrent(), "custom")) { + if (StringUtils.equalsIgnoreCase(dynamicTimeSetting.getAround(), "f")) { + instance.add(Calendar.YEAR, -dynamicTimeSetting.getTimeNum()); + } else { + instance.add(Calendar.YEAR, dynamicTimeSetting.getTimeNum()); + } + } + return "" + instance.get(Calendar.YEAR); + } else if (StringUtils.equalsIgnoreCase(dynamicTimeSetting.getTimeGranularity(), "month")) { + if (StringUtils.equalsIgnoreCase(dynamicTimeSetting.getRelativeToCurrent(), "thisMonth")) { + } else if (StringUtils.equalsIgnoreCase(dynamicTimeSetting.getRelativeToCurrent(), "lastMonth")) { + instance.add(Calendar.MONTH, -1); + } else if (StringUtils.equalsIgnoreCase(dynamicTimeSetting.getRelativeToCurrent(), "custom")) { + if (StringUtils.equalsIgnoreCase(dynamicTimeSetting.getRelativeToCurrentType(), "year")) { + if (StringUtils.equalsIgnoreCase(dynamicTimeSetting.getAround(), "f")) { + instance.add(Calendar.YEAR, -dynamicTimeSetting.getTimeNum()); + } else { + instance.add(Calendar.YEAR, dynamicTimeSetting.getTimeNum()); + } + } else if (StringUtils.equalsIgnoreCase(dynamicTimeSetting.getRelativeToCurrentType(), "month")) { + if (StringUtils.equalsIgnoreCase(dynamicTimeSetting.getAround(), "f")) { + instance.add(Calendar.MONTH, -dynamicTimeSetting.getTimeNum()); + } else { + instance.add(Calendar.MONTH, dynamicTimeSetting.getTimeNum()); + } + } + } + return instance.get(Calendar.YEAR) + "-" + (instance.get(Calendar.MONTH) + 1 < 10 ? "0" : "") + (instance.get(Calendar.MONTH) + 1); + } else if (StringUtils.equalsIgnoreCase(dynamicTimeSetting.getTimeGranularity(), "date")) { + if (StringUtils.equalsIgnoreCase(dynamicTimeSetting.getRelativeToCurrent(), "today")) { + } else if (StringUtils.equalsIgnoreCase(dynamicTimeSetting.getRelativeToCurrent(), "yesterday")) { + instance.add(Calendar.DAY_OF_MONTH, -1); + } else if (StringUtils.equalsIgnoreCase(dynamicTimeSetting.getRelativeToCurrent(), "monthBeginning")) { + instance.set(Calendar.DAY_OF_MONTH, 1); + } else if (StringUtils.equalsIgnoreCase(dynamicTimeSetting.getRelativeToCurrent(), "yearBeginning")) { + instance.set(Calendar.MONTH, 0); + instance.set(Calendar.DAY_OF_MONTH, 1); + } else if (StringUtils.equalsIgnoreCase(dynamicTimeSetting.getRelativeToCurrent(), "custom")) { + if (StringUtils.equalsIgnoreCase(dynamicTimeSetting.getRelativeToCurrentType(), "year")) { + if (StringUtils.equalsIgnoreCase(dynamicTimeSetting.getAround(), "f")) { + instance.add(Calendar.YEAR, -dynamicTimeSetting.getTimeNum()); + } else { + instance.add(Calendar.YEAR, dynamicTimeSetting.getTimeNum()); + } + } else if (StringUtils.equalsIgnoreCase(dynamicTimeSetting.getRelativeToCurrentType(), "month")) { + if (StringUtils.equalsIgnoreCase(dynamicTimeSetting.getAround(), "f")) { + instance.add(Calendar.MONTH, -dynamicTimeSetting.getTimeNum()); + } else { + instance.add(Calendar.MONTH, dynamicTimeSetting.getTimeNum()); + } + } else if (StringUtils.equalsIgnoreCase(dynamicTimeSetting.getRelativeToCurrentType(), "date")) { + if (StringUtils.equalsIgnoreCase(dynamicTimeSetting.getAround(), "f")) { + instance.add(Calendar.DAY_OF_MONTH, -dynamicTimeSetting.getTimeNum()); + } else { + instance.add(Calendar.DAY_OF_MONTH, dynamicTimeSetting.getTimeNum()); + } + } + } + return instance.get(Calendar.YEAR) + "-" + (instance.get(Calendar.MONTH) + 1 < 10 ? "0" : "") + (instance.get(Calendar.MONTH) + 1) + "-" + (instance.get(Calendar.DAY_OF_MONTH) < 10 ? "0" : "") + instance.get(Calendar.DAY_OF_MONTH); + } else if (StringUtils.equalsIgnoreCase(dynamicTimeSetting.getTimeGranularity(), "datetime")) { + String time = " 00:00:00"; + if (StringUtils.equalsIgnoreCase(dynamicTimeSetting.getRelativeToCurrent(), "today")) { + } else if (StringUtils.equalsIgnoreCase(dynamicTimeSetting.getRelativeToCurrent(), "yesterday")) { + instance.add(Calendar.DAY_OF_MONTH, -1); + } else if (StringUtils.equalsIgnoreCase(dynamicTimeSetting.getRelativeToCurrent(), "monthBeginning")) { + instance.set(Calendar.DAY_OF_MONTH, 1); + } else if (StringUtils.equalsIgnoreCase(dynamicTimeSetting.getRelativeToCurrent(), "yearBeginning")) { + instance.set(Calendar.MONTH, 0); + instance.set(Calendar.DAY_OF_MONTH, 1); + } else if (StringUtils.equalsIgnoreCase(dynamicTimeSetting.getRelativeToCurrent(), "custom")) { + time = " " + dynamicTimeSetting.getArbitraryTime().substring(11, 19); + if (StringUtils.equalsIgnoreCase(dynamicTimeSetting.getRelativeToCurrentType(), "year")) { + if (StringUtils.equalsIgnoreCase(dynamicTimeSetting.getAround(), "f")) { + instance.add(Calendar.YEAR, -dynamicTimeSetting.getTimeNum()); + } else { + instance.add(Calendar.YEAR, dynamicTimeSetting.getTimeNum()); + } + } else if (StringUtils.equalsIgnoreCase(dynamicTimeSetting.getRelativeToCurrentType(), "month")) { + if (StringUtils.equalsIgnoreCase(dynamicTimeSetting.getAround(), "f")) { + instance.add(Calendar.MONTH, -dynamicTimeSetting.getTimeNum()); + } else { + instance.add(Calendar.MONTH, dynamicTimeSetting.getTimeNum()); + } + } else if (StringUtils.equalsIgnoreCase(dynamicTimeSetting.getRelativeToCurrentType(), "date")) { + if (StringUtils.equalsIgnoreCase(dynamicTimeSetting.getAround(), "f")) { + instance.add(Calendar.DAY_OF_MONTH, -dynamicTimeSetting.getTimeNum()); + } else { + instance.add(Calendar.DAY_OF_MONTH, dynamicTimeSetting.getTimeNum()); + } + } + } + return instance.get(Calendar.YEAR) + "-" + (instance.get(Calendar.MONTH) + 1 < 10 ? "0" : "") + (instance.get(Calendar.MONTH) + 1) + "-" + (instance.get(Calendar.DAY_OF_MONTH) < 10 ? "0" : "") + instance.get(Calendar.DAY_OF_MONTH) + time; + } + } + return item.getValue(); + } } diff --git a/core/core-backend/src/main/java/io/dataease/listener/ChartFilterDynamicListener.java b/core/core-backend/src/main/java/io/dataease/listener/ChartFilterDynamicListener.java new file mode 100644 index 0000000000..08787b222e --- /dev/null +++ b/core/core-backend/src/main/java/io/dataease/listener/ChartFilterDynamicListener.java @@ -0,0 +1,45 @@ +package io.dataease.listener; + +import io.dataease.chart.manage.ChartViewOldDataMergeService; +import io.dataease.startup.dao.auto.entity.CoreSysStartupJob; +import io.dataease.startup.dao.auto.mapper.CoreSysStartupJobMapper; +import jakarta.annotation.Resource; +import org.apache.commons.lang3.ObjectUtils; +import org.apache.commons.lang3.StringUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.boot.context.event.ApplicationReadyEvent; +import org.springframework.context.ApplicationListener; +import org.springframework.core.annotation.Order; +import org.springframework.stereotype.Component; + + +/** + * @Author Junjun + */ +@Component +@Order(value = 9) +public class ChartFilterDynamicListener implements ApplicationListener { + private final Logger logger = LoggerFactory.getLogger(ChartFilterDynamicListener.class); + public static final String JOB_ID = "chartFilterDynamic"; + @Resource + private CoreSysStartupJobMapper coreSysStartupJobMapper; + @Resource + private ChartViewOldDataMergeService chartViewOldDataMergeService; + + @Override + public void onApplicationEvent(ApplicationReadyEvent applicationReadyEvent) { + logger.info("====chart filter dynamic [start]===="); + + CoreSysStartupJob sysStartupJob = coreSysStartupJobMapper.selectById(JOB_ID); + if (ObjectUtils.isNotEmpty(sysStartupJob) && StringUtils.equalsIgnoreCase(sysStartupJob.getStatus(), "ready")) { + logger.info("====chart filter dynamic [doing]===="); + + chartViewOldDataMergeService.refreshFilter(); + + sysStartupJob.setStatus("done"); + coreSysStartupJobMapper.updateById(sysStartupJob); + } + logger.info("====chart filter dynamic [end]===="); + } +} diff --git a/core/core-backend/src/main/resources/db/desktop/V2.10__ddl.sql b/core/core-backend/src/main/resources/db/desktop/V2.10__ddl.sql new file mode 100644 index 0000000000..e081ee1bb5 --- /dev/null +++ b/core/core-backend/src/main/resources/db/desktop/V2.10__ddl.sql @@ -0,0 +1,3 @@ +BEGIN; +INSERT INTO `core_sys_startup_job` VALUES ('chartFilterDynamic', 'chartFilterDynamic', 'ready'); +COMMIT; diff --git a/core/core-backend/src/main/resources/db/migration/V2.10__ddl.sql b/core/core-backend/src/main/resources/db/migration/V2.10__ddl.sql new file mode 100644 index 0000000000..e081ee1bb5 --- /dev/null +++ b/core/core-backend/src/main/resources/db/migration/V2.10__ddl.sql @@ -0,0 +1,3 @@ +BEGIN; +INSERT INTO `core_sys_startup_job` VALUES ('chartFilterDynamic', 'chartFilterDynamic', 'ready'); +COMMIT; diff --git a/sdk/extensions/extensions-view/src/main/java/io/dataease/extensions/view/filter/DynamicTimeSetting.java b/sdk/extensions/extensions-view/src/main/java/io/dataease/extensions/view/filter/DynamicTimeSetting.java new file mode 100644 index 0000000000..ced081459b --- /dev/null +++ b/sdk/extensions/extensions-view/src/main/java/io/dataease/extensions/view/filter/DynamicTimeSetting.java @@ -0,0 +1,18 @@ +package io.dataease.extensions.view.filter; + +import lombok.Data; + +import java.io.Serializable; + +/** + * @Author Junjun + */ +@Data +public class DynamicTimeSetting implements Serializable { + private String relativeToCurrent;//相对当前 thisYear | lastYear | thisMonth | lastMonth | today | yesterday | monthBeginning | yearBeginning + private String timeGranularity;//时间粒度 year | month | date | datetime + private Integer timeNum;// 数值 + private String relativeToCurrentType;// year | month | date + private String around;// 前 f | 后 b + private String arbitraryTime;//timeGranularity = datetime时 取时分秒 +} diff --git a/sdk/extensions/extensions-view/src/main/java/io/dataease/extensions/view/filter/FilterTreeItem.java b/sdk/extensions/extensions-view/src/main/java/io/dataease/extensions/view/filter/FilterTreeItem.java index 8bb0d261e7..f4e8ab2a0c 100644 --- a/sdk/extensions/extensions-view/src/main/java/io/dataease/extensions/view/filter/FilterTreeItem.java +++ b/sdk/extensions/extensions-view/src/main/java/io/dataease/extensions/view/filter/FilterTreeItem.java @@ -22,6 +22,8 @@ public class FilterTreeItem implements Serializable { private String term;//'eq','not_eq','lt','le','gt','ge','in','not in','like','not like','null','not_null','empty','not_empty','between' private String value;// 'a' private List enumValue;// ['a','b'] + private String filterTypeTime;// dateValue | dynamicDate + private DynamicTimeSetting dynamicTimeSetting; // tree private FilterTreeObj subTree; }