diff --git a/core/backend/src/main/java/io/dataease/service/chart/util/ChartDataBuild.java b/core/backend/src/main/java/io/dataease/service/chart/util/ChartDataBuild.java index 28f1fc450f..1a9037c5cf 100644 --- a/core/backend/src/main/java/io/dataease/service/chart/util/ChartDataBuild.java +++ b/core/backend/src/main/java/io/dataease/service/chart/util/ChartDataBuild.java @@ -1,7 +1,11 @@ package io.dataease.service.chart.util; +import io.dataease.auth.api.dto.CurrentUserDto; +import io.dataease.commons.utils.AuthUtils; import io.dataease.controller.request.chart.ChartDrillRequest; import io.dataease.dto.chart.*; +import io.dataease.i18n.Lang; +import io.dataease.i18n.Translator; import io.dataease.plugins.common.base.domain.ChartViewWithBLOBs; import io.dataease.plugins.common.dto.chart.ChartViewFieldDTO; import io.dataease.plugins.xpack.auth.dto.request.ColumnPermissionItem; @@ -1390,20 +1394,24 @@ public class ChartDataBuild { values.add(row[xAxis.size() - 2]); values.add(row[xAxis.size() - 1]); obj.put("values", values); + Date date1 = null, date2 = null; try { - Date date = sdf.parse(row[xAxis.size() - 2]); - if (date != null) { - dates.add(date); + date1 = sdf.parse(row[xAxis.size() - 2]); + if (date1 != null) { + dates.add(date1); } } catch (Exception ignore) { } try { - Date date = sdf.parse(row[xAxis.size() - 1]); - if (date != null) { - dates.add(date); + date2 = sdf.parse(row[xAxis.size() - 1]); + if (date2 != null) { + dates.add(date2); } } catch (Exception ignore) { } + //间隔时间 + obj.put("gap", getTimeGap(date1, date2, xAxis1.getDateStyle())); + } else { values.add(new BigDecimal(row[xAxis.size() - 2])); values.add(new BigDecimal(row[xAxis.size() - 1])); @@ -1411,6 +1419,9 @@ public class ChartDataBuild { numbers.add(new BigDecimal(row[xAxis.size() - 2])); numbers.add(new BigDecimal(row[xAxis.size() - 1])); + + //间隔差 + obj.put("gap", new BigDecimal(row[xAxis.size() - 1]).subtract(new BigDecimal(row[xAxis.size() - 2]))); } dataList.add(obj); @@ -1436,6 +1447,114 @@ public class ChartDataBuild { } + private static String getTimeGap(Date from, Date to, String dateStyle) { + if (from == null || to == null) { + return ""; + } + Calendar fromCalender = Calendar.getInstance(); + fromCalender.setTime(from); + + Calendar toCalender = Calendar.getInstance(); + toCalender.setTime(to); + + long yearGap = 0; + long monthGap = 0; + long dayGap = (toCalender.getTimeInMillis() - fromCalender.getTimeInMillis()) / (1000 * 3600 * 24); + long hourGap = ((toCalender.getTimeInMillis() - fromCalender.getTimeInMillis()) / (1000 * 3600)) % 24; + long minuteGap = ((toCalender.getTimeInMillis() - fromCalender.getTimeInMillis()) / (1000 * 60)) % 60; + long secondGap = ((toCalender.getTimeInMillis() - fromCalender.getTimeInMillis()) / 1000) % 60; + + CurrentUserDto user = AuthUtils.getUser(); + String language = null; + if (user != null) { + language = user.getLanguage(); + } + Lang lang = Lang.getLangWithoutDefault(language); + boolean isEnUs = Lang.en_US.equals(lang); + String splitter = isEnUs ? " " : ""; + + String yearGapStr = ""; + String monthGapStr = ""; + + String dayGapStr = ""; + if (dayGap != 0) { + dayGapStr = dayGap + splitter + Translator.get("i18n_day") + (isEnUs && dayGap != 1 ? "s" : ""); + } + String hourGapStr = ""; + if (hourGap != 0) { + hourGapStr = hourGap + splitter + Translator.get("i18n_hour") + (isEnUs && hourGap != 1 ? "s" : ""); + } + String minuteGapStr = ""; + if (minuteGap != 0) { + minuteGapStr = minuteGap + splitter + Translator.get("i18n_minute") + (isEnUs && minuteGap != 1 ? "s" : ""); + } + String secondGapStr = ""; + if (secondGap != 0) { + secondGapStr = secondGap + splitter + Translator.get("i18n_second") + (isEnUs && secondGap != 1 ? "s" : ""); + } + + List list = new ArrayList<>(); + + switch (dateStyle) { + case "y": + yearGap = toCalender.get(Calendar.YEAR) - fromCalender.get(Calendar.YEAR); + yearGapStr = yearGap == 0 ? "" : (yearGap + splitter + Translator.get("i18n_year") + (isEnUs && yearGap != 1 ? "s" : "")); + return yearGapStr; + case "y_M": + yearGap = ((toCalender.get(Calendar.YEAR) - fromCalender.get(Calendar.YEAR)) * 12L + (toCalender.get(Calendar.MONTH) - fromCalender.get(Calendar.MONTH))) / 12; + monthGap = ((toCalender.get(Calendar.YEAR) - fromCalender.get(Calendar.YEAR)) * 12L + (toCalender.get(Calendar.MONTH) - fromCalender.get(Calendar.MONTH))) % 12; + + yearGapStr = yearGap == 0 ? "" : (yearGap + splitter + Translator.get("i18n_year") + (isEnUs && yearGap != 1 ? "s" : "")); + monthGapStr = monthGap == 0 ? "" : (monthGap + splitter + Translator.get("i18n_month") + (isEnUs && monthGap != 1 ? "s" : "")); + + if (!yearGapStr.isEmpty()) { + list.add(yearGapStr); + } + if (!monthGapStr.isEmpty()) { + list.add(monthGapStr); + } + return StringUtils.join(list, splitter); + case "y_M_d": + return dayGapStr; + case "y_M_d_H": + if (!dayGapStr.isEmpty()) { + list.add(dayGapStr); + } + if (!hourGapStr.isEmpty()) { + list.add(hourGapStr); + } + return StringUtils.join(list, splitter); + case "y_M_d_H_m": + if (!dayGapStr.isEmpty()) { + list.add(dayGapStr); + } + if (!hourGapStr.isEmpty()) { + list.add(hourGapStr); + } + if (!minuteGapStr.isEmpty()) { + list.add(minuteGapStr); + } + return StringUtils.join(list, splitter); + case "H_m_s": + case "y_M_d_H_m_s": + if (!dayGapStr.isEmpty()) { + list.add(dayGapStr); + } + if (!hourGapStr.isEmpty()) { + list.add(hourGapStr); + } + if (!minuteGapStr.isEmpty()) { + list.add(minuteGapStr); + } + if (!secondGapStr.isEmpty()) { + list.add(secondGapStr); + } + return StringUtils.join(list, splitter); + default: + return ""; + } + } + public static Map transBidirectionalBarData(List xAxis, List yAxis, ChartViewDTO view, List data, boolean isDrill) { Map map = new HashMap<>(); diff --git a/core/backend/src/main/resources/i18n/messages_en_US.properties b/core/backend/src/main/resources/i18n/messages_en_US.properties index 466514f092..12654fe7d6 100644 --- a/core/backend/src/main/resources/i18n/messages_en_US.properties +++ b/core/backend/src/main/resources/i18n/messages_en_US.properties @@ -292,3 +292,9 @@ i18n_field_circular_ref=Field has Circular Reference \u8868\u5355\u7BA1\u7406=From Manage \u6211\u7684\u586B\u62A5=My Job \u8868\u5355\u521B\u5EFA=Form Create +i18n_year=Year +i18n_month=Month +i18n_day=Day +i18n_hour=Hour +i18n_minute=Minute +i18n_second=Second \ No newline at end of file diff --git a/core/backend/src/main/resources/i18n/messages_zh_CN.properties b/core/backend/src/main/resources/i18n/messages_zh_CN.properties index 2111f2f73e..ff7b9e6490 100644 --- a/core/backend/src/main/resources/i18n/messages_zh_CN.properties +++ b/core/backend/src/main/resources/i18n/messages_zh_CN.properties @@ -282,3 +282,9 @@ i18n_field_circular_ref=\u5B57\u6BB5\u5B58\u5728\u5FAA\u73AF\u5F15\u7528 \u8868\u5355\u7BA1\u7406=\u8868\u5355\u7BA1\u7406 \u6211\u7684\u586B\u62A5=\u6211\u7684\u586B\u62A5 \u8868\u5355\u521B\u5EFA=\u8868\u5355\u521B\u5EFA +i18n_year=\u5E74 +i18n_month=\u6708 +i18n_day=\u5929 +i18n_hour=\u5C0F\u65F6 +i18n_minute=\u5206\u949F +i18n_second=\u79D2 \ No newline at end of file diff --git a/core/backend/src/main/resources/i18n/messages_zh_TW.properties b/core/backend/src/main/resources/i18n/messages_zh_TW.properties index 9c7aebdfa4..d2eeab8433 100644 --- a/core/backend/src/main/resources/i18n/messages_zh_TW.properties +++ b/core/backend/src/main/resources/i18n/messages_zh_TW.properties @@ -287,3 +287,9 @@ i18n_field_circular_ref=\u5B57\u6BB5\u5B58\u5728\u5FAA\u74B0\u5F15\u7528 \u8868\u5355\u7BA1\u7406=\u8868\u55AE\u7BA1\u7406 \u6211\u7684\u586B\u62A5=\u6211\u7684\u586B\u5831 \u8868\u5355\u521B\u5EFA=\u8868\u55AE\u5275\u5EFA +i18n_year=\u5E74 +i18n_month=\u6708 +i18n_day=\u5929 +i18n_hour=\u5C0F\u6642 +i18n_minute=\u5206\u9418 +i18n_second=\u79D2 \ No newline at end of file diff --git a/core/frontend/src/lang/en.js b/core/frontend/src/lang/en.js index 593c8e1876..230abdc5e8 100644 --- a/core/frontend/src/lang/en.js +++ b/core/frontend/src/lang/en.js @@ -1289,6 +1289,7 @@ export default { label_shadow_color: 'Shadow Color', content_formatter: 'Content Format', label_reserve_decimal_count: 'Reserve Decimal', + show_gap: 'Show Gap', inside: 'Inside', tooltip: 'Tips', tooltip_item: 'Data Item', diff --git a/core/frontend/src/lang/tw.js b/core/frontend/src/lang/tw.js index 786d80fb80..a99a72a384 100644 --- a/core/frontend/src/lang/tw.js +++ b/core/frontend/src/lang/tw.js @@ -1286,6 +1286,7 @@ export default { label: '標簽', label_position: '標簽位置', label_reserve_decimal_count: '保留小數', + show_gap: '顯示間隔值', label_bg: '標簽背景', label_shadow: '標簽陰影', label_shadow_color: '陰影顏色', diff --git a/core/frontend/src/lang/zh.js b/core/frontend/src/lang/zh.js index c4cb352dae..156929132a 100644 --- a/core/frontend/src/lang/zh.js +++ b/core/frontend/src/lang/zh.js @@ -1285,6 +1285,7 @@ export default { label_shadow: '标签阴影', label_shadow_color: '阴影颜色', label_reserve_decimal_count: '保留小数', + show_gap: '显示间隔值', content_formatter: '内容格式', inside: '内', tooltip: '提示', diff --git a/core/frontend/src/views/chart/chart/common/common_antv.js b/core/frontend/src/views/chart/chart/common/common_antv.js index b4a5ff778e..62c22af423 100644 --- a/core/frontend/src/views/chart/chart/common/common_antv.js +++ b/core/frontend/src/views/chart/chart/common/common_antv.js @@ -174,6 +174,9 @@ export function getLabel(chart) { } // label value formatter if (chart.type && chart.type !== 'waterfall') { + if (chart.type === 'bar-time-range') { + label.content = '' + } label.formatter = function(param) { let xAxis, yAxis, extStack, xaxisExt let res = param.value @@ -266,6 +269,12 @@ export function getLabel(chart) { } else if (chart.type === 'scatter' && xAxis && xAxis.length > 0 && xAxis[0].groupType === 'q') { // 针对散点图 res = param.field + } else if (chart.type === 'bar-time-range') { + if (l.showGap) { + res = param.gap + } else { + res = param.values[0] + ' ~ ' + param.values[1] + } } else { for (let i = 0; i < yAxis.length; i++) { const f = yAxis[i] @@ -363,7 +372,10 @@ export function getTooltip(chart) { if (chart.type && chart.type !== 'waterfall') { if (chart.type === 'bar-group-stack') { tooltip.fields = [] + } else if (chart.type === 'bar-time-range') { + tooltip.fields = ['gap', 'category', 'values', 'group', 'field'] } + tooltip.formatter = function(param) { let res = param.value @@ -492,7 +504,10 @@ export function getTooltip(chart) { } } else if (chart.type === 'bar-time-range') { obj = { values: param.values, name: param.category } - res = param.values[0] + ' - ' + param.values[1] + res = param.values[0] + ' ~ ' + param.values[1] + if (t.showGap) { + res = res + ' (' + param.gap + ')' + } } else { res = param.value } diff --git a/core/frontend/src/views/chart/chart/util.js b/core/frontend/src/views/chart/chart/util.js index 7053160075..35035ef69a 100644 --- a/core/frontend/src/views/chart/chart/util.js +++ b/core/frontend/src/views/chart/chart/util.js @@ -1117,7 +1117,6 @@ export const TYPE_CONFIGS = [ icon: 'bar-time-range', properties: [ 'color-selector', - 'label-selector-ant-v', 'tooltip-selector-ant-v', 'x-axis-selector-ant-v', @@ -1141,11 +1140,13 @@ export const TYPE_CONFIGS = [ 'show', 'fontSize', 'color', - 'position-h' + 'position-h', + 'showGap' ], 'tooltip-selector-ant-v': [ 'show', - 'textStyle' + 'textStyle', + 'showGap' ], 'x-axis-selector-ant-v': [ 'show', diff --git a/core/frontend/src/views/chart/components/shapeAttr/LabelSelectorAntV.vue b/core/frontend/src/views/chart/components/shapeAttr/LabelSelectorAntV.vue index 2b297fbd5d..c8aea7c09c 100644 --- a/core/frontend/src/views/chart/components/shapeAttr/LabelSelectorAntV.vue +++ b/core/frontend/src/views/chart/components/shapeAttr/LabelSelectorAntV.vue @@ -139,6 +139,16 @@ >{{ option.name }} + + + + + +