diff --git a/src/main/java/com/gaotao/modules/base/entity/ReportLabelList.java b/src/main/java/com/gaotao/modules/base/entity/ReportLabelList.java index e99ca3e..dbcfc77 100644 --- a/src/main/java/com/gaotao/modules/base/entity/ReportLabelList.java +++ b/src/main/java/com/gaotao/modules/base/entity/ReportLabelList.java @@ -34,5 +34,26 @@ public class ReportLabelList { private Integer digits; @TableField(exist = false) private Integer step; + + // 数据类型相关字段 + private String dataType; + + // 日期类型处理字段 + private String dateExtractType; + private String firstWeekDate; + private String firstDayOfWeek; + private String dateFormat; + private String dateSeparator; + private String yearDigits; + private String monthDayDigits; + + // 字符串类型处理字段 + private String stringProcessType; + private Integer substringStartLength; + private Integer substringEndLength; + private String splitCharacter; + private Integer splitIndex; + private String replaceFrom; + private String replaceTo; } diff --git a/src/main/java/com/gaotao/modules/base/service/Impl/LabelDataProcessorServiceImpl.java b/src/main/java/com/gaotao/modules/base/service/Impl/LabelDataProcessorServiceImpl.java index 6aa8dd4..291e330 100644 --- a/src/main/java/com/gaotao/modules/base/service/Impl/LabelDataProcessorServiceImpl.java +++ b/src/main/java/com/gaotao/modules/base/service/Impl/LabelDataProcessorServiceImpl.java @@ -6,13 +6,19 @@ import com.gaotao.modules.base.service.LabelDataProcessorService; import com.gaotao.modules.base.utils.CoordinateTransformer; import com.gaotao.modules.base.utils.ZplGenerator; import lombok.extern.slf4j.Slf4j; +import org.apache.commons.lang3.time.DateUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import java.math.BigDecimal; import java.math.RoundingMode; import java.text.DecimalFormat; +import java.time.LocalDate; +import java.time.ZoneId; +import java.time.format.DateTimeFormatter; +import java.time.temporal.ChronoUnit; import java.util.ArrayList; +import java.util.Date; import java.util.List; import java.util.Map; import java.util.regex.Matcher; @@ -123,15 +129,35 @@ public class LabelDataProcessorServiceImpl implements LabelDataProcessorService } /** - * 处理文本元素,支持数字格式化 + * 处理文本元素,支持数字、日期、字符串格式化 */ private String processTextElement(String originalData, Map dataMap, ReportLabelList element) { // 首先替换数据源字段 String replacedData = replaceDataSourceFields(originalData, dataMap); - // 如果元素有数字格式化设置,尝试格式化数字 - if (hasNumberFormatSettings(element)) { - return formatTextAsNumber(replacedData, element); + // 根据数据类型进行不同的处理 + String dataType = element.getDataType(); + if (dataType == null) { + dataType = "text"; // 默认为文本类型 + } + + switch (dataType) { + case "number": + if (hasNumberFormatSettings(element)) { + return formatTextAsNumber(replacedData, element); + } + break; + case "date": + return processDateElement(replacedData, element); + case "string": + return processStringElement(replacedData, element); + case "text": + default: + // 文本类型也可能需要数字格式化(向后兼容) + if (hasNumberFormatSettings(element)) { + return formatTextAsNumber(replacedData, element); + } + break; } return replacedData; @@ -253,6 +279,259 @@ public class LabelDataProcessorServiceImpl implements LabelDataProcessorService return result.toString(); } + /** + * 处理日期元素 + */ + private String processDateElement(String dateValue, ReportLabelList element) { + if (dateValue == null || dateValue.trim().isEmpty()) { + return dateValue; + } + + try { + String extractType = element.getDateExtractType(); + if (extractType == null) { + extractType = "full"; + } + + // 尝试解析日期 + java.time.LocalDate date = parseDate(dateValue); + if (date == null) { + log.warn("无法解析日期: {}", dateValue); + return dateValue; + } + + switch (extractType) { + case "year": + return String.valueOf(date.getYear()); + case "month": + return String.valueOf(date.getMonthValue()); + case "day": + return String.valueOf(date.getDayOfMonth()); + case "week": + return calculateWeekNumber(date, element.getFirstWeekDate()); + case "weekday": + return calculateWeekday(date, element.getFirstDayOfWeek()); + case "full": + default: + return formatFullDate(date, element); + } + + } catch (Exception e) { + log.error("日期处理失败: dateValue={}, error={}", dateValue, e.getMessage()); + return dateValue; + } + } + + /** + * 解析日期字符串 + */ + private LocalDate parseDate(String dateValue) { + String[] patterns = { + // 年月日 + "yyyy-MM-dd", "yyyy/MM/dd", "yyyy.MM.dd", + "dd-MM-yyyy", "dd/MM/yyyy", "dd.MM.yyyy", + "MM-dd-yyyy", "MM/dd/yyyy", "MM.dd.yyyy", + "yyyyMMdd", + + // 年月日 + 时分秒 + "yyyy-MM-dd HH:mm:ss", "yyyy/MM/dd HH:mm:ss", "yyyy.MM.dd HH:mm:ss", + "dd-MM-yyyy HH:mm:ss", "dd/MM/yyyy HH:mm:ss", "dd.MM.yyyy HH:mm:ss", + "MM-dd-yyyy HH:mm:ss", "MM/dd/yyyy HH:mm:ss", "MM.dd.yyyy HH:mm:ss", + "yyyyMMdd HHmmss", + + // 年月日 + 时分 + "yyyy-MM-dd HH:mm", "yyyy/MM/dd HH:mm", "yyyy.MM.dd HH:mm", + "dd-MM-yyyy HH:mm", "dd/MM/yyyy HH:mm", "dd.MM.yyyy HH:mm", + "MM-dd-yyyy HH:mm", "MM/dd/yyyy HH:mm", "MM.dd.yyyy HH:mm", + "yyyyMMdd HHmm", + + // 带毫秒 + "yyyy-MM-dd HH:mm:ss.SSS", "yyyy/MM/dd HH:mm:ss.SSS", "yyyy.MM.dd HH:mm:ss.SSS" + }; + + try { + Date date = DateUtils.parseDate(dateValue.trim(), patterns); + return date.toInstant().atZone(ZoneId.systemDefault()).toLocalDate(); + } catch (Exception e) { + log.debug("日期解析失败: {}", dateValue); + return null; + } + } + + /** + * 计算周数 + */ + private String calculateWeekNumber(java.time.LocalDate date, String firstWeekDateStr) { + try { + java.time.LocalDate firstWeekDate; + if (firstWeekDateStr != null && !firstWeekDateStr.trim().isEmpty()) { + firstWeekDate = parseDate(firstWeekDateStr); + if (firstWeekDate == null) { + // 如果解析失败,使用年初作为第一周 + firstWeekDate = java.time.LocalDate.of(date.getYear(), 1, 1); + } + } else { + // 默认使用年初作为第一周 + firstWeekDate = java.time.LocalDate.of(date.getYear(), 1, 1); + } + + long daysBetween = java.time.temporal.ChronoUnit.DAYS.between(firstWeekDate, date); + int weekNumber = (int) (daysBetween / 7) + 1; + return String.valueOf(Math.max(1, weekNumber)); + + } catch (Exception e) { + log.error("周数计算失败: date={}, firstWeekDate={}", date, firstWeekDateStr); + return "1"; + } + } + + /** + * 计算星期几 + */ + private String calculateWeekday(java.time.LocalDate date, String firstDayOfWeekStr) { + try { + int firstDayOfWeek = 1; // 默认周一为第一天 + if (firstDayOfWeekStr != null && !firstDayOfWeekStr.trim().isEmpty()) { + firstDayOfWeek = Integer.parseInt(firstDayOfWeekStr); + } + + int dayOfWeek = date.getDayOfWeek().getValue(); // 1=周一, 7=周日 + + // 调整为指定的第一天 + int adjustedDay = ((dayOfWeek - firstDayOfWeek + 7) % 7) + 1; + return String.valueOf(adjustedDay); + + } catch (Exception e) { + log.error("星期几计算失败: date={}, firstDayOfWeek={}", date, firstDayOfWeekStr); + return "1"; + } + } + + /** + * 格式化完整日期 + */ + private String formatFullDate(java.time.LocalDate date, ReportLabelList element) { + try { + String dateFormat = element.getDateFormat() != null ? element.getDateFormat() : "ymd"; + String separator = element.getDateSeparator() != null ? element.getDateSeparator() : "-"; + String yearDigits = element.getYearDigits() != null ? element.getYearDigits() : "4"; + String monthDayDigits = element.getMonthDayDigits() != null ? element.getMonthDayDigits() : "2"; + + // 格式化年份 + String year = "4".equals(yearDigits) ? + String.format("%04d", date.getYear()) : + String.format("%02d", date.getYear() % 100); + + // 格式化月份和日期 + String month = "2".equals(monthDayDigits) ? + String.format("%02d", date.getMonthValue()) : + String.valueOf(date.getMonthValue()); + + String day = "2".equals(monthDayDigits) ? + String.format("%02d", date.getDayOfMonth()) : + String.valueOf(date.getDayOfMonth()); + + // 根据格式组合 + switch (dateFormat) { + case "dmy": + return day + separator + month + separator + year; + case "mdy": + return month + separator + day + separator + year; + case "ymd": + default: + return year + separator + month + separator + day; + } + + } catch (Exception e) { + log.error("日期格式化失败: date={}", date); + return date.toString(); + } + } + + /** + * 处理字符串元素 + */ + private String processStringElement(String stringValue, ReportLabelList element) { + if (stringValue == null || stringValue.isEmpty()) { + return stringValue; + } + + try { + String processType = element.getStringProcessType(); + if (processType == null || "none".equals(processType)) { + return stringValue; + } + + switch (processType) { + case "substring_start": + return processSubstringStart(stringValue, element.getSubstringStartLength()); + case "substring_end": + return processSubstringEnd(stringValue, element.getSubstringEndLength()); + case "split": + return processSplit(stringValue, element.getSplitCharacter(), element.getSplitIndex()-1); + case "replace": + return processReplace(stringValue, element.getReplaceFrom(), element.getReplaceTo()); + default: + return stringValue; + } + + } catch (Exception e) { + log.error("字符串处理失败: stringValue={}, processType={}, error={}", + stringValue, element.getStringProcessType(), e.getMessage()); + return stringValue; + } + } + + /** + * 截取前面字符 + */ + private String processSubstringStart(String value, Integer length) { + if (length == null || length <= 0) { + return value; + } + return value.length() <= length ? value : value.substring(0, length); + } + + /** + * 截取后面字符 + */ + private String processSubstringEnd(String value, Integer length) { + if (length == null || length <= 0) { + return value; + } + return value.length() <= length ? value : value.substring(value.length() - length); + } + + /** + * 按字符分割 + */ + private String processSplit(String value, String splitChar, Integer index) { + if (splitChar == null || splitChar.isEmpty() || index == null || index < 0) { + return value; + } + + try { + String[] parts = value.split(Pattern.quote(splitChar)); + return index < parts.length ? parts[index] : ""; + } catch (Exception e) { + log.error("字符串分割失败: value={}, splitChar={}, index={}", value, splitChar, index); + return value; + } + } + + /** + * 替换字符 + */ + private String processReplace(String value, String from, String to) { + if (from == null || from.isEmpty()) { + return value; + } + if (to == null) { + to = ""; + } + return value.replace(from, to); + } + /** * 复制元素对象 */ @@ -282,6 +561,24 @@ public class LabelDataProcessorServiceImpl implements LabelDataProcessorService copy.setThousandsSeparator(original.getThousandsSeparator()); copy.setDigits(original.getDigits()); copy.setStep(original.getStep()); + + // 复制新增的数据类型相关字段 + copy.setDataType(original.getDataType()); + copy.setDateExtractType(original.getDateExtractType()); + copy.setFirstWeekDate(original.getFirstWeekDate()); + copy.setFirstDayOfWeek(original.getFirstDayOfWeek()); + copy.setDateFormat(original.getDateFormat()); + copy.setDateSeparator(original.getDateSeparator()); + copy.setYearDigits(original.getYearDigits()); + copy.setMonthDayDigits(original.getMonthDayDigits()); + copy.setStringProcessType(original.getStringProcessType()); + copy.setSubstringStartLength(original.getSubstringStartLength()); + copy.setSubstringEndLength(original.getSubstringEndLength()); + copy.setSplitCharacter(original.getSplitCharacter()); + copy.setSplitIndex(original.getSplitIndex()); + copy.setReplaceFrom(original.getReplaceFrom()); + copy.setReplaceTo(original.getReplaceTo()); + return copy; } @Override